Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Handle onesided=detached comms and clean up the comm_fault_scenario test
[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 std::vector<Scenario> scenarios;
159 sg4::Mailbox* mbox_eager = nullptr;
160 sg4::Mailbox* mbox_rdv   = nullptr;
161
162 class SendAgent {
163
164   static int run;
165   static size_t scenario;
166   int id;
167   sg4::Host* other_host;
168
169   sg4::CommPtr do_put(CommType type, double& send_value)
170   {
171     switch (type) {
172       case CommType::EAGER_SYNC:
173         mbox_eager->put(&send_value, MsgSize);
174         return nullptr;
175       case CommType::EAGER_ASYNC:
176         return mbox_eager->put_async(&send_value, MsgSize);
177       case CommType::EAGER_INIT:
178         return mbox_eager->put_init(&send_value, MsgSize);
179       case CommType::RDV_SYNC:
180         mbox_rdv->put(&send_value, MsgSize);
181         return nullptr;
182       case CommType::RDV_ASYNC:
183         return mbox_rdv->put_async(&send_value, MsgSize);
184       case CommType::RDV_INIT:
185         return mbox_rdv->put_init(&send_value, MsgSize);
186       case CommType::ONESIDE_SYNC:
187         sg4::Comm::sendto(sg4::this_actor::get_host(), other_host, MsgSize);
188         return nullptr;
189       case CommType::ONESIDE_ASYNC:
190         return sg4::Comm::sendto_async(sg4::this_actor::get_host(), other_host, MsgSize);
191     }
192     return nullptr;
193   }
194
195   void send_message(const Scenario& s)
196   {
197     std::string scenario_string = to_string(s);
198      XBT_DEBUG("Will try: %s", scenario_string.c_str());
199     double send_value;
200     sg4::CommPtr comm = nullptr;
201     Action expected = s.snd_expected;
202     double end_time = s.start_time + s.duration;
203     send_value        = end_time;
204     size_t step_index = 0;
205
206     sg4::this_actor::sleep_until(s.start_time);
207
208     //Make sure we have a clean slate
209     xbt_assert(not mbox_eager->listen(),"Eager mailbox should be empty when starting a test");
210     xbt_assert(not mbox_rdv->listen(),"RDV mailbox should be empty when starting a test");
211
212     for (; step_index < s.steps.size(); step_index++) {
213       const Step& step = s.steps[step_index];
214       if (step.entity != Step::SND || step.type != Step::ACTION)
215         continue;
216
217       try {
218         sg4::this_actor::sleep_until(s.start_time + step.rel_time);
219       } catch (std::exception& e) {
220         XBT_DEBUG("During Sleep, failed to send message because of a %s exception (%s)", typeid(e).name(), e.what());
221         break;
222       }
223
224       // Check if the other host is still OK.
225       if (not other_host->is_on())
226         break;
227
228       // Perform the action
229       try {
230         switch (step.action_type) {
231           case Action::PUT:
232             comm=do_put(s.type, send_value);
233             break;
234           case Action::START:
235             comm->start();
236             break;
237           case Action::WAIT:
238             comm->wait();
239             break;
240           default:
241             xbt_die("Not a valid action for SND");
242         }
243       } catch (std::exception& e) {
244         XBT_DEBUG("During %s, failed to send message because of a %s exception (%s)", to_string(step.action_type),
245                   typeid(e).name(), e.what());
246         break;
247       }
248     }
249
250     try {
251       sg4::this_actor::sleep_until(end_time);
252     } catch (std::exception& e) {
253       XBT_DEBUG("During Sleep, failed to send message because of a %s exception (%s)", typeid(e).name(), e.what());
254     }
255
256     Action outcome = Action::END;
257     if (step_index < s.steps.size()) {
258       const Step& step = s.steps[step_index];
259       assert(step.entity == Step::SND && step.type == Step::ACTION);
260       outcome = step.action_type;
261     }
262
263     if (outcome != expected) {
264       XBT_ERROR("Expected %s but got %s in %s", to_string(expected), to_string(outcome), scenario_string.c_str());
265     } else {
266       XBT_DEBUG("OK: %s", scenario_string.c_str());
267     }
268     sg4::this_actor::sleep_until(end_time);
269
270     xbt_assert(not mbox_eager->listen(), "Mailbox should not have ongoing communication!");
271     xbt_assert(not mbox_rdv->listen(), "Mailbox should not have ongoing communication!");
272
273   }
274
275 public:
276   explicit SendAgent(int id, sg4::Host* other_host) : id(id), other_host(other_host) {}
277
278   void operator()()
279   {
280     run++;
281     XBT_DEBUG("Host %i starts run %i and scenario %lu.", id, run, scenario);
282     while (scenario < scenarios.size()) {
283       Scenario& s = 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
302   sg4::CommPtr do_get(CommType type, double*& receive_ptr)
303   {
304     switch (type) {
305       case CommType::EAGER_SYNC:
306         receive_ptr = mbox_eager->get<double>();
307         return nullptr;
308       case CommType::EAGER_ASYNC:
309         return mbox_eager->get_async(&receive_ptr);
310       case CommType::EAGER_INIT:
311         return mbox_eager->get_init()->set_dst_data((void**)(&receive_ptr));
312       case CommType::RDV_SYNC:
313         receive_ptr = mbox_rdv->get<double>();
314         return nullptr;
315       case CommType::RDV_ASYNC:
316         return mbox_rdv->get_async(&receive_ptr);
317       case CommType::RDV_INIT:
318         return mbox_rdv->get_init()->set_dst_data((void**)(&receive_ptr));
319       case CommType::ONESIDE_SYNC:
320       case CommType::ONESIDE_ASYNC:
321         xbt_die("No get in One Sided comunications!");
322     }
323     return nullptr;
324   }
325
326   void receive_message(const Scenario& s)
327   {
328     sg4::CommPtr comm = nullptr;
329     CommType type     = s.type;
330     Action expected   = s.rcv_expected;
331     double end_time   = s.start_time + s.duration;
332     double* receive_ptr = nullptr;
333     size_t step_index   = 0;
334     sg4::this_actor::sleep_until(s.start_time);
335
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
340     for (; step_index < s.steps.size(); step_index++) {
341       const Step& step = s.steps[step_index];
342       if (step.entity != Step::RCV || step.type != Step::ACTION)
343         continue;
344
345       try {
346         sg4::this_actor::sleep_until(s.start_time + step.rel_time);
347       } catch (std::exception& e) {
348         XBT_DEBUG("During Sleep, failed to receive message because of a %s exception (%s)", typeid(e).name(), e.what());
349         break;
350       }
351
352       // Check if the other host is still OK.
353       if (not other_host->is_on())
354         break;
355
356       // Perform the action
357       try {
358         switch (step.action_type) {
359           case Action::GET:
360             comm = do_get(type, receive_ptr);
361             break;
362           case Action::START:
363             comm->start();
364             break;
365           case Action::WAIT:
366             comm->wait();
367             break;
368           default:
369             xbt_die("Not a valid action for RCV");
370         }
371       } catch (std::exception& e) {
372         XBT_DEBUG("During %s, failed to receive message because of a %s exception (%s)", to_string(step.action_type),
373                   typeid(e).name(), e.what());
374         break;
375       }
376     }
377
378     try {
379       sg4::this_actor::sleep_until(end_time - .1);
380     } catch (std::exception& e) {
381       XBT_DEBUG("During Sleep, failed to send message because of a %s exception (%s)", typeid(e).name(), e.what());
382     }
383
384     Action outcome              = Action::END;
385     std::string scenario_string = to_string(s);
386     if (step_index < s.steps.size()) {
387       const Step& step = s.steps[step_index];
388       assert(step.entity == Step::RCV && step.type == Step::ACTION);
389       outcome = step.action_type;
390     } else if (s.type!=CommType::ONESIDE_SYNC && 
391           s.type!=CommType::ONESIDE_ASYNC
392           ) {
393             //One sided / detached operations do not actually transfer anything
394             if(receive_ptr == nullptr ) {
395               XBT_ERROR("Received address is NULL in %s", scenario_string.c_str());
396             } else if (*receive_ptr != end_time) {
397               XBT_ERROR("Received value invalid: expected %f but got %f in %s", end_time, *receive_ptr,
398                 scenario_string.c_str());
399           }
400     }
401
402     if (outcome != expected) {
403       XBT_ERROR("Expected %s but got %s in %s", to_string(expected), to_string(outcome), scenario_string.c_str());
404     } else {
405       XBT_DEBUG("OK: %s", scenario_string.c_str());
406     }
407
408     sg4::this_actor::sleep_until(end_time);
409     xbt_assert(not mbox_eager->listen(), "Mailbox should not have ongoing communication!");
410     xbt_assert(not mbox_rdv->listen(), "Mailbox should not have ongoing communication!");
411   }
412
413 public:
414   explicit ReceiveAgent(int id, sg4::Host* other_host) : id(id), other_host(other_host) {}
415
416   void operator()()
417   {
418     run++;
419     XBT_DEBUG("Host %i starts run %i and scenario %lu.", id, run, scenario);
420     mbox_eager->set_receiver(sg4::Actor::self());
421     while (scenario < scenarios.size()) {
422       Scenario& s = scenarios[scenario];
423       scenario++;
424       receive_message(s);
425     }
426   }
427 };
428
429 int ReceiveAgent::run         = 0;
430 size_t ReceiveAgent::scenario = 0;
431
432 /*************************************************************************************************/
433
434 static void on_host_state_change(sg4::Host const& host)
435 {
436   XBT_DEBUG("Host %s is now %s", host.get_cname(), host.is_on() ? "ON " : "OFF");
437   if(not host.is_on()) {
438     mbox_eager->clear();
439     mbox_rdv->clear();
440   }
441 }
442
443 static void on_link_state_change(sg4::Link const& link)
444 {
445   XBT_DEBUG("Link %s is now %s", link.get_cname(), link.is_on() ? "ON " : "OFF");
446 }
447
448 static void addStateEvent(std::ostream& out, double date, bool isOn)
449 {
450   if (isOn)
451     out << date << " 1\n";
452   else
453     out << date << " 0\n";
454 }
455
456 static int prepareScenario(CommType type, int& index, double& start_time, double duration, std::ostream& sndP, std::ostream& rcvP,
457                             std::ostream& lnkP, Action snd_expected, Action rcv_expected, std::vector<Step> steps, std::vector<int> active_indices)
458 {
459   int ret=0;
460   if(std::find(active_indices.begin(),active_indices.end(),index)!=active_indices.end()) {
461     // Update fault profiles
462     for (Step& step : steps) {
463       assert(step.rel_time < duration);
464       if (step.type != Step::STATE)
465         continue;
466       int val = step.new_state ? 1 : 0;
467       switch (step.entity) {
468         case Step::SND:
469           sndP << start_time + step.rel_time << " " << val << std::endl;
470           break;
471         case Step::RCV:
472           rcvP << start_time + step.rel_time << " " << val << std::endl;
473           break;
474         case Step::LNK:
475           lnkP << start_time + step.rel_time << " " << val << std::endl;
476           break;
477       }
478     }
479     scenarios.push_back({type, start_time, duration, snd_expected, rcv_expected, steps, index}); 
480     ret=1;
481   }
482   index++;
483   start_time += duration;
484   return ret;
485 }
486
487 /*************************************************************************************************/
488
489 // State profiles for the resources
490 std::string SndStateProfile;
491 std::string RcvStateProfile;
492 std::string LnkStateProfile;
493
494 /*************************************************************************************************/
495
496 double build_scenarios(std::vector<int>& active_indices );
497
498 int main(int argc, char* argv[])
499 {
500
501   sg4::Engine e(&argc, argv);
502
503   std::vector<int> active_indices;
504   //Parse index of tests that need to be run
505
506   int previous_index=-1;
507   bool is_range_last=false;
508   for(int i=1; i<argc; i++) {
509     if(not strcmp(argv[i],"-"))
510       is_range_last=true;
511     else {
512       int index=atoi(argv[i]);
513       xbt_assert(index>previous_index);
514       if(is_range_last) 
515         for(int j=previous_index+1;j<=index;j++)
516           active_indices.push_back(j);
517       else
518          active_indices.push_back(index);
519        is_range_last=false;
520        previous_index=index;
521     }
522   }
523
524   double end_time = build_scenarios(active_indices);
525
526   XBT_INFO("Will run for %f seconds", end_time);
527
528
529   mbox_eager = e.mailbox_by_name_or_create("eager");
530   mbox_rdv   = e.mailbox_by_name_or_create("rdv");
531   sg4::NetZone* zone = sg4::create_full_zone("Top");
532   pr::Profile* profile_sender = pr::ProfileBuilder::from_string("sender_profile", SndStateProfile, 0);
533   sg4::Host* sender_host = zone->create_host("senderHost", HostComputePower)->set_state_profile(profile_sender)->seal();
534   pr::Profile* profile_receiver = pr::ProfileBuilder::from_string("receiver_profile", RcvStateProfile, 0);
535   sg4::Host* receiver_host = zone->create_host("receiverHost", HostComputePower)->set_state_profile(profile_receiver)->seal();
536   sg4::ActorPtr sender = sg4::Actor::create("sender", sender_host, SendAgent(0, receiver_host));
537   sender->set_auto_restart(true);
538   sg4::ActorPtr receiver = sg4::Actor::create("receiver", receiver_host, ReceiveAgent(1, sender_host));
539   receiver->set_auto_restart(true);
540   pr::Profile* profile_link = pr::ProfileBuilder::from_string("link_profile", LnkStateProfile, 0);
541   sg4::Link* link =
542       zone->create_link("link", LinkBandwidth)->set_latency(LinkLatency)->set_state_profile(profile_link)->seal();
543   zone->add_route(sender_host->get_netpoint(), receiver_host->get_netpoint(), nullptr, nullptr,
544                   {sg4::LinkInRoute{link}}, false);
545   zone->seal();
546   sg4::Host::on_state_change.connect(on_host_state_change);
547   sg4::Link::on_state_change_cb(on_link_state_change);
548
549   e.run_until(end_time);
550
551   //Make sure we have a clean slate
552   xbt_assert(not mbox_eager->listen(),"Eager mailbox should be empty in the end");
553   xbt_assert(not mbox_rdv->listen(),"RDV mailbox should be empty in the end");
554   return 0;
555 }
556
557 /*************************************************************************************************/
558
559 // A bunch of dirty macros to help readability (supposedly)
560 #define _MK(type, duration, snd_expected, rcv_expected, steps...)                                                      \
561   active+=prepareScenario(CommType::type, index, start_time, duration, sndP, rcvP, lnkP, Action::snd_expected, Action::rcv_expected,  \
562                   {steps}, active_indices )
563 // Link
564 #define LOFF(relTime)                                                                                                  \
565   {                                                                                                                    \
566     relTime, Step::STATE, Step::LNK, Action::END, false                                                                \
567   }
568 #define LON(relTime)                                                                                                   \
569   {                                                                                                                    \
570     relTime, Step::STATE, Step::LNK, Action::END, true                                                                 \
571   }
572 // Sender
573 #define SOFF(relTime)                                                                                                  \
574   {                                                                                                                    \
575     relTime, Step::STATE, Step::SND, Action::END, false                                                                \
576   }
577 #define SON(relTime)                                                                                                   \
578   {                                                                                                                    \
579     relTime, Step::STATE, Step::SND, Action::END, true                                                                 \
580   }
581 #define SPUT(relTime)                                                                                                  \
582   {                                                                                                                    \
583     relTime, Step::ACTION, Step::SND, Action::PUT, false                                                               \
584   }
585 #define SWAT(relTime)                                                                                                  \
586   {                                                                                                                    \
587     relTime, Step::ACTION, Step::SND, Action::WAIT, false                                                              \
588   }
589 // Receiver
590 #define ROFF(relTime)                                                                                                  \
591   {                                                                                                                    \
592     relTime, Step::STATE, Step::RCV, Action::END, false                                                                \
593   }
594 #define RON(relTime)                                                                                                   \
595   {                                                                                                                    \
596     relTime, Step::STATE, Step::RCV, Action::END, true                                                                 \
597   }
598 #define RGET(relTime)                                                                                                  \
599   {                                                                                                                    \
600     relTime, Step::ACTION, Step::RCV, Action::GET, false                                                               \
601   }
602 #define RWAT(relTime)                                                                                                  \
603   {                                                                                                                    \
604     relTime, Step::ACTION, Step::RCV, Action::WAIT, false                                                              \
605   }
606
607 double build_scenarios(std::vector<int>& active_indices )
608 {
609
610   // Build the set of simulation stages
611   std::stringstream sndP;
612   std::stringstream rcvP;
613   std::stringstream lnkP;
614
615   double start_time = 0;
616   int index=0;
617   int active=0;
618
619   // EAGER SYNC use cases
620   // All good
621   _MK(EAGER_SYNC, 1, END, END, SPUT(.2), RGET(.4));
622   _MK(EAGER_SYNC, 1, END, END, RGET(.2), SPUT(.4));
623   // Receiver off
624   _MK(EAGER_SYNC, 2, PUT, DIE, ROFF(.1), SPUT(.2), RON(1));
625   _MK(EAGER_SYNC, 2, PUT, DIE, SPUT(.2), ROFF(.3), RON(1));
626   _MK(EAGER_SYNC, 2, PUT, DIE, SPUT(.2), RGET(.4), ROFF(.5), RON(1));
627   _MK(EAGER_SYNC, 2, PUT, DIE, RGET(.2), SPUT(.4), ROFF(.5), RON(1));
628   // Sender off
629   _MK(EAGER_SYNC, 2, DIE, GET, SPUT(.2), SOFF(.3), RGET(.4), SON(1));
630   _MK(EAGER_SYNC, 2, DIE, GET, SPUT(.2), RGET(.4), SOFF(.5), SON(1));
631   // Link off
632   _MK(EAGER_SYNC, 2, PUT, GET, LOFF(.1), SPUT(.2), RGET(.4), LON(1));
633   _MK(EAGER_SYNC, 2, PUT, GET, SPUT(.2), LOFF(.3), RGET(.4), LON(1));
634   _MK(EAGER_SYNC, 2, PUT, GET, SPUT(.2), RGET(.4), LOFF(.5), LON(1));
635   _MK(EAGER_SYNC, 2, PUT, GET, LOFF(.1), RGET(.2), SPUT(.4), LON(1));
636   _MK(EAGER_SYNC, 2, PUT, GET, RGET(.2), LOFF(.3), SPUT(.4), LON(1));
637   _MK(EAGER_SYNC, 2, PUT, GET, RGET(.2), SPUT(.4), LOFF(.5), LON(1));
638
639   // EAGER ASYNC use cases
640   // All good
641   _MK(EAGER_ASYNC, 2, END, END, SPUT(.2), SWAT(.4), RGET(.6), RWAT(.8));
642   _MK(EAGER_ASYNC, 2, END, END, SPUT(.2), RGET(.4), SWAT(.6), RWAT(.8));
643   _MK(EAGER_ASYNC, 2, END, END, SPUT(.2), RGET(.4), RWAT(.6), SWAT(.8));
644   _MK(EAGER_ASYNC, 2, END, END, RGET(.2), SPUT(.4), SWAT(.6), RWAT(.8));
645   _MK(EAGER_ASYNC, 2, END, END, RGET(.2), SPUT(.4), RWAT(.6), SWAT(.8));
646   _MK(EAGER_ASYNC, 2, END, END, RGET(.2), RWAT(.4), SPUT(.6), SWAT(.8));
647   
648   // Receiver off
649   _MK(EAGER_ASYNC, 2, PUT, DIE, ROFF(.1), SPUT(.2), SWAT(.4), RON(1));
650   _MK(EAGER_ASYNC, 2, WAIT, DIE, SPUT(.2), ROFF(.3), SWAT(.4), RON(1));
651   _MK(EAGER_ASYNC, 2, PUT, DIE, RGET(.2), ROFF(.3), SPUT(.4), SWAT(.6), RON(1));
652   _MK(EAGER_ASYNC, 2, WAIT, DIE, SPUT(.2), SWAT(.4), ROFF(.5), RON(1));
653   _MK(EAGER_ASYNC, 2, WAIT, DIE, SPUT(.2), RGET(.4), ROFF(.5), SWAT(.6), RON(1));
654   _MK(EAGER_ASYNC, 2, WAIT, DIE, RGET(.2), SPUT(.4), ROFF(.5), SWAT(.6), RON(1));
655   _MK(EAGER_ASYNC, 2, PUT , DIE, RGET(.2), RWAT(.4), ROFF(.5), SPUT(.6), SWAT(.8), RON(1));
656   _MK(EAGER_ASYNC, 2, WAIT, DIE, SPUT(.2), SWAT(.4), RGET(.6), ROFF(.7), RON(1));
657   _MK(EAGER_ASYNC, 2, WAIT, DIE, SPUT(.2), RGET(.4), SWAT(.6), ROFF(.7), RON(1));
658   _MK(EAGER_ASYNC, 2, WAIT, DIE, SPUT(.2), RGET(.4), RWAT(.6), ROFF(.7), SWAT(.8), RON(1));
659   _MK(EAGER_ASYNC, 2, WAIT, DIE, RGET(.2), SPUT(.4), SWAT(.6), ROFF(.7), RON(1));
660   _MK(EAGER_ASYNC, 2, WAIT, DIE, RGET(.2), SPUT(.4), RWAT(.6), ROFF(.7), SWAT(.8), RON(1));
661   _MK(EAGER_ASYNC, 2, WAIT, DIE, RGET(.2), RWAT(.4), SPUT(.6), ROFF(.7), SWAT(.8), RON(1));
662   // Sender off (only cases where sender did put, because otherwise receiver cannot find out there was a fault)
663   _MK(EAGER_ASYNC, 2, DIE, GET, SPUT(.2), SOFF(.3), RGET(.4), RWAT(.6), SON(1));
664   _MK(EAGER_ASYNC, 2, DIE, WAIT, RGET(.2), SPUT(.4), SOFF(.5), RWAT(.6), SON(1));
665   _MK(EAGER_ASYNC, 2, DIE, WAIT, SPUT(.2), RGET(.4), SOFF(.5), RWAT(.6), SON(1));
666   _MK(EAGER_ASYNC, 2, DIE, GET, SPUT(.2), SWAT(.4), SOFF(.5), RGET(.6), RWAT(.8), SON(1));
667   _MK(EAGER_ASYNC, 2, DIE, WAIT, RGET(.2), RWAT(.4), SPUT(.6), SOFF(.7), SON(1));
668   _MK(EAGER_ASYNC, 2, DIE, WAIT, RGET(.2), SPUT(.4), RWAT(.6), SOFF(.7), SON(1));
669   _MK(EAGER_ASYNC, 2, DIE, WAIT, RGET(.2), SPUT(.4), SWAT(.6), SOFF(.7), RWAT(.8), SON(1));
670   _MK(EAGER_ASYNC, 2, DIE, WAIT, SPUT(.2), RGET(.4), RWAT(.6), SOFF(.7), SON(1));
671   _MK(EAGER_ASYNC, 2, DIE, WAIT, SPUT(.2), RGET(.4), SWAT(.6), SOFF(.7), RWAT(.8), SON(1));
672   _MK(EAGER_ASYNC, 2, DIE, WAIT, SPUT(.2), SWAT(.4), RGET(.6), SOFF(.7), RWAT(.8), SON(1));
673   // Link off
674   _MK(EAGER_ASYNC, 2, WAIT, WAIT, LOFF(.1), SPUT(.2), SWAT(.4), RGET(.6), RWAT(.8), LON(1));
675   _MK(EAGER_ASYNC, 2, WAIT, WAIT, LOFF(.1), SPUT(.2), RGET(.4), SWAT(.6), RWAT(.8), LON(1));
676   _MK(EAGER_ASYNC, 2, WAIT, WAIT, LOFF(.1), SPUT(.2), RGET(.4), RWAT(.6), SWAT(.8), LON(1));
677   _MK(EAGER_ASYNC, 2, WAIT, WAIT, LOFF(.1), RGET(.2), SPUT(.4), SWAT(.6), RWAT(.8), LON(1));
678   _MK(EAGER_ASYNC, 2, WAIT, WAIT, LOFF(.1), RGET(.2), SPUT(.4), RWAT(.6), SWAT(.8), LON(1));
679   _MK(EAGER_ASYNC, 2, WAIT, WAIT, LOFF(.1), RGET(.2), RWAT(.4), SPUT(.6), SWAT(.8), LON(1));
680   _MK(EAGER_ASYNC, 2, WAIT, WAIT, SPUT(.2), LOFF(.3), SWAT(.4), RGET(.6), RWAT(.8), LON(1));
681   _MK(EAGER_ASYNC, 2, WAIT, WAIT, SPUT(.2), LOFF(.3), RGET(.4), SWAT(.6), RWAT(.8), LON(1));
682   _MK(EAGER_ASYNC, 2, WAIT, WAIT, SPUT(.2), LOFF(.3), RGET(.4), RWAT(.6), SWAT(.8), LON(1));
683   _MK(EAGER_ASYNC, 2, WAIT, WAIT, RGET(.2), LOFF(.3), SPUT(.4), SWAT(.6), RWAT(.8), LON(1));
684   _MK(EAGER_ASYNC, 2, WAIT, WAIT, RGET(.2), LOFF(.3), SPUT(.4), RWAT(.6), SWAT(.8), LON(1));
685   _MK(EAGER_ASYNC, 2, WAIT, WAIT, RGET(.2), LOFF(.3), RWAT(.4), SPUT(.6), SWAT(.8), LON(1));
686   _MK(EAGER_ASYNC, 2, WAIT, WAIT, SPUT(.2), SWAT(.4), LOFF(.5), RGET(.6), RWAT(.8), LON(1));
687   _MK(EAGER_ASYNC, 2, WAIT, WAIT, SPUT(.2), RGET(.4), LOFF(.5), SWAT(.6), RWAT(.8), LON(1));
688   _MK(EAGER_ASYNC, 2, WAIT, WAIT, SPUT(.2), RGET(.4), LOFF(.5), RWAT(.6), SWAT(.8), LON(1));
689   _MK(EAGER_ASYNC, 2, WAIT, WAIT, RGET(.2), SPUT(.4), LOFF(.5), SWAT(.6), RWAT(.8), LON(1));
690   _MK(EAGER_ASYNC, 2, WAIT, WAIT, RGET(.2), SPUT(.4), LOFF(.5), RWAT(.6), SWAT(.8), LON(1));
691   _MK(EAGER_ASYNC, 2, WAIT, WAIT, RGET(.2), RWAT(.4), LOFF(.5), SPUT(.6), SWAT(.8), LON(1));
692   _MK(EAGER_ASYNC, 2, WAIT, WAIT, SPUT(.2), SWAT(.4), RGET(.6), LOFF(.7), RWAT(.8), LON(1));
693   _MK(EAGER_ASYNC, 2, WAIT, WAIT, SPUT(.2), RGET(.4), SWAT(.6), LOFF(.7), RWAT(.8), LON(1));
694   _MK(EAGER_ASYNC, 2, WAIT, WAIT, SPUT(.2), RGET(.4), RWAT(.6), LOFF(.7), SWAT(.8), LON(1));
695   _MK(EAGER_ASYNC, 2, WAIT, WAIT, RGET(.2), SPUT(.4), SWAT(.6), LOFF(.7), RWAT(.8), LON(1));
696   _MK(EAGER_ASYNC, 2, WAIT, WAIT, RGET(.2), SPUT(.4), RWAT(.6), LOFF(.7), SWAT(.8), LON(1));
697   _MK(EAGER_ASYNC, 2, WAIT, WAIT, RGET(.2), RWAT(.4), SPUT(.6), LOFF(.7), SWAT(.8), LON(1));
698
699   // RDV SYNC use cases
700
701   // All good
702   _MK(RDV_SYNC, 1, END, END, SPUT(.2), RGET(.4));
703   _MK(RDV_SYNC, 1, END, END, RGET(.2), SPUT(.4));
704   
705   // Receiver off
706   _MK(RDV_SYNC, 2, PUT, DIE, ROFF(.1), SPUT(.2), RON(1));
707   _MK(RDV_SYNC, 2, PUT, DIE, SPUT(.2), ROFF(.3), RON(1)); //Fails because put comm cancellation does not trigger sender exception
708   _MK(RDV_SYNC, 2, PUT, DIE, SPUT(.2), RGET(.4), ROFF(.5), RON(1));
709   _MK(RDV_SYNC, 2, PUT, DIE, RGET(.2), SPUT(.4), ROFF(.5), RON(1));
710   // Sender off
711   _MK(RDV_SYNC, 2, DIE, GET, SPUT(.2), RGET(.4), SOFF(.5), SON(1));
712   // Link off
713   _MK(RDV_SYNC, 2, PUT, GET, LOFF(.1), SPUT(.2), RGET(.4), LON(1));
714   _MK(RDV_SYNC, 2, PUT, GET, SPUT(.2), LOFF(.3), RGET(.4), LON(1));
715   _MK(RDV_SYNC, 2, PUT, GET, SPUT(.2), RGET(.4), LOFF(.5), LON(1));
716   _MK(RDV_SYNC, 2, PUT, GET, LOFF(.1), RGET(.2), SPUT(.4), LON(1));
717   _MK(RDV_SYNC, 2, PUT, GET, RGET(.2), LOFF(.3), SPUT(.4), LON(1));
718   _MK(RDV_SYNC, 2, PUT, GET, RGET(.2), SPUT(.4), LOFF(.5), LON(1));
719
720   // RDV ASYNC use cases
721   // All good
722   _MK(RDV_ASYNC, 2, END, END, SPUT(.2), SWAT(.4), RGET(.6), RWAT(.8));
723   _MK(RDV_ASYNC, 2, END, END, SPUT(.2), RGET(.4), SWAT(.6), RWAT(.8));
724   _MK(RDV_ASYNC, 2, END, END, SPUT(.2), RGET(.4), RWAT(.6), SWAT(.8));
725   _MK(RDV_ASYNC, 2, END, END, RGET(.2), SPUT(.4), SWAT(.6), RWAT(.8));
726   _MK(RDV_ASYNC, 2, END, END, RGET(.2), SPUT(.4), RWAT(.6), SWAT(.8));
727   _MK(RDV_ASYNC, 2, END, END, RGET(.2), RWAT(.4), SPUT(.6), SWAT(.8));
728   // Receiver off
729   _MK(RDV_ASYNC, 2, PUT, DIE, ROFF(.1), SPUT(.2), SWAT(.4), RON(1));
730   _MK(RDV_ASYNC, 2, WAIT, DIE, SPUT(.2), ROFF(.3), SWAT(.4), RON(1));
731   _MK(RDV_ASYNC, 2, PUT, DIE, RGET(.2), ROFF(.3), SPUT(.4), SWAT(.6), RON(1));
732   _MK(RDV_ASYNC, 2, WAIT, DIE, SPUT(.2), SWAT(.4), ROFF(.5), RON(1)); //Fails because put comm cancellation does not trigger sender exception
733   _MK(RDV_ASYNC, 2, WAIT, DIE, SPUT(.2), RGET(.4), ROFF(.5), SWAT(.6), RON(1));
734   _MK(RDV_ASYNC, 2, WAIT, DIE, RGET(.2), SPUT(.4), ROFF(.5), SWAT(.6), RON(1));
735   _MK(RDV_ASYNC, 2, PUT , DIE, RGET(.2), RWAT(.4), ROFF(.5), SPUT(.6), SWAT(.8), RON(1));
736   _MK(RDV_ASYNC, 2, WAIT, DIE, SPUT(.2), SWAT(.4), RGET(.6), ROFF(.7), RON(1));
737   _MK(RDV_ASYNC, 2, WAIT, DIE, SPUT(.2), RGET(.4), SWAT(.6), ROFF(.7), RON(1));
738   _MK(RDV_ASYNC, 2, WAIT, DIE, SPUT(.2), RGET(.4), RWAT(.6), ROFF(.7), SWAT(.8), RON(1));
739   _MK(RDV_ASYNC, 2, WAIT, DIE, RGET(.2), SPUT(.4), SWAT(.6), ROFF(.7), RON(1));
740   _MK(RDV_ASYNC, 2, WAIT, DIE, RGET(.2), SPUT(.4), RWAT(.6), ROFF(.7), SWAT(.8), RON(1));
741   _MK(RDV_ASYNC, 2, WAIT, DIE, RGET(.2), RWAT(.4), SPUT(.6), ROFF(.7), SWAT(.8), RON(1));
742   // Sender off (only cases where sender did put, because otherwise receiver cannot find out there was a fault)
743   _MK(RDV_ASYNC, 2, DIE, GET, SPUT(.2), SOFF(.3), RGET(.4), RWAT(.6), SON(1));
744   _MK(RDV_ASYNC, 2, DIE, WAIT, RGET(.2), SPUT(.4), SOFF(.5), RWAT(.6), SON(1));
745   _MK(RDV_ASYNC, 2, DIE, WAIT, SPUT(.2), RGET(.4), SOFF(.5), RWAT(.6), SON(1));
746   _MK(RDV_ASYNC, 2, DIE, GET, SPUT(.2), SWAT(.4), SOFF(.5), RGET(.6), RWAT(.8), SON(1));
747   _MK(RDV_ASYNC, 2, DIE, WAIT, RGET(.2), RWAT(.4), SPUT(.6), SOFF(.7), SON(1));
748   _MK(RDV_ASYNC, 2, DIE, WAIT, RGET(.2), SPUT(.4), RWAT(.6), SOFF(.7), SON(1));
749   _MK(RDV_ASYNC, 2, DIE, WAIT, RGET(.2), SPUT(.4), SWAT(.6), SOFF(.7), RWAT(.8), SON(1));
750   _MK(RDV_ASYNC, 2, DIE, WAIT, SPUT(.2), RGET(.4), RWAT(.6), SOFF(.7), SON(1));
751   _MK(RDV_ASYNC, 2, DIE, WAIT, SPUT(.2), RGET(.4), SWAT(.6), SOFF(.7), RWAT(.8), SON(1));
752   _MK(RDV_ASYNC, 2, DIE, WAIT, SPUT(.2), SWAT(.4), RGET(.6), SOFF(.7), RWAT(.8), SON(1));
753   // Link off
754   _MK(RDV_ASYNC, 2, WAIT, WAIT, LOFF(.1), SPUT(.2), SWAT(.4), RGET(.6), RWAT(.8), LON(1));
755   _MK(RDV_ASYNC, 2, WAIT, WAIT, LOFF(.1), SPUT(.2), RGET(.4), SWAT(.6), RWAT(.8), LON(1));
756   _MK(RDV_ASYNC, 2, WAIT, WAIT, LOFF(.1), SPUT(.2), RGET(.4), RWAT(.6), SWAT(.8), LON(1));
757   _MK(RDV_ASYNC, 2, WAIT, WAIT, LOFF(.1), RGET(.2), SPUT(.4), SWAT(.6), RWAT(.8), LON(1));
758   _MK(RDV_ASYNC, 2, WAIT, WAIT, LOFF(.1), RGET(.2), SPUT(.4), RWAT(.6), SWAT(.8), LON(1));
759   _MK(RDV_ASYNC, 2, WAIT, WAIT, LOFF(.1), RGET(.2), RWAT(.4), SPUT(.6), SWAT(.8), LON(1));
760   _MK(RDV_ASYNC, 2, WAIT, WAIT, SPUT(.2), LOFF(.3), SWAT(.4), RGET(.6), RWAT(.8), LON(1));
761   _MK(RDV_ASYNC, 2, WAIT, WAIT, SPUT(.2), LOFF(.3), RGET(.4), SWAT(.6), RWAT(.8), LON(1));
762   _MK(RDV_ASYNC, 2, WAIT, WAIT, SPUT(.2), LOFF(.3), RGET(.4), RWAT(.6), SWAT(.8), LON(1));
763   _MK(RDV_ASYNC, 2, WAIT, WAIT, RGET(.2), LOFF(.3), SPUT(.4), SWAT(.6), RWAT(.8), LON(1));
764   _MK(RDV_ASYNC, 2, WAIT, WAIT, RGET(.2), LOFF(.3), SPUT(.4), RWAT(.6), SWAT(.8), LON(1));
765   _MK(RDV_ASYNC, 2, WAIT, WAIT, RGET(.2), LOFF(.3), RWAT(.4), SPUT(.6), SWAT(.8), LON(1));
766   _MK(RDV_ASYNC, 2, WAIT, WAIT, SPUT(.2), SWAT(.4), LOFF(.5), RGET(.6), RWAT(.8), LON(1));
767   _MK(RDV_ASYNC, 2, WAIT, WAIT, SPUT(.2), RGET(.4), LOFF(.5), SWAT(.6), RWAT(.8), LON(1));
768   _MK(RDV_ASYNC, 2, WAIT, WAIT, SPUT(.2), RGET(.4), LOFF(.5), RWAT(.6), SWAT(.8), LON(1));
769   _MK(RDV_ASYNC, 2, WAIT, WAIT, RGET(.2), SPUT(.4), LOFF(.5), SWAT(.6), RWAT(.8), LON(1));
770   _MK(RDV_ASYNC, 2, WAIT, WAIT, RGET(.2), SPUT(.4), LOFF(.5), RWAT(.6), SWAT(.8), LON(1));
771   _MK(RDV_ASYNC, 2, WAIT, WAIT, RGET(.2), RWAT(.4), LOFF(.5), SPUT(.6), SWAT(.8), LON(1));
772   _MK(RDV_ASYNC, 2, WAIT, WAIT, SPUT(.2), SWAT(.4), RGET(.6), LOFF(.7), RWAT(.8), LON(1));
773   _MK(RDV_ASYNC, 2, WAIT, WAIT, SPUT(.2), RGET(.4), SWAT(.6), LOFF(.7), RWAT(.8), LON(1));
774   _MK(RDV_ASYNC, 2, WAIT, WAIT, SPUT(.2), RGET(.4), RWAT(.6), LOFF(.7), SWAT(.8), LON(1));
775   _MK(RDV_ASYNC, 2, WAIT, WAIT, RGET(.2), SPUT(.4), SWAT(.6), LOFF(.7), RWAT(.8), LON(1));
776   _MK(RDV_ASYNC, 2, WAIT, WAIT, RGET(.2), SPUT(.4), RWAT(.6), LOFF(.7), SWAT(.8), LON(1));
777   _MK(RDV_ASYNC, 2, WAIT, WAIT, RGET(.2), RWAT(.4), SPUT(.6), LOFF(.7), SWAT(.8), LON(1));
778
779   // ONESIDE SYNC use cases
780
781   // All good
782   _MK(ONESIDE_SYNC, 1, END, END, SPUT(.2));
783   // Receiver off
784   _MK(ONESIDE_SYNC, 2, PUT, DIE, ROFF(.1), SPUT(.2), RON(1));
785   _MK(ONESIDE_SYNC, 2, PUT, DIE, SPUT(.2), ROFF(.3), RON(1));
786   // Sender off
787   _MK(ONESIDE_SYNC, 2, DIE, END, SPUT(.2), SOFF(.3), SON(1));
788   // Link off
789   _MK(ONESIDE_SYNC, 2, PUT, END, LOFF(.1), SPUT(.2), LON(1));
790   _MK(ONESIDE_SYNC, 2, PUT, END, SPUT(.2), LOFF(.3), LON(1));
791
792   // ONESIDE ASYNC use cases
793   // All good
794   _MK(ONESIDE_ASYNC, 2, END, END, SPUT(.2), SWAT(.4));
795   // Receiver off
796   _MK(ONESIDE_ASYNC, 2, PUT, DIE, ROFF(.1), SPUT(.2), SWAT(.4), RON(1));
797   _MK(ONESIDE_ASYNC, 2, WAIT, DIE, SPUT(.2), ROFF(.3), SWAT(.4), RON(1));
798   _MK(ONESIDE_ASYNC, 2, WAIT, DIE, SPUT(.2), SWAT(.4), ROFF(.5), RON(1));
799   // Sender off
800   _MK(ONESIDE_ASYNC, 2, DIE, END, SPUT(.2), SOFF(.3), SON(1));
801   // Link off
802   _MK(ONESIDE_ASYNC, 2, WAIT, END, LOFF(.1), SPUT(.2), SWAT(.4), LON(1));
803   _MK(ONESIDE_ASYNC, 2, WAIT, END, SPUT(.2), LOFF(.3), SWAT(.4), LON(1));
804   _MK(ONESIDE_ASYNC, 2, WAIT, END, SPUT(.2), SWAT(.4), LOFF(.5), LON(1));
805
806
807   SndStateProfile = sndP.str();
808   RcvStateProfile = rcvP.str();
809   LnkStateProfile = lnkP.str();
810
811   XBT_INFO("Will execute %i active scenarios out of %i.",active,index);
812   return start_time + 1;
813 }