Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Workaround false alarm stack-use-after-scope from Asan with operator<<.
[simgrid.git] / teshsuite / s4u / activity-lifecycle / testing_test-wait.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
8 //========== Creators: create an async activity
9
10 template <typename Activity> using creator_type = Activity (*)(double);
11
12 // Create a new async execution with given duration
13 static simgrid::s4u::ExecPtr create_exec(double duration)
14 {
15   double speed = simgrid::s4u::this_actor::get_host()->get_speed();
16   return simgrid::s4u::this_actor::exec_async(speed * duration);
17 }
18
19 // TODO: check other kinds of activities too (Io, Comm, ...)
20
21 //========== Testers: test the completion of an activity
22
23 template <typename Activity> using tester_type = bool (*)(const Activity&);
24
25 // Calls activity->test() and returns its result
26 template <typename Activity> bool tester_test(const Activity& activity)
27 {
28   return activity->test();
29 }
30
31 // Calls activity->wait_for(Duration / 128.0) and returns true when activity is terminated, just like test()
32 template <int Duration, typename Activity> bool tester_wait(const Activity& activity)
33 {
34   constexpr double duration = Duration / 128.0;
35   const double timeout      = simgrid::s4u::Engine::get_clock() + duration;
36   bool ret;
37   try {
38     XBT_DEBUG("calling wait_for(%f)", duration);
39     activity->wait_for(duration);
40     XBT_DEBUG("wait_for() returned normally");
41     ret = true;
42   } catch (const simgrid::TimeoutException& e) {
43     XBT_DEBUG("wait_for() timed out (%s)", e.what());
44     INFO("wait_for() timeout should expire at expected date: " + std::to_string(timeout));
45     REQUIRE(simgrid::s4u::Engine::get_clock() == Approx(timeout));
46     ret = false;
47   } catch (const simgrid::Exception& e) {
48     XBT_DEBUG("wait_for() threw an exception: %s", e.what());
49     ret = true;
50   }
51   INFO("wait_for() should return before timeout expiration at date: " << timeout);
52   REQUIRE(simgrid::s4u::Engine::get_clock() <= Approx(timeout));
53   return ret;
54 }
55
56 // Calls wait_any_for([activity], Duration / 128.0) and returns true when activity is terminated, just like test()
57 template <int Duration, typename Activity> bool tester_wait_any(const Activity& activity)
58 {
59   constexpr double duration = Duration / 128.0;
60   const double timeout      = simgrid::s4u::Engine::get_clock() + duration;
61   bool ret;
62   try {
63     std::vector<Activity> activities = {activity};
64     XBT_DEBUG("calling wait_any_for(%f)", duration);
65     int index = Activity::element_type::wait_any_for(&activities, duration);
66     if (index == -1) {
67       XBT_DEBUG("wait_any_for() timed out");
68       INFO("wait_any_for() timeout should expire at expected date: " << timeout);
69       REQUIRE(simgrid::s4u::Engine::get_clock() == Approx(timeout));
70       ret = false;
71     } else {
72       XBT_DEBUG("wait_any_for() returned index %d", index);
73       REQUIRE(index == 0);
74       ret = true;
75     }
76   } catch (const simgrid::Exception& e) {
77     XBT_DEBUG("wait_any_for() threw an exception: %s", e.what());
78     ret = true;
79   }
80   INFO("wait_any_for() should return before timeout expiration at date: " << timeout);
81   REQUIRE(simgrid::s4u::Engine::get_clock() <= Approx(timeout));
82   return ret;
83 }
84
85 //========== Waiters: wait for the completion of an activity
86
87 template <typename Activity> using waiter_type = void (*)(const Activity&);
88
89 // Wait for 6s
90 template <typename Activity> void waiter_sleep6(const Activity&)
91 {
92   simgrid::s4u::this_actor::sleep_for(6.0);
93   XBT_DEBUG("wake up after 6s sleep");
94 }
95
96 // Wait for completion of activity
97 template <typename Activity> void waiter_wait(const Activity& activity)
98 {
99   activity->wait();
100   XBT_DEBUG("end of wait()");
101 }
102
103 //========== Finally, the test templates
104
105 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test> void test_trivial()
106 {
107   XBT_INFO("Launch an activity for 5s, and let it proceed before test");
108
109   simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], []() {
110     assert_exit(true, 6.);
111     Activity activity = Create(5.0);
112     simgrid::s4u::this_actor::sleep_for(6.0);
113     INFO("activity should be terminated now");
114     REQUIRE(Test(activity));
115   });
116   actor->join();
117 }
118
119 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test> void test_basic()
120 {
121   XBT_INFO("Launch an activity for 5s, and test while it proceeds");
122
123   simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], []() {
124     assert_exit(true, 6.);
125     Activity activity = Create(5.0);
126     for (int i = 0; i < 3; i++) {
127       const double timestep = simgrid::s4u::Engine::get_clock() + 2.0;
128       INFO("activity should be still running (i = " << i << ")");
129       REQUIRE(not Test(activity));
130       simgrid::s4u::this_actor::sleep_until(timestep);
131     }
132     INFO("activity should be terminated now");
133     REQUIRE(Test(activity));
134   });
135   actor->join();
136 }
137
138 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test> void test_cancel()
139 {
140   XBT_INFO("Launch an activity for 5s, and cancel it after 2s");
141
142   simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], []() {
143     assert_exit(true, 2.);
144     Activity activity = Create(5.0);
145     simgrid::s4u::this_actor::sleep_for(2.0);
146     activity->cancel();
147     INFO("activity should be terminated now");
148     REQUIRE(Test(activity));
149   });
150   actor->join();
151 }
152
153 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test, waiter_type<Activity> Wait>
154 void test_failure_actor()
155 {
156   XBT_INFO("Launch an activity for 5s, and kill running actor after 2s");
157
158   Activity activity;
159   simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], [&activity]() {
160     assert_exit(false, 2.);
161     activity = Create(5.0);
162     Wait(activity);
163     FAIL("should not be here!");
164   });
165   const double timestep = simgrid::s4u::Engine::get_clock() + 2.0;
166   simgrid::s4u::this_actor::sleep_for(1.0);
167   INFO("activity should be still running");
168   REQUIRE(not Test(activity));
169   simgrid::s4u::this_actor::sleep_until(timestep);
170   actor->kill();
171   INFO("activity should be terminated now");
172   REQUIRE(Test(activity));
173 }
174
175 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test, waiter_type<Activity> Wait>
176 void test_failure_host()
177 {
178   XBT_INFO("Launch an activity for 5s, and shutdown host 2s");
179
180   Activity activity;
181   simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], [&activity]() {
182     assert_exit(false, 2.);
183     activity = Create(5.0);
184     Wait(activity);
185     FAIL("should not be here!");
186   });
187   const double timestep = simgrid::s4u::Engine::get_clock() + 2.0;
188   simgrid::s4u::this_actor::sleep_for(1.0);
189   INFO("activity should be still running");
190   REQUIRE(not Test(activity));
191   simgrid::s4u::this_actor::sleep_until(timestep);
192   actor->get_host()->turn_off();
193   actor->get_host()->turn_on();
194   INFO("activity should be terminated now");
195   REQUIRE(Test(activity));
196 }
197
198 //==========
199
200 using simgrid::s4u::ExecPtr;
201
202 TEST_CASE("Activity test/wait: using <tester_test>")
203 {
204   XBT_INFO("#####[ launch next test ]#####");
205
206   RUN_SECTION("exec: run and test once", test_trivial<ExecPtr, create_exec, tester_test>);
207   RUN_SECTION("exec: run and test many", test_basic<ExecPtr, create_exec, tester_test>);
208   RUN_SECTION("exec: cancel and test", test_cancel<ExecPtr, create_exec, tester_test>);
209   RUN_SECTION("exec: actor failure and test / sleep",
210               test_failure_actor<ExecPtr, create_exec, tester_test, waiter_sleep6>);
211   RUN_SECTION("exec: host failure and test / sleep",
212               test_failure_host<ExecPtr, create_exec, tester_test, waiter_sleep6>);
213   RUN_SECTION("exec: actor failure and test / wait",
214               test_failure_actor<ExecPtr, create_exec, tester_test, waiter_wait>);
215   RUN_SECTION("exec: host failure and test / wait",
216               test_failure_host<ExecPtr, create_exec, tester_test, waiter_wait>);
217
218   simgrid::s4u::this_actor::sleep_for(10);
219   assert_cleanup();
220 }
221
222 TEST_CASE("Activity test/wait: using <tester_wait<0>>")
223 {
224   XBT_INFO("#####[ launch next test ]#####");
225
226   RUN_SECTION("exec: run and wait<0> once", test_trivial<ExecPtr, create_exec, tester_wait<0>>);
227   RUN_SECTION("exec: run and wait<0> many", test_basic<ExecPtr, create_exec, tester_wait<0>>);
228   RUN_SECTION("exec: cancel and wait<0>", test_cancel<ExecPtr, create_exec, tester_wait<0>>);
229   RUN_SECTION("exec: actor failure and wait<0> / sleep",
230               test_failure_actor<ExecPtr, create_exec, tester_wait<0>, waiter_sleep6>);
231   RUN_SECTION("exec: host failure and wait<0> / sleep",
232               test_failure_host<ExecPtr, create_exec, tester_wait<0>, waiter_sleep6>);
233   RUN_SECTION("exec: actor failure and wait<0> / wait",
234               test_failure_actor<ExecPtr, create_exec, tester_wait<0>, waiter_wait>);
235   RUN_SECTION("exec: host failure and wait<0> / wait",
236               test_failure_host<ExecPtr, create_exec, tester_wait<0>, waiter_wait>);
237
238   simgrid::s4u::this_actor::sleep_for(10);
239   assert_cleanup();
240 }
241
242 TEST_CASE("Activity test/wait: using <tester_wait<1>>")
243 {
244   XBT_INFO("#####[ launch next test ]#####");
245
246   RUN_SECTION("exec: run and wait<1> once", test_trivial<ExecPtr, create_exec, tester_wait<1>>);
247   RUN_SECTION("exec: run and wait<1> many", test_basic<ExecPtr, create_exec, tester_wait<1>>);
248   RUN_SECTION("exec: cancel and wait<1>", test_cancel<ExecPtr, create_exec, tester_wait<1>>);
249   RUN_SECTION("exec: actor failure and wait<1> / sleep",
250               test_failure_actor<ExecPtr, create_exec, tester_wait<1>, waiter_sleep6>);
251   RUN_SECTION("exec: host failure and wait<1> / sleep",
252               test_failure_host<ExecPtr, create_exec, tester_wait<1>, waiter_sleep6>);
253   RUN_SECTION("exec: actor failure and wait<1> / wait",
254               test_failure_actor<ExecPtr, create_exec, tester_wait<1>, waiter_wait>);
255   RUN_SECTION("exec: host failure and wait<1> / wait",
256               test_failure_host<ExecPtr, create_exec, tester_wait<1>, waiter_wait>);
257
258   simgrid::s4u::this_actor::sleep_for(10);
259   assert_cleanup();
260 }
261
262 TEST_CASE("Activity test/wait: using <tester_wait_any<0>>")
263 {
264   XBT_INFO("#####[ launch next test ]#####");
265
266   RUN_SECTION("exec: run and wait_any<0> once", test_trivial<ExecPtr, create_exec, tester_wait_any<0>>);
267   RUN_SECTION("exec: run and wait_any<0> many", test_basic<ExecPtr, create_exec, tester_wait_any<0>>);
268   RUN_SECTION("exec: cancel and wait_any<0>", test_cancel<ExecPtr, create_exec, tester_wait_any<1>>);
269   RUN_SECTION("exec: actor failure and wait_any<0> / sleep",
270               test_failure_actor<ExecPtr, create_exec, tester_wait_any<0>, waiter_sleep6>);
271   RUN_SECTION("exec: host failure and wait_any<0> / sleep",
272               test_failure_host<ExecPtr, create_exec, tester_wait_any<0>, waiter_sleep6>);
273   RUN_SECTION("exec: actor failure and wait_any<0> / wait",
274               test_failure_actor<ExecPtr, create_exec, tester_wait_any<0>, waiter_wait>);
275   RUN_SECTION("exec: host failure and wait_any<0> / wait",
276               test_failure_host<ExecPtr, create_exec, tester_wait_any<0>, waiter_wait>);
277
278   simgrid::s4u::this_actor::sleep_for(10);
279   assert_cleanup();
280 }
281
282 TEST_CASE("Activity test/wait: using <tester_wait_any<1>>")
283 {
284   XBT_INFO("#####[ launch next test ]#####");
285
286   RUN_SECTION("exec: run and wait_any<1> once", test_trivial<ExecPtr, create_exec, tester_wait_any<1>>);
287   RUN_SECTION("exec: run and wait_any<1> many", test_basic<ExecPtr, create_exec, tester_wait_any<1>>);
288   RUN_SECTION("exec: cancel and wait_any<1>", test_cancel<ExecPtr, create_exec, tester_wait_any<1>>);
289   RUN_SECTION("exec: actor failure and wait_any<1> / sleep",
290               test_failure_actor<ExecPtr, create_exec, tester_wait_any<1>, waiter_sleep6>);
291   RUN_SECTION("exec: host failure and wait_any<1> / sleep",
292               test_failure_host<ExecPtr, create_exec, tester_wait_any<1>, waiter_sleep6>);
293   RUN_SECTION("exec: actor failure and wait_any<1> / wait",
294               test_failure_actor<ExecPtr, create_exec, tester_wait_any<1>, waiter_wait>);
295   RUN_SECTION("exec: host failure and wait_any<1> / wait",
296               test_failure_host<ExecPtr, create_exec, tester_wait_any<1>, waiter_wait>);
297
298   simgrid::s4u::this_actor::sleep_for(10);
299   assert_cleanup();
300 }