1 module tagion.testbench.actor.handler;
2 
3 import tagion.testbench.actor.util;
4 
5 // Default import list for bdd
6 import core.time;
7 import std.stdio;
8 import std.typecons : Tuple;
9 import tagion.actor.actor;
10 import tagion.behaviour;
11 import tagion.hibon.Document;
12 import tagion.testbench.tools.Environment;
13 import tagion.utils.pretend_safe_concurrency;
14 
15 enum feature = Feature(
16             "Actor handler request",
17             ["This feature should verify that you can request a handler for an actor that you don\\'t own"]);
18 
19 alias FeatureContext = Tuple!(
20         SendAMessageToAnActorYouDontOwn, "SendAMessageToAnActorYouDontOwn",
21         FeatureGroup*, "result"
22 );
23 
24 enum child_task_name = "handle_child_task";
25 enum super_task_name = "handle_super_task";
26 
27 @safe
28 struct MyActor {
29     int status = 0;
30 
31     void setstatus(Msg!"setstatus", int i, Tid returnTid) {
32         status = i;
33         send(returnTid, "hey we received that number");
34     }
35 
36     void task() nothrow {
37         run(&setstatus);
38     }
39 }
40 
41 @safe
42 struct MySuperActor {
43     ActorHandle childHandle;
44 
45     void task() {
46         childHandle = spawn!MyActor(child_task_name);
47         waitforChildren(Ctrl.ALIVE);
48         run();
49     }
50 }
51 
52 @safe @Scenario("send a message to an actor you don't own",
53         [])
54 class SendAMessageToAnActorYouDontOwn {
55     ActorHandle super_actor_handler;
56     ActorHandle child_handler;
57 
58     @Given("a supervisor #super and one child actor #child")
59     Document actorChild() {
60         super_actor_handler = spawn!MySuperActor(super_task_name);
61 
62         check(waitforChildren(Ctrl.ALIVE), "Supervisor did not alive");
63         return result_ok;
64     }
65 
66     @When("#we request the handler for #child")
67     Document forChild() {
68         child_handler = ActorHandle(child_task_name);
69         check(child_handler.tid !is Tid.init, "Child task was not running");
70         return result_ok;
71     }
72 
73     @When("#we send a message to #child")
74     Document toChild() {
75         child_handler.send(Msg!"setstatus"(), 42, thisTid);
76         return result_ok;
77     }
78 
79     @When("#we receive confirmation that shild has received the message.")
80     Document theMessage() {
81         string message = receiveOnlyTimeout!string;
82 
83         check(message !is string.init, "Never got the confirmation from the child");
84         writeln(message);
85         return result_ok;
86     }
87 
88     @Then("stop the #super")
89     Document theSuper() {
90         super_actor_handler.send(Sig.STOP);
91         check(waitforChildren(Ctrl.END), "Child did not end");
92         return result_ok;
93     }
94 
95 }