Logo AND Algorithmique Numérique Distribuée

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