Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Use Simgrid macro to get cleaner enums
[simgrid.git] / teshsuite / s4u / comm-fault-scenarios / comm-fault-scenarios.cpp
1 /* Copyright (c) 2010-2021. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 /* This example validates the behaviour in presence of node and link fault.
7  * Each test scenario consists in one host/actor (named sender) sending one message to another host/actor.
8  * The space to cover is quite large, since we consider:
9  * * communication types (eager, rendez-vous, one-sided=detached)
10  * * use type (synchronous, asynchronous, init)
11  * * fault type (sender node, link, receiver node)
12  * * any legal permutation of the scenario steps
13  *
14  * This program also presents a way to simulate applications that are resilient to links and node faults.
15  * Essentially, it catches exceptions related to communications and it clears the mailboxes when one of the nodes gets
16  * turned off. However, this model would suppose that there would be 2 mailboxes for each pair of nodes, which is
17  * probably unacceptable.
18  *
19  */
20
21 #include <algorithm>
22 #include <random>
23 #include <simgrid/kernel/ProfileBuilder.hpp>
24 #include <simgrid/s4u.hpp>
25 #include <sstream>
26 #include <time.h>
27 #include <vector>
28
29 namespace sg4 = simgrid::s4u;
30 namespace pr  = simgrid::kernel::profile;
31
32 XBT_LOG_NEW_DEFAULT_CATEGORY(comm_fault_scenarios, "Messages specific for this s4u example");
33
34 /*************************************************************************************************/
35
36 // Constants for platform configuration
37 constexpr double HostComputePower = 1e9;  // FLOPs
38 constexpr double LinkBandwidth    = 1e9;  // Bytes/second
39 constexpr double LinkLatency      = 1e-6; // Seconds
40
41 // Constants for application behaviour
42 constexpr uint64_t MsgSize = LinkBandwidth / 2;
43
44 /*************************************************************************************************/
45
46 XBT_DECLARE_ENUM_CLASS(CommType, EAGER_SYNC, EAGER_ASYNC, EAGER_INIT, RDV_SYNC, RDV_ASYNC, RDV_INIT, ONESIDE_SYNC,
47                        ONESIDE_ASYNC
48                        // ONESIDE_INIT is equivalent to ONESIDE_ASYNC
49 );
50
51 XBT_DECLARE_ENUM_CLASS(Action, SLEEP, PUT, GET, START, WAIT, DIE, END);
52
53 struct Step {
54   double rel_time; // Time relative to Scenario startTime
55   enum { STATE, ACTION } type;
56   enum { LNK, SND, RCV } entity;
57   Action action_type;
58   bool new_state;
59 };
60
61 struct Scenario {
62   CommType type;
63   double start_time;
64   double duration;
65   Action snd_expected;
66   Action rcv_expected;
67   std::vector<Step> steps;
68   int index;
69 };
70
71 static std::string to_string(const Scenario& s)
72 {
73   std::stringstream ss;
74   ss << "#" << s.index << "[" << s.start_time << "s," << s.start_time + s.duration << "s[: (" << to_c_str(s.type);
75   ss << ") Expected: S:" << to_c_str(s.snd_expected) << " R:" << to_c_str(s.rcv_expected) << " Steps: ";
76   for (const Step& step : s.steps) {
77     ss << "+" << step.rel_time << "s:";
78     switch (step.entity) {
79       case Step::LNK:
80         ss << "LNK";
81         break;
82       case Step::SND:
83         ss << "SND";
84         break;
85       case Step::RCV:
86         ss << "RCV";
87         break;
88     }
89
90     if (step.type == Step::STATE) {
91       ss << "->";
92       if (step.new_state)
93         ss << "ON";
94       else
95         ss << "OFF";
96     } else {
97       ss << "." << to_c_str(step.action_type);
98     }
99     ss << " ";
100   }
101   return ss.str().c_str();
102 }
103
104 struct ScenarioContext {
105   int index;
106   int active;
107   double start_time;
108   std::stringstream sender_profile;
109   std::stringstream receiver_profile;
110   std::stringstream link_profile;
111   std::vector<int> active_indices;
112   std::vector<Scenario> scenarios;
113 };
114
115 sg4::Mailbox* mbox_eager = nullptr;
116 sg4::Mailbox* mbox_rdv   = nullptr;
117
118 class SendAgent {
119
120   static int run_;
121   static size_t scenario_;
122   int id_;
123   sg4::Host* other_host_;
124   const ScenarioContext& ctx_;
125
126   sg4::CommPtr do_put(CommType type, double& send_value)
127   {
128     switch (type) {
129       case CommType::EAGER_SYNC:
130         mbox_eager->put(&send_value, MsgSize);
131         return nullptr;
132       case CommType::EAGER_ASYNC:
133         return mbox_eager->put_async(&send_value, MsgSize);
134       case CommType::EAGER_INIT:
135         return mbox_eager->put_init(&send_value, MsgSize);
136       case CommType::RDV_SYNC:
137         mbox_rdv->put(&send_value, MsgSize);
138         return nullptr;
139       case CommType::RDV_ASYNC:
140         return mbox_rdv->put_async(&send_value, MsgSize);
141       case CommType::RDV_INIT:
142         return mbox_rdv->put_init(&send_value, MsgSize);
143       case CommType::ONESIDE_SYNC:
144         sg4::Comm::sendto(sg4::this_actor::get_host(), other_host_, MsgSize);
145         return nullptr;
146       case CommType::ONESIDE_ASYNC:
147         return sg4::Comm::sendto_async(sg4::this_actor::get_host(), other_host_, MsgSize);
148     }
149     return nullptr;
150   }
151
152   void send_message(const Scenario& s)
153   {
154     std::string scenario_string = to_string(s);
155     XBT_DEBUG("Will try: %s", scenario_string.c_str());
156     double send_value;
157     sg4::CommPtr comm = nullptr;
158     Action expected   = s.snd_expected;
159     double end_time   = s.start_time + s.duration;
160     send_value        = end_time;
161     size_t step_index = 0;
162     sg4::this_actor::sleep_until(s.start_time);
163     // Make sure we have a clean slate
164     xbt_assert(not mbox_eager->listen(), "Eager mailbox should be empty when starting a test");
165     xbt_assert(not mbox_rdv->listen(), "RDV mailbox should be empty when starting a test");
166     for (; step_index < s.steps.size(); step_index++) {
167       const Step& step = s.steps[step_index];
168       if (step.entity != Step::SND || step.type != Step::ACTION)
169         continue;
170       try {
171         sg4::this_actor::sleep_until(s.start_time + step.rel_time);
172       } catch (std::exception& e) {
173         XBT_DEBUG("During Sleep, failed to send message because of a %s exception (%s)", typeid(e).name(), e.what());
174         break;
175       }
176       // Check if the other host is still OK.
177       if (not other_host_->is_on())
178         break;
179       // Perform the action
180       try {
181         switch (step.action_type) {
182           case Action::PUT:
183             comm = do_put(s.type, send_value);
184             break;
185           case Action::START:
186             comm->start();
187             break;
188           case Action::WAIT:
189             comm->wait();
190             break;
191           default:
192             xbt_die("Not a valid action for SND");
193         }
194       } catch (std::exception& e) {
195         XBT_DEBUG("During %s, failed to send message because of a %s exception (%s)", to_c_str(step.action_type),
196                   typeid(e).name(), e.what());
197         break;
198       }
199     }
200     try {
201       sg4::this_actor::sleep_until(end_time);
202     } catch (std::exception& e) {
203       XBT_DEBUG("During Sleep, failed to send message because of a %s exception (%s)", typeid(e).name(), e.what());
204     }
205     Action outcome = Action::END;
206     if (step_index < s.steps.size()) {
207       const Step& step = s.steps[step_index];
208       assert(step.entity == Step::SND && step.type == Step::ACTION);
209       outcome = step.action_type;
210     }
211     if (outcome != expected) {
212       XBT_ERROR("Expected %s but got %s in %s", to_c_str(expected), to_c_str(outcome), scenario_string.c_str());
213     } else {
214       XBT_DEBUG("OK: %s", scenario_string.c_str());
215     }
216     sg4::this_actor::sleep_until(end_time);
217     xbt_assert(not mbox_eager->listen(), "Mailbox should not have ongoing communication!");
218     xbt_assert(not mbox_rdv->listen(), "Mailbox should not have ongoing communication!");
219   }
220
221 public:
222   explicit SendAgent(int id, sg4::Host* other_host, const ScenarioContext& ctx)
223       : id_(id), other_host_(other_host), ctx_(ctx)
224   {
225   }
226
227   void operator()()
228   {
229     run_++;
230     XBT_DEBUG("Host %i starts run %i and scenario %lu.", id_, run_, scenario_);
231     while (scenario_ < ctx_.scenarios.size()) {
232       const Scenario& s = ctx_.scenarios[scenario_];
233       scenario_++;
234       send_message(s);
235     }
236   }
237 };
238
239 int SendAgent::run_         = 0;
240 size_t SendAgent::scenario_ = 0;
241
242 /*************************************************************************************************/
243
244 class ReceiveAgent {
245
246   static int run_;
247   static size_t scenario_;
248   int id_;
249   sg4::Host* other_host_;
250   const ScenarioContext& ctx_;
251
252   sg4::CommPtr do_get(CommType type, double*& receive_ptr)
253   {
254     switch (type) {
255       case CommType::EAGER_SYNC:
256         receive_ptr = mbox_eager->get<double>();
257         return nullptr;
258       case CommType::EAGER_ASYNC:
259         return mbox_eager->get_async(&receive_ptr);
260       case CommType::EAGER_INIT:
261         return mbox_eager->get_init()->set_dst_data((void**)(&receive_ptr));
262       case CommType::RDV_SYNC:
263         receive_ptr = mbox_rdv->get<double>();
264         return nullptr;
265       case CommType::RDV_ASYNC:
266         return mbox_rdv->get_async(&receive_ptr);
267       case CommType::RDV_INIT:
268         return mbox_rdv->get_init()->set_dst_data((void**)(&receive_ptr));
269       case CommType::ONESIDE_SYNC:
270       case CommType::ONESIDE_ASYNC:
271         xbt_die("No get in One Sided comunications!");
272     }
273     return nullptr;
274   }
275
276   void receive_message(const Scenario& s)
277   {
278     sg4::CommPtr comm   = nullptr;
279     CommType type       = s.type;
280     Action expected     = s.rcv_expected;
281     double end_time     = s.start_time + s.duration;
282     double* receive_ptr = nullptr;
283     size_t step_index   = 0;
284     sg4::this_actor::sleep_until(s.start_time);
285     // Make sure we have a clean slate
286     xbt_assert(not mbox_eager->listen(), "Eager mailbox should be empty when starting a test");
287     xbt_assert(not mbox_rdv->listen(), "RDV mailbox should be empty when starting a test");
288     for (; step_index < s.steps.size(); step_index++) {
289       const Step& step = s.steps[step_index];
290       if (step.entity != Step::RCV || step.type != Step::ACTION)
291         continue;
292       try {
293         sg4::this_actor::sleep_until(s.start_time + step.rel_time);
294       } catch (std::exception& e) {
295         XBT_DEBUG("During Sleep, failed to receive message because of a %s exception (%s)", typeid(e).name(), e.what());
296         break;
297       }
298       // Check if the other host is still OK.
299       if (not other_host_->is_on())
300         break;
301       // Perform the action
302       try {
303         switch (step.action_type) {
304           case Action::GET:
305             comm = do_get(type, receive_ptr);
306             break;
307           case Action::START:
308             comm->start();
309             break;
310           case Action::WAIT:
311             comm->wait();
312             break;
313           default:
314             xbt_die("Not a valid action for RCV");
315         }
316       } catch (std::exception& e) {
317         XBT_DEBUG("During %s, failed to receive message because of a %s exception (%s)", to_c_str(step.action_type),
318                   typeid(e).name(), e.what());
319         break;
320       }
321     }
322     try {
323       sg4::this_actor::sleep_until(end_time - .1);
324     } catch (std::exception& e) {
325       XBT_DEBUG("During Sleep, failed to send message because of a %s exception (%s)", typeid(e).name(), e.what());
326     }
327     Action outcome              = Action::END;
328     std::string scenario_string = to_string(s);
329     if (step_index < s.steps.size()) {
330       const Step& step = s.steps[step_index];
331       assert(step.entity == Step::RCV && step.type == Step::ACTION);
332       outcome = step.action_type;
333     } else if (s.type != CommType::ONESIDE_SYNC && s.type != CommType::ONESIDE_ASYNC) {
334       // One sided / detached operations do not actually transfer anything
335       if (receive_ptr == nullptr) {
336         XBT_ERROR("Received address is NULL in %s", scenario_string.c_str());
337       } else if (*receive_ptr != end_time) {
338         XBT_ERROR("Received value invalid: expected %f but got %f in %s", end_time, *receive_ptr,
339                   scenario_string.c_str());
340       }
341     }
342     if (outcome != expected) {
343       XBT_ERROR("Expected %s but got %s in %s", to_c_str(expected), to_c_str(outcome), scenario_string.c_str());
344     } else {
345       XBT_DEBUG("OK: %s", scenario_string.c_str());
346     }
347     sg4::this_actor::sleep_until(end_time);
348     xbt_assert(not mbox_eager->listen(), "Mailbox should not have ongoing communication!");
349     xbt_assert(not mbox_rdv->listen(), "Mailbox should not have ongoing communication!");
350   }
351
352 public:
353   explicit ReceiveAgent(int id, sg4::Host* other_host, const ScenarioContext& ctx)
354       : id_(id), other_host_(other_host), ctx_(ctx)
355   {
356   }
357   void operator()()
358   {
359     run_++;
360     XBT_DEBUG("Host %i starts run %i and scenario %lu.", id_, run_, scenario_);
361     mbox_eager->set_receiver(sg4::Actor::self());
362     while (scenario_ < ctx_.scenarios.size()) {
363       const Scenario& s = ctx_.scenarios[scenario_];
364       scenario_++;
365       receive_message(s);
366     }
367   }
368 };
369
370 int ReceiveAgent::run_         = 0;
371 size_t ReceiveAgent::scenario_ = 0;
372
373 static void on_host_state_change(sg4::Host const& host)
374 {
375   XBT_DEBUG("Host %s is now %s", host.get_cname(), host.is_on() ? "ON " : "OFF");
376   if (not host.is_on()) {
377     mbox_eager->clear();
378     mbox_rdv->clear();
379   }
380 }
381
382 static void on_link_state_change(sg4::Link const& link)
383 {
384   XBT_DEBUG("Link %s is now %s", link.get_cname(), link.is_on() ? "ON " : "OFF");
385 }
386
387 double build_scenarios(ScenarioContext& ctx);
388
389 int main(int argc, char* argv[])
390 {
391   sg4::Engine e(&argc, argv);
392   ScenarioContext ctx;
393   int previous_index = -1;
394   bool is_range_last = false;
395   for (int i = 1; i < argc; i++) {
396     if (not strcmp(argv[i], "-"))
397       is_range_last = true;
398     else {
399       int index = atoi(argv[i]);
400       xbt_assert(index > previous_index);
401       if (is_range_last)
402         for (int j = previous_index + 1; j <= index; j++)
403           ctx.active_indices.push_back(j);
404       else
405         ctx.active_indices.push_back(index);
406       is_range_last  = false;
407       previous_index = index;
408     }
409   }
410   double end_time = build_scenarios(ctx);
411   XBT_INFO("Will run for %f seconds", end_time);
412   mbox_eager                  = e.mailbox_by_name_or_create("eager");
413   mbox_rdv                    = e.mailbox_by_name_or_create("rdv");
414   sg4::NetZone* zone          = sg4::create_full_zone("Top");
415   pr::Profile* profile_sender = pr::ProfileBuilder::from_string("sender_profile", ctx.sender_profile.str(), 0);
416   sg4::Host* sender_host = zone->create_host("senderHost", HostComputePower)->set_state_profile(profile_sender)->seal();
417   pr::Profile* profile_receiver = pr::ProfileBuilder::from_string("receiver_profile", ctx.receiver_profile.str(), 0);
418   sg4::Host* receiver_host =
419       zone->create_host("receiverHost", HostComputePower)->set_state_profile(profile_receiver)->seal();
420   sg4::ActorPtr sender = sg4::Actor::create("sender", sender_host, SendAgent(0, receiver_host, ctx));
421   sender->set_auto_restart(true);
422   sg4::ActorPtr receiver = sg4::Actor::create("receiver", receiver_host, ReceiveAgent(1, sender_host, ctx));
423   receiver->set_auto_restart(true);
424   pr::Profile* profile_link = pr::ProfileBuilder::from_string("link_profile", ctx.link_profile.str(), 0);
425   sg4::Link* link =
426       zone->create_link("link", LinkBandwidth)->set_latency(LinkLatency)->set_state_profile(profile_link)->seal();
427   zone->add_route(sender_host->get_netpoint(), receiver_host->get_netpoint(), nullptr, nullptr,
428                   {sg4::LinkInRoute{link}}, false);
429   zone->seal();
430   sg4::Host::on_state_change.connect(on_host_state_change);
431   sg4::Link::on_state_change_cb(on_link_state_change);
432   e.run_until(end_time);
433
434   // Make sure we have a clean slate
435   xbt_assert(not mbox_eager->listen(), "Eager mailbox should be empty in the end");
436   xbt_assert(not mbox_rdv->listen(), "RDV mailbox should be empty in the end");
437   XBT_INFO("Done.");
438   return 0;
439 }
440
441 static void addStateEvent(std::ostream& out, double date, bool isOn)
442 {
443   if (isOn)
444     out << date << " 1\n";
445   else
446     out << date << " 0\n";
447 }
448
449 static void prepareScenario(ScenarioContext& ctx, CommType type, double duration, Action sender_expected,
450                             Action receiver_expected, std::vector<Step> steps)
451 {
452   if (std::find(ctx.active_indices.begin(), ctx.active_indices.end(), ctx.index) != ctx.active_indices.end()) {
453     // Update fault profiles
454     for (Step& step : steps) {
455       assert(step.rel_time < duration);
456       if (step.type != Step::STATE)
457         continue;
458       int val = step.new_state ? 1 : 0;
459       switch (step.entity) {
460         case Step::SND:
461           ctx.sender_profile << ctx.start_time + step.rel_time << " " << val << std::endl;
462           break;
463         case Step::RCV:
464           ctx.receiver_profile << ctx.start_time + step.rel_time << " " << val << std::endl;
465           break;
466         case Step::LNK:
467           ctx.link_profile << ctx.start_time + step.rel_time << " " << val << std::endl;
468           break;
469       }
470     }
471     ctx.scenarios.push_back({type, ctx.start_time, duration, sender_expected, receiver_expected, steps, ctx.index});
472     ctx.active++;
473   }
474   ctx.index++;
475   ctx.start_time += duration;
476 }
477
478 /*************************************************************************************************/
479
480 // A bunch of dirty macros to help readability (supposedly)
481 #define MAKE_SCENARIO(type, duration, snd_expected, rcv_expected, steps...)                                            \
482   prepareScenario(ctx, CommType::type, duration, Action::snd_expected, Action::rcv_expected, {steps})
483
484 // Link
485 static Step loff(double rel_time)
486 {
487   return {rel_time, Step::STATE, Step::LNK, Action::END, false};
488 }
489 static Step lon(double rel_time)
490 {
491   return {rel_time, Step::STATE, Step::LNK, Action::END, true};
492 }
493 // Sender
494 static Step soff(double rel_time)
495 {
496   return {rel_time, Step::STATE, Step::SND, Action::END, false};
497 }
498 static Step son(double rel_time)
499 {
500   return {rel_time, Step::STATE, Step::SND, Action::END, true};
501 }
502 static Step sput(double rel_time)
503 {
504   return {rel_time, Step::ACTION, Step::SND, Action::PUT, false};
505 }
506 static Step swait(double rel_time)
507 {
508   return {rel_time, Step::ACTION, Step::SND, Action::WAIT, false};
509 }
510 // Receiver
511 static Step roff(double rel_time)
512 {
513   return {rel_time, Step::STATE, Step::RCV, Action::END, false};
514 }
515 static Step ron(double rel_time)
516 {
517   return {rel_time, Step::STATE, Step::RCV, Action::END, true};
518 }
519 static Step rget(double rel_time)
520 {
521   return {rel_time, Step::ACTION, Step::RCV, Action::GET, false};
522 }
523 static Step rwait(double rel_time)
524 {
525   return {rel_time, Step::ACTION, Step::RCV, Action::WAIT, false};
526 }
527
528 double build_scenarios(ScenarioContext& ctx)
529 {
530   ctx.start_time = 0;
531   ctx.index      = 0;
532   ctx.active     = 0;
533
534   // EAGER SYNC use cases
535   // All good
536   MAKE_SCENARIO(EAGER_SYNC, 1, END, END, sput(.2), rget(.4));
537   MAKE_SCENARIO(EAGER_SYNC, 1, END, END, rget(.2), sput(.4));
538   // Receiver off
539   MAKE_SCENARIO(EAGER_SYNC, 2, PUT, DIE, roff(.1), sput(.2), ron(1));
540   MAKE_SCENARIO(EAGER_SYNC, 2, PUT, DIE, sput(.2), roff(.3), ron(1));
541   MAKE_SCENARIO(EAGER_SYNC, 2, PUT, DIE, sput(.2), rget(.4), roff(.5), ron(1));
542   MAKE_SCENARIO(EAGER_SYNC, 2, PUT, DIE, rget(.2), sput(.4), roff(.5), ron(1));
543   // Sender off
544   MAKE_SCENARIO(EAGER_SYNC, 2, DIE, GET, sput(.2), soff(.3), rget(.4), son(1));
545   MAKE_SCENARIO(EAGER_SYNC, 2, DIE, GET, sput(.2), rget(.4), soff(.5), son(1));
546   // Link off
547   MAKE_SCENARIO(EAGER_SYNC, 2, PUT, GET, loff(.1), sput(.2), rget(.4), lon(1));
548   MAKE_SCENARIO(EAGER_SYNC, 2, PUT, GET, sput(.2), loff(.3), rget(.4), lon(1));
549   MAKE_SCENARIO(EAGER_SYNC, 2, PUT, GET, sput(.2), rget(.4), loff(.5), lon(1));
550   MAKE_SCENARIO(EAGER_SYNC, 2, PUT, GET, loff(.1), rget(.2), sput(.4), lon(1));
551   MAKE_SCENARIO(EAGER_SYNC, 2, PUT, GET, rget(.2), loff(.3), sput(.4), lon(1));
552   MAKE_SCENARIO(EAGER_SYNC, 2, PUT, GET, rget(.2), sput(.4), loff(.5), lon(1));
553
554   // EAGER ASYNC use cases
555   // All good
556   MAKE_SCENARIO(EAGER_ASYNC, 2, END, END, sput(.2), swait(.4), rget(.6), rwait(.8));
557   MAKE_SCENARIO(EAGER_ASYNC, 2, END, END, sput(.2), rget(.4), swait(.6), rwait(.8));
558   MAKE_SCENARIO(EAGER_ASYNC, 2, END, END, sput(.2), rget(.4), rwait(.6), swait(.8));
559   MAKE_SCENARIO(EAGER_ASYNC, 2, END, END, rget(.2), sput(.4), swait(.6), rwait(.8));
560   MAKE_SCENARIO(EAGER_ASYNC, 2, END, END, rget(.2), sput(.4), rwait(.6), swait(.8));
561   MAKE_SCENARIO(EAGER_ASYNC, 2, END, END, rget(.2), rwait(.4), sput(.6), swait(.8));
562   // Receiver off
563   MAKE_SCENARIO(EAGER_ASYNC, 2, PUT, DIE, roff(.1), sput(.2), swait(.4), ron(1));
564   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, DIE, sput(.2), roff(.3), swait(.4), ron(1));
565   MAKE_SCENARIO(EAGER_ASYNC, 2, PUT, DIE, rget(.2), roff(.3), sput(.4), swait(.6), ron(1));
566   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, DIE, sput(.2), swait(.4), roff(.5), ron(1));
567   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, DIE, sput(.2), rget(.4), roff(.5), swait(.6), ron(1));
568   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, DIE, rget(.2), sput(.4), roff(.5), swait(.6), ron(1));
569   MAKE_SCENARIO(EAGER_ASYNC, 2, PUT, DIE, rget(.2), rwait(.4), roff(.5), sput(.6), swait(.8), ron(1));
570   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, DIE, sput(.2), swait(.4), rget(.6), roff(.7), ron(1));
571   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, DIE, sput(.2), rget(.4), swait(.6), roff(.7), ron(1));
572   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, DIE, sput(.2), rget(.4), rwait(.6), roff(.7), swait(.8), ron(1));
573   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, DIE, rget(.2), sput(.4), swait(.6), roff(.7), ron(1));
574   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, DIE, rget(.2), sput(.4), rwait(.6), roff(.7), swait(.8), ron(1));
575   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, DIE, rget(.2), rwait(.4), sput(.6), roff(.7), swait(.8), ron(1));
576   // Sender off (only cases where sender did put, because otherwise receiver cannot find out there was a fault)
577   MAKE_SCENARIO(EAGER_ASYNC, 2, DIE, GET, sput(.2), soff(.3), rget(.4), rwait(.6), son(1));
578   MAKE_SCENARIO(EAGER_ASYNC, 2, DIE, WAIT, rget(.2), sput(.4), soff(.5), rwait(.6), son(1));
579   MAKE_SCENARIO(EAGER_ASYNC, 2, DIE, WAIT, sput(.2), rget(.4), soff(.5), rwait(.6), son(1));
580   MAKE_SCENARIO(EAGER_ASYNC, 2, DIE, GET, sput(.2), swait(.4), soff(.5), rget(.6), rwait(.8), son(1));
581   MAKE_SCENARIO(EAGER_ASYNC, 2, DIE, WAIT, rget(.2), rwait(.4), sput(.6), soff(.7), son(1));
582   MAKE_SCENARIO(EAGER_ASYNC, 2, DIE, WAIT, rget(.2), sput(.4), rwait(.6), soff(.7), son(1));
583   MAKE_SCENARIO(EAGER_ASYNC, 2, DIE, WAIT, rget(.2), sput(.4), swait(.6), soff(.7), rwait(.8), son(1));
584   MAKE_SCENARIO(EAGER_ASYNC, 2, DIE, WAIT, sput(.2), rget(.4), rwait(.6), soff(.7), son(1));
585   MAKE_SCENARIO(EAGER_ASYNC, 2, DIE, WAIT, sput(.2), rget(.4), swait(.6), soff(.7), rwait(.8), son(1));
586   MAKE_SCENARIO(EAGER_ASYNC, 2, DIE, WAIT, sput(.2), swait(.4), rget(.6), soff(.7), rwait(.8), son(1));
587   // Link off
588   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, loff(.1), sput(.2), swait(.4), rget(.6), rwait(.8), lon(1));
589   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, loff(.1), sput(.2), rget(.4), swait(.6), rwait(.8), lon(1));
590   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, loff(.1), sput(.2), rget(.4), rwait(.6), swait(.8), lon(1));
591   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, loff(.1), rget(.2), sput(.4), swait(.6), rwait(.8), lon(1));
592   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, loff(.1), rget(.2), sput(.4), rwait(.6), swait(.8), lon(1));
593   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, loff(.1), rget(.2), rwait(.4), sput(.6), swait(.8), lon(1));
594   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, sput(.2), loff(.3), swait(.4), rget(.6), rwait(.8), lon(1));
595   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, sput(.2), loff(.3), rget(.4), swait(.6), rwait(.8), lon(1));
596   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, sput(.2), loff(.3), rget(.4), rwait(.6), swait(.8), lon(1));
597   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, rget(.2), loff(.3), sput(.4), swait(.6), rwait(.8), lon(1));
598   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, rget(.2), loff(.3), sput(.4), rwait(.6), swait(.8), lon(1));
599   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, rget(.2), loff(.3), rwait(.4), sput(.6), swait(.8), lon(1));
600   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, sput(.2), swait(.4), loff(.5), rget(.6), rwait(.8), lon(1));
601   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, sput(.2), rget(.4), loff(.5), swait(.6), rwait(.8), lon(1));
602   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, sput(.2), rget(.4), loff(.5), rwait(.6), swait(.8), lon(1));
603   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, rget(.2), sput(.4), loff(.5), swait(.6), rwait(.8), lon(1));
604   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, rget(.2), sput(.4), loff(.5), rwait(.6), swait(.8), lon(1));
605   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, rget(.2), rwait(.4), loff(.5), sput(.6), swait(.8), lon(1));
606   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, sput(.2), swait(.4), rget(.6), loff(.7), rwait(.8), lon(1));
607   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, sput(.2), rget(.4), swait(.6), loff(.7), rwait(.8), lon(1));
608   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, sput(.2), rget(.4), rwait(.6), loff(.7), swait(.8), lon(1));
609   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, rget(.2), sput(.4), swait(.6), loff(.7), rwait(.8), lon(1));
610   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, rget(.2), sput(.4), rwait(.6), loff(.7), swait(.8), lon(1));
611   MAKE_SCENARIO(EAGER_ASYNC, 2, WAIT, WAIT, rget(.2), rwait(.4), sput(.6), loff(.7), swait(.8), lon(1));
612
613   // RDV SYNC use cases
614   // All good
615   MAKE_SCENARIO(RDV_SYNC, 1, END, END, sput(.2), rget(.4));
616   MAKE_SCENARIO(RDV_SYNC, 1, END, END, rget(.2), sput(.4));
617   // Receiver off
618   MAKE_SCENARIO(RDV_SYNC, 2, PUT, DIE, roff(.1), sput(.2), ron(1));
619   MAKE_SCENARIO(RDV_SYNC, 2, PUT, DIE, sput(.2), roff(.3),
620                 ron(1)); // Fails because put comm cancellation does not trigger sender exception
621   MAKE_SCENARIO(RDV_SYNC, 2, PUT, DIE, sput(.2), rget(.4), roff(.5), ron(1));
622   MAKE_SCENARIO(RDV_SYNC, 2, PUT, DIE, rget(.2), sput(.4), roff(.5), ron(1));
623   // Sender off
624   MAKE_SCENARIO(RDV_SYNC, 2, DIE, GET, sput(.2), rget(.4), soff(.5), son(1));
625   // Link off
626   MAKE_SCENARIO(RDV_SYNC, 2, PUT, GET, loff(.1), sput(.2), rget(.4), lon(1));
627   MAKE_SCENARIO(RDV_SYNC, 2, PUT, GET, sput(.2), loff(.3), rget(.4), lon(1));
628   MAKE_SCENARIO(RDV_SYNC, 2, PUT, GET, sput(.2), rget(.4), loff(.5), lon(1));
629   MAKE_SCENARIO(RDV_SYNC, 2, PUT, GET, loff(.1), rget(.2), sput(.4), lon(1));
630   MAKE_SCENARIO(RDV_SYNC, 2, PUT, GET, rget(.2), loff(.3), sput(.4), lon(1));
631   MAKE_SCENARIO(RDV_SYNC, 2, PUT, GET, rget(.2), sput(.4), loff(.5), lon(1));
632
633   // RDV ASYNC use cases
634   // All good
635   MAKE_SCENARIO(RDV_ASYNC, 2, END, END, sput(.2), swait(.4), rget(.6), rwait(.8));
636   MAKE_SCENARIO(RDV_ASYNC, 2, END, END, sput(.2), rget(.4), swait(.6), rwait(.8));
637   MAKE_SCENARIO(RDV_ASYNC, 2, END, END, sput(.2), rget(.4), rwait(.6), swait(.8));
638   MAKE_SCENARIO(RDV_ASYNC, 2, END, END, rget(.2), sput(.4), swait(.6), rwait(.8));
639   MAKE_SCENARIO(RDV_ASYNC, 2, END, END, rget(.2), sput(.4), rwait(.6), swait(.8));
640   MAKE_SCENARIO(RDV_ASYNC, 2, END, END, rget(.2), rwait(.4), sput(.6), swait(.8));
641   // Receiver off
642   MAKE_SCENARIO(RDV_ASYNC, 2, PUT, DIE, roff(.1), sput(.2), swait(.4), ron(1));
643   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, DIE, sput(.2), roff(.3), swait(.4), ron(1));
644   MAKE_SCENARIO(RDV_ASYNC, 2, PUT, DIE, rget(.2), roff(.3), sput(.4), swait(.6), ron(1));
645   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, DIE, sput(.2), swait(.4), roff(.5),
646                 ron(1)); // Fails because put comm cancellation does not trigger sender exception
647   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, DIE, sput(.2), rget(.4), roff(.5), swait(.6), ron(1));
648   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, DIE, rget(.2), sput(.4), roff(.5), swait(.6), ron(1));
649   MAKE_SCENARIO(RDV_ASYNC, 2, PUT, DIE, rget(.2), rwait(.4), roff(.5), sput(.6), swait(.8), ron(1));
650   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, DIE, sput(.2), swait(.4), rget(.6), roff(.7), ron(1));
651   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, DIE, sput(.2), rget(.4), swait(.6), roff(.7), ron(1));
652   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, DIE, sput(.2), rget(.4), rwait(.6), roff(.7), swait(.8), ron(1));
653   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, DIE, rget(.2), sput(.4), swait(.6), roff(.7), ron(1));
654   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, DIE, rget(.2), sput(.4), rwait(.6), roff(.7), swait(.8), ron(1));
655   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, DIE, rget(.2), rwait(.4), sput(.6), roff(.7), swait(.8), ron(1));
656   // Sender off (only cases where sender did put, because otherwise receiver cannot find out there was a fault)
657   MAKE_SCENARIO(RDV_ASYNC, 2, DIE, GET, sput(.2), soff(.3), rget(.4), rwait(.6), son(1));
658   MAKE_SCENARIO(RDV_ASYNC, 2, DIE, WAIT, rget(.2), sput(.4), soff(.5), rwait(.6), son(1));
659   MAKE_SCENARIO(RDV_ASYNC, 2, DIE, WAIT, sput(.2), rget(.4), soff(.5), rwait(.6), son(1));
660   MAKE_SCENARIO(RDV_ASYNC, 2, DIE, GET, sput(.2), swait(.4), soff(.5), rget(.6), rwait(.8), son(1));
661   MAKE_SCENARIO(RDV_ASYNC, 2, DIE, WAIT, rget(.2), rwait(.4), sput(.6), soff(.7), son(1));
662   MAKE_SCENARIO(RDV_ASYNC, 2, DIE, WAIT, rget(.2), sput(.4), rwait(.6), soff(.7), son(1));
663   MAKE_SCENARIO(RDV_ASYNC, 2, DIE, WAIT, rget(.2), sput(.4), swait(.6), soff(.7), rwait(.8), son(1));
664   MAKE_SCENARIO(RDV_ASYNC, 2, DIE, WAIT, sput(.2), rget(.4), rwait(.6), soff(.7), son(1));
665   MAKE_SCENARIO(RDV_ASYNC, 2, DIE, WAIT, sput(.2), rget(.4), swait(.6), soff(.7), rwait(.8), son(1));
666   MAKE_SCENARIO(RDV_ASYNC, 2, DIE, WAIT, sput(.2), swait(.4), rget(.6), soff(.7), rwait(.8), son(1));
667   // Link off
668   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, loff(.1), sput(.2), swait(.4), rget(.6), rwait(.8), lon(1));
669   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, loff(.1), sput(.2), rget(.4), swait(.6), rwait(.8), lon(1));
670   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, loff(.1), sput(.2), rget(.4), rwait(.6), swait(.8), lon(1));
671   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, loff(.1), rget(.2), sput(.4), swait(.6), rwait(.8), lon(1));
672   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, loff(.1), rget(.2), sput(.4), rwait(.6), swait(.8), lon(1));
673   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, loff(.1), rget(.2), rwait(.4), sput(.6), swait(.8), lon(1));
674   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, sput(.2), loff(.3), swait(.4), rget(.6), rwait(.8), lon(1));
675   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, sput(.2), loff(.3), rget(.4), swait(.6), rwait(.8), lon(1));
676   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, sput(.2), loff(.3), rget(.4), rwait(.6), swait(.8), lon(1));
677   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, rget(.2), loff(.3), sput(.4), swait(.6), rwait(.8), lon(1));
678   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, rget(.2), loff(.3), sput(.4), rwait(.6), swait(.8), lon(1));
679   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, rget(.2), loff(.3), rwait(.4), sput(.6), swait(.8), lon(1));
680   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, sput(.2), swait(.4), loff(.5), rget(.6), rwait(.8), lon(1));
681   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, sput(.2), rget(.4), loff(.5), swait(.6), rwait(.8), lon(1));
682   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, sput(.2), rget(.4), loff(.5), rwait(.6), swait(.8), lon(1));
683   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, rget(.2), sput(.4), loff(.5), swait(.6), rwait(.8), lon(1));
684   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, rget(.2), sput(.4), loff(.5), rwait(.6), swait(.8), lon(1));
685   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, rget(.2), rwait(.4), loff(.5), sput(.6), swait(.8), lon(1));
686   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, sput(.2), swait(.4), rget(.6), loff(.7), rwait(.8), lon(1));
687   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, sput(.2), rget(.4), swait(.6), loff(.7), rwait(.8), lon(1));
688   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, sput(.2), rget(.4), rwait(.6), loff(.7), swait(.8), lon(1));
689   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, rget(.2), sput(.4), swait(.6), loff(.7), rwait(.8), lon(1));
690   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, rget(.2), sput(.4), rwait(.6), loff(.7), swait(.8), lon(1));
691   MAKE_SCENARIO(RDV_ASYNC, 2, WAIT, WAIT, rget(.2), rwait(.4), sput(.6), loff(.7), swait(.8), lon(1));
692
693   // ONESIDE SYNC use cases
694   // All good
695   MAKE_SCENARIO(ONESIDE_SYNC, 1, END, END, sput(.2));
696   // Receiver off
697   MAKE_SCENARIO(ONESIDE_SYNC, 2, PUT, DIE, roff(.1), sput(.2), ron(1));
698   MAKE_SCENARIO(ONESIDE_SYNC, 2, PUT, DIE, sput(.2), roff(.3), ron(1));
699   // Sender off
700   MAKE_SCENARIO(ONESIDE_SYNC, 2, DIE, END, sput(.2), soff(.3), son(1));
701   // Link off
702   MAKE_SCENARIO(ONESIDE_SYNC, 2, PUT, END, loff(.1), sput(.2), lon(1));
703   MAKE_SCENARIO(ONESIDE_SYNC, 2, PUT, END, sput(.2), loff(.3), lon(1));
704
705   // ONESIDE ASYNC use cases
706   // All good
707   MAKE_SCENARIO(ONESIDE_ASYNC, 2, END, END, sput(.2), swait(.4));
708   // Receiver off
709   MAKE_SCENARIO(ONESIDE_ASYNC, 2, PUT, DIE, roff(.1), sput(.2), swait(.4), ron(1));
710   MAKE_SCENARIO(ONESIDE_ASYNC, 2, WAIT, DIE, sput(.2), roff(.3), swait(.4), ron(1));
711   MAKE_SCENARIO(ONESIDE_ASYNC, 2, WAIT, DIE, sput(.2), swait(.4), roff(.5), ron(1));
712   // Sender off
713   MAKE_SCENARIO(ONESIDE_ASYNC, 2, DIE, END, sput(.2), soff(.3), son(1));
714   // Link off
715   MAKE_SCENARIO(ONESIDE_ASYNC, 2, WAIT, END, loff(.1), sput(.2), swait(.4), lon(1));
716   MAKE_SCENARIO(ONESIDE_ASYNC, 2, WAIT, END, sput(.2), loff(.3), swait(.4), lon(1));
717   MAKE_SCENARIO(ONESIDE_ASYNC, 2, WAIT, END, sput(.2), swait(.4), loff(.5), lon(1));
718
719   XBT_INFO("Will execute %i active scenarios out of %i.", ctx.active, ctx.index);
720   return ctx.start_time + 1;
721 }