// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in // the main distribution directory for license terms and copyright or visit // https://github.com/actor-framework/actor-framework/blob/master/LICENSE. #define CAF_SUITE io.remote_spawn #include "caf/config.hpp" #include "io-test.hpp" #include #include #include #include #include #include #include "caf/all.hpp" #include "caf/io/all.hpp" using namespace caf; namespace { // function-based, dynamically typed, event-based API behavior calculator_fun(event_based_actor*) { return { [](add_atom, int a, int b) { return a + b; }, [](sub_atom, int a, int b) { return a - b; }, }; } class calculator_class : public event_based_actor { public: calculator_class(actor_config& cfg) : event_based_actor(cfg) { // nop } behavior make_behavior() override { return { [](add_atom, int a, int b) { return a + b; }, [](sub_atom, int a, int b) { return a - b; }, }; } }; // function-based, statically typed, event-based API calculator::behavior_type typed_calculator_fun() { return { [](add_atom, int a, int b) { return a + b; }, [](sub_atom, int a, int b) { return a - b; }, }; } struct config : actor_system_config { config() { load(); add_actor_type("calculator-class"); add_actor_type("calculator", calculator_fun); add_actor_type("typed_calculator", typed_calculator_fun); } }; struct fixture : point_to_point_fixture> { fixture() { prepare_connection(mars, earth, "mars", 8080); } }; } // namespace CAF_TEST_FIXTURE_SCOPE(dynamic_remote_actor_tests, fixture) CAF_TEST(nodes can spawn actors remotely) { loop_after_next_enqueue(mars); CAF_CHECK_EQUAL(unbox(mars.mm.open(8080)), 8080); loop_after_next_enqueue(earth); auto nid = unbox(earth.mm.connect("mars", 8080)); CAF_REQUIRE_EQUAL(nid, mars.sys.node()); CAF_MESSAGE("remote_spawn perform type checks on the handle"); loop_after_next_enqueue(earth); auto calc = earth.mm.remote_spawn(nid, "calculator", make_message()); CAF_REQUIRE_EQUAL(calc, sec::unexpected_actor_messaging_interface); loop_after_next_enqueue(earth); calc = earth.mm.remote_spawn(nid, "typed_calculator", make_message()); CAF_MESSAGE("remotely spawned actors respond to messages"); earth.self->send(*calc, add_atom_v, 10, 20); run(); expect_on(earth, (int), from(*calc).to(earth.self).with(30)); earth.self->send(*calc, sub_atom_v, 10, 20); run(); expect_on(earth, (int), from(*calc).to(earth.self).with(-10)); anon_send_exit(*calc, exit_reason::user_shutdown); CAF_MESSAGE("remote_spawn works with class-based actors as well"); loop_after_next_enqueue(earth); auto dyn_calc = earth.mm.remote_spawn(nid, "calculator-class", make_message()); CAF_REQUIRE(dyn_calc); earth.self->send(*dyn_calc, add_atom_v, 10, 20); run(); expect_on(earth, (int), from(*dyn_calc).to(earth.self).with(30)); anon_send_exit(*dyn_calc, exit_reason::user_shutdown); } CAF_TEST_FIXTURE_SCOPE_END()