1 module tagion.testbench.actor.taskfailure;
2 
3 import tagion.testbench.actor.util;
4 
5 // Default import list for bdd
6 import core.time;
7 import std.format : format;
8 import std.stdio;
9 import std.typecons : Tuple;
10 import tagion.actor.actor;
11 import tagion.actor.exceptions;
12 import tagion.basic.tagionexceptions;
13 import tagion.behaviour;
14 import tagion.hibon.Document;
15 import tagion.testbench.tools.Environment;
16 import tagion.utils.pretend_safe_concurrency;
17 
18 enum feature = Feature(
19             "Actor TaskFailure",
20             ["While there is no handling of that type of taskfailure resend it up to the owner."]);
21 
22 alias FeatureContext = Tuple!(
23         SendATaskFailureToAnActor, "SendATaskFailureToAnActor",
24         FeatureGroup*, "result"
25 );
26 
27 enum actor_task = "actor_task";
28 
29 @safe
30 struct MyActor {
31     void task() nothrow {
32         run();
33     }
34 }
35 
36 @safe @Scenario("Send a TaskFailure to an actor",
37         [])
38 class SendATaskFailureToAnActor {
39     ActorHandle myActor;
40 
41     @Given("an #actor")
42     Document anActor() {
43         myActor = spawn!MyActor(actor_task);
44 
45         return result_ok;
46     }
47 
48     @When("the #actor has started")
49     Document actorHasStarted() {
50         check(waitforChildren(Ctrl.ALIVE), "Actor never alived");
51         check(myActor.tid !is Tid.init, "Actor task is not running");
52 
53         return result_ok;
54     }
55 
56     @Then("send a `TaskFailure` to the actor")
57     Document toTheActor() {
58         myActor.send(TaskFailure("main", new immutable Exception("This big fail")));
59         return result_ok;
60     }
61 
62     @Then("the actor should echo it back to the main thread")
63     Document theMainThread() {
64         bool received = receiveTimeout(
65                 1.seconds,
66                 (TaskFailure tf) @safe {
67             writefln("Task failed succesfully with: %s, %s", typeid(tf.throwable), tf.throwable.msg);
68         },
69                 (Variant val) @trusted { check(0, format("Unexpected value: %s", val)); }
70         );
71         check(received, "Timed out before receiving taskfailure");
72         return result_ok;
73     }
74 
75     @Then("stop the #actor")
76     Document stopTheActor() {
77         myActor.send(Sig.STOP);
78         check(waitforChildren(Ctrl.END), "Actor never stopped");
79         return result_ok;
80     }
81 
82 }