diff --git a/meson.build b/meson.build index 78e6e21..67e1121 100644 --- a/meson.build +++ b/meson.build @@ -126,9 +126,12 @@ alltests = executable('alltests', 'test/webfuse/timer/test_timer.cc', 'test/webfuse/test_util/tempdir.cc', 'test/webfuse/test_util/file_utils.cc', + 'test/webfuse/test_util/server.cc', 'test/webfuse/test_util/ws_server.cc', + 'test/webfuse/test_util/ws_client.cc', 'test/webfuse/test_util/adapter_client.cc', 'test/webfuse/test_util/jansson_test_environment.cc', + 'test/webfuse/test_util/lws_test_environment.cc', 'test/webfuse/mocks/mock_authenticator.cc', 'test/webfuse/mocks/mock_fuse.cc', 'test/webfuse/mocks/mock_operation_context.cc', diff --git a/test/webfuse/mocks/mock_invokation_handler.hpp b/test/webfuse/mocks/mock_invokation_handler.hpp index 9a70482..9c79159 100644 --- a/test/webfuse/mocks/mock_invokation_handler.hpp +++ b/test/webfuse/mocks/mock_invokation_handler.hpp @@ -2,7 +2,7 @@ #define WF_MOCK_INVOKATION_HANDLER_HPP #include "webfuse/test_util/invokation_handler.hpp" -#include +#include namespace webfuse_test { diff --git a/test/webfuse/test_server.cc b/test/webfuse/test_server.cc index 34524b2..73cea7e 100644 --- a/test/webfuse/test_server.cc +++ b/test/webfuse/test_server.cc @@ -4,9 +4,20 @@ #include #include #include +#include #include "webfuse/server.h" #include "webfuse/server_config.h" +#include "webfuse/test_util/server.hpp" +#include "webfuse/test_util/ws_client.hpp" +#include "webfuse/mocks/mock_invokation_handler.hpp" +#include "webfuse/protocol_names.h" + +using webfuse_test::MockInvokationHander; +using webfuse_test::WsClient; +using webfuse_test::Server; + +#define TIMEOUT (std::chrono::seconds(10)) namespace { @@ -36,4 +47,15 @@ TEST(server, create_dispose) wf_server_config_dispose(config); rmdir("test"); +} + +TEST(server, connect) +{ + Server server; + MockInvokationHander handler; + WsClient client(handler, WF_PROTOCOL_NAME_PROVIDER_CLIENT); + + auto future = client.Connect(server.GetPort(), WF_PROTOCOL_NAME_ADAPTER_SERVER); + ASSERT_EQ(std::future_status::ready, future.wait_for(TIMEOUT)); + // future.get(); } \ No newline at end of file diff --git a/test/webfuse/test_util/lws_test_environment.cc b/test/webfuse/test_util/lws_test_environment.cc new file mode 100644 index 0000000..3d5de7c --- /dev/null +++ b/test/webfuse/test_util/lws_test_environment.cc @@ -0,0 +1,16 @@ +#include +#include "webfuse/impl/util/lws_log.h" + +namespace webfuse_test +{ + +class LwsTestEnvironment: public testing::Environment +{ +public: + void SetUp() + { + wf_impl_lwslog_disable(); + } +}; + +} \ No newline at end of file diff --git a/test/webfuse/integration/server.cc b/test/webfuse/test_util/server.cc similarity index 76% rename from test/webfuse/integration/server.cc rename to test/webfuse/test_util/server.cc index fe86258..46d7bd3 100644 --- a/test/webfuse/integration/server.cc +++ b/test/webfuse/test_util/server.cc @@ -1,13 +1,15 @@ -#include "webfuse/tests/integration/server.hpp" +#include "webfuse/test_util/server.hpp" #include #include -#include #include #include #include #include +#include + #include "webfuse/webfuse.h" #include "webfuse/impl/server.h" +#include "webfuse/test_util/tempdir.hpp" #define WF_PATH_MAX (100) @@ -50,20 +52,13 @@ class Server::Private public: Private() : is_shutdown_requested(false) + , tempdir("webfuse_test_integration") { - snprintf(base_dir, WF_PATH_MAX, "%s", "/tmp/webfuse_test_integration_XXXXXX"); - char const * result = mkdtemp(base_dir); - if (NULL == result) - { - throw std::runtime_error("unable to create temp dir"); - } - - config = wf_server_config_create(); wf_server_config_set_port(config, 0); wf_server_config_set_mountpoint_factory(config, &webfuse_test_server_create_mountpoint, - reinterpret_cast(base_dir)); + reinterpret_cast(const_cast(tempdir.path()))); wf_server_config_set_keypath(config, "server-key.pem"); wf_server_config_set_certpath(config, "server-cert.pem"); @@ -82,26 +77,35 @@ public: { RequestShutdown(); thread.join(); - rmdir(base_dir); wf_server_dispose(server); wf_server_config_dispose(config); } + char const * GetBaseDir() + { + return tempdir.path(); + } + + int GetPort(void) const + { + return wf_server_get_port(server); + } + +private: + static void Run(Private * context) + { + while (!context->IsShutdownRequested()) + { + wf_server_service(context->server); + } + } + bool IsShutdownRequested() { std::lock_guard lock(shutdown_lock); return is_shutdown_requested; } - std::string GetUrl(void) const - { - int const port = wf_server_get_port(server); - std::ostringstream stream; - stream << "wss://localhost:" << port << "/"; - return stream.str(); - } - -private: void RequestShutdown() { std::lock_guard lock(shutdown_lock); @@ -109,22 +113,10 @@ private: wf_server_interrupt(server); } - static void Run(Server::Private * context) - { - while (!context->IsShutdownRequested()) - { - wf_server_service(context->server); - } - } - - std::mutex shutdown_lock; std::thread thread; bool is_shutdown_requested; - - -public: - char base_dir[WF_PATH_MAX]; + TempDir tempdir; wf_server_config * config; wf_server * server; }; @@ -142,12 +134,12 @@ Server::~Server() char const * Server::GetBaseDir(void) const { - return d->base_dir; + return d->GetBaseDir(); } -std::string Server::GetUrl(void) const +int Server::GetPort(void) const { - return d->GetUrl(); + return d->GetPort(); } diff --git a/test/webfuse/integration/server.hpp b/test/webfuse/test_util/server.hpp similarity index 72% rename from test/webfuse/integration/server.hpp rename to test/webfuse/test_util/server.hpp index de7864c..b4d1ac8 100644 --- a/test/webfuse/integration/server.hpp +++ b/test/webfuse/test_util/server.hpp @@ -1,8 +1,6 @@ #ifndef WF_TEST_INTEGRATION_SERVER_HPP #define WF_TEST_INTEGRATION_SERVER_HPP -#include - namespace webfuse_test { @@ -11,10 +9,8 @@ class Server public: Server(); ~Server(); - void Start(void); - void Stop(void); char const * GetBaseDir(void) const; - std::string GetUrl(void) const; + int GetPort(void) const; private: class Private; Private * d; diff --git a/test/webfuse/test_util/ws_client.cc b/test/webfuse/test_util/ws_client.cc new file mode 100644 index 0000000..834f531 --- /dev/null +++ b/test/webfuse/test_util/ws_client.cc @@ -0,0 +1,197 @@ +#include "webfuse/test_util/ws_client.hpp" +#include "webfuse/test_util/invokation_handler.hpp" + +#include + +#include +#include +#include +#include + +namespace +{ + +class IServer +{ +public: + virtual ~IServer() = default; +}; + +} + +extern "C" +{ + +static int webfuse_test_WsClient_callback( + lws * wsi, + lws_callback_reasons reason, + void * user, + void * in, + size_t len) +{ + return 0; +} + +} + +namespace webfuse_test +{ + +class WsClient::Private: public IServer +{ +public: + Private( + InvokationHandler & handler, + std::string const & protocol) + : handler_(handler) + , protocol_(protocol) + , remote_port(0) + , remote_use_tls(false) + { + IServer * self = this; + + memset(protocols, 0, sizeof(lws_protocols) * 2); + protocols[0].name = protocol_.c_str(); + protocols[0].callback = &webfuse_test_WsClient_callback; + protocols[0].per_session_data_size = 0; + protocols[0].user = self; + + memset(&info, 0, sizeof(lws_context_creation_info)); + info.port = CONTEXT_PORT_NO_LISTEN; + info.protocols = protocols; + info.uid = -1; + info.gid = -1; + info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS; + + context = lws_create_context(&info); + + lws_vhost * vhost = lws_create_vhost(context, & info); + info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + info.client_ssl_cert_filepath = "client-cert.pem"; + info.client_ssl_private_key_filepath = "client-key.pem"; + info.client_ssl_ca_filepath = "server-cert.pem"; + lws_init_vhost_client_ssl(&info, vhost); + + thread = std::thread(&Run, this); + } + + ~Private() + { + Invoke(command::shutdown); + lws_cancel_service(context); + + thread.join(); + lws_context_destroy(context); + } + + std::future Connect(int port, std::string const & protocol, bool use_tls) + { + { + std::unique_lock lock(mutex); + remote_port = port; + remote_protocol = protocol; + remote_use_tls = use_tls; + commands.push(command::connect); + } + + std::promise p; + p.set_exception(std::make_exception_ptr(std::runtime_error("not implemented"))); + return p.get_future(); + } + + std::future Invoke(std::string const & message) + { + std::promise p; + p.set_exception(std::make_exception_ptr(std::runtime_error("not implemented"))); + return p.get_future(); + } + +private: + enum class command + { + run, + shutdown, + connect + }; + + static void Run(Private * self) + { + bool is_running = true; + + while (is_running) + { + switch (self->GetCommand()) + { + case command::run: + lws_service(self->context, 0); + break; + case command::shutdown: + is_running = false; + break; + case command::connect: + // ToDo: connect + break; + default: + break; + } + } + } + + command GetCommand() + { + std::unique_lock lock(mutex); + + command command = command::run; + if (!commands.empty()) + { + command = commands.front(); + commands.pop(); + } + + return command; + } + + void Invoke(command command) + { + std::unique_lock lock(mutex); + commands.push(command); + } + + InvokationHandler & handler_; + std::string protocol_; + lws_context_creation_info info; + lws_protocols protocols[2]; + lws_context * context; + std::thread thread; + std::mutex mutex; + std::queue commands; + int remote_port; + std::string remote_protocol; + bool remote_use_tls; +}; + +WsClient::WsClient( + InvokationHandler& handler, + std::string const & protocol) +: d(new Private(handler, protocol)) +{ + +} + +WsClient::~WsClient() +{ + delete d; +} + +std::future WsClient::Connect(int port, std::string const & protocol, bool use_tls) +{ + return d->Connect(port, protocol, use_tls); +} + +std::future WsClient::Invoke(std::string const & message) +{ + return d->Invoke(message); +} + + +} \ No newline at end of file diff --git a/test/webfuse/test_util/ws_client.hpp b/test/webfuse/test_util/ws_client.hpp new file mode 100644 index 0000000..376de58 --- /dev/null +++ b/test/webfuse/test_util/ws_client.hpp @@ -0,0 +1,30 @@ +#ifndef WF_TEST_UTIL_WS_CLIENT_HPP +#define WF_TEST_UTIL_WS_CLIENT_HPP + +#include +#include + +namespace webfuse_test +{ + +class InvokationHandler; + +class WsClient +{ + WsClient(WsClient const &) = delete; + WsClient & operator=(WsClient const &) = delete; +public: + WsClient( + InvokationHandler& handler, + std::string const & protocol); + virtual ~WsClient(); + std::future Connect(int port, std::string const & protocol, bool use_tls = true); + std::future Invoke(std::string const & message); +private: + class Private; + Private *d; +}; + +} + +#endif diff --git a/test/webfuse/test_util/ws_server.cc b/test/webfuse/test_util/ws_server.cc index e2161d5..1d75ea3 100644 --- a/test/webfuse/test_util/ws_server.cc +++ b/test/webfuse/test_util/ws_server.cc @@ -143,7 +143,6 @@ WsServer::Private::Private( , is_shutdown_requested(false) , wsi_(nullptr) { - wf_impl_lwslog_disable(); IServer * server = this; memset(ws_protocols, 0, sizeof(struct lws_protocols) * 2 );