7#include <mp/test/foo.capnp.h>
8#include <mp/test/foo.capnp.proxy.h>
11#include <condition_variable>
29#include <sys/socket.h>
38constexpr auto FAILURE_TIMEOUT = std::chrono::seconds{30};
48 std::string dir_template = (std::filesystem::temp_directory_path() /
"mptest-listener-XXXXXX").
string();
49 char* dir = mkdtemp(dir_template.data());
50 KJ_REQUIRE(dir !=
nullptr);
54 m_fd = socket(AF_UNIX, SOCK_STREAM, 0);
55 KJ_REQUIRE(
m_fd >= 0);
58 addr.sun_family = AF_UNIX;
59 KJ_REQUIRE(
m_path.size() <
sizeof(addr.sun_path));
60 std::strncpy(addr.sun_path,
m_path.c_str(),
sizeof(addr.sun_path) - 1);
61 KJ_REQUIRE(bind(
m_fd,
reinterpret_cast<sockaddr*
>(&addr),
sizeof(addr)) == 0);
62 KJ_REQUIRE(listen(
m_fd, SOMAXCONN) == 0);
80 int MakeConnectedSocket()
const
82 int fd = socket(AF_UNIX, SOCK_STREAM, 0);
86 addr.sun_family = AF_UNIX;
87 KJ_REQUIRE(
m_path.size() <
sizeof(addr.sun_path));
88 std::strncpy(addr.sun_path,
m_path.c_str(),
sizeof(addr.sun_path) - 1);
89 KJ_REQUIRE(connect(fd,
reinterpret_cast<sockaddr*
>(&addr),
sizeof(addr)) == 0);
105 explicit ClientSetup(
int fd)
111 client_promise.set_value(ConnectStream<messages::FooInterface>(loop, fd));
124 std::promise<std::unique_ptr<ProxyClient<messages::FooInterface>>>
client_promise;
125 std::unique_ptr<ProxyClient<messages::FooInterface>>
client;
138 explicit ListenSetup(std::optional<size_t> max_connections = std::nullopt)
139 :
thread([
this, max_connections] {
144 loop.testing_hook_disconnected = [&] {
146 ++disconnected_count;
149 loop.testing_hook_connected = [&] {
156 ListenConnections<messages::FooInterface>(loop,
listener.release(), foo, max_connections);
170 size_t ConnectedCount()
173 return connected_count;
176 size_t DisconnectedCount()
179 return disconnected_count;
182 void WaitForConnectedCount(
size_t expected_count)
185 const auto deadline = std::chrono::steady_clock::now() + FAILURE_TIMEOUT;
187 return connected_count >= expected_count;
192 void WaitForDisconnectedCount(
size_t expected_count)
195 const auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(5);
197 return disconnected_count >= expected_count;
214KJ_TEST(
"ListenConnections accepts incoming connections")
217 KJ_EXPECT(server.ConnectedCount() == 0)
218 auto
client =
std::make_unique<ClientSetup>(server.
listener.MakeConnectedSocket());
220 server.WaitForConnectedCount(1);
230 ListenSetup server(1);
232 KJ_EXPECT(server.ConnectedCount() == 0)
233 auto client1 =
std::make_unique<ClientSetup>(server.
listener.MakeConnectedSocket());
234 server.WaitForConnectedCount(1);
236 KJ_EXPECT(client1->
client->add(1, 2) == 3);
238 auto client2 =
std::make_unique<ClientSetup>(server.
listener.MakeConnectedSocket());
244 KJ_EXPECT(server.ConnectedCount() == 1);
245 KJ_EXPECT(server.DisconnectedCount() == 0);
247 server.WaitForDisconnectedCount(1);
248 server.WaitForConnectedCount(2);
250 KJ_EXPECT(client2->client->add(2, 3) == 5);
252 KJ_EXPECT(server.DisconnectedCount() == 1);
254 server.WaitForDisconnectedCount(2);
256 KJ_EXPECT(server.DisconnectedCount() == 2);
257 auto client3 = std::make_unique<ClientSetup>(server.listener.MakeConnectedSocket());
258 server.WaitForConnectedCount(3);
259 KJ_EXPECT(client3->client->add(3, 4) == 7);
262KJ_TEST(
"ListenConnections accepts multiple connections")
267 ListenSetup server(2);
269 KJ_EXPECT(server.ConnectedCount() == 0);
270 auto client1 = std::make_unique<ClientSetup>(server.listener.MakeConnectedSocket());
271 auto client2 = std::make_unique<ClientSetup>(server.listener.MakeConnectedSocket());
272 server.WaitForConnectedCount(2);
274 KJ_EXPECT(client1->client->add(1, 2) == 3);
275 KJ_EXPECT(client2->client->add(2, 3) == 5);
277 auto client3 = std::make_unique<ClientSetup>(server.listener.MakeConnectedSocket());
281 (**server.m_loop_ref).sync([] {});
283 KJ_EXPECT(server.ConnectedCount() == 2);
284 KJ_EXPECT(server.DisconnectedCount() == 0);
286 server.WaitForDisconnectedCount(1);
287 server.WaitForConnectedCount(3);
289 KJ_EXPECT(client3->client->add(3, 4) == 7);
std::unique_ptr< ProxyClient< messages::FooInterface > > client
std::optional< EventLoopRef > m_loop_ref
std::promise< std::unique_ptr< ProxyClient< messages::FooInterface > > > client_promise
std::condition_variable counter_cv
std::thread thread
Thread variable should be after other struct members so the thread does not start until the other mem...
std::promise< void > ready_promise
KJ_TEST("Call FooInterface methods")
Functions to serialize / deserialize common bitcoin types.
void ListenConnections(EventLoop &loop, int fd, InitImpl &init, std::optional< size_t > max_connections=std::nullopt)
Given listening socket file descriptor and an init object, handle incoming connections and requests b...
Log level
The severity level of this message.
std::string message
Message to be logged.