diff --git a/swish/connection/running_session.cpp b/swish/connection/running_session.cpp index b04d247..bab8f82 100644 --- a/swish/connection/running_session.cpp +++ b/swish/connection/running_session.cpp @@ -1,46 +1,24 @@ -/** - @file - - Libssh2 SSH and SFTP session management - - @if license - - Copyright (C) 2008, 2009, 2010, 2011, 2013 - Alexander Lamaison +// Copyright 2008, 2009, 2010, 2011, 2013, 2016 Alexander Lamaison - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - In addition, as a special exception, the the copyright holders give you - permission to combine this program with free software programs or the - OpenSSL project's "OpenSSL" library (or with modified versions of it, - with unchanged license). You may copy and distribute such a system - following the terms of the GNU GPL for this program and the licenses - of the other code concerned. The GNU General Public License gives - permission to release a modified version without this exception; this - exception also makes it possible to release a modified version which - carries forward this exception. - - @endif -*/ +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . #include "running_session.hpp" #include "swish/remotelimits.h" -#include "swish/debug.hpp" // Debug macros +#include "swish/debug.hpp" // Debug macros #include "swish/port_conversion.hpp" // port_to_string -#include "swish/utils.hpp" // WideStringToUtf8String +#include "swish/utils.hpp" // WideStringToUtf8String #include #include // sftp_filesystem @@ -70,76 +48,77 @@ using boost::system::error_code; using std::string; using std::wstring; +namespace swish +{ +namespace connection +{ -namespace swish { -namespace connection { +namespace +{ -namespace { - - /** - * Connect a socket to the given port on the given host. - * - * @throws A boost::system::system_error if there is a failure. - */ - void connect_socket_to_host( - tcp::socket& socket, const wstring& host, unsigned int port, - io_service& io) - { - assert(!host.empty()); - assert(host[0] != L'\0'); - - // Convert host address to a UTF-8 string - string host_name = WideStringToUtf8String(host); - - tcp::resolver resolver(io); - typedef tcp::resolver::query Lookup; - Lookup query(host_name, port_to_string(port)); - - tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); - tcp::resolver::iterator end; - - error_code error = host_not_found; - while (error && endpoint_iterator != end) - { - socket.close(); - socket.connect(*endpoint_iterator++, error); - } - if (error) - BOOST_THROW_EXCEPTION(system_error(error)); - - assert(socket.is_open()); - assert(socket.available() == 0); - } +/** + * Connect a socket to the given port on the given host. + * + * @throws A boost::system::system_error if there is a failure. + */ +void connect_socket_to_host(tcp::socket& socket, const wstring& host, + unsigned int port, io_service& io) +{ + assert(!host.empty()); + assert(host[0] != L'\0'); - // We have to have this weird function because Boost.ASIO doesn't - // support Boost.Move rvalue-emulation. - // - // Ideally, connect_socket_to_host would return the connected sockets - // so could be used in the running_session initialiser list below. And - // the the initialiser for m_session would have a valid socket to use. - // - // But as we can't return the valid socket, we have to connect it *during* - // the m_session initialisation, *after* the m_socket initialisation. Yuk! - ssh::session session_on_socket( - tcp::socket& socket, const wstring& host, unsigned int port, - io_service& io, const string& disconnection_message) + // Convert host address to a UTF-8 string + string host_name = WideStringToUtf8String(host); + + tcp::resolver resolver(io); + typedef tcp::resolver::query Lookup; + Lookup query(host_name, port_to_string(port)); + + tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); + tcp::resolver::iterator end; + + error_code error = host_not_found; + while (error && endpoint_iterator != end) { - connect_socket_to_host(socket, host, port, io); - return ssh::session(socket.native(), disconnection_message); + socket.close(); + socket.connect(*endpoint_iterator++, error); } + if (error) + BOOST_THROW_EXCEPTION(system_error(error)); +} + +// We have to have this weird function because Boost.ASIO doesn't +// support Boost.Move rvalue-emulation. +// +// Ideally, connect_socket_to_host would return the connected sockets +// so could be used in the running_session initialiser list below. And +// the the initialiser for m_session would have a valid socket to use. +// +// But as we can't return the valid socket, we have to connect it *during* +// the m_session initialisation, *after* the m_socket initialisation. Yuk! +ssh::session session_on_socket(tcp::socket& socket, const wstring& host, + unsigned int port, io_service& io, + const string& disconnection_message) +{ + connect_socket_to_host(socket, host, port, io); + return ssh::session(socket.native(), disconnection_message); +} } running_session::running_session(const wstring& host, unsigned int port) -: -m_io(new io_service(0)), m_socket(new tcp::socket(*m_io)), -m_session( - session_on_socket(*m_socket, host, port, *m_io, "Swish says goodbye.")) -{} + : m_io(new io_service(0)), + m_socket(new tcp::socket(*m_io)), + m_session(session_on_socket(*m_socket, host, port, *m_io, + "Swish says goodbye.")) +{ +} running_session::running_session(BOOST_RV_REF(running_session) other) -: -m_io(move(other.m_io)), -m_socket(move(other.m_socket)), m_session(move(other.m_session)) {} + : m_io(move(other.m_io)), + m_socket(move(other.m_socket)), + m_session(move(other.m_session)) +{ +} running_session& running_session::operator=(BOOST_RV_REF(running_session) other) { @@ -172,5 +151,5 @@ void swap(running_session& lhs, running_session& rhs) boost::swap(lhs.m_socket, rhs.m_socket); boost::swap(lhs.m_session, rhs.m_session); } - -}} // namespace swish::connection \ No newline at end of file +} +} // namespace swish::connection diff --git a/test/connection/CMakeLists.txt b/test/connection/CMakeLists.txt index c82c996..c192c82 100644 --- a/test/connection/CMakeLists.txt +++ b/test/connection/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2015 Alexander Lamaison +# Copyright (C) 2015, 2016 Alexander Lamaison # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software @@ -13,17 +13,24 @@ # You should have received a copy of the GNU General Public License along with # this program. If not, see . -set(SOURCES +set(UNIT_TESTS + connection_spec_test.cpp) + +set(INTEGRATION_TESTS authenticated_session_test.cpp - connection_spec_test.cpp + connection_spec_create_session_test.cpp running_session_test.cpp session_manager_test.cpp session_pool_test.cpp) swish_test_suite( - SUBJECT connection - SOURCES ${SOURCES} + SUBJECT connection VARIANT unit + SOURCES ${UNIT_TESTS} LIBRARIES ${Boost_LIBRARIES} - LABELS integration) + LABELS unit) -swish_copy_fixture_files(test-connection) +swish_test_suite( + SUBJECT connection VARIANT integration + SOURCES ${INTEGRATION_TESTS} + LIBRARIES ${Boost_LIBRARIES} openssh_fixture + LABELS integration) diff --git a/test/connection/authenticated_session_test.cpp b/test/connection/authenticated_session_test.cpp index 99b4b05..300fe82 100644 --- a/test/connection/authenticated_session_test.cpp +++ b/test/connection/authenticated_session_test.cpp @@ -1,49 +1,37 @@ -/** - @file - - Tests for the authenticated_session class. - - @if license - - Copyright (C) 2013, 2014 Alexander Lamaison +// Copyright 2013, 2014, 2016 Alexander Lamaison - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - @endif -*/ +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . #include "swish/connection/authenticated_session.hpp" // Test subject -#include "swish/utils.hpp" // Utf8StringToWideString #include "test/common_boost/ConsumerStub.hpp" -#include "test/common_boost/fixtures.hpp" // OpenSshFixture +#include "test/fixtures/openssh_fixture.hpp" #include #include #include -#include // this_thread #include +#include +#include // this_thread #include #include using test::CConsumerStub; -using test::OpenSshFixture; +using test::fixtures::openssh_fixture; using swish::connection::authenticated_session; -using swish::utils::Utf8StringToWideString; using boost::make_shared; using boost::move; @@ -53,51 +41,47 @@ using boost::test_tools::predicate_result; using std::vector; using std::wstring; -BOOST_FIXTURE_TEST_SUITE( authenticated_session_tests, OpenSshFixture ) +BOOST_FIXTURE_TEST_SUITE(authenticated_session_tests, openssh_fixture) -namespace { +namespace +{ - predicate_result sftp_is_alive(authenticated_session& session) +predicate_result sftp_is_alive(authenticated_session& session) +{ + try { - try - { - session.get_sftp_filesystem().directory_iterator("/"); - return true; - } - catch (...) - { - predicate_result res(false); - res.message() << - "SFTP not working; unable to access root directory"; - return res; - } + session.get_sftp_filesystem().directory_iterator("/"); + return true; + } + catch (...) + { + predicate_result res(false); + res.message() << "SFTP not working; unable to access root directory"; + return res; } - +} } /** * Test that connecting succeeds. */ -BOOST_AUTO_TEST_CASE( connect ) +BOOST_AUTO_TEST_CASE(connect) { authenticated_session session( - Utf8StringToWideString(GetHost()), GetPort(), - Utf8StringToWideString(GetUser()), - new CConsumerStub(PrivateKeyPath(), PublicKeyPath())); + whost(), port(), wuser(), + new CConsumerStub(private_key_path(), public_key_path())); BOOST_CHECK(!session.is_dead()); BOOST_CHECK(sftp_is_alive(session)); } -BOOST_AUTO_TEST_CASE( multiple_connections ) +BOOST_AUTO_TEST_CASE(multiple_connections) { vector> sessions; for (int i = 0; i < 5; i++) { - sessions.push_back( - make_shared( - Utf8StringToWideString(GetHost()), GetPort(), - Utf8StringToWideString(GetUser()), - new CConsumerStub(PrivateKeyPath(), PublicKeyPath()))); + sessions.push_back(make_shared( + whost(), port(), wuser(), + new CConsumerStub(private_key_path(), public_key_path()))); } for (int i = 0; i < 5; i++) @@ -107,15 +91,33 @@ BOOST_AUTO_TEST_CASE( multiple_connections ) } } +/** + * Test that session reports its death. + */ +BOOST_AUTO_TEST_CASE(server_death) +{ + authenticated_session session( + whost(), port(), wuser(), + new CConsumerStub(private_key_path(), public_key_path())); + + BOOST_CHECK(sftp_is_alive(session)); + + stop_server(); + + boost::this_thread::sleep(boost::posix_time::milliseconds(2000)); + + BOOST_CHECK(session.is_dead()); + BOOST_CHECK(!sftp_is_alive(session)); +} + /** * Test that session reports its death if server is restarted. */ -BOOST_AUTO_TEST_CASE( server_restart ) +BOOST_AUTO_TEST_CASE(server_restart) { authenticated_session session( - Utf8StringToWideString(GetHost()), GetPort(), - Utf8StringToWideString(GetUser()), - new CConsumerStub(PrivateKeyPath(), PublicKeyPath())); + whost(), port(), wuser(), + new CConsumerStub(private_key_path(), public_key_path())); BOOST_CHECK(sftp_is_alive(session)); @@ -127,37 +129,34 @@ BOOST_AUTO_TEST_CASE( server_restart ) BOOST_CHECK(!sftp_is_alive(session)); } -namespace { +namespace +{ - authenticated_session move_create( - const wstring& host, unsigned int port, const wstring& user, - ISftpConsumer* consumer) - { - authenticated_session session(host, port, user, consumer); - return move(session); - } +authenticated_session move_create(const wstring& host, unsigned int port, + const wstring& user, ISftpConsumer* consumer) +{ + authenticated_session session(host, port, user, consumer); + return move(session); +} } -BOOST_AUTO_TEST_CASE( move_contruct ) +BOOST_AUTO_TEST_CASE(move_contruct) { - authenticated_session session = move_create( - Utf8StringToWideString(GetHost()), GetPort(), - Utf8StringToWideString(GetUser()), - new CConsumerStub(PrivateKeyPath(), PublicKeyPath())); + authenticated_session session = + move_create(whost(), port(), wuser(), + new CConsumerStub(private_key_path(), public_key_path())); BOOST_CHECK(!session.is_dead()); BOOST_CHECK(sftp_is_alive(session)); } -BOOST_AUTO_TEST_CASE( move_assign ) +BOOST_AUTO_TEST_CASE(move_assign) { authenticated_session session1( - Utf8StringToWideString(GetHost()), GetPort(), - Utf8StringToWideString(GetUser()), - new CConsumerStub(PrivateKeyPath(), PublicKeyPath())); + whost(), port(), wuser(), + new CConsumerStub(private_key_path(), public_key_path())); authenticated_session session2( - Utf8StringToWideString(GetHost()), GetPort(), - Utf8StringToWideString(GetUser()), - new CConsumerStub(PrivateKeyPath(), PublicKeyPath())); + whost(), port(), wuser(), + new CConsumerStub(private_key_path(), public_key_path())); session1 = move(session2); diff --git a/test/connection/connection_spec_create_session_test.cpp b/test/connection/connection_spec_create_session_test.cpp new file mode 100644 index 0000000..1d6eed1 --- /dev/null +++ b/test/connection/connection_spec_create_session_test.cpp @@ -0,0 +1,92 @@ +// Copyright 2013, 2016 Alexander Lamaison + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "swish/connection/connection_spec.hpp" // Test subject +#include "swish/connection/authenticated_session.hpp" + +#include "test/common_boost/ConsumerStub.hpp" +#include "test/common_boost/helpers.hpp" +#include "test/fixtures/openssh_fixture.hpp" + +#include // com_ptr + +#include + +#include +#include + +using swish::connection::authenticated_session; +using swish::connection::connection_spec; + +using test::fixtures::openssh_fixture; +using test::CConsumerStub; + +using comet::com_ptr; + +using boost::test_tools::predicate_result; + +using std::exception; +using std::map; + +namespace +{ + +class fixture : private openssh_fixture +{ +public: + connection_spec get_connection() + { + return connection_spec(whost(), wuser(), port()); + } + + com_ptr consumer() + { + com_ptr consumer = + new CConsumerStub(private_key_path(), public_key_path()); + return consumer; + } + + /** + * Check that the given session responds sensibly to a request. + */ + predicate_result alive(authenticated_session& session) + { + try + { + session.get_sftp_filesystem().directory_iterator("/"); + + predicate_result res(true); + res.message() << "Provider seems to be alive"; + return res; + } + catch (const exception& e) + { + predicate_result res(false); + res.message() << "Provider seems to be dead: " << e.what(); + return res; + } + } +}; +} + +BOOST_FIXTURE_TEST_SUITE(connection_spec_session_create, fixture) + +BOOST_AUTO_TEST_CASE(create) +{ + authenticated_session session(get_connection().create_session(consumer())); + BOOST_CHECK(alive(session)); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/connection/connection_spec_test.cpp b/test/connection/connection_spec_test.cpp index e6cb5e3..ce38b78 100644 --- a/test/connection/connection_spec_test.cpp +++ b/test/connection/connection_spec_test.cpp @@ -1,175 +1,90 @@ -/** - @file +// Copyright 2013, 2016 Alexander Lamaison - Tests the connection_spec class. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. - @if license +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. - Copyright (C) 2013 Alexander Lamaison +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - @endif -*/ - -#include "swish/connection/connection_spec.hpp" // Test subject -#include "swish/connection/authenticated_session.hpp" -#include "swish/utils.hpp" +#include "swish/connection/connection_spec.hpp" // Test subject #include "test/common_boost/helpers.hpp" -#include "test/common_boost/fixtures.hpp" -#include "test/common_boost/ConsumerStub.hpp" - -#include // com_ptr #include -#include #include -using swish::connection::authenticated_session; using swish::connection::connection_spec; -using swish::utils::Utf8StringToWideString; -using test::OpenSshFixture; -using test::CConsumerStub; - -using comet::com_ptr; - -using boost::test_tools::predicate_result; - -using std::exception; using std::map; -namespace { - - class ConnectionSpecFixture : public OpenSshFixture - { - public: - - connection_spec get_connection() - { - return connection_spec( - Utf8StringToWideString(GetHost()), - Utf8StringToWideString(GetUser()), GetPort()); - } - - com_ptr Consumer() - { - com_ptr consumer = new CConsumerStub( - PrivateKeyPath(), PublicKeyPath()); - return consumer; - } - - /** - * Check that the given session responds sensibly to a request. - */ - predicate_result alive(authenticated_session& session) - { - try - { - session.get_sftp_filesystem().directory_iterator("/"); - - predicate_result res(true); - res.message() << "Provider seems to be alive"; - return res; - } - catch(const exception& e) - { - predicate_result res(false); - res.message() << "Provider seems to be dead: " << e.what(); - return res; - } - } - - }; -} - - -BOOST_FIXTURE_TEST_SUITE( - connection_spec_session_create, ConnectionSpecFixture) - -BOOST_AUTO_TEST_CASE( create ) -{ - authenticated_session session( - get_connection().create_session(Consumer())); - BOOST_CHECK(alive(session)); -} - -BOOST_AUTO_TEST_SUITE_END() - BOOST_AUTO_TEST_SUITE(connection_spec_comparison) -BOOST_AUTO_TEST_CASE( self ) +BOOST_AUTO_TEST_CASE(self) { - connection_spec s(L"A",L"b",12); + connection_spec s(L"A", L"b", 12); BOOST_CHECK(!(s < s)); } -BOOST_AUTO_TEST_CASE( equal ) +BOOST_AUTO_TEST_CASE(equal) { - connection_spec s1(L"A",L"b",12); - connection_spec s2(L"A",L"b",12); + connection_spec s1(L"A", L"b", 12); + connection_spec s2(L"A", L"b", 12); BOOST_CHECK(!(s1 < s2)); BOOST_CHECK(!(s2 < s1)); } -BOOST_AUTO_TEST_CASE( less_host ) +BOOST_AUTO_TEST_CASE(less_host) { - connection_spec s1(L"A",L"b",12); - connection_spec s2(L"B",L"b",12); + connection_spec s1(L"A", L"b", 12); + connection_spec s2(L"B", L"b", 12); BOOST_CHECK(s1 < s2); BOOST_CHECK(!(s2 < s1)); } -BOOST_AUTO_TEST_CASE( equal_host_less_user ) +BOOST_AUTO_TEST_CASE(equal_host_less_user) { - connection_spec s1(L"A",L"a",12); - connection_spec s2(L"A",L"b",12); + connection_spec s1(L"A", L"a", 12); + connection_spec s2(L"A", L"b", 12); BOOST_CHECK(s1 < s2); BOOST_CHECK(!(s2 < s1)); } -BOOST_AUTO_TEST_CASE( greater_host_less_user ) +BOOST_AUTO_TEST_CASE(greater_host_less_user) { - connection_spec s1(L"B",L"a",12); - connection_spec s2(L"A",L"b",12); + connection_spec s1(L"B", L"a", 12); + connection_spec s2(L"A", L"b", 12); BOOST_CHECK(!(s1 < s2)); BOOST_CHECK(s2 < s1); } -BOOST_AUTO_TEST_CASE( equal_host_equal_user_less_port ) +BOOST_AUTO_TEST_CASE(equal_host_equal_user_less_port) { - connection_spec s1(L"A",L"b",11); - connection_spec s2(L"A",L"b",12); + connection_spec s1(L"A", L"b", 11); + connection_spec s2(L"A", L"b", 12); BOOST_CHECK(s1 < s2); BOOST_CHECK(!(s2 < s1)); } -BOOST_AUTO_TEST_CASE( equal_host_greater_user_less_port ) +BOOST_AUTO_TEST_CASE(equal_host_greater_user_less_port) { - connection_spec s1(L"A",L"c",11); - connection_spec s2(L"A",L"b",12); + connection_spec s1(L"A", L"c", 11); + connection_spec s2(L"A", L"b", 12); BOOST_CHECK(!(s1 < s2)); BOOST_CHECK(s2 < s1); } -BOOST_AUTO_TEST_CASE( use_as_map_key_same ) +BOOST_AUTO_TEST_CASE(use_as_map_key_same) { - connection_spec s1(L"A",L"b",12); - connection_spec s2(L"A",L"b",12); + connection_spec s1(L"A", L"b", 12); + connection_spec s2(L"A", L"b", 12); map m; m[s1] = 3; m[s2] = 7; @@ -178,10 +93,10 @@ BOOST_AUTO_TEST_CASE( use_as_map_key_same ) BOOST_CHECK_EQUAL(m[s2], 7); } -BOOST_AUTO_TEST_CASE( use_as_map_key_different_user ) +BOOST_AUTO_TEST_CASE(use_as_map_key_different_user) { - connection_spec s1(L"A",L"b",12); - connection_spec s2(L"A",L"a",12); + connection_spec s1(L"A", L"b", 12); + connection_spec s2(L"A", L"a", 12); map m; m[s1] = 3; m[s2] = 7; @@ -191,4 +106,3 @@ BOOST_AUTO_TEST_CASE( use_as_map_key_different_user ) } BOOST_AUTO_TEST_SUITE_END() - diff --git a/test/connection/running_session_test.cpp b/test/connection/running_session_test.cpp index 73836e6..cd66e9d 100644 --- a/test/connection/running_session_test.cpp +++ b/test/connection/running_session_test.cpp @@ -1,46 +1,34 @@ -/** - @file +// Copyright 2013, 2016 Alexander Lamaison - Tests for the running_session class. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. - @if license +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. - Copyright (C) 2013 Alexander Lamaison - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - @endif -*/ +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . #include "swish/connection/running_session.hpp" // Test subject -#include "swish/utils.hpp" // Utf8StringToWideString -#include "test/common_boost/fixtures.hpp" // OpenSshFixture +#include "test/fixtures/openssh_fixture.hpp" #include #include #include +#include #include // runtime_error #include #include -using test::OpenSshFixture; +using test::fixtures::openssh_fixture; using swish::connection::running_session; -using swish::utils::Utf8StringToWideString; using boost::make_shared; using boost::move; @@ -50,35 +38,26 @@ using std::runtime_error; using std::vector; using std::wstring; -BOOST_FIXTURE_TEST_SUITE( running_session_tests, OpenSshFixture ) +BOOST_FIXTURE_TEST_SUITE(running_session_tests, openssh_fixture) -/** - * Test that connecting succeeds. - */ -BOOST_AUTO_TEST_CASE( connect ) +BOOST_AUTO_TEST_CASE(connecting_with_correct_host_and_port_succeeds) { - running_session session( - Utf8StringToWideString(GetHost()), GetPort()); + running_session session(whost(), port()); BOOST_CHECK(!session.is_dead()); } -/** - * Test that connecting throws when it fails. - */ -BOOST_AUTO_TEST_CASE( connect_fail ) +BOOST_AUTO_TEST_CASE(connection_failure_throws_error) { - BOOST_CHECK_THROW( - running_session(L"nonsense.invalid", 65535), runtime_error); + BOOST_CHECK_THROW(running_session(L"nonsense.invalid", 65535), + runtime_error); } -BOOST_AUTO_TEST_CASE( multiple_connections ) +BOOST_AUTO_TEST_CASE(multiple_connections_do_not_interfere) { vector> sessions; for (int i = 0; i < 5; i++) { - sessions.push_back( - make_shared( - Utf8StringToWideString(GetHost()), GetPort())); + sessions.push_back(make_shared(whost(), port())); } for (int i = 0; i < 5; i++) @@ -87,28 +66,26 @@ BOOST_AUTO_TEST_CASE( multiple_connections ) } } -namespace { +namespace +{ - running_session move_create(const wstring& host, unsigned int port) - { - running_session session(host, port); - return move(session); - } +running_session move_create(const wstring& host, unsigned int port) +{ + running_session session(host, port); + return move(session); +} } -BOOST_AUTO_TEST_CASE( move_contruct ) +BOOST_AUTO_TEST_CASE(session_survives_move_construction) { - running_session session = move_create( - Utf8StringToWideString(GetHost()), GetPort()); + running_session session = move_create(whost(), port()); BOOST_CHECK(!session.is_dead()); } -BOOST_AUTO_TEST_CASE( move_assign ) +BOOST_AUTO_TEST_CASE(session_survives_move_assignment) { - running_session session1( - Utf8StringToWideString(GetHost()), GetPort()); - running_session session2( - Utf8StringToWideString(GetHost()), GetPort()); + running_session session1(whost(), port()); + running_session session2(whost(), port()); session1 = move(session2); diff --git a/test/connection/session_manager_test.cpp b/test/connection/session_manager_test.cpp index 2d6b501..176689e 100644 --- a/test/connection/session_manager_test.cpp +++ b/test/connection/session_manager_test.cpp @@ -1,37 +1,25 @@ -/** - @file - - Tests for the SFTP session coordinator. - - @if license +// Copyright 2013, 2016 Alexander Lamaison - Copyright (C) 2013 Alexander Lamaison +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - @endif -*/ +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . #include "swish/connection/session_manager.hpp" // Test subject #include "swish/connection/authenticated_session.hpp" #include "swish/connection/connection_spec.hpp" -#include "swish/utils.hpp" #include "test/common_boost/helpers.hpp" -#include "test/common_boost/fixtures.hpp" +#include "test/fixtures/openssh_fixture.hpp" #include "test/common_boost/ConsumerStub.hpp" #include // com_ptr @@ -50,10 +38,9 @@ using swish::connection::authenticated_session; using swish::connection::connection_spec; using swish::connection::session_manager; using swish::connection::session_reservation; -using swish::utils::Utf8StringToWideString; using test::CConsumerStub; -using test::OpenSshFixture; +using test::fixtures::openssh_fixture; using comet::com_ptr; @@ -68,66 +55,60 @@ using boost::thread; using std::exception; using std::string; -namespace { // private +namespace +{ // private - /** - * Fixture that returns backend connections from the connection pool. - */ - class ConnectionFixture : public OpenSshFixture +/** + * Fixture that returns backend connections from the connection pool. + */ +class fixture : private openssh_fixture +{ +public: + connection_spec get_connection() { - public: - - connection_spec get_connection() - { - return connection_spec( - Utf8StringToWideString(GetHost()), - Utf8StringToWideString(GetUser()), GetPort()); - } - - com_ptr consumer() - { - com_ptr consumer = new CConsumerStub( - PrivateKeyPath(), PublicKeyPath()); - return consumer; - } + return connection_spec(whost(), wuser(), port()); + } - }; + com_ptr consumer() + { + com_ptr consumer = + new CConsumerStub(private_key_path(), public_key_path()); + return consumer; + } +}; - /** - * Check that the given provider responds sensibly to a request. - */ - predicate_result alive(authenticated_session& session) +/** + * Check that the given provider responds sensibly to a request. + */ +predicate_result alive(authenticated_session& session) +{ + try { - try - { - session.get_sftp_filesystem().directory_iterator("/"); + session.get_sftp_filesystem().directory_iterator("/"); - predicate_result res(true); - res.message() << "Session seems to be alive"; - return res; - } - catch(const exception& e) - { - predicate_result res(false); - res.message() << "Session seems to be dead: " << e.what(); - return res; - } + predicate_result res(true); + res.message() << "Session seems to be alive"; + return res; + } + catch (const exception& e) + { + predicate_result res(false); + res.message() << "Session seems to be dead: " << e.what(); + return res; } } +} -BOOST_FIXTURE_TEST_SUITE(session_manager_tests, ConnectionFixture) +BOOST_FIXTURE_TEST_SUITE(session_manager_tests, fixture) -/** - * Ensures a new new reservation is registered. - */ -BOOST_AUTO_TEST_CASE( new_reservation ) +BOOST_AUTO_TEST_CASE(new_reservation_are_registered_with_session_manager) { connection_spec spec(get_connection()); BOOST_CHECK(!session_manager().has_session(spec)); - session_reservation ticket = session_manager().reserve_session( - spec, consumer(), "Testing"); + session_reservation ticket = + session_manager().reserve_session(spec, consumer(), "Testing"); BOOST_CHECK(session_manager().has_session(spec)); @@ -138,7 +119,7 @@ BOOST_AUTO_TEST_CASE( new_reservation ) BOOST_CHECK(alive(session)); } -BOOST_AUTO_TEST_CASE( session_outlives_reservation ) +BOOST_AUTO_TEST_CASE(session_outlives_reservation) { connection_spec spec(get_connection()); @@ -149,10 +130,7 @@ BOOST_AUTO_TEST_CASE( session_outlives_reservation ) BOOST_CHECK(session_manager().has_session(spec)); } -/** - * Test that the factory reuses existing sessions. - */ -BOOST_AUTO_TEST_CASE( existing_session ) +BOOST_AUTO_TEST_CASE(factory_reuses_existing_sessions) { connection_spec spec(get_connection()); @@ -167,63 +145,62 @@ BOOST_AUTO_TEST_CASE( existing_session ) namespace { - class progress_callback : boost::noncopyable +class progress_callback : boost::noncopyable +{ +public: + progress_callback( + vector tickets = vector()) + : m_releasing_started(false), m_tickets(move(tickets)) { - public: - - progress_callback( - vector tickets=vector()) - : m_releasing_started(false), m_tickets(move(tickets)) {} + } - template - bool operator()(const Range& pending_tasks) - { - mutex::scoped_lock lock(m_mutex); + template + bool operator()(const Range& pending_tasks) + { + mutex::scoped_lock lock(m_mutex); - m_notified_task_ranges.push_back( - std::vector( - boost::begin(pending_tasks), boost::end(pending_tasks))); - - if (!m_releasing_started) - { - thread(&progress_callback::release_tickets, this); + m_notified_task_ranges.push_back(std::vector( + boost::begin(pending_tasks), boost::end(pending_tasks))); - m_releasing_started = true; - } + if (!m_releasing_started) + { + thread(&progress_callback::release_tickets, this); - return true; + m_releasing_started = true; } - std::vector> notifications() - { - mutex::scoped_lock lock(m_mutex); - return m_notified_task_ranges; - } + return true; + } - private: + std::vector> notifications() + { + mutex::scoped_lock lock(m_mutex); + return m_notified_task_ranges; + } - void release_tickets() +private: + void release_tickets() + { + while (!m_tickets.empty()) { - while (!m_tickets.empty()) - { - m_tickets.erase(m_tickets.end() - 1); - } + m_tickets.erase(m_tickets.end() - 1); } + } - mutex m_mutex; - bool m_releasing_started; + mutex m_mutex; + bool m_releasing_started; - // Stores the tickets we need to simulate other task gradually - // releasing their reservations on this - vector m_tickets; + // Stores the tickets we need to simulate other task gradually + // releasing their reservations on this + vector m_tickets; - // Stores each range of tasks we are notified of, in the - // order we are notified of them - std::vector> m_notified_task_ranges; - }; + // Stores each range of tasks we are notified of, in the + // order we are notified of them + std::vector> m_notified_task_ranges; +}; } -BOOST_AUTO_TEST_CASE( removing_session_really_removes_it ) +BOOST_AUTO_TEST_CASE(removing_session_really_removes_it) { connection_spec spec(get_connection()); @@ -243,7 +220,7 @@ BOOST_AUTO_TEST_CASE( removing_session_really_removes_it ) BOOST_CHECK_EQUAL(progress.notifications()[0].size(), 0U); } -BOOST_AUTO_TEST_CASE( removing_session_with_pending_task ) +BOOST_AUTO_TEST_CASE(removing_session_with_pending_task) { connection_spec spec(get_connection()); @@ -265,7 +242,7 @@ BOOST_AUTO_TEST_CASE( removing_session_with_pending_task ) BOOST_CHECK_EQUAL(progress.notifications()[1].size(), 0U); } -BOOST_AUTO_TEST_CASE( removing_session_with_multiple_pending_tasks ) +BOOST_AUTO_TEST_CASE(removing_session_with_multiple_pending_tasks) { connection_spec spec(get_connection()); @@ -298,7 +275,7 @@ BOOST_AUTO_TEST_CASE( removing_session_with_multiple_pending_tasks ) BOOST_CHECK_EQUAL(progress.notifications()[3].size(), 0U); } -BOOST_AUTO_TEST_CASE( removing_session_with_colliding_task_names ) +BOOST_AUTO_TEST_CASE(removing_session_with_colliding_task_names) { connection_spec spec(get_connection()); @@ -326,4 +303,3 @@ BOOST_AUTO_TEST_CASE( removing_session_with_colliding_task_names ) } BOOST_AUTO_TEST_SUITE_END() - diff --git a/test/connection/session_pool_test.cpp b/test/connection/session_pool_test.cpp index d56dd7f..4b1c0ab 100644 --- a/test/connection/session_pool_test.cpp +++ b/test/connection/session_pool_test.cpp @@ -1,44 +1,31 @@ -/** - @file - - Tests for the pool of SFTP connections. - - @if license - - Copyright (C) 2009, 2010, 2011, 2013, 2014 - Alexander Lamaison - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. +// Copyright 2009, 2010, 2011, 2013, 2014, 2016 Alexander Lamaison - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. - @endif -*/ +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . #include "swish/connection/session_pool.hpp" // Test subject #include "swish/connection/connection_spec.hpp" -#include "swish/utils.hpp" -#include "test/common_boost/helpers.hpp" -#include "test/common_boost/fixtures.hpp" #include "test/common_boost/ConsumerStub.hpp" +#include "test/common_boost/helpers.hpp" +#include "test/fixtures/openssh_fixture.hpp" #include // com_ptr #include // thread #include -#include // shared_ptr -#include // BOOST_FOREACH +#include // shared_ptr +#include // BOOST_FOREACH #include // diagnostic_information #include @@ -46,14 +33,12 @@ #include #include - using swish::connection::authenticated_session; using swish::connection::connection_spec; using swish::connection::session_pool; -using swish::utils::Utf8StringToWideString; using test::CConsumerStub; -using test::OpenSshFixture; +using test::fixtures::openssh_fixture; using comet::com_ptr; using comet::thread; @@ -65,54 +50,48 @@ using boost::test_tools::predicate_result; using std::exception; using std::vector; -namespace { // private +namespace +{ // private + +class fixture : public openssh_fixture +{ +public: + connection_spec get_connection() + { + return connection_spec(whost(), wuser(), port()); + } + + com_ptr consumer() + { + com_ptr consumer = + new CConsumerStub(private_key_path(), public_key_path()); + return consumer; + } /** - * Fixture that returns backend connections from the connection pool. + * Check that the given session responds sensibly to a request. */ - class PoolFixture : public OpenSshFixture + predicate_result alive(authenticated_session& session) { - public: - - connection_spec get_connection() + try { - return connection_spec( - Utf8StringToWideString(GetHost()), - Utf8StringToWideString(GetUser()), GetPort()); - } + session.get_sftp_filesystem().directory_iterator("/"); - com_ptr Consumer() - { - com_ptr consumer = new CConsumerStub( - PrivateKeyPath(), PublicKeyPath()); - return consumer; + predicate_result res(true); + res.message() << "Provider seems to be alive"; + return res; } - - /** - * Check that the given session responds sensibly to a request. - */ - predicate_result alive(authenticated_session& session) + catch (const exception& e) { - try - { - session.get_sftp_filesystem().directory_iterator("/"); - - predicate_result res(true); - res.message() << "Provider seems to be alive"; - return res; - } - catch(const exception& e) - { - predicate_result res(false); - res.message() << "Provider seems to be dead: " << e.what(); - return res; - } + predicate_result res(false); + res.message() << "Provider seems to be dead: " << e.what(); + return res; } - - }; + } +}; } -BOOST_FIXTURE_TEST_SUITE(pool_tests, PoolFixture) +BOOST_FIXTURE_TEST_SUITE(pool_tests, fixture) /** * Test the situation where the specified connection is not already in the @@ -121,14 +100,14 @@ BOOST_FIXTURE_TEST_SUITE(pool_tests, PoolFixture) * Ensures a connection specification can create a session and that the * pool reports session status correctly. */ -BOOST_AUTO_TEST_CASE( new_session ) +BOOST_AUTO_TEST_CASE(new_session) { connection_spec spec(get_connection()); BOOST_CHECK(!session_pool().has_session(spec)); authenticated_session& session = - session_pool().pooled_session(spec, Consumer()); + session_pool().pooled_session(spec, consumer()); BOOST_CHECK(session_pool().has_session(spec)); @@ -139,14 +118,14 @@ BOOST_AUTO_TEST_CASE( new_session ) * Test that creating a session does not affect the status of unrelated * connections. */ -BOOST_AUTO_TEST_CASE( unrelated_unaffected_by_creation ) +BOOST_AUTO_TEST_CASE(unrelated_unaffected_by_creation) { connection_spec unrelated_spec(L"Unrelated", L"Spec", 123); BOOST_CHECK(!session_pool().has_session(unrelated_spec)); authenticated_session& session = - session_pool().pooled_session(get_connection(), Consumer()); + session_pool().pooled_session(get_connection(), consumer()); BOOST_CHECK(!session_pool().has_session(unrelated_spec)); } @@ -154,15 +133,15 @@ BOOST_AUTO_TEST_CASE( unrelated_unaffected_by_creation ) /** * Test that the pool reuses existing sessions. */ -BOOST_AUTO_TEST_CASE( existing_session ) +BOOST_AUTO_TEST_CASE(existing_session) { connection_spec spec(get_connection()); authenticated_session& first_session = - session_pool().pooled_session(spec, Consumer()); + session_pool().pooled_session(spec, consumer()); - authenticated_session& second_session = - session_pool().pooled_session(spec, Consumer()); + authenticated_session& second_session = + session_pool().pooled_session(spec, consumer()); BOOST_CHECK(&second_session == &first_session); @@ -177,8 +156,10 @@ template class use_session_thread : public thread { public: - use_session_thread(T* fixture, exception_ptr& error) : - thread(), m_fixture(fixture), m_error(error) {} + use_session_thread(T* fixture, exception_ptr& error) + : thread(), m_fixture(fixture), m_error(error) + { + } private: DWORD thread_main() @@ -194,29 +175,31 @@ class use_session_thread : public thread session_pool().has_session(spec); authenticated_session& first_session = - session_pool().pooled_session(spec, m_fixture->Consumer()); + session_pool().pooled_session(spec, m_fixture->consumer()); // However, by this point it *must* be running if (!session_pool().has_session(spec)) - BOOST_THROW_EXCEPTION(std::exception("Test failed: no session")); + BOOST_THROW_EXCEPTION( + std::exception("Test failed: no session")); - if(!m_fixture->alive(first_session)) - BOOST_THROW_EXCEPTION( - std::exception("Test failed: first session is dead")); + if (!m_fixture->alive(first_session)) + BOOST_THROW_EXCEPTION( + std::exception("Test failed: first session is dead")); - authenticated_session& second_session = - session_pool().pooled_session(spec, m_fixture->Consumer()); + authenticated_session& second_session = + session_pool().pooled_session(spec, m_fixture->consumer()); - if(!session_pool().has_session(spec)) - BOOST_THROW_EXCEPTION(std::exception("Test failed: no session")); + if (!session_pool().has_session(spec)) + BOOST_THROW_EXCEPTION( + std::exception("Test failed: no session")); - if(!m_fixture->alive(second_session)) - BOOST_THROW_EXCEPTION( - std::exception("Test failed: second session is dead")); + if (!m_fixture->alive(second_session)) + BOOST_THROW_EXCEPTION( + std::exception("Test failed: second session is dead")); - if(&second_session != &first_session) - BOOST_THROW_EXCEPTION( - std::exception("Test failed: session was not reused")); + if (&second_session != &first_session) + BOOST_THROW_EXCEPTION( + std::exception("Test failed: session was not reused")); } } catch (...) @@ -234,23 +217,23 @@ class use_session_thread : public thread T* m_fixture; }; -typedef use_session_thread test_thread; +typedef use_session_thread test_thread; /** * Retrieve and prod a session from many threads. */ -BOOST_AUTO_TEST_CASE( threaded ) +BOOST_AUTO_TEST_CASE(threaded) { vector> threads(THREAD_COUNT); vector errors(THREAD_COUNT); - for (size_t i=0; i < threads.size(); ++i) + for (size_t i = 0; i < threads.size(); ++i) { threads[i] = shared_ptr(new test_thread(this, errors[i])); threads[i]->start(); } - for (size_t i=0; i < threads.size(); ++i) + for (size_t i = 0; i < threads.size(); ++i) { threads[i]->wait(); } @@ -258,7 +241,7 @@ BOOST_AUTO_TEST_CASE( threaded ) // Must process errors after finished waiting for all threads, otherwise // remaining threads will try to write to errors vector after it has been // destroyed - for (size_t i=0; i < errors.size(); ++i) + for (size_t i = 0; i < errors.size(); ++i) { if (errors[i]) { @@ -267,12 +250,12 @@ BOOST_AUTO_TEST_CASE( threaded ) } } -BOOST_AUTO_TEST_CASE( remove_session ) +BOOST_AUTO_TEST_CASE(remove_session) { connection_spec spec(get_connection()); authenticated_session& session = - session_pool().pooled_session(spec, Consumer()); + session_pool().pooled_session(spec, consumer()); session_pool().remove_session(spec); @@ -283,22 +266,21 @@ BOOST_AUTO_TEST_CASE( remove_session ) * Test that sessions in the pool survive server restarts * (modulo re-authentication). * - * By 'survive', we mean the pool is able to server a usable session + * By 'survive', we mean the pool is able to serve a usable session * with the same specification, not that the actual session instance has * to be the same (value-semantics and all that jazz). */ -BOOST_AUTO_TEST_CASE( sessions_across_server_restart ) +BOOST_AUTO_TEST_CASE(sessions_across_server_restart) { connection_spec spec(get_connection()); - session_pool().pooled_session(spec, Consumer()); + session_pool().pooled_session(spec, consumer()); BOOST_CHECK(session_pool().has_session(spec)); restart_server(); - BOOST_CHECK(alive(session_pool().pooled_session(spec, Consumer()))); + BOOST_CHECK(alive(session_pool().pooled_session(spec, consumer()))); } BOOST_AUTO_TEST_SUITE_END() - diff --git a/test/fixtures/openssh_fixture.cpp b/test/fixtures/openssh_fixture.cpp index 36409e3..6d59cf3 100644 --- a/test/fixtures/openssh_fixture.cpp +++ b/test/fixtures/openssh_fixture.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -36,8 +37,9 @@ #include using boost::assign::list_of; -using boost::io::quoted; using boost::filesystem::path; +using boost::io::quoted; +using boost::lexical_cast; using boost::locale::conv::to_utf; using boost::locale::generator; using boost::locale::util::get_system_locale; @@ -218,14 +220,34 @@ openssh_fixture::~openssh_fixture() { try { - vector stop_command = (list_of(string("stop")), m_container_id); - run_docker_command(stop_command); + stop_server(); } catch (...) { } } +void openssh_fixture::stop_server() +{ + vector stop_command = (list_of(string("stop")), m_container_id); + run_docker_command(stop_command); +} + +void openssh_fixture::restart_server() +{ + stop_server(); + + vector docker_command = + (list_of(string("run")), "--detach", "-p", + lexical_cast(m_port) + ":22", "swish/openssh_server"); + m_container_id = single_value_from_docker_command(docker_command); + // We make sure we bind to the same port in the new docker container. Do we + // have to do anything to ensure we get the same IP? Presumably not unless + // docker-machine changed machine in the middle of restarting. + assert(ask_docker_for_host() == m_host); + assert(ask_docker_for_port() == m_port); +} + string openssh_fixture::host() const { return m_host; diff --git a/test/fixtures/openssh_fixture.hpp b/test/fixtures/openssh_fixture.hpp index c50f340..06663e7 100644 --- a/test/fixtures/openssh_fixture.hpp +++ b/test/fixtures/openssh_fixture.hpp @@ -33,6 +33,8 @@ class openssh_fixture public: openssh_fixture(); virtual ~openssh_fixture(); + void stop_server(); + void restart_server(); std::string host() const; std::string user() const;