Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Revert "Include the output of this test in the tesh file, because it's linked from...
[simgrid.git] / teshsuite / s4u / activity-lifecycle / testing_comm.cpp
1 /* Copyright (c) 2010-2023. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "teshsuite/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 + precision_timing 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 + precision_timing 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 = sender_basic(send_done, false, 2);
210
211     simgrid::s4u::Actor::create("receiver", all_hosts[2], [&recv_done]() {
212       assert_exit(true, 2);
213       REQUIRE_NETWORK_FAILURE({
214         char* payload = simgrid::s4u::Mailbox::by_name("mb")->get<char>();
215         xbt_free(payload);
216       });
217       recv_done = true;
218     });
219
220     simgrid::s4u::this_actor::sleep_for(2);
221     sender->kill();
222     // let the test ends by itself. waiting for precision_timing should be enough.
223     simgrid::s4u::this_actor::sleep_for(0.00001);
224
225     INFO("Sender was not killed properly or receiver killed somehow. It shouldn't");
226     REQUIRE(not send_done);
227     REQUIRE(recv_done);
228
229     END_SECTION;
230   }
231
232   BEGIN_SECTION("comm recv and kill")
233   {
234     XBT_INFO("Launch an actor that waits on a recv, kill its host");
235     bool in_on_exit              = false;
236     bool returned_from_main      = false;
237     bool in_catch_before_on_exit = false;
238     bool in_catch_after_on_exit  = false;
239     bool send_done               = false;
240
241     simgrid::s4u::ActorPtr receiver =
242         simgrid::s4u::Actor::create("receiver", all_hosts[1], [&in_on_exit, &returned_from_main,
243                                                                &in_catch_before_on_exit, &in_catch_after_on_exit]() {
244           assert_exit(false, 1);
245           try {
246             simgrid::s4u::Mailbox::by_name("mb")->get<int>();
247           } catch (simgrid::NetworkFailureException const&) {
248             // Shouldn't get in here after the on_exit function
249             in_catch_before_on_exit = not in_on_exit;
250             in_catch_after_on_exit  = in_on_exit;
251           }
252           returned_from_main = true;
253         });
254
255     receiver->on_exit([&in_on_exit](bool) { in_on_exit = true; });
256
257     simgrid::s4u::ActorPtr sender = simgrid::s4u::Actor::create("sender", all_hosts[2], [&send_done]() {
258       assert_exit(true, 1);
259       int data = 42;
260       REQUIRE_NETWORK_FAILURE(simgrid::s4u::Mailbox::by_name("mb")->put(&data, 100000));
261       send_done = true;
262     });
263
264     simgrid::s4u::this_actor::sleep_for(1);
265     receiver->get_host()->turn_off();
266
267     // Note: If we don't sleep here, we don't "see" the bug
268     simgrid::s4u::this_actor::sleep_for(1);
269
270     INFO("Receiver's on_exit function was never called");
271     REQUIRE(in_on_exit);
272     INFO("or receiver mistakenly went to catch clause (before the on_exit function was called)");
273     REQUIRE(not in_catch_before_on_exit);
274     INFO("or receiver mistakenly went to catch clause (after the on_exit function was called)");
275     REQUIRE(not in_catch_after_on_exit);
276     INFO("or receiver returned from main normally even though its host was killed");
277     REQUIRE(not returned_from_main);
278     INFO("or sender killed somehow, and it shouldn't");
279     REQUIRE(send_done);
280     receiver->get_host()->turn_on();
281
282     END_SECTION;
283   }
284
285   BEGIN_SECTION("comm turn link off before send/recv")
286   {
287     XBT_INFO("try to communicate with communicating link turned off before start");
288     test_link_off_helper(0.0);
289
290     END_SECTION;
291   }
292
293   BEGIN_SECTION("comm turn link off between send/recv")
294   {
295     XBT_INFO("try to communicate with communicating link turned off between send and receive");
296     test_link_off_helper(1.0);
297
298     END_SECTION;
299   }
300
301   BEGIN_SECTION("comm turn link off during transfer")
302   {
303     XBT_INFO("try to communicate with communicating link turned off during transfer");
304     test_link_off_helper(2.0);
305
306     END_SECTION;
307   }
308
309   BEGIN_SECTION("comm turn link off during wait_any")
310   {
311     XBT_INFO("try to communicate with communicating link turned off during wait_any");
312     simgrid::s4u::ActorPtr receiver = simgrid::s4u::Actor::create("receiver", all_hosts[1], []() {
313       assert_exit(true, 2);
314       int* data;
315       simgrid::s4u::CommPtr comm                       = simgrid::s4u::Mailbox::by_name("mb")->get_async<int>(&data);
316       std::vector<simgrid::s4u::CommPtr> pending_comms = {comm};
317       REQUIRE_NETWORK_FAILURE(simgrid::s4u::Comm::wait_any(pending_comms));
318     });
319
320     simgrid::s4u::ActorPtr sender = simgrid::s4u::Actor::create("sender", all_hosts[2], []() {
321       assert_exit(true, 2);
322       int data = 42;
323       REQUIRE_NETWORK_FAILURE(simgrid::s4u::Mailbox::by_name("mb")->put(&data, 100000));
324     });
325
326     simgrid::s4u::this_actor::sleep_for(2.0);
327     XBT_VERB("link off");
328     simgrid::s4u::Link::by_name("link1")->turn_off();
329     simgrid::s4u::this_actor::sleep_for(2.0);
330     XBT_VERB("link on");
331     simgrid::s4u::Link::by_name("link1")->turn_on();
332
333     END_SECTION;
334   }
335
336   simgrid::s4u::this_actor::sleep_for(10);
337   assert_cleanup();
338 }