5#include <mp/test/foo.capnp.h>
6#include <mp/test/foo.capnp.proxy.h>
9#include <capnp/capability.h>
13#include <condition_variable>
19#include <kj/async-io.h>
26#include <mp/proxy.capnp.h>
46static_assert(std::is_integral_v<
decltype(
kMP_MAJOR_VERSION)>,
"MP_MAJOR_VERSION must be an integral constant");
47static_assert(std::is_integral_v<
decltype(
kMP_MINOR_VERSION)>,
"MP_MINOR_VERSION must be an integral constant");
69 std::promise<std::unique_ptr<ProxyClient<messages::FooInterface>>>
client_promise;
70 std::unique_ptr<ProxyClient<messages::FooInterface>>
client;
86 std::make_unique<Connection>(loop, kj::mv(
pipe.ends[0]), [&](
Connection& connection) {
87 auto server_proxy = kj::heap<ProxyServer<messages::FooInterface>>(
88 std::make_shared<FooImplementation>(), connection);
89 server = server_proxy;
90 return capnp::Capability::Client(kj::mv(server_proxy));
94 assert(std::this_thread::get_id() == loop.m_thread_id);
102 auto client_proxy = std::make_unique<ProxyClient<messages::FooInterface>>(
115 client = client_promise.get_future().get();
146 in.
vbool.push_back(
false);
147 in.
vbool.push_back(
true);
148 in.
vbool.push_back(
false);
156 for (
size_t i = 0; i < in.
vbool.size(); ++i) {
172 int call(
int arg)
override
177 int callExtended(
int arg)
override
185 foo->initThreadMap();
188 KJ_EXPECT(
foo->callbackUnique(std::make_unique<Callback>(3, 4), 3) == 4);
189 KJ_EXPECT(
foo->callbackShared(std::make_shared<Callback>(5, 6), 5) == 6);
190 auto saved = std::make_shared<Callback>(7, 8);
194 foo->callbackSaved(7);
196 foo->saveCallback(
nullptr);
216 foo->passMutable(mut);
221 std::vector<FooDataRef>
data_in;
231KJ_TEST(
"Call IPC method after client connection is closed")
236 setup.client_disconnect();
238 bool disconnected{
false};
241 }
catch (
const std::runtime_error&
e) {
242 KJ_EXPECT(std::string_view{
e.what()} ==
"IPC client method called after disconnect.");
248KJ_TEST(
"Calling IPC method after server connection is closed")
253 setup.server_disconnect();
255 bool disconnected{
false};
258 }
catch (
const std::runtime_error&
e) {
259 KJ_EXPECT(std::string_view{
e.what()} ==
"IPC client method call interrupted by disconnect.");
265KJ_TEST(
"Calling IPC method and disconnecting during the call")
273 setup.server->m_impl->m_fn =
setup.client_disconnect;
275 bool disconnected{
false};
278 }
catch (
const std::runtime_error&
e) {
279 KJ_EXPECT(std::string_view{
e.what()} ==
"IPC client method call interrupted by disconnect.");
285KJ_TEST(
"Calling IPC method, disconnecting and blocking during the call")
305 std::promise<void>
signal;
310 foo->initThreadMap();
311 setup.server->m_impl->m_fn = [&] {
313 setup.client_disconnect();
314 signal.get_future().get();
317 bool disconnected{
false};
320 }
catch (
const std::runtime_error&
e) {
321 KJ_EXPECT(std::string_view{
e.what()} ==
"IPC client method call interrupted by disconnect.");
334KJ_TEST(
"Worker thread destroyed before it is initialized")
345 foo->initThreadMap();
346 setup.server->m_impl->m_fn = [] {};
353 setup.server_disconnect_later();
358 std::this_thread::sleep_for(std::chrono::milliseconds(10));
361 bool disconnected{
false};
364 }
catch (
const std::runtime_error&
e) {
365 KJ_EXPECT(std::string_view{
e.what()} ==
"IPC client method call interrupted by disconnect.");
371KJ_TEST(
"Calling async IPC method, with server disconnect racing the call")
382 foo->initThreadMap();
383 setup.server->m_impl->m_fn = [] {};
387 setup.server_disconnect();
390 std::this_thread::sleep_for(std::chrono::milliseconds(10));
396 }
catch (
const std::runtime_error&
e) {
397 KJ_EXPECT(std::string_view{
e.what()} ==
"IPC client method call interrupted by disconnect.");
401KJ_TEST(
"Calling async IPC method, with server disconnect after cleanup")
414 foo->initThreadMap();
415 setup.server->m_impl->m_fn = [] {};
419 setup.server_disconnect();
425 }
catch (
const std::runtime_error&
e) {
426 KJ_EXPECT(std::string_view{
e.what()} ==
"IPC client method call interrupted by disconnect.");
430KJ_TEST(
"Make simultaneous IPC calls on single remote thread")
434 std::promise<void>
signal;
436 foo->initThreadMap();
439 setup.server->m_impl->m_fn = [&] {};
443 foo->m_context.loop->sync([&] {
444 Lock lock(
tc.waiter->m_mutex);
450 std::atomic<int> expected = 100;
452 setup.server->m_impl->m_int_fn = [&](
int n) {
458 auto client{
foo->m_client};
459 std::atomic<size_t>
running{3};
460 foo->m_context.loop->sync([&]
462 for (
size_t i = 0; i <
running; i++)
464 auto request{client.callIntFnAsyncRequest()};
465 auto context{request.initContext()};
468 request.setArg(100 * (i+1));
469 foo->m_context.loop->m_task_set->add(request.send().then(
471 assert(results.getResult() == static_cast<int32_t>(100 * (i+1)));
473 tc.waiter->m_cv.notify_all();
478 Lock lock(
tc.waiter->m_mutex);
Object holding network & rpc state associated with either an incoming server connection,...
Event loop implementation.
kj::AsyncIoContext m_io_context
Capnp IO context.
void * m_context
External context pointer.
std::function< void()> testing_hook_makethread
Hook called when ProxyServer<ThreadMap>::makeThread() is called.
std::function< void()> testing_hook_makethread_created
Hook called on the worker thread inside makeThread(), after the thread context is set up and thread_c...
std::function< void()> testing_hook_async_request_done
Hook called on the worker thread just before returning results.
std::function< void()> testing_hook_async_request_start
Hook called on the worker thread when it starts to execute an async request.
Event loop smart pointer automatically managing m_num_clients.
Test setup class creating a two way connection between a ProxyServer<FooInterface> object and a Proxy...
std::promise< std::unique_ptr< ProxyClient< messages::FooInterface > > > client_promise
TestSetup(bool client_owns_connection=true)
std::function< void()> server_disconnect
std::function< void()> client_disconnect
std::thread thread
Thread variable should be after other struct members so the thread does not start until the other mem...
std::function< void()> server_disconnect_later
ProxyServer< messages::FooInterface > * server
std::unique_ptr< ProxyClient< messages::FooInterface > > client
std::vector< char > FooData
constexpr auto kMP_MAJOR_VERSION
Check version.h header values.
constexpr auto kMP_MINOR_VERSION
Functions to serialize / deserialize common bitcoin types.
thread_local ThreadContext g_thread_context
KJ_TEST("SpawnProcess does not run callback in child")
Log level
The severity level of this message.
std::string message
Message to be logged.
Mapping from capnp interface type to proxy client implementation (specializations are generated by pr...
Mapping from capnp interface type to proxy server implementation (specializations are generated by pr...
Vat id for server side of connection.
The thread_local ThreadContext g_thread_context struct provides information about individual threads ...
std::vector< bool > vbool
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
Major and minor version numbers.
#define MP_MAJOR_VERSION
Major version number.
#define MP_MINOR_VERSION
Minor version number.