Commit 7478b485 authored by Dominik Charousset's avatar Dominik Charousset

Split test_spawn into more unit tests

The previous implementation of test_spawn consumed GBs of RAM during
compilation because it did too much in a single file. All parts that were
independent of test_spawn itself have thus been separated.
parent b7170962
...@@ -26,6 +26,12 @@ add_unit_test(uniform_type) ...@@ -26,6 +26,12 @@ add_unit_test(uniform_type)
add_unit_test(fixed_vector) add_unit_test(fixed_vector)
add_unit_test(intrusive_ptr) add_unit_test(intrusive_ptr)
add_unit_test(spawn ping_pong.cpp) add_unit_test(spawn ping_pong.cpp)
add_unit_test(simple_reply_response)
add_unit_test(serial_reply)
add_unit_test(or_else)
add_unit_test(continuation)
add_unit_test(constructor_attach)
add_unit_test(custom_exception_handler)
add_unit_test(typed_spawn) add_unit_test(typed_spawn)
add_unit_test(local_group) add_unit_test(local_group)
add_unit_test(sync_send) add_unit_test(sync_send)
...@@ -33,3 +39,4 @@ add_unit_test(broker) ...@@ -33,3 +39,4 @@ add_unit_test(broker)
add_unit_test(remote_actor ping_pong.cpp) add_unit_test(remote_actor ping_pong.cpp)
add_unit_test(typed_remote_actor) add_unit_test(typed_remote_actor)
add_unit_test(optional) add_unit_test(optional)
add_unit_test(fixed_stack_actor)
#include "test.hpp"
#include "caf/all.hpp"
using namespace caf;
void test_constructor_attach() {
class testee : public event_based_actor {
public:
testee(actor buddy) : m_buddy(buddy) {
attach_functor([=](uint32_t reason) {
send(m_buddy, atom("done"), reason);
});
}
behavior make_behavior() {
return {
on(atom("die")) >> [=] {
quit(exit_reason::user_shutdown);
}
};
}
private:
actor m_buddy;
};
class spawner : public event_based_actor {
public:
spawner() : m_downs(0) {
}
behavior make_behavior() {
m_testee = spawn<testee, monitored>(this);
return {
[=](const down_msg& msg) {
CAF_CHECK_EQUAL(msg.reason, exit_reason::user_shutdown);
if (++m_downs == 2) {
quit(msg.reason);
}
},
on(atom("done"), arg_match) >> [=](uint32_t reason) {
CAF_CHECK_EQUAL(reason, exit_reason::user_shutdown);
if (++m_downs == 2) {
quit(reason);
}
},
others() >> [=] {
forward_to(m_testee);
}
};
}
private:
int m_downs;
actor m_testee;
};
anon_send(spawn<spawner>(), atom("die"));
}
int main() {
CAF_TEST(test_constructor_attach);
test_constructor_attach();
return CAF_TEST_RESULT();
}
#include "test.hpp"
#include "caf/all.hpp"
using namespace caf;
behavior simple_mirror(event_based_actor* self) {
return {
others() >> [=] {
return self->last_dequeued();
}
};
}
void test_continuation() {
auto mirror = spawn(simple_mirror);
spawn([=](event_based_actor* self) {
self->sync_send(mirror, 42).then(
on(42) >> [] {
return "fourty-two";
}
).continue_with(
[=](const std::string& ref) {
CAF_CHECK_EQUAL(ref, "fourty-two");
return 4.2f;
}
).continue_with(
[=](float f) {
CAF_CHECK_EQUAL(f, 4.2f);
self->send_exit(mirror, exit_reason::user_shutdown);
self->quit();
}
);
});
await_all_actors_done();
}
int main() {
CAF_TEST(test_continuation);
test_continuation();
return CAF_TEST_RESULT();
}
#include "test.hpp"
#include "caf/all.hpp"
using namespace caf;
class exception_testee : public event_based_actor {
public:
exception_testee() {
set_exception_handler([](const std::exception_ptr&) -> optional<uint32_t> {
return exit_reason::user_defined + 2;
});
}
behavior make_behavior() override {
return {
others() >> [] {
throw std::runtime_error("whatever");
}
};
}
};
void test_custom_exception_handler() {
auto handler = [](const std::exception_ptr& eptr) -> optional<uint32_t> {
try {
std::rethrow_exception(eptr);
}
catch (std::runtime_error&) {
return exit_reason::user_defined;
}
catch (...) {
// "fall through"
}
return exit_reason::user_defined + 1;
};
scoped_actor self;
auto testee1 = self->spawn<monitored>([=](event_based_actor* eb_self) {
eb_self->set_exception_handler(handler);
throw std::runtime_error("ping");
});
auto testee2 = self->spawn<monitored>([=](event_based_actor* eb_self) {
eb_self->set_exception_handler(handler);
throw std::logic_error("pong");
});
auto testee3 = self->spawn<exception_testee, monitored>();
self->send(testee3, "foo");
// receive all down messages
auto i = 0;
self->receive_for(i, 3)(
[&](const down_msg& dm) {
if (dm.source == testee1) {
CAF_CHECK_EQUAL(dm.reason, exit_reason::user_defined);
}
else if (dm.source == testee2) {
CAF_CHECK_EQUAL(dm.reason, exit_reason::user_defined + 1);
}
else if (dm.source == testee3) {
CAF_CHECK_EQUAL(dm.reason, exit_reason::user_defined + 2);
}
else {
CAF_CHECK(false); // report error
}
}
);
}
int main() {
CAF_TEST(test_custom_exception_handler);
test_custom_exception_handler();
return CAF_TEST_RESULT();
}
#include <vector>
#include "test.hpp"
#include "caf/all.hpp"
using namespace caf;
class fixed_stack : public sb_actor<fixed_stack> {
public:
friend class sb_actor<fixed_stack>;
fixed_stack(size_t max) : max_size(max) {
full = (
on(atom("push"), arg_match) >> [=](int) { /* discard */ },
on(atom("pop")) >> [=]() -> cow_tuple<atom_value, int> {
auto result = data.back();
data.pop_back();
become(filled);
return {atom("ok"), result};
}
);
filled = (
on(atom("push"), arg_match) >> [=](int what) {
data.push_back(what);
if (data.size() == max_size) become(full);
},
on(atom("pop")) >> [=]() -> cow_tuple<atom_value, int> {
auto result = data.back();
data.pop_back();
if (data.empty()) become(empty);
return {atom("ok"), result};
}
);
empty = (
on(atom("push"), arg_match) >> [=](int what) {
data.push_back(what);
become(filled);
},
on(atom("pop")) >> [=] {
return atom("failure");
}
);
}
private:
size_t max_size = 10;
std::vector<int> data;
behavior full;
behavior filled;
behavior empty;
behavior& init_state = empty;
};
void test_fixed_stack_actor() {
scoped_actor self;
auto st = spawn<fixed_stack>(size_t{10});
// push 20 values
for (int i = 0; i < 20; ++i) self->send(st, atom("push"), i);
// pop 20 times
for (int i = 0; i < 20; ++i) self->send(st, atom("pop"));
// expect 10 failure messages
{
int i = 0;
self->receive_for(i, 10) (
on(atom("failure")) >> CAF_CHECKPOINT_CB()
);
CAF_CHECKPOINT();
}
// expect 10 {'ok', value} messages
{
std::vector<int> values;
int i = 0;
self->receive_for(i, 10) (
on(atom("ok"), arg_match) >> [&](int value) {
values.push_back(value);
}
);
std::vector<int> expected{9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
CAF_CHECK_EQUAL(join(values, ","), join(expected, ","));
}
// terminate st
self->send_exit(st, exit_reason::user_shutdown);
self->await_all_other_actors_done();
}
int main() {
CAF_TEST(test_fixed_stack_actor);
test_fixed_stack_actor();
return CAF_TEST_RESULT();
}
#include "test.hpp"
#include "caf/all.hpp"
using namespace caf;
void test_or_else() {
scoped_actor self;
message_handler handle_a {
on("a") >> [] { return 1; }
};
message_handler handle_b {
on("b") >> [] { return 2; }
};
message_handler handle_c {
on("c") >> [] { return 3; }
};
auto run_testee([&](actor testee) {
self->sync_send(testee, "a").await([](int i) {
CAF_CHECK_EQUAL(i, 1);
});
self->sync_send(testee, "b").await([](int i) {
CAF_CHECK_EQUAL(i, 2);
});
self->sync_send(testee, "c").await([](int i) {
CAF_CHECK_EQUAL(i, 3);
});
self->send_exit(testee, exit_reason::user_shutdown);
self->await_all_other_actors_done();
});
CAF_PRINT("run_testee: handle_a.or_else(handle_b).or_else(handle_c)");
run_testee(
spawn([=] {
return handle_a.or_else(handle_b).or_else(handle_c);
})
);
CAF_PRINT("run_testee: handle_a.or_else(handle_b), on(\"c\") ...");
run_testee(
spawn([=] {
return (
handle_a.or_else(handle_b),
on("c") >> [] { return 3; }
);
})
);
CAF_PRINT("run_testee: on(\"a\") ..., handle_b.or_else(handle_c)");
run_testee(
spawn([=] {
return (
on("a") >> [] { return 1; },
handle_b.or_else(handle_c)
);
})
);
}
int main() {
CAF_TEST(test_or_else);
test_or_else();
return CAF_TEST_RESULT();
}
#include <iostream>
#include "test.hpp"
#include "caf/all.hpp"
using std::cout;
using std::endl;
using namespace caf;
void test_serial_reply() {
auto mirror_behavior = [=](event_based_actor* self) {
self->become(others() >> [=]() -> message {
CAF_PRINT("return self->last_dequeued()");
return self->last_dequeued();
});
};
auto master = spawn([=](event_based_actor* self) {
cout << "ID of master: " << self->id() << endl;
// spawn 5 mirror actors
auto c0 = self->spawn<linked>(mirror_behavior);
auto c1 = self->spawn<linked>(mirror_behavior);
auto c2 = self->spawn<linked>(mirror_behavior);
auto c3 = self->spawn<linked>(mirror_behavior);
auto c4 = self->spawn<linked>(mirror_behavior);
self->become (
on(atom("hi there")) >> [=]() -> continue_helper {
CAF_PRINT("received 'hi there'");
return self->sync_send(c0, atom("sub0")).then(
on(atom("sub0")) >> [=]() -> continue_helper {
CAF_PRINT("received 'sub0'");
return self->sync_send(c1, atom("sub1")).then(
on(atom("sub1")) >> [=]() -> continue_helper {
CAF_PRINT("received 'sub1'");
return self->sync_send(c2, atom("sub2")).then(
on(atom("sub2")) >> [=]() -> continue_helper {
CAF_PRINT("received 'sub2'");
return self->sync_send(c3, atom("sub3")).then(
on(atom("sub3")) >> [=]() -> continue_helper {
CAF_PRINT("received 'sub3'");
return self->sync_send(c4, atom("sub4")).then(
on(atom("sub4")) >> [=]() -> atom_value {
CAF_PRINT("received 'sub4'");
return atom("hiho");
}
);
}
);
}
);
}
);
}
);
}
);
}
);
{ // lifetime scope of self
scoped_actor self;
cout << "ID of main: " << self->id() << endl;
self->sync_send(master, atom("hi there")).await(
on(atom("hiho")) >> [] {
CAF_CHECKPOINT();
},
others() >> CAF_UNEXPECTED_MSG_CB_REF(self)
);
self->send_exit(master, exit_reason::user_shutdown);
}
await_all_actors_done();
}
int main() {
CAF_TEST(test_serial_reply);
test_serial_reply();
return CAF_TEST_RESULT();
}
#include "test.hpp"
#include "caf/all.hpp"
using namespace caf;
void test_simple_reply_response() {
auto s = spawn([](event_based_actor* self) -> behavior {
return (
others() >> [=]() -> message {
CAF_CHECK(self->last_dequeued() == make_message(atom("hello")));
self->quit();
return self->last_dequeued();
}
);
});
scoped_actor self;
self->send(s, atom("hello"));
self->receive(
others() >> [&] {
CAF_CHECK(self->last_dequeued() == make_message(atom("hello")));
}
);
self->await_all_other_actors_done();
}
int main() {
CAF_TEST(test_simple_reply_response);
test_simple_reply_response();
return CAF_TEST_RESULT();
}
...@@ -195,58 +195,6 @@ string behavior_test(scoped_actor& self, actor et) { ...@@ -195,58 +195,6 @@ string behavior_test(scoped_actor& self, actor et) {
return result; return result;
} }
class fixed_stack : public sb_actor<fixed_stack> {
friend class sb_actor<fixed_stack>;
size_t max_size = 10;
vector<int> data;
behavior full;
behavior filled;
behavior empty;
behavior& init_state = empty;
public:
fixed_stack(size_t max) : max_size(max) {
full = (
on(atom("push"), arg_match) >> [=](int) { /* discard */ },
on(atom("pop")) >> [=]() -> cow_tuple<atom_value, int> {
auto result = data.back();
data.pop_back();
become(filled);
return {atom("ok"), result};
}
);
filled = (
on(atom("push"), arg_match) >> [=](int what) {
data.push_back(what);
if (data.size() == max_size) become(full);
},
on(atom("pop")) >> [=]() -> cow_tuple<atom_value, int> {
auto result = data.back();
data.pop_back();
if (data.empty()) become(empty);
return {atom("ok"), result};
}
);
empty = (
on(atom("push"), arg_match) >> [=](int what) {
data.push_back(what);
become(filled);
},
on(atom("pop")) >> [=] {
return atom("failure");
}
);
}
};
behavior echo_actor(event_based_actor* self) { behavior echo_actor(event_based_actor* self) {
return ( return (
others() >> [=]() -> message { others() >> [=]() -> message {
...@@ -256,19 +204,13 @@ behavior echo_actor(event_based_actor* self) { ...@@ -256,19 +204,13 @@ behavior echo_actor(event_based_actor* self) {
); );
} }
struct simple_mirror : sb_actor<simple_mirror> { behavior simple_mirror(event_based_actor* self) {
return {
behavior init_state; others() >> [=] {
return self->last_dequeued();
simple_mirror() { }
init_state = ( };
others() >> [=]() -> message { }
return last_dequeued();
}
);
}
};
behavior high_priority_testee(event_based_actor* self) { behavior high_priority_testee(event_based_actor* self) {
self->send(self, atom("b")); self->send(self, atom("b"));
...@@ -330,171 +272,7 @@ struct slave : event_based_actor { ...@@ -330,171 +272,7 @@ struct slave : event_based_actor {
}; };
void test_serial_reply() {
auto mirror_behavior = [=](event_based_actor* self) {
self->become(others() >> [=]() -> message {
CAF_PRINT("return self->last_dequeued()");
return self->last_dequeued();
});
};
auto master = spawn([=](event_based_actor* self) {
cout << "ID of master: " << self->id() << endl;
// spawn 5 mirror actors
auto c0 = self->spawn<linked>(mirror_behavior);
auto c1 = self->spawn<linked>(mirror_behavior);
auto c2 = self->spawn<linked>(mirror_behavior);
auto c3 = self->spawn<linked>(mirror_behavior);
auto c4 = self->spawn<linked>(mirror_behavior);
self->become (
on(atom("hi there")) >> [=]() -> continue_helper {
CAF_PRINT("received 'hi there'");
return self->sync_send(c0, atom("sub0")).then(
on(atom("sub0")) >> [=]() -> continue_helper {
CAF_PRINT("received 'sub0'");
return self->sync_send(c1, atom("sub1")).then(
on(atom("sub1")) >> [=]() -> continue_helper {
CAF_PRINT("received 'sub1'");
return self->sync_send(c2, atom("sub2")).then(
on(atom("sub2")) >> [=]() -> continue_helper {
CAF_PRINT("received 'sub2'");
return self->sync_send(c3, atom("sub3")).then(
on(atom("sub3")) >> [=]() -> continue_helper {
CAF_PRINT("received 'sub3'");
return self->sync_send(c4, atom("sub4")).then(
on(atom("sub4")) >> [=]() -> atom_value {
CAF_PRINT("received 'sub4'");
return atom("hiho");
}
);
}
);
}
);
}
);
}
);
}
);
}
);
{ // lifetime scope of self
scoped_actor self;
cout << "ID of main: " << self->id() << endl;
self->sync_send(master, atom("hi there")).await(
on(atom("hiho")) >> [] {
CAF_CHECKPOINT();
},
others() >> CAF_UNEXPECTED_MSG_CB_REF(self)
);
self->send_exit(master, exit_reason::user_shutdown);
}
await_all_actors_done();
}
void test_or_else() {
scoped_actor self;
message_handler handle_a {
on("a") >> [] { return 1; }
};
message_handler handle_b {
on("b") >> [] { return 2; }
};
message_handler handle_c {
on("c") >> [] { return 3; }
};
auto run_testee([&](actor testee) {
self->sync_send(testee, "a").await([](int i) {
CAF_CHECK_EQUAL(i, 1);
});
self->sync_send(testee, "b").await([](int i) {
CAF_CHECK_EQUAL(i, 2);
});
self->sync_send(testee, "c").await([](int i) {
CAF_CHECK_EQUAL(i, 3);
});
self->send_exit(testee, exit_reason::user_shutdown);
self->await_all_other_actors_done();
});
CAF_PRINT("run_testee: handle_a.or_else(handle_b).or_else(handle_c)");
run_testee(
spawn([=] {
return handle_a.or_else(handle_b).or_else(handle_c);
})
);
CAF_PRINT("run_testee: handle_a.or_else(handle_b), on(\"c\") ...");
run_testee(
spawn([=] {
return (
handle_a.or_else(handle_b),
on("c") >> [] { return 3; }
);
})
);
CAF_PRINT("run_testee: on(\"a\") ..., handle_b.or_else(handle_c)");
run_testee(
spawn([=] {
return (
on("a") >> [] { return 1; },
handle_b.or_else(handle_c)
);
})
);
}
void test_continuation() {
auto mirror = spawn<simple_mirror>();
spawn([=](event_based_actor* self) {
self->sync_send(mirror, 42).then(
on(42) >> [] {
return "fourty-two";
}
).continue_with(
[=](const string& ref) {
CAF_CHECK_EQUAL(ref, "fourty-two");
return 4.2f;
}
).continue_with(
[=](float f) {
CAF_CHECK_EQUAL(f, 4.2f);
self->send_exit(mirror, exit_reason::user_shutdown);
self->quit();
}
);
});
await_all_actors_done();
}
void test_simple_reply_response() {
auto s = spawn([](event_based_actor* self) -> behavior {
return (
others() >> [=]() -> message {
CAF_CHECK(self->last_dequeued() == make_message(atom("hello")));
self->quit();
return self->last_dequeued();
}
);
});
scoped_actor self;
self->send(s, atom("hello"));
self->receive(
others() >> [&] {
CAF_CHECK(self->last_dequeued() == make_message(atom("hello")));
}
);
self->await_all_other_actors_done();
}
void test_spawn() { void test_spawn() {
test_simple_reply_response();
CAF_CHECKPOINT();
test_serial_reply();
CAF_CHECKPOINT();
test_or_else();
CAF_CHECKPOINT();
test_continuation();
CAF_CHECKPOINT();
scoped_actor self; scoped_actor self;
// check whether detached actors and scheduled actors interact w/o errors // check whether detached actors and scheduled actors interact w/o errors
auto m = spawn<master, detached>(); auto m = spawn<master, detached>();
...@@ -521,7 +299,7 @@ void test_spawn() { ...@@ -521,7 +299,7 @@ void test_spawn() {
CAF_CHECKPOINT(); CAF_CHECKPOINT();
CAF_PRINT("test mirror"); { CAF_PRINT("test mirror"); {
auto mirror = self->spawn<simple_mirror, monitored>(); auto mirror = self->spawn<monitored>(simple_mirror);
self->send(mirror, "hello mirror"); self->send(mirror, "hello mirror");
self->receive ( self->receive (
on("hello mirror") >> CAF_CHECKPOINT_CB(), on("hello mirror") >> CAF_CHECKPOINT_CB(),
...@@ -542,7 +320,7 @@ void test_spawn() { ...@@ -542,7 +320,7 @@ void test_spawn() {
} }
CAF_PRINT("test detached mirror"); { CAF_PRINT("test detached mirror"); {
auto mirror = self->spawn<simple_mirror, monitored+detached>(); auto mirror = self->spawn<monitored+detached>(simple_mirror);
self->send(mirror, "hello mirror"); self->send(mirror, "hello mirror");
self->receive ( self->receive (
on("hello mirror") >> CAF_CHECKPOINT_CB(), on("hello mirror") >> CAF_CHECKPOINT_CB(),
...@@ -563,7 +341,7 @@ void test_spawn() { ...@@ -563,7 +341,7 @@ void test_spawn() {
} }
CAF_PRINT("test priority aware mirror"); { CAF_PRINT("test priority aware mirror"); {
auto mirror = self->spawn<simple_mirror, monitored+priority_aware>(); auto mirror = self->spawn<monitored+priority_aware>(simple_mirror);
CAF_CHECKPOINT(); CAF_CHECKPOINT();
self->send(mirror, "hello mirror"); self->send(mirror, "hello mirror");
self->receive ( self->receive (
...@@ -624,39 +402,7 @@ void test_spawn() { ...@@ -624,39 +402,7 @@ void test_spawn() {
); );
self->await_all_other_actors_done(); self->await_all_other_actors_done();
CAF_CHECKPOINT(); CAF_CHECKPOINT();
auto st = spawn<fixed_stack>(size_t{10});
// push 20 values
for (int i = 0; i < 20; ++i) self->send(st, atom("push"), i);
// pop 20 times
for (int i = 0; i < 20; ++i) self->send(st, atom("pop"));
// expect 10 failure messages
{
int i = 0;
self->receive_for(i, 10) (
on(atom("failure")) >> CAF_CHECKPOINT_CB()
);
CAF_CHECKPOINT();
}
// expect 10 {'ok', value} messages
{
vector<int> values;
int i = 0;
self->receive_for(i, 10) (
on(atom("ok"), arg_match) >> [&](int value) {
values.push_back(value);
}
);
vector<int> expected{9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
CAF_CHECK_EQUAL(join(values, ","), join(expected, ","));
}
// terminate st
self->send_exit(st, exit_reason::user_shutdown);
self->await_all_other_actors_done();
CAF_CHECKPOINT();
CAF_PRINT("test sync send"); CAF_PRINT("test sync send");
CAF_CHECKPOINT(); CAF_CHECKPOINT();
auto sync_testee = spawn<blocking_api>([](blocking_actor* s) { auto sync_testee = spawn<blocking_api>([](blocking_actor* s) {
s->receive ( s->receive (
...@@ -875,14 +621,6 @@ void test_spawn() { ...@@ -875,14 +621,6 @@ void test_spawn() {
CAF_CHECKPOINT(); CAF_CHECKPOINT();
} }
class actor_size_getter : public event_based_actor {
public:
behavior make_behavior() override {
CAF_PRINT("size of one event-based actor: " << sizeof(*this) << " bytes");
return {};
}
};
void counting_actor(event_based_actor* self) { void counting_actor(event_based_actor* self) {
for (int i = 0; i < 100; ++i) { for (int i = 0; i < 100; ++i) {
self->send(self, atom("dummy")); self->send(self, atom("dummy"));
...@@ -894,129 +632,13 @@ void counting_actor(event_based_actor* self) { ...@@ -894,129 +632,13 @@ void counting_actor(event_based_actor* self) {
CAF_CHECK_EQUAL(self->mailbox().count(), 200); CAF_CHECK_EQUAL(self->mailbox().count(), 200);
} }
// tests attach_functor() inside of an actor's constructor
void test_constructor_attach() {
class testee : public event_based_actor {
public:
testee(actor buddy) : m_buddy(buddy) {
attach_functor([=](uint32_t reason) {
send(m_buddy, atom("done"), reason);
});
}
behavior make_behavior() {
return {
on(atom("die")) >> [=] {
quit(exit_reason::user_shutdown);
}
};
}
private:
actor m_buddy;
};
class spawner : public event_based_actor {
public:
spawner() : m_downs(0) {
}
behavior make_behavior() {
m_testee = spawn<testee, monitored>(this);
return {
[=](const down_msg& msg) {
CAF_CHECK_EQUAL(msg.reason, exit_reason::user_shutdown);
if (++m_downs == 2) {
quit(msg.reason);
}
},
on(atom("done"), arg_match) >> [=](uint32_t reason) {
CAF_CHECK_EQUAL(reason, exit_reason::user_shutdown);
if (++m_downs == 2) {
quit(reason);
}
},
others() >> [=] {
forward_to(m_testee);
}
};
}
private:
int m_downs;
actor m_testee;
};
anon_send(spawn<spawner>(), atom("die"));
}
class exception_testee : public event_based_actor {
public:
exception_testee() {
set_exception_handler([](const std::exception_ptr&) -> optional<uint32_t> {
return exit_reason::user_defined + 2;
});
}
behavior make_behavior() override {
return {
others() >> [] {
throw std::runtime_error("whatever");
}
};
}
};
void test_custom_exception_handler() {
auto handler = [](const std::exception_ptr& eptr) -> optional<uint32_t> {
try {
std::rethrow_exception(eptr);
}
catch (std::runtime_error&) {
return exit_reason::user_defined;
}
catch (...) {
// "fall through"
}
return exit_reason::user_defined + 1;
};
scoped_actor self;
auto testee1 = self->spawn<monitored>([=](event_based_actor* eb_self) {
eb_self->set_exception_handler(handler);
throw std::runtime_error("ping");
});
auto testee2 = self->spawn<monitored>([=](event_based_actor* eb_self) {
eb_self->set_exception_handler(handler);
throw std::logic_error("pong");
});
auto testee3 = self->spawn<exception_testee, monitored>();
self->send(testee3, "foo");
// receive all down messages
auto i = 0;
self->receive_for(i, 3)(
[&](const down_msg& dm) {
if (dm.source == testee1) {
CAF_CHECK_EQUAL(dm.reason, exit_reason::user_defined);
}
else if (dm.source == testee2) {
CAF_CHECK_EQUAL(dm.reason, exit_reason::user_defined + 1);
}
else if (dm.source == testee3) {
CAF_CHECK_EQUAL(dm.reason, exit_reason::user_defined + 2);
}
else {
CAF_CHECK(false); // report error
}
}
);
}
} // namespace <anonymous> } // namespace <anonymous>
int main() { int main() {
CAF_TEST(test_spawn); CAF_TEST(test_spawn);
spawn<actor_size_getter>();
await_all_actors_done();
CAF_CHECKPOINT();
spawn(counting_actor); spawn(counting_actor);
await_all_actors_done(); await_all_actors_done();
CAF_CHECKPOINT(); CAF_CHECKPOINT();
test_custom_exception_handler();
await_all_actors_done();
CAF_CHECKPOINT();
test_spawn(); test_spawn();
CAF_CHECKPOINT(); CAF_CHECKPOINT();
await_all_actors_done(); await_all_actors_done();
...@@ -1029,9 +651,6 @@ int main() { ...@@ -1029,9 +651,6 @@ int main() {
} }
await_all_actors_done(); await_all_actors_done();
CAF_CHECKPOINT(); CAF_CHECKPOINT();
test_constructor_attach();
await_all_actors_done();
CAF_CHECKPOINT();
shutdown(); shutdown();
CAF_CHECKPOINT(); CAF_CHECKPOINT();
return CAF_TEST_RESULT(); return CAF_TEST_RESULT();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment