Logo AND Algorithmique Numérique Distribuée

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