diff --git a/cmake/unit_tests.cmake b/cmake/unit_tests.cmake index 3e445ed..1ff1be5 100644 --- a/cmake/unit_tests.cmake +++ b/cmake/unit_tests.cmake @@ -17,6 +17,7 @@ add_executable(alltests test/webfuse/utils/ws_server.cc test/webfuse/mocks/mock_authenticator.cc test/webfuse/mocks/mock_request.cc + test/webfuse/mocks/mock_provider_client.cc test/webfuse/tests/core/test_container_of.cc test/webfuse/tests/core/test_string.cc test/webfuse/tests/core/test_slist.cc diff --git a/test/webfuse/mocks/mock_provider_client.cc b/test/webfuse/mocks/mock_provider_client.cc new file mode 100644 index 0000000..a906d95 --- /dev/null +++ b/test/webfuse/mocks/mock_provider_client.cc @@ -0,0 +1,204 @@ +#include "webfuse/mocks/mock_provider_client.hpp" +#include "webfuse/provider/operation/error.h" +#include "webfuse/provider/dirbuffer.h" + +extern "C" +{ +using webfuse_test::IProviderClient; +using webfuse_test::ProviderClientException; + +static void webfuse_test_iproviderclient_onconnected( + void * user_data) +{ + auto * self = reinterpret_cast(user_data); + self->OnConnected(); +} + +static void webfuse_test_iproviderclient_ondisconnected( + void * user_data) +{ + auto * self = reinterpret_cast(user_data); + self->OnDisconnected(); +} + +static void webfuse_test_iproviderclient_ontimer( + void * user_data) +{ + auto * self = reinterpret_cast(user_data); + self->OnTimer(); +} + +static void webfuse_test_iproviderclient_onlookup( + struct wfp_request * request, + ino_t parent, + char const * name, + void * user_data) +{ + auto * self = reinterpret_cast(user_data); + + try + { + struct stat buffer; + self->Lookup(parent, name, &buffer); + wfp_respond_lookup(request, &buffer); + } + catch (ProviderClientException ex) + { + wfp_respond_error(request, ex.GetErrorCode()); + } + catch (...) + { + wfp_respond_error(request, WF_BAD); + } +} + +static void webfuse_test_iproviderclient_ongetattr( + struct wfp_request * request, + ino_t inode, + void * user_data) +{ + auto * self = reinterpret_cast(user_data); + + try + { + struct stat buffer; + memset(&buffer, 0, sizeof(struct stat)); + self->GetAttr(inode, &buffer); + wfp_respond_getattr(request,&buffer); + } + catch (ProviderClientException ex) + { + wfp_respond_error(request, ex.GetErrorCode()); + } + catch (...) + { + wfp_respond_error(request, WF_BAD); + } + +} + +static void webfuse_test_iproviderclient_onreaddir( + struct wfp_request * request, + ino_t directory, + void * user_data) +{ + auto * self = reinterpret_cast(user_data); + wfp_dirbuffer * buffer = wfp_dirbuffer_create(); + + try + { + self->ReadDir(directory, buffer); + wfp_respond_readdir(request, buffer); + } + catch (ProviderClientException ex) + { + wfp_respond_error(request, ex.GetErrorCode()); + } + catch (...) + { + wfp_respond_error(request, WF_BAD); + } + + wfp_dirbuffer_dispose(buffer); + +} + +static void webfuse_test_iproviderclient_onopen( + struct wfp_request * request, + ino_t inode, + int flags, + void * user_data) +{ + auto * self = reinterpret_cast(user_data); + + try + { + uint32_t handle = 0; + self->Open(inode, flags, &handle); + wfp_respond_open(request, handle); + } + catch (ProviderClientException ex) + { + wfp_respond_error(request, ex.GetErrorCode()); + } + catch (...) + { + wfp_respond_error(request, WF_BAD); + } + +} + +static void webfuse_test_iproviderclient_onclose( + ino_t inode, + uint32_t handle, + int flags, + void * user_data) +{ + auto * self = reinterpret_cast(user_data); + self->Close(inode, handle, flags); +} + +static void webfuse_test_iproviderclient_onread( + struct wfp_request * request, + ino_t inode, + uint32_t handle, + size_t offset, + size_t length, + void * user_data) +{ + auto * self = reinterpret_cast(user_data); + char * data = new char[length]; + + try + { + size_t bytes_read = 0; + self->Read(inode, handle, offset, length, data, &bytes_read); + wfp_respond_read(request, data, bytes_read); + } + catch (ProviderClientException ex) + { + wfp_respond_error(request, ex.GetErrorCode()); + } + catch (...) + { + wfp_respond_error(request, WF_BAD); + } + + delete[] data; +} + +} + +namespace webfuse_test +{ + +ProviderClientException::ProviderClientException(wf_status error_code) +: runtime_error("ProviderClientException") +, error_code_(error_code) +{ + +} + +wf_status ProviderClientException::GetErrorCode() +{ + return error_code_; +} + + +void IProviderClient::AttachTo(wfp_client_config * config) +{ + void * self = reinterpret_cast(this); + wfp_client_config_set_userdata(config, self); + wfp_client_config_set_onconnected(config, &webfuse_test_iproviderclient_onconnected); + wfp_client_config_set_ondisconnected(config, &webfuse_test_iproviderclient_ondisconnected); + wfp_client_config_set_ontimer(config, &webfuse_test_iproviderclient_ontimer); + + wfp_client_config_set_onlookup(config, &webfuse_test_iproviderclient_onlookup); + wfp_client_config_set_ongetattr(config, &webfuse_test_iproviderclient_ongetattr); + wfp_client_config_set_onreaddir(config, &webfuse_test_iproviderclient_onreaddir); + wfp_client_config_set_onopen(config, &webfuse_test_iproviderclient_onopen); + wfp_client_config_set_onclose(config, &webfuse_test_iproviderclient_onclose); + wfp_client_config_set_onread(config, &webfuse_test_iproviderclient_onread); +} + +} \ No newline at end of file diff --git a/test/webfuse/mocks/mock_provider_client.hpp b/test/webfuse/mocks/mock_provider_client.hpp new file mode 100644 index 0000000..2db3127 --- /dev/null +++ b/test/webfuse/mocks/mock_provider_client.hpp @@ -0,0 +1,55 @@ +#ifndef WF_MOCK_PROVIDER_CLIENT_HPP +#define WF_MOCK_PROVIDER_CLIENT_HPP + +#include +#include "webfuse/provider/client_config.h" +#include "webfuse/core/status.h" +#include + +namespace webfuse_test +{ + class ProviderClientException: public std::runtime_error + { + public: + ProviderClientException(wf_status error_code); + wf_status GetErrorCode(); + private: + wf_status error_code_; + }; + + + + class IProviderClient + { + public: + virtual ~IProviderClient() = default; + virtual void OnConnected() = 0; + virtual void OnDisconnected() = 0; + virtual void OnTimer() = 0; + virtual void Lookup(ino_t parent, char const * name, struct stat * result) = 0; + virtual void GetAttr(ino_t inode, struct stat * buffer) = 0; + virtual void ReadDir(ino_t directory, wfp_dirbuffer * buffer) = 0; + virtual void Open(ino_t inode, int flags, uint32_t * handle) = 0; + virtual void Close(ino_t inode, uint32_t handle, int flags) = 0; + virtual void Read(ino_t inode, uint32_t handle, size_t offset, size_t length, char * buffer, size_t * bytes_read) = 0; + + void AttachTo(wfp_client_config * config); + }; + + class MockProviderClient: public IProviderClient + { + public: + ~MockProviderClient() override = default; + MOCK_METHOD0( OnConnected, void()); + MOCK_METHOD0( OnDisconnected, void()); + MOCK_METHOD0( OnTimer, void()); + MOCK_METHOD3( Lookup, void(ino_t parent, char const * name, struct stat * result)); + MOCK_METHOD2( GetAttr, void(ino_t inode, struct stat * buffer)); + MOCK_METHOD2( ReadDir, void(ino_t directory, wfp_dirbuffer * buffer)); + MOCK_METHOD3( Open, void(ino_t inode, int flags, uint32_t * handle)); + MOCK_METHOD3( Close, void(ino_t inode, uint32_t handle, int flags)); + MOCK_METHOD6( Read, void(ino_t inode, uint32_t handle, size_t offset, size_t length, char * buffer, size_t * bytes_read)); + }; +} + +#endif diff --git a/test/webfuse/tests/provider/test_client_protocol.cc b/test/webfuse/tests/provider/test_client_protocol.cc index b602e58..954a253 100644 --- a/test/webfuse/tests/provider/test_client_protocol.cc +++ b/test/webfuse/tests/provider/test_client_protocol.cc @@ -4,17 +4,20 @@ #include #include #include "webfuse/utils/ws_server.hpp" +#include "webfuse/mocks/mock_provider_client.hpp" #include #include #include using webfuse_test::WebsocketServer; +using webfuse_test::MockProviderClient; using testing::_; namespace { +// ToDo: Refactor Me class ClientProtocolTest: public ::testing::Test { public: @@ -30,6 +33,22 @@ protected: void SetUp() { config = wfp_client_config_create(); + + server = nullptr; + protocol = nullptr; + } + + void TearDown() + { + if (nullptr != server) + { + StopServer(); + } + + } + + void StartServer() + { protocol = wfp_client_protocol_create(config); struct lws_protocols client_protocol; @@ -39,22 +58,29 @@ protected: server = new WebsocketServer(54321, &client_protocol, 1); } - void TearDown() + void StopServer() { delete server; - wfp_client_protocol_dispose(protocol); wfp_client_config_dispose(config); + server = nullptr; + protocol = nullptr; + config = nullptr; } - void connect() + wfp_client_config * GetClientConfig() + { + return config; + } + + void Connect() { wfp_client_protocol_connect(protocol, server->getContext(), "ws://localhost:54321/"); server->waitForConnection(); } - void awaitAddFilesystem(std::string& filesystemName) + void AwaitAddFilesystem(std::string& filesystemName) { json_t * addFilesystemRequest = server->receiveMessage(); ASSERT_NE(nullptr, addFilesystemRequest); @@ -94,24 +120,33 @@ private: wfp_client_protocol * protocol; }; - - } TEST_F(ClientProtocolTest, connect) { - connect(); + StartServer(); + Connect(); if (HasFatalFailure()) { return; } + + StopServer(); } TEST_F(ClientProtocolTest, getattr) { - connect(); + MockProviderClient client; + client.AttachTo(GetClientConfig()); + + EXPECT_CALL(client, OnConnected()).Times(1); + EXPECT_CALL(client, OnDisconnected()).Times(1); + EXPECT_CALL(client, GetAttr(1, _)).Times(1); + + StartServer(); + Connect(); if (HasFatalFailure()) { return; } std::string filesystem; - awaitAddFilesystem(filesystem); + AwaitAddFilesystem(filesystem); if (HasFatalFailure()) { return; } json_t * params = json_array(); @@ -127,4 +162,6 @@ TEST_F(ClientProtocolTest, getattr) ASSERT_TRUE(json_is_object(response)); json_decref(response); + + StopServer(); } \ No newline at end of file