Skip to content

Commit

Permalink
Update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
leemaguire committed Jul 10, 2024
1 parent e244af0 commit 5d1851e
Showing 1 changed file with 167 additions and 23 deletions.
190 changes: 167 additions & 23 deletions tests/sync/networking_tests.cpp
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@

using namespace realm;

TEST_CASE("sends plaintext data to proxy", "[proxy]") {
TEST_CASE("custom transport to proxy", "[proxy]") {

tests::utils::proxy_server::config cfg;
cfg.port = 1234;
@@ -18,23 +18,24 @@ TEST_CASE("sends plaintext data to proxy", "[proxy]") {
proxy_events.insert(e);
});

realm::App::configuration config;
config.app_id = Admin::Session::shared().create_app({"str_col", "_id"}, "test", false, false);
config.base_url = Admin::Session::shared().base_url();
config.enable_caching = true;

auto transport_config = ::realm::networking::default_transport_configuration();
proxy_config pc;
pc.port = 1234;
pc.address = "127.0.0.1";
realm::App::configuration config;
config.proxy_configuration = pc;
config.app_id = Admin::Session::shared().cached_app_id();
config.base_url = Admin::Session::shared().base_url();
config.enable_caching = false;
transport_config.proxy_config = pc;

struct foo_socket_provider : public ::realm::networking::default_socket_provider {

foo_socket_provider(const ::realm::networking::default_transport_configuration& configuration) {
m_configuration = configuration;
}
std::unique_ptr<::realm::networking::websocket_interface> connect(std::unique_ptr<::realm::networking::websocket_observer> o,
::realm::networking::websocket_endpoint&& ep) override {
const std::string from = "wss:";
const std::string to = "ws:";
if (ep.url.find(from) == 0) {
ep.url.replace(0, from.length(), to);
}
m_called = true;
return ::realm::networking::default_socket_provider::connect(std::move(o), std::move(ep));
}
@@ -47,10 +48,15 @@ TEST_CASE("sends plaintext data to proxy", "[proxy]") {
bool m_called = false;
};

auto foo_socket = std::make_shared<foo_socket_provider>();
auto foo_socket = std::make_shared<foo_socket_provider>(transport_config);
config.sync_socket_provider = foo_socket;

struct foo_http_transport : public ::realm::networking::default_http_transport {

foo_http_transport(const ::realm::networking::default_transport_configuration& configuration) {
m_configuration = configuration;
}

void send_request_to_server(const ::realm::networking::request& request,
std::function<void(const ::realm::networking::response&)>&& completion) override {
auto req_copy = request;
@@ -71,7 +77,7 @@ TEST_CASE("sends plaintext data to proxy", "[proxy]") {
bool m_called = false;
};

auto foo_transport = std::make_shared<foo_http_transport>();
auto foo_transport = std::make_shared<foo_http_transport>(transport_config);
config.http_transport_client = foo_transport;

auto app = realm::App(config);
@@ -107,13 +113,12 @@ TEST_CASE("sends plaintext data to proxy", "[proxy]") {
expected_events.insert(tests::utils::proxy_server::event::websocket_upgrade);
expected_events.insert(tests::utils::proxy_server::event::websocket);

bool is_subset = std::includes(expected_events.begin(), expected_events.end(), proxy_events.begin(), proxy_events.end());
CHECK(is_subset);
CHECK(proxy_events == expected_events);
CHECK(foo_transport->was_called());
CHECK(foo_socket->was_called());
}

TEST_CASE("proxy roundtrip", "[proxy]") {
TEST_CASE("built in transport to proxy roundtrip", "[proxy]") {

tests::utils::proxy_server::config cfg;
cfg.port = 1234;
@@ -125,15 +130,20 @@ TEST_CASE("proxy roundtrip", "[proxy]") {
proxy_events.insert(e);
});

proxy_config pc;
pc.port = 1234;
pc.address = "127.0.0.1";
realm::App::configuration config;
config.proxy_configuration = pc;
config.app_id = Admin::Session::shared().cached_app_id();
config.app_id = Admin::Session::shared().create_app({"str_col", "_id"}, "test", false, false);
config.base_url = Admin::Session::shared().base_url();
config.enable_caching = false;

auto transport_config = ::realm::networking::default_transport_configuration();
proxy_config pc;
pc.port = 1234;
pc.address = "127.0.0.1";
transport_config.proxy_config = pc;

config.sync_socket_provider = std::make_shared<realm::networking::default_socket_provider>(transport_config);
config.http_transport_client = std::make_shared<realm::networking::default_http_transport>(transport_config);

auto app = realm::App(config);

auto user = app.login(realm::App::credentials::anonymous()).get();
@@ -167,6 +177,140 @@ TEST_CASE("proxy roundtrip", "[proxy]") {
expected_events.insert(tests::utils::proxy_server::event::websocket_upgrade);
expected_events.insert(tests::utils::proxy_server::event::websocket);

bool is_subset = std::includes(expected_events.begin(), expected_events.end(), proxy_events.begin(), proxy_events.end());
CHECK(is_subset);
CHECK(proxy_events == expected_events);
}

TEST_CASE("WebsocketEndpoint", "[proxy]") {
realm::networking::websocket_endpoint ep;
ep.url = "wss://my-server.com:443";
ep.protocols = std::vector<std::string>({"test_protocol"});

::realm::networking::default_transport_configuration config;
config.proxy_config = ::realm::proxy_config();
config.proxy_config->address = "127.0.0.1";
config.proxy_config->port = 1234;
config.proxy_config->username_password = std::pair<std::string, std::string>("foo", "bar");

config.ssl_trust_certificate_path = "test_path";

auto res = ::realm::internal::networking::to_core_websocket_endpoint(ep, config);
CHECK(res.is_ssl);
CHECK(res.protocols.size() == 1);
CHECK(res.protocols[0] == "test_protocol");
CHECK(res.address == "my-server.com");

CHECK(res.proxy);
CHECK(res.proxy->port == 1234);
CHECK(res.proxy->address == "127.0.0.1");
CHECK(res.headers.find("Proxy-Authorization") != res.headers.end());

CHECK(res.ssl_trust_certificate_path == "test_path");

ep.url = "ws://my-server.com:80";
res = ::realm::internal::networking::to_core_websocket_endpoint(ep, std::nullopt);
CHECK_FALSE(res.is_ssl);
}

TEST_CASE("proxy custom impl", "[proxy]") {
// Naive round-trip test to ensure custom socket impl's succeed.
realm::App::configuration config;
config.app_id = Admin::Session::shared().create_app({"str_col", "_id"}, "test", false, false);
config.base_url = Admin::Session::shared().base_url();
config.enable_caching = false;

std::promise<void> websocket_promise;
std::future<void> websocket_future = websocket_promise.get_future();

struct mock_websocket : public ::realm::networking::websocket_interface {
mock_websocket(std::unique_ptr<::realm::networking::websocket_observer>&& observer, std::promise<void>&& p) : m_websocket_promise(std::move(p)) {
std::thread([o = std::move(observer)]() {
std::this_thread::sleep_for(std::chrono::seconds(1));
o->websocket_connected_handler("com.mongodb.realm-query-sync#13");
}).detach();
}

void async_write_binary(std::string_view data, FunctionHandler&& handler) override {
m_websocket_promise.set_value();
}

private:
std::promise<void> m_websocket_promise;
};

struct mock_socket_provider : public ::realm::networking::sync_socket_provider {
std::unique_ptr<::realm::networking::websocket_interface> connect(
std::unique_ptr<::realm::networking::websocket_observer> observer,
::realm::networking::websocket_endpoint&& endpoint) override {
m_called = true;
return std::make_unique<mock_websocket>(std::move(observer), std::move(m_websocket_promise));
}

mock_socket_provider(std::promise<void>&& p) : m_websocket_promise(std::move(p)) {
worker_thread = std::thread([this]() {
while (running) {
std::vector<FunctionHandler> local_queue;
{
std::unique_lock<std::mutex> lock(mtx);
if (m_queue.empty()) {
lock.unlock();
std::this_thread::sleep_for(std::chrono::seconds(1));
continue;
}
local_queue.swap(m_queue);
}

for (auto fn : local_queue) {
fn(::realm::networking::status::ok());
}
}
});
worker_thread.detach();
}

~mock_socket_provider() {
running = false;
if (worker_thread.joinable()) {
worker_thread.join();
}
}

void post(FunctionHandler&& handler) override {
std::lock_guard<std::mutex> guard(mtx);
m_queue.push_back(std::move(handler));
}

struct timer : sync_socket_provider::timer {
~timer() = default;
void cancel() override { }
};

std::unique_ptr<sync_socket_provider::timer> create_timer(std::chrono::milliseconds delay, FunctionHandler&& handler) override {
static bool did_issue_connect = false;
if (!did_issue_connect)
m_queue.push_back(std::move(handler));
did_issue_connect = true;
return std::make_unique<timer>();
}

bool was_called() const {
return m_called;
}

private:
std::vector<FunctionHandler> m_queue;
std::mutex mtx;
bool m_called = false;
std::thread worker_thread;
std::atomic<bool> running{true};
std::promise<void> m_websocket_promise;
};

config.sync_socket_provider = std::make_shared<mock_socket_provider>(std::move(websocket_promise));

auto app = realm::App(config);

auto user = app.login(realm::App::credentials::anonymous()).get();
auto flx_sync_config = user.flexible_sync_configuration();
auto synced_realm = db(flx_sync_config);
websocket_future.get();
}

0 comments on commit 5d1851e

Please sign in to comment.