Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add server tests. #46

Merged
merged 3 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/common/server/NetRemoteServer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ NetRemoteServer::NetRemoteServer(std::string_view serverAddress) :
m_serverAddress{ serverAddress }
{}

NetRemoteServer::~NetRemoteServer()
{
Stop();
}

std::unique_ptr<grpc::Server>& NetRemoteServer::GetGrpcServer() noexcept
{
return m_server;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ namespace Microsoft::Net::Remote
*/
struct NetRemoteServer
{
virtual ~NetRemoteServer();

/**
* @brief Construct a new NetRemoteServer object.
*
Expand Down
4 changes: 3 additions & 1 deletion tests/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ add_executable(netremote-test-unit)

target_sources(netremote-test-unit
PRIVATE
${CMAKE_CURRENT_LIST_DIR}/TestNetRemoteCommon.cxx
${CMAKE_CURRENT_LIST_DIR}/TestNetRemoteServer.cxx
${CMAKE_CURRENT_LIST_DIR}/TestNetRemoteServiceClient.cxx
)

Expand All @@ -17,7 +19,7 @@ target_link_libraries(netremote-test-unit
Catch2::Catch2WithMain
gRPC::grpc++
magic_enum::magic_enum
netremote-service
netremote-server
)

catch_discover_tests(netremote-test-unit)
Expand Down
24 changes: 24 additions & 0 deletions tests/unit/TestNetRemoteCommon.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

#include <catch2/catch_test_macros.hpp>
#include <grpcpp/create_channel.h>

#include "TestNetRemoteCommon.hxx"

using namespace Microsoft::Net::Remote;
using namespace Microsoft::Net::Remote::Test;
using namespace Microsoft::Net::Remote::Service;

std::vector<std::tuple<std::shared_ptr<grpc::Channel>, std::unique_ptr<NetRemote::Stub>>> Microsoft::Net::Remote::Test::EstablishClientConnections(std::size_t numConnectionsToEstablish, std::string_view serverAddress)
{
std::vector<std::tuple<std::shared_ptr<grpc::Channel>, std::unique_ptr<NetRemote::Stub>>> clients(numConnectionsToEstablish);
std::ranges::transform(clients, std::begin(clients), [&](auto&&)
{
auto channel = grpc::CreateChannel(std::data(serverAddress), grpc::InsecureChannelCredentials());
auto client = NetRemote::NewStub(channel);
REQUIRE(channel->WaitForConnected(std::chrono::system_clock::now() + RemoteServiceConnectionTimeout));

return std::make_tuple(std::move(channel), std::move(client));
});

return clients;
}
41 changes: 41 additions & 0 deletions tests/unit/TestNetRemoteCommon.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

#ifndef TEST_NET_REMOTE_COMMON_HXX
#define TEST_NET_REMOTE_COMMON_HXX

#include <algorithm>
#include <chrono>
#include <memory>
#include <ranges>
#include <string_view>
#include <tuple>
#include <vector>

#include <NetRemoteService.grpc.pb.h>

namespace Microsoft::Net::Remote::Test
{
using namespace std::chrono_literals;

/**
* @brief Default server address (insecure).
*/
constexpr auto RemoteServiceAddressHttp = "localhost:5047";

/**
* @brief Default client connection timeout.
*/
constexpr auto RemoteServiceConnectionTimeout = 3s;

/**
* @brief Establish the specified number of connections to a netremote server
* with specified address and default credentials.
*
* @param numConnectionsToEstablish The number of client connections to establish.
* @param serverAddress The server address to connect to. Defaults to RemoteServiceAddressHttp.
* @return std::vector<std::tuple<std::shared_ptr<grpc::Channel>, std::unique_ptr<Microsoft::Net::Remote::Service::NetRemote::Stub>>>
*/
std::vector<std::tuple<std::shared_ptr<grpc::Channel>, std::unique_ptr<Microsoft::Net::Remote::Service::NetRemote::Stub>>> EstablishClientConnections(std::size_t numConnectionsToEstablish, std::string_view serverAddress = RemoteServiceAddressHttp);

} // namespace Micosoft::Net::Remote::Test

#endif // TEST_NET_REMOTE_COMMON_HXX
136 changes: 136 additions & 0 deletions tests/unit/TestNetRemoteServer.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@

#include <optional>

#include <catch2/catch_test_macros.hpp>
#include <catch2/generators/catch_generators_range.hpp>
#include <grpcpp/create_channel.h>
#include <microsoft/net/remote/NetRemoteServer.hxx>
#include <NetRemoteService.grpc.pb.h>

#include "TestNetRemoteCommon.hxx"

TEST_CASE("Create a NetRemoteServer instance", "[basic][rpc][remote]")
{
using namespace Microsoft::Net::Remote;

SECTION("Create doesn't cause a crash")
{
REQUIRE_NOTHROW(NetRemoteServer{ Test::RemoteServiceAddressHttp });
}
}

TEST_CASE("Destroy a NetRemoteServer instance", "[basic][rpc][remote]")
{
using namespace Microsoft::Net::Remote;
using namespace Microsoft::Net::Remote::Service;

std::optional<NetRemoteServer> server{ Test::RemoteServiceAddressHttp };
server->Run();

SECTION("Destroy doesn't cause a crash")
{
REQUIRE_NOTHROW(server.reset());
}

SECTION("Destroy doesn't cause a crash with connected clients")
{
// Vary the number of connected clients and validate test section for each.
const auto numClientsToCreate = Catch::Generators::range(1, 2);

// Establish client connections to the server.
const auto clients = Test::EstablishClientConnections(static_cast<std::size_t>(numClientsToCreate.get()));

REQUIRE_NOTHROW(server.reset());
}
}

TEST_CASE("NetRemoteServer can be reached", "[basic][rpc][remote]")
{
using namespace Microsoft::Net::Remote;
using namespace Microsoft::Net::Remote::Service;

NetRemoteServer server{ Test::RemoteServiceAddressHttp };
server.Run();

SECTION("Can be reached using insecure channel")
{
auto channel = grpc::CreateChannel(Test::RemoteServiceAddressHttp, grpc::InsecureChannelCredentials());
auto client = NetRemote::NewStub(channel);

REQUIRE(channel->WaitForConnected(std::chrono::system_clock::now() + Test::RemoteServiceConnectionTimeout));
}
}

TEST_CASE("NetRemoteServer shuts down correctly", "[basic][rpc][remote]")
{
using namespace Microsoft::Net::Remote;
using namespace Microsoft::Net::Remote::Service;

NetRemoteServer server{ Test::RemoteServiceAddressHttp };
server.Run();

SECTION("Stop() doesn't cause a crash with no connected clients")
{
REQUIRE_NOTHROW(server.Stop());
}

SECTION("Stop() severs connections for connected clients")
{
// Vary the number of connected clients and validate test section for each.
const auto numClientsToCreate = Catch::Generators::range(1, 3);

// Establish client connections to the server.
const auto clients = Test::EstablishClientConnections(static_cast<std::size_t>(numClientsToCreate.get()));

// Stop the server.
REQUIRE_NOTHROW(server.Stop());

// Validate each channel is in IDLE state.
for (const auto& [channel, _] : clients)
{
REQUIRE(channel->GetState(false) == GRPC_CHANNEL_IDLE);
}
}

SECTION("Stop() invalidates gRPC server instance with no connected clients")
{
REQUIRE_NOTHROW(server.Stop());
REQUIRE(server.GetGrpcServer() == nullptr);
}

SECTION("Stop() invalidates gRPC server instance with connected clients")
{
// Vary the number of connected clients and validate test section for each.
const auto numClientsToCreate = Catch::Generators::range(1, 3);

// Establish client connections to the server.
const auto clients = Test::EstablishClientConnections(static_cast<std::size_t>(numClientsToCreate.get()));

REQUIRE_NOTHROW(server.Stop());
REQUIRE(server.GetGrpcServer() == nullptr);
}
}

TEST_CASE("NetRemoteServer can be cycled through run/stop states", "[basic][rpc][remote]")
{
using namespace Microsoft::Net::Remote;
using namespace Microsoft::Net::Remote::Service;

NetRemoteServer server{ Test::RemoteServiceAddressHttp };
REQUIRE_NOTHROW(server.Run());

SECTION("Can be cycled multiple times")
{
const auto numCycles = Catch::Generators::range(1, 3);

for ([[maybe_unused]] auto _ : std::views::iota(0, numCycles.get()))
{
REQUIRE_NOTHROW(server.Stop());
REQUIRE_NOTHROW(server.Run());

auto channel = grpc::CreateChannel(Test::RemoteServiceAddressHttp, grpc::InsecureChannelCredentials());
auto client = NetRemote::NewStub(channel);
REQUIRE(channel->WaitForConnected(std::chrono::system_clock::now() + Test::RemoteServiceConnectionTimeout));
}
}
}
28 changes: 6 additions & 22 deletions tests/unit/TestNetRemoteServiceClient.cxx
Original file line number Diff line number Diff line change
@@ -1,41 +1,25 @@

#include <array>
#include <chrono>
#include <cstdint>
#include <format>
#include <iostream>

#include <catch2/catch_test_macros.hpp>
#include <grpcpp/create_channel.h>
#include <magic_enum.hpp>
#include <microsoft/net/remote/NetRemoteService.hxx>
#include <NetRemoteService.grpc.pb.h>

using namespace std::chrono_literals;
#include <microsoft/net/remote/NetRemoteServer.hxx>

namespace detail
{
constexpr auto RemoteServiceAddressHttp = "localhost:5047";
[[maybe_unused]] constexpr auto RemoteServiceAddressHttps = "localhost:7073";
constexpr auto RemoteServiceConnectionTimeout = 3s;
} // namespace detail

TEST_CASE("net remote service can be reached", "[basic][rpc][client][remote]")
{
using namespace Microsoft::Net::Remote::Service;

auto channel = grpc::CreateChannel(detail::RemoteServiceAddressHttp, grpc::InsecureChannelCredentials());
auto client = NetRemote::NewStub(channel);

REQUIRE(channel->WaitForConnected(std::chrono::system_clock::now() + detail::RemoteServiceConnectionTimeout));
}
#include "TestNetRemoteCommon.hxx"

TEST_CASE("WifiConfigureAccessPoint API can be called", "[basic][rpc][client][remote]")
{
using namespace Microsoft::Net::Remote;
using namespace Microsoft::Net::Remote::Service;

auto channel = grpc::CreateChannel(detail::RemoteServiceAddressHttp, grpc::InsecureChannelCredentials());
NetRemoteServer server{ Test::RemoteServiceAddressHttp };
server.Run();

auto channel = grpc::CreateChannel(Test::RemoteServiceAddressHttp, grpc::InsecureChannelCredentials());
auto client = NetRemote::NewStub(channel);

SECTION("Can be called")
Expand Down
Loading