1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
#include <mbgl/actor/actor.hpp>
#include <mbgl/actor/scheduler.hpp>
#include <mbgl/test/util.hpp>
#include <future>
using namespace mbgl;
TEST(ActorRef, CanOutliveActor) {
// An ActorRef can outlive its actor. Doing does not extend the actor's lifetime.
// Sending a message to an ActorRef whose actor has died is a no-op.
struct TestActorRef {
bool& died;
TestActorRef(ActorRef<TestActorRef>, bool& died_) : died(died_) {}
~TestActorRef() { died = true; }
void receive() {
FAIL();
}
};
bool died = false;
ActorRef<TestActorRef> test = [&]() {
return Actor<TestActorRef>(Scheduler::GetBackground(), std::ref(died)).self();
}();
EXPECT_TRUE(died);
test.invoke(&TestActorRef::receive);
}
TEST(ActorRef, Ask) {
// Ask returns a Future eventually returning the result
struct TestActorRef {
TestActorRef(ActorRef<TestActorRef>) {}
int gimme() {
return 20;
}
int echo(int i) {
return i;
}
};
Actor<TestActorRef> actor(Scheduler::GetBackground());
ActorRef<TestActorRef> ref = actor.self();
EXPECT_EQ(20, ref.ask(&TestActorRef::gimme).get());
EXPECT_EQ(30, ref.ask(&TestActorRef::echo, 30).get());
}
TEST(ActorRef, AskVoid) {
// Ask waits for void methods
struct TestActorRef {
bool& executed;
TestActorRef(bool& executed_) : executed(executed_) {}
void doIt() {
executed = true;
}
};
bool executed = false;
Actor<TestActorRef> actor(Scheduler::GetBackground(), executed);
ActorRef<TestActorRef> ref = actor.self();
ref.ask(&TestActorRef::doIt).get();
EXPECT_TRUE(executed);
}
TEST(ActorRef, AskOnDestroyedActor) {
// Tests behavior when calling ask() after the
// Actor has gone away. Should set a exception_ptr.
struct TestActorRef {
bool& died;
TestActorRef(ActorRef<TestActorRef>, bool& died_) : died(died_) {}
~TestActorRef() { died = true; }
int receive() {
return 1;
}
};
bool died = false;
auto actor = std::make_unique<Actor<TestActorRef>>(Scheduler::GetBackground(), died);
ActorRef<TestActorRef> ref = actor->self();
actor.reset();
EXPECT_TRUE(died);
auto result = ref.ask(&TestActorRef::receive);
EXPECT_ANY_THROW(result.get());
}
|