Logo AND Algorithmique Numérique Distribuée

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