Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
47b665790f1499c63321fc60c5c42db0d63de355
[simgrid.git] / teshsuite / s4u / activity-lifecycle / testing_comm.cpp
1 /* Copyright (c) 2010-2020. 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 #include "activity-lifecycle.hpp"
7
8 static void test_link_off_helper(double delay)
9 {
10   const double start = simgrid::s4u::Engine::get_clock();
11
12   simgrid::s4u::ActorPtr receiver = simgrid::s4u::Actor::create("receiver", all_hosts[1], [&start]() {
13     assert_exit(true, 9);
14     double milestone[5] = {0.5, 3.5, 4.5, 7.5, 9.0};
15     for (int i = 0; i < 5; i++)
16       milestone[i] += start;
17     for (int i = 0; i < 4; i++) {
18       simgrid::s4u::this_actor::sleep_until(milestone[i]);
19       try {
20         XBT_VERB("get(%c)", 'A' + i);
21         simgrid::s4u::Mailbox::by_name("mb")->get();
22         return;
23       } catch (simgrid::NetworkFailureException const&) {
24         XBT_VERB("got expected NetworkFailureException");
25       }
26     }
27     simgrid::s4u::this_actor::sleep_until(milestone[4]);
28   });
29
30   simgrid::s4u::ActorPtr sender = simgrid::s4u::Actor::create("sender", all_hosts[2], [&start]() {
31     assert_exit(true, 9);
32     int data            = 42;
33     double milestone[5] = {1.5, 2.5, 5.5, 6.5, 9.0};
34     for (int i = 0; i < 5; i++)
35       milestone[i] += start;
36     for (int i = 0; i < 2; i++) {
37       simgrid::s4u::this_actor::sleep_until(milestone[i]);
38       XBT_VERB("dsend(%c)", 'A' + i);
39       simgrid::s4u::Mailbox::by_name("mb")->put_init(&data, 100000)->detach();
40     }
41     for (int i = 2; i < 4; i++) {
42       simgrid::s4u::this_actor::sleep_until(milestone[i]);
43       try {
44         XBT_VERB("put(%c)", 'A' + i);
45         simgrid::s4u::Mailbox::by_name("mb")->put(&data, 100000);
46         return;
47       } catch (simgrid::NetworkFailureException const&) {
48         XBT_VERB("got expected NetworkFailureException");
49       }
50     }
51     simgrid::s4u::this_actor::sleep_until(milestone[4]);
52   });
53
54   for (int i = 0; i < 4; i++) {
55     XBT_VERB("##### %d / 4 #####", i + 1);
56     simgrid::s4u::this_actor::sleep_for(delay);
57     XBT_VERB("link off");
58     simgrid::s4u::Link::by_name("link1")->turn_off();
59     simgrid::s4u::this_actor::sleep_for(2.0 - delay);
60     XBT_VERB("link on");
61     simgrid::s4u::Link::by_name("link1")->turn_on();
62   }
63   simgrid::s4u::this_actor::sleep_for(1.5);
64 };
65
66 TEST_CASE("Activity lifecycle: comm activities")
67 {
68   XBT_INFO("#####[ launch next \"comm\" test ]#####");
69
70   BEGIN_SECTION("comm")
71   {
72     XBT_INFO("Launch a communication");
73     bool send_done = false;
74     bool recv_done = false;
75
76     simgrid::s4u::Actor::create("sender", all_hosts[1], [&send_done]() {
77       assert_exit(true, 5);
78       char* payload = xbt_strdup("toto");
79       simgrid::s4u::Mailbox::by_name("mb")->put(payload, 5000);
80       send_done = true;
81     });
82
83     simgrid::s4u::Actor::create("receiver", all_hosts[2], [&recv_done]() {
84       assert_exit(true, 5);
85       void* payload = simgrid::s4u::Mailbox::by_name("mb")->get();
86       xbt_free(payload);
87       recv_done = true;
88     });
89
90     simgrid::s4u::this_actor::sleep_for(9);
91     INFO("Sender or receiver killed somehow. It shouldn't");
92     REQUIRE(send_done);
93     REQUIRE(recv_done);
94
95     END_SECTION;
96   }
97
98   BEGIN_SECTION("comm dsend and quit (put before get)")
99   {
100     XBT_INFO("Launch a detached communication and end right after");
101     bool dsend_done = false;
102     bool recv_done  = false;
103
104     simgrid::s4u::ActorPtr sender = simgrid::s4u::Actor::create("sender", all_hosts[1], [&dsend_done]() {
105       assert_exit(true, 0);
106       char* payload = xbt_strdup("toto");
107       simgrid::s4u::Mailbox::by_name("mb")->put_init(payload, 1000)->detach();
108       dsend_done = true;
109     });
110
111     simgrid::s4u::Actor::create("receiver", all_hosts[2], [&recv_done]() {
112       assert_exit(true, 3);
113       simgrid::s4u::this_actor::sleep_for(2);
114       void* payload = simgrid::s4u::Mailbox::by_name("mb")->get();
115       xbt_free(payload);
116       recv_done = true;
117     });
118
119     // Sleep long enough to let the test ends by itself. 3 + surf_precision should be enough.
120     simgrid::s4u::this_actor::sleep_for(4);
121     INFO("Sender or receiver killed somehow. It shouldn't");
122     REQUIRE(dsend_done);
123     REQUIRE(recv_done);
124
125     END_SECTION;
126   }
127
128   BEGIN_SECTION("comm dsend and quit (get before put)")
129   {
130     XBT_INFO("Launch a detached communication and end right after");
131     bool dsend_done = false;
132     bool recv_done  = false;
133
134     simgrid::s4u::ActorPtr sender = simgrid::s4u::Actor::create("sender", all_hosts[1], [&dsend_done]() {
135       assert_exit(true, 2);
136       char* payload = xbt_strdup("toto");
137       simgrid::s4u::this_actor::sleep_for(2);
138       simgrid::s4u::Mailbox::by_name("mb")->put_init(payload, 1000)->detach();
139       dsend_done = true;
140     });
141
142     simgrid::s4u::Actor::create("receiver", all_hosts[2], [&recv_done]() {
143       assert_exit(true, 3);
144       void* payload = simgrid::s4u::Mailbox::by_name("mb")->get();
145       xbt_free(payload);
146       recv_done = true;
147     });
148
149     // Sleep long enough to let the test ends by itself. 3 + surf_precision should be enough.
150     simgrid::s4u::this_actor::sleep_for(4);
151     INFO("Sender or receiver killed somehow. It shouldn't");
152     REQUIRE(dsend_done);
153     REQUIRE(recv_done);
154
155     END_SECTION;
156   }
157
158   BEGIN_SECTION("comm kill sender")
159   {
160     XBT_INFO("Launch a communication and kill the sender");
161     bool send_done = false;
162     bool recv_done = false;
163
164     simgrid::s4u::ActorPtr sender = simgrid::s4u::Actor::create("sender", all_hosts[1], [&send_done]() {
165       assert_exit(false, 2);
166       // Encapsulate the payload in a std::unique_ptr so that it is correctly free'd when the sender is killed during
167       // its communication (thanks to RAII).  The pointer is then released when the communication is over.
168       std::unique_ptr<char, decltype(&xbt_free_f)> payload(xbt_strdup("toto"), &xbt_free_f);
169       simgrid::s4u::Mailbox::by_name("mb")->put(payload.get(), 5000);
170       payload.release();
171       send_done = true;
172     });
173
174     simgrid::s4u::Actor::create("receiver", all_hosts[2], [&recv_done]() {
175       assert_exit(true, 2);
176       void* payload = nullptr;
177       REQUIRE_THROWS_AS(payload = simgrid::s4u::Mailbox::by_name("mb")->get(), simgrid::NetworkFailureException);
178       xbt_free(payload);
179       recv_done = true;
180     });
181
182     simgrid::s4u::this_actor::sleep_for(2);
183     sender->kill();
184     // let the test ends by itself. waiting for surf_precision should be enough.
185     simgrid::s4u::this_actor::sleep_for(0.00001);
186
187     INFO("Sender was not killed properly or receiver killed somehow. It shouldn't");
188     REQUIRE(not send_done);
189     REQUIRE(recv_done);
190
191     END_SECTION;
192   }
193
194   BEGIN_SECTION("comm recv and kill")
195   {
196     XBT_INFO("Launch an actor that waits on a recv, kill its host");
197     bool in_on_exit              = false;
198     bool returned_from_main      = false;
199     bool in_catch_before_on_exit = false;
200     bool in_catch_after_on_exit  = false;
201     bool send_done               = false;
202
203     simgrid::s4u::ActorPtr receiver =
204         simgrid::s4u::Actor::create("receiver", all_hosts[1], [&in_on_exit, &returned_from_main,
205                                                                &in_catch_before_on_exit, &in_catch_after_on_exit]() {
206           assert_exit(false, 1);
207           try {
208             simgrid::s4u::Mailbox::by_name("mb")->get();
209           } catch (simgrid::NetworkFailureException const&) {
210             // Shouldn't get in here
211             in_catch_before_on_exit = not in_on_exit;
212             in_catch_after_on_exit  = in_on_exit;
213           }
214           returned_from_main = true;
215         });
216
217     receiver->on_exit([&in_on_exit](bool) { in_on_exit = true; });
218
219     simgrid::s4u::ActorPtr sender = simgrid::s4u::Actor::create("sender", all_hosts[2], [&send_done]() {
220       assert_exit(true, 1);
221       int data = 42;
222       REQUIRE_THROWS_AS(simgrid::s4u::Mailbox::by_name("mb")->put(&data, 100000), simgrid::NetworkFailureException);
223       send_done = true;
224     });
225
226     simgrid::s4u::this_actor::sleep_for(1);
227     receiver->get_host()->turn_off();
228
229     // Note: If we don't sleep here, we don't "see" the bug
230     simgrid::s4u::this_actor::sleep_for(1);
231
232     INFO("Receiver's on_exit function was never called");
233     REQUIRE(in_on_exit);
234     INFO("or receiver mistakenly went to catch clause (before the on_exit function was called)");
235     REQUIRE(not in_catch_before_on_exit);
236     INFO("or receiver mistakenly went to catch clause (after the on_exit function was called)");
237     REQUIRE(not in_catch_after_on_exit);
238     INFO("or receiver returned from main normally even though its host was killed");
239     REQUIRE(not returned_from_main);
240     INFO("or sender killed somehow, and it shouldn't");
241     REQUIRE(send_done);
242     receiver->get_host()->turn_on();
243
244     END_SECTION;
245   }
246
247   BEGIN_SECTION("comm turn link off before send/recv")
248   {
249     XBT_INFO("try to communicate with communicating link turned off before start");
250     test_link_off_helper(0.0);
251
252     END_SECTION;
253   }
254
255   BEGIN_SECTION("comm turn link off between send/recv")
256   {
257     XBT_INFO("try to communicate with communicating link turned off between send and receive");
258     test_link_off_helper(1.0);
259
260     END_SECTION;
261   }
262
263   BEGIN_SECTION("comm turn link off during transfer")
264   {
265     XBT_INFO("try to communicate with communicating link turned off during transfer");
266     test_link_off_helper(2.0);
267
268     END_SECTION;
269   }
270
271   BEGIN_SECTION("comm turn link off during wait_any")
272   {
273     XBT_INFO("try to communicate with communicating link turned off during wait_any");
274     simgrid::s4u::ActorPtr receiver = simgrid::s4u::Actor::create("receiver", all_hosts[1], []() {
275       assert_exit(true, 2);
276       int* data;
277       std::vector<simgrid::s4u::CommPtr> pending_comms;
278       simgrid::s4u::CommPtr comm = simgrid::s4u::Mailbox::by_name("mb")->get_async((void**)&data);
279       pending_comms.push_back(comm);
280       REQUIRE_THROWS_AS(simgrid::s4u::Comm::wait_any(&pending_comms), simgrid::NetworkFailureException);
281     });
282
283     simgrid::s4u::ActorPtr sender = simgrid::s4u::Actor::create("sender", all_hosts[2], []() {
284       assert_exit(true, 2);
285       int data = 42;
286       REQUIRE_THROWS_AS(simgrid::s4u::Mailbox::by_name("mb")->put(&data, 100000), simgrid::NetworkFailureException);
287     });
288
289     simgrid::s4u::this_actor::sleep_for(2.0);
290     XBT_VERB("link off");
291     simgrid::s4u::Link::by_name("link1")->turn_off();
292     simgrid::s4u::this_actor::sleep_for(2.0);
293     XBT_VERB("link on");
294     simgrid::s4u::Link::by_name("link1")->turn_on();
295
296     END_SECTION;
297   }
298
299   simgrid::s4u::this_actor::sleep_for(10);
300   assert_cleanup();
301 }