5#include <mp/test/foo.capnp.h>
6#include <mp/test/foo.capnp.proxy.h>
8#include <capnp/capability.h>
15#include <kj/async-io.h>
54 std::promise<std::unique_ptr<ProxyClient<messages::FooInterface>>>
client_promise;
55 std::unique_ptr<ProxyClient<messages::FooInterface>>
client;
63 EventLoop loop(
"mptest", [](
bool raise,
const std::string& log) {
64 std::cout <<
"LOG" << raise <<
": " << log <<
"\n";
65 if (raise)
throw std::runtime_error(log);
69 auto server_connection =
70 std::make_unique<Connection>(loop, kj::mv(pipe.ends[0]), [&](
Connection& connection) {
71 auto server_proxy = kj::heap<ProxyServer<messages::FooInterface>>(
72 std::make_shared<FooImplementation>(), connection);
73 server = server_proxy;
74 return capnp::Capability::Client(kj::mv(server_proxy));
79 server_connection->onDisconnect([&] { server_connection.reset(); });
81 auto client_connection = std::make_unique<Connection>(loop, kj::mv(pipe.ends[1]));
82 auto client_proxy = std::make_unique<ProxyClient<messages::FooInterface>>(
83 client_connection->m_rpc_system->bootstrap(
ServerVatId().vat_id).castAs<messages::FooInterface>(),
84 client_connection.get(), client_owns_connection);
85 if (client_owns_connection) {
86 client_connection.release();
95 client = client_promise.get_future().get();
101 bool destroyed =
false;
102 client->m_context.cleanup_fns.emplace_front([&destroyed] { destroyed =
true; });
104 KJ_EXPECT(destroyed);
115 KJ_EXPECT(foo->add(1, 2) == 3);
121 in.
vbool.push_back(
false);
122 in.
vbool.push_back(
true);
123 in.
vbool.push_back(
false);
125 KJ_EXPECT(in.
name ==
out.name);
126 KJ_EXPECT(in.
setint.size() ==
out.setint.size());
128 KJ_EXPECT(*
init == *outit);
130 KJ_EXPECT(in.
vbool.size() ==
out.vbool.size());
131 for (
size_t i = 0; i < in.
vbool.size(); ++i) {
132 KJ_EXPECT(in.
vbool[i] ==
out.vbool[i]);
147 int call(
int arg)
override
149 KJ_EXPECT(arg == m_expect);
152 int callExtended(
int arg)
override
154 KJ_EXPECT(arg == m_expect + 10);
160 foo->initThreadMap();
161 Callback callback(1, 2);
162 KJ_EXPECT(foo->callback(callback, 1) == 2);
163 KJ_EXPECT(foo->callbackUnique(std::make_unique<Callback>(3, 4), 3) == 4);
164 KJ_EXPECT(foo->callbackShared(std::make_shared<Callback>(5, 6), 5) == 6);
165 auto saved = std::make_shared<Callback>(7, 8);
166 KJ_EXPECT(saved.use_count() == 1);
167 foo->saveCallback(saved);
168 KJ_EXPECT(saved.use_count() == 2);
169 foo->callbackSaved(7);
170 KJ_EXPECT(foo->callbackSaved(7) == 8);
171 foo->saveCallback(
nullptr);
172 KJ_EXPECT(saved.use_count() == 1);
173 KJ_EXPECT(foo->callbackExtended(callback, 11) == 12);
178 FooCustom custom_out = foo->passCustom(custom_in);
179 KJ_EXPECT(custom_in.
v1 == custom_out.
v1);
180 KJ_EXPECT(custom_in.
v2 == custom_out.
v2);
186 FooMessage message2{foo->passMessage(message1)};
187 KJ_EXPECT(message2.message ==
"init build read call build read");
191 foo->passMutable(mut);
192 KJ_EXPECT(mut.
message ==
"init build pass call return read");
194 KJ_EXPECT(foo->passFn([]{ return 10; }) == 10);
197KJ_TEST(
"Call IPC method after client connection is closed")
201 KJ_EXPECT(foo->add(1, 2) == 3);
202 setup.client_disconnect();
204 bool disconnected{
false};
207 }
catch (
const std::runtime_error& e) {
208 KJ_EXPECT(std::string_view{e.what()} ==
"IPC client method called after disconnect.");
211 KJ_EXPECT(disconnected);
214KJ_TEST(
"Calling IPC method after server connection is closed")
218 KJ_EXPECT(foo->add(1, 2) == 3);
221 bool disconnected{
false};
224 }
catch (
const std::runtime_error& e) {
225 KJ_EXPECT(std::string_view{e.what()} ==
"IPC client method call interrupted by disconnect.");
228 KJ_EXPECT(disconnected);
231KJ_TEST(
"Calling IPC method and disconnecting during the call")
235 KJ_EXPECT(foo->add(1, 2) == 3);
239 setup.server->m_impl->m_fn = setup.client_disconnect;
241 bool disconnected{
false};
244 }
catch (
const std::runtime_error& e) {
245 KJ_EXPECT(std::string_view{e.what()} ==
"IPC client method call interrupted by disconnect.");
248 KJ_EXPECT(disconnected);
251KJ_TEST(
"Calling IPC method, disconnecting and blocking during the call")
271 std::promise<void> signal;
274 KJ_EXPECT(foo->add(1, 2) == 3);
276 foo->initThreadMap();
277 setup.server->m_impl->m_fn = [&] {
279 setup.client_disconnect();
280 signal.get_future().get();
283 bool disconnected{
false};
286 }
catch (
const std::runtime_error& e) {
287 KJ_EXPECT(std::string_view{e.what()} ==
"IPC client method call interrupted by disconnect.");
290 KJ_EXPECT(disconnected);
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.
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...
ProxyServer< messages::FooInterface > * server
std::unique_ptr< ProxyClient< messages::FooInterface > > client
KJ_TEST("Calling IPC method, disconnecting and blocking during the call")
Functions to serialize / deserialize common bitcoin types.
Mapping from capnp interface type to proxy client implementation (specializations are generated by pr...
Vat id for server side of connection.
std::vector< bool > vbool