1
0
mirror of https://github.com/falk-werner/webfuse-provider synced 2024-10-27 20:44:10 +00:00

refactored fake adapter server into ws server; added test for client protocol getattr

This commit is contained in:
Falk Werner 2020-02-22 16:46:21 +01:00
parent 1a1367eae7
commit e21c716d34
5 changed files with 153 additions and 48 deletions

View File

@ -14,7 +14,7 @@ add_executable(alltests
test/webfuse/utils/timeout_watcher.cc test/webfuse/utils/timeout_watcher.cc
test/webfuse/utils/path.c test/webfuse/utils/path.c
test/webfuse/utils/static_filesystem.c test/webfuse/utils/static_filesystem.c
test/webfuse/fakes/fake_adapter_server.cc test/webfuse/utils/ws_server.cc
test/webfuse/mocks/mock_authenticator.cc test/webfuse/mocks/mock_authenticator.cc
test/webfuse/mocks/mock_request.cc test/webfuse/mocks/mock_request.cc
test/webfuse/tests/core/test_container_of.cc test/webfuse/tests/core/test_container_of.cc

View File

@ -1,24 +0,0 @@
#ifndef WF_TEST_FAKE_SERVER_HPP
#define WF_TEST_FAKE_SERVER_HPP
#include <libwebsockets.h>
namespace webfuse_test
{
class FakeAdapterServer
{
FakeAdapterServer(FakeAdapterServer const &) = delete;
FakeAdapterServer & operator=(FakeAdapterServer const &) = delete;
public:
explicit FakeAdapterServer(int port);
~FakeAdapterServer();
void waitForConnection();
private:
class Private;
Private * d;
};
}
#endif

View File

@ -3,13 +3,13 @@
#include <webfuse/provider/client_protocol.h> #include <webfuse/provider/client_protocol.h>
#include <webfuse/provider/client_config.h> #include <webfuse/provider/client_config.h>
#include "webfuse/fakes/fake_adapter_server.hpp" #include "webfuse/utils/ws_server.hpp"
#include <cstring> #include <cstring>
#include <thread> #include <thread>
#include <atomic> #include <atomic>
using webfuse_test::FakeAdapterServer; using webfuse_test::WebsocketServer;
using testing::_; using testing::_;
namespace namespace
@ -20,7 +20,7 @@ class ClientProtocolTest: public ::testing::Test
protected: protected:
void SetUp() void SetUp()
{ {
server = new FakeAdapterServer(54321); server = new WebsocketServer(54321);
config = wfp_client_config_create(); config = wfp_client_config_create();
protocol = wfp_client_protocol_create(config); protocol = wfp_client_protocol_create(config);
@ -57,7 +57,40 @@ protected:
delete server; delete server;
} }
FakeAdapterServer * server; void awaitAddFilesystem(std::string& filesystemName)
{
json_t * addFilesystemRequest = server->receiveMessage();
ASSERT_NE(nullptr, addFilesystemRequest);
ASSERT_TRUE(json_is_object(addFilesystemRequest));
json_t * method = json_object_get(addFilesystemRequest, "method");
ASSERT_TRUE(json_is_string(method));
ASSERT_STREQ("add_filesystem", json_string_value(method));
json_t * params = json_object_get(addFilesystemRequest, "params");
ASSERT_TRUE(json_is_array(params));
ASSERT_EQ(1, json_array_size(params));
json_t * filesystem = json_array_get(params, 0);
ASSERT_TRUE(json_is_string(filesystem));
filesystemName = json_string_value(filesystem);
json_t * id = json_object_get(addFilesystemRequest, "id");
ASSERT_TRUE(json_is_integer(id));
json_t * response = json_object();
json_t * result = json_object();
json_object_set(result, "id", filesystem);
json_object_set_new(response, "result", result);
json_object_set(response, "id", id);
server->sendMessage(response);
json_decref(addFilesystemRequest);
}
WebsocketServer * server;
private: private:
static void run(ClientProtocolTest * self) static void run(ClientProtocolTest * self)
@ -77,10 +110,34 @@ private:
}; };
} }
TEST_F(ClientProtocolTest, connect) TEST_F(ClientProtocolTest, connect)
{ {
server->waitForConnection(); server->waitForConnection();
}
TEST_F(ClientProtocolTest, getattr)
{
server->waitForConnection();
std::string filesystem;
awaitAddFilesystem(filesystem);
if (HasFatalFailure()) { return; }
json_t * params = json_array();
json_array_append_new(params, json_string(filesystem.c_str()));
json_array_append_new(params, json_integer(1));
json_t * request = json_object();
json_object_set_new(request, "method", json_string("getattr"));
json_object_set_new(request, "params", params);
json_object_set_new(request, "id", json_integer(42));
server->sendMessage(request);
json_t * response = server->receiveMessage();
ASSERT_TRUE(json_is_object(response));
json_decref(response);
} }

View File

@ -1,4 +1,4 @@
#include "webfuse/fakes/fake_adapter_server.hpp" #include "webfuse/utils/ws_server.hpp"
#include "webfuse/utils/timeout_watcher.hpp" #include "webfuse/utils/timeout_watcher.hpp"
#include "webfuse/core/util.h" #include "webfuse/core/util.h"
@ -30,7 +30,7 @@ public:
extern "C" extern "C"
{ {
static int wf_test_fake_adapter_server_callback( static int wf_test_utils_ws_server_callback(
struct lws * wsi, struct lws * wsi,
enum lws_callback_reasons reason, enum lws_callback_reasons reason,
void * WF_UNUSED_PARAM(user), void * WF_UNUSED_PARAM(user),
@ -65,7 +65,6 @@ static int wf_test_fake_adapter_server_callback(
break; break;
} }
return 0; return 0;
} }
@ -74,16 +73,15 @@ static int wf_test_fake_adapter_server_callback(
namespace webfuse_test namespace webfuse_test
{ {
class FakeAdapterServer::Private: public IServer class WebsocketServer::Private: public IServer
{ {
public: public:
explicit Private(int port) explicit Private(int port)
: client_wsi(nullptr) : client_wsi(nullptr)
, message_received(false)
{ {
memset(ws_protocols, 0, sizeof(struct lws_protocols) * 2); memset(ws_protocols, 0, sizeof(struct lws_protocols) * 2);
ws_protocols[0].name = "fs"; ws_protocols[0].name = "fs";
ws_protocols[0].callback = &wf_test_fake_adapter_server_callback; ws_protocols[0].callback = &wf_test_utils_ws_server_callback;
ws_protocols[0].per_session_data_size = 0; ws_protocols[0].per_session_data_size = 0;
ws_protocols[0].user = reinterpret_cast<void*>(this); ws_protocols[0].user = reinterpret_cast<void*>(this);
@ -114,6 +112,44 @@ public:
} }
} }
void sendMessage(json_t * message)
{
char* message_text = json_dumps(message, JSON_COMPACT);
writeQueue.push(message_text);
json_decref(message);
free(message_text);
if (nullptr != client_wsi)
{
lws_callback_on_writable(client_wsi);
TimeoutWatcher watcher(DEFAULT_TIMEOUT);
while (!writeQueue.empty())
{
watcher.check();
lws_service(context, 100);
}
}
}
json_t * receiveMessage()
{
TimeoutWatcher watcher(DEFAULT_TIMEOUT);
while (recvQueue.empty())
{
watcher.check();
lws_service(context, 100);
}
std::string const & message_text = recvQueue.front();
json_t * message = json_loads(message_text.c_str(), JSON_DECODE_ANY, nullptr);
recvQueue.pop();
return message;
}
void onConnectionEstablished(struct lws * wsi) override void onConnectionEstablished(struct lws * wsi) override
{ {
client_wsi = wsi; client_wsi = wsi;
@ -131,24 +167,23 @@ public:
{ {
if (wsi == client_wsi) if (wsi == client_wsi)
{ {
last_message.assign(length, *data); recvQueue.push(std::string(data, length));
message_received = true;
} }
} }
void onWritable(struct lws * wsi) override void onWritable(struct lws * wsi) override
{ {
if (!queue.empty()) if (!writeQueue.empty())
{ {
std::string const & message = queue.front(); std::string const & message = writeQueue.front();
unsigned char * data = new unsigned char[LWS_PRE + message.size()]; unsigned char * data = new unsigned char[LWS_PRE + message.size()];
memcpy(&data[LWS_PRE], message.c_str(), message.size()); memcpy(&data[LWS_PRE], message.c_str(), message.size());
lws_write(wsi, &data[LWS_PRE], message.size(), LWS_WRITE_TEXT); lws_write(wsi, &data[LWS_PRE], message.size(), LWS_WRITE_TEXT);
delete[] data; delete[] data;
queue.pop(); writeQueue.pop();
if (!queue.empty()) if (!writeQueue.empty())
{ {
lws_callback_on_writable(wsi); lws_callback_on_writable(wsi);
} }
@ -161,36 +196,46 @@ private:
{ {
if (nullptr != client_wsi) if (nullptr != client_wsi)
{ {
queue.push(message); writeQueue.push(message);
lws_callback_on_writable(client_wsi); lws_callback_on_writable(client_wsi);
} }
} }
struct lws * client_wsi; struct lws * client_wsi;
bool message_received;
struct lws_protocols ws_protocols[2]; struct lws_protocols ws_protocols[2];
struct lws_context_creation_info info; struct lws_context_creation_info info;
struct lws_context * context; struct lws_context * context;
std::vector<char> last_message; std::queue<std::string> writeQueue;
std::queue<std::string> queue; std::queue<std::string> recvQueue;
}; };
FakeAdapterServer::FakeAdapterServer(int port) WebsocketServer::WebsocketServer(int port)
: d(new Private(port)) : d(new Private(port))
{ {
} }
FakeAdapterServer::~FakeAdapterServer() WebsocketServer::~WebsocketServer()
{ {
delete d; delete d;
} }
void FakeAdapterServer::waitForConnection() void WebsocketServer::waitForConnection()
{ {
d->waitForConnection(); d->waitForConnection();
} }
void WebsocketServer::sendMessage(json_t * message)
{
d->sendMessage(message);
}
json_t * WebsocketServer::receiveMessage()
{
return d->receiveMessage();
}
} }

View File

@ -0,0 +1,27 @@
#ifndef WF_TEST_UTILS_WS_SERVER_HPP
#define WF_TEST_UTILS_WS_SERVER_HPP
#include <libwebsockets.h>
#include <jansson.h>
namespace webfuse_test
{
class WebsocketServer
{
WebsocketServer(WebsocketServer const &) = delete;
WebsocketServer & operator=(WebsocketServer const &) = delete;
public:
explicit WebsocketServer(int port);
~WebsocketServer();
void waitForConnection();
void sendMessage(json_t * message);
json_t * receiveMessage();
private:
class Private;
Private * d;
};
}
#endif