Logo AND Algorithmique Numérique Distribuée

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