Logo AND Algorithmique Numérique Distribuée

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