Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Port one test from Exec::wait_any_for to ActivitySet
[simgrid.git] / teshsuite / s4u / activity-lifecycle / testing_test-wait.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
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     simgrid::s4u::ActivitySet set;
64     set.push(activity);
65
66     XBT_DEBUG("calling wait_any_for(%f)", duration);
67     auto waited_activity = set.wait_any_for(duration);
68
69     XBT_DEBUG("wait_any_for() returned activity %p", waited_activity.get());
70     REQUIRE(waited_activity.get() == activity);
71     ret = true;
72
73   } catch (const simgrid::TimeoutException& e) {
74     XBT_DEBUG("wait_any_for() timed out");
75     INFO("wait_any_for() timeout should expire at expected date: " << timeout);
76     REQUIRE(simgrid::s4u::Engine::get_clock() == Approx(timeout));
77     ret = false;
78   } catch (const simgrid::Exception& e) {
79     XBT_DEBUG("wait_any_for() threw an exception: %s", e.what());
80     ret = true;
81   }
82   INFO("wait_any_for() should return before timeout expiration at date: " << timeout);
83   REQUIRE(simgrid::s4u::Engine::get_clock() <= Approx(timeout));
84   return ret;
85 }
86
87 //========== Waiters: wait for the completion of an activity
88
89 template <typename Activity> using waiter_type = void (*)(const Activity&);
90
91 // Wait for 6s
92 template <typename Activity> void waiter_sleep6(const Activity&)
93 {
94   simgrid::s4u::this_actor::sleep_for(6.0);
95   XBT_DEBUG("wake up after 6s sleep");
96 }
97
98 // Wait for completion of activity
99 template <typename Activity> void waiter_wait(const Activity& activity)
100 {
101   activity->wait();
102   XBT_DEBUG("end of wait()");
103 }
104
105 //========== Finally, the test templates
106
107 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test> void test_trivial()
108 {
109   XBT_INFO("Launch an activity for 5s, and let it proceed before test");
110
111   simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], []() {
112     assert_exit(true, 6.);
113     Activity activity = Create(5.0);
114     simgrid::s4u::this_actor::sleep_for(6.0);
115     INFO("activity should be terminated now");
116     REQUIRE(Test(activity));
117   });
118   actor->join();
119 }
120
121 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test> void test_basic()
122 {
123   XBT_INFO("Launch an activity for 5s, and test while it proceeds");
124
125   simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], []() {
126     assert_exit(true, 6.);
127     Activity activity = Create(5.0);
128     for (int i = 0; i < 3; i++) {
129       const double timestep = simgrid::s4u::Engine::get_clock() + 2.0;
130       INFO("activity should be still running (i = " << i << ")");
131       REQUIRE(not Test(activity));
132       simgrid::s4u::this_actor::sleep_until(timestep);
133     }
134     INFO("activity should be terminated now");
135     REQUIRE(Test(activity));
136   });
137   actor->join();
138 }
139
140 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test> void test_cancel()
141 {
142   XBT_INFO("Launch an activity for 5s, and cancel it after 2s");
143
144   simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], []() {
145     assert_exit(true, 2.);
146     Activity activity = Create(5.0);
147     simgrid::s4u::this_actor::sleep_for(2.0);
148     activity->cancel();
149     INFO("activity should be terminated now");
150     REQUIRE(Test(activity));
151   });
152   actor->join();
153 }
154
155 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test, waiter_type<Activity> Wait>
156 void test_failure_actor()
157 {
158   XBT_INFO("Launch an activity for 5s, and kill running actor after 2s");
159
160   Activity activity;
161   simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], [&activity]() {
162     assert_exit(false, 2.);
163     activity = Create(5.0);
164     Wait(activity);
165     FAIL("should not be here!");
166   });
167   const double timestep = simgrid::s4u::Engine::get_clock() + 2.0;
168   simgrid::s4u::this_actor::sleep_for(1.0);
169   INFO("activity should be still running");
170   REQUIRE(not Test(activity));
171   simgrid::s4u::this_actor::sleep_until(timestep);
172   actor->kill();
173   INFO("activity should be terminated now");
174   REQUIRE(Test(activity));
175 }
176
177 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test, waiter_type<Activity> Wait>
178 void test_failure_host()
179 {
180   XBT_INFO("Launch an activity for 5s, and shutdown host 2s");
181
182   Activity activity;
183   simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], [&activity]() {
184     assert_exit(false, 2.);
185     activity = Create(5.0);
186     Wait(activity);
187     FAIL("should not be here!");
188   });
189   const double timestep = simgrid::s4u::Engine::get_clock() + 2.0;
190   simgrid::s4u::this_actor::sleep_for(1.0);
191   INFO("activity should be still running");
192   REQUIRE(not Test(activity));
193   simgrid::s4u::this_actor::sleep_until(timestep);
194   actor->get_host()->turn_off();
195   actor->get_host()->turn_on();
196   INFO("activity should be terminated now");
197   REQUIRE(Test(activity));
198 }
199
200 //==========
201
202 using simgrid::s4u::ExecPtr;
203
204 TEST_CASE("Activity test/wait: using <tester_test>")
205 {
206   XBT_INFO("#####[ launch next test ]#####");
207
208   RUN_SECTION("exec: run and test once", test_trivial<ExecPtr, create_exec, tester_test>);
209   RUN_SECTION("exec: run and test many", test_basic<ExecPtr, create_exec, tester_test>);
210   RUN_SECTION("exec: cancel and test", test_cancel<ExecPtr, create_exec, tester_test>);
211   RUN_SECTION("exec: actor failure and test / sleep",
212               test_failure_actor<ExecPtr, create_exec, tester_test, waiter_sleep6>);
213   RUN_SECTION("exec: host failure and test / sleep",
214               test_failure_host<ExecPtr, create_exec, tester_test, waiter_sleep6>);
215   RUN_SECTION("exec: actor failure and test / wait",
216               test_failure_actor<ExecPtr, create_exec, tester_test, waiter_wait>);
217   RUN_SECTION("exec: host failure and test / wait",
218               test_failure_host<ExecPtr, create_exec, tester_test, waiter_wait>);
219
220   simgrid::s4u::this_actor::sleep_for(10);
221   assert_cleanup();
222 }
223
224 TEST_CASE("Activity test/wait: using <tester_wait<0>>")
225 {
226   XBT_INFO("#####[ launch next test ]#####");
227
228   RUN_SECTION("exec: run and wait<0> once", test_trivial<ExecPtr, create_exec, tester_wait<0>>);
229   RUN_SECTION("exec: run and wait<0> many", test_basic<ExecPtr, create_exec, tester_wait<0>>);
230   RUN_SECTION("exec: cancel and wait<0>", test_cancel<ExecPtr, create_exec, tester_wait<0>>);
231   RUN_SECTION("exec: actor failure and wait<0> / sleep",
232               test_failure_actor<ExecPtr, create_exec, tester_wait<0>, waiter_sleep6>);
233   RUN_SECTION("exec: host failure and wait<0> / sleep",
234               test_failure_host<ExecPtr, create_exec, tester_wait<0>, waiter_sleep6>);
235   RUN_SECTION("exec: actor failure and wait<0> / wait",
236               test_failure_actor<ExecPtr, create_exec, tester_wait<0>, waiter_wait>);
237   RUN_SECTION("exec: host failure and wait<0> / wait",
238               test_failure_host<ExecPtr, create_exec, tester_wait<0>, waiter_wait>);
239
240   simgrid::s4u::this_actor::sleep_for(10);
241   assert_cleanup();
242 }
243
244 TEST_CASE("Activity test/wait: using <tester_wait<1>>")
245 {
246   XBT_INFO("#####[ launch next test ]#####");
247
248   RUN_SECTION("exec: run and wait<1> once", test_trivial<ExecPtr, create_exec, tester_wait<1>>);
249   RUN_SECTION("exec: run and wait<1> many", test_basic<ExecPtr, create_exec, tester_wait<1>>);
250   RUN_SECTION("exec: cancel and wait<1>", test_cancel<ExecPtr, create_exec, tester_wait<1>>);
251   RUN_SECTION("exec: actor failure and wait<1> / sleep",
252               test_failure_actor<ExecPtr, create_exec, tester_wait<1>, waiter_sleep6>);
253   RUN_SECTION("exec: host failure and wait<1> / sleep",
254               test_failure_host<ExecPtr, create_exec, tester_wait<1>, waiter_sleep6>);
255   RUN_SECTION("exec: actor failure and wait<1> / wait",
256               test_failure_actor<ExecPtr, create_exec, tester_wait<1>, waiter_wait>);
257   RUN_SECTION("exec: host failure and wait<1> / wait",
258               test_failure_host<ExecPtr, create_exec, tester_wait<1>, waiter_wait>);
259
260   simgrid::s4u::this_actor::sleep_for(10);
261   assert_cleanup();
262 }
263
264 TEST_CASE("Activity test/wait: using <tester_wait_any<0>>")
265 {
266   XBT_INFO("#####[ launch next test ]#####");
267
268   RUN_SECTION("exec: run and wait_any<0> once", test_trivial<ExecPtr, create_exec, tester_wait_any<0>>);
269   RUN_SECTION("exec: run and wait_any<0> many", test_basic<ExecPtr, create_exec, tester_wait_any<0>>);
270   RUN_SECTION("exec: cancel and wait_any<0>", test_cancel<ExecPtr, create_exec, tester_wait_any<1>>);
271   RUN_SECTION("exec: actor failure and wait_any<0> / sleep",
272               test_failure_actor<ExecPtr, create_exec, tester_wait_any<0>, waiter_sleep6>);
273   RUN_SECTION("exec: host failure and wait_any<0> / sleep",
274               test_failure_host<ExecPtr, create_exec, tester_wait_any<0>, waiter_sleep6>);
275   RUN_SECTION("exec: actor failure and wait_any<0> / wait",
276               test_failure_actor<ExecPtr, create_exec, tester_wait_any<0>, waiter_wait>);
277   RUN_SECTION("exec: host failure and wait_any<0> / wait",
278               test_failure_host<ExecPtr, create_exec, tester_wait_any<0>, waiter_wait>);
279
280   simgrid::s4u::this_actor::sleep_for(10);
281   assert_cleanup();
282 }
283
284 TEST_CASE("Activity test/wait: using <tester_wait_any<1>>")
285 {
286   XBT_INFO("#####[ launch next test ]#####");
287
288   RUN_SECTION("exec: run and wait_any<1> once", test_trivial<ExecPtr, create_exec, tester_wait_any<1>>);
289   RUN_SECTION("exec: run and wait_any<1> many", test_basic<ExecPtr, create_exec, tester_wait_any<1>>);
290   RUN_SECTION("exec: cancel and wait_any<1>", test_cancel<ExecPtr, create_exec, tester_wait_any<1>>);
291   RUN_SECTION("exec: actor failure and wait_any<1> / sleep",
292               test_failure_actor<ExecPtr, create_exec, tester_wait_any<1>, waiter_sleep6>);
293   RUN_SECTION("exec: host failure and wait_any<1> / sleep",
294               test_failure_host<ExecPtr, create_exec, tester_wait_any<1>, waiter_sleep6>);
295   RUN_SECTION("exec: actor failure and wait_any<1> / wait",
296               test_failure_actor<ExecPtr, create_exec, tester_wait_any<1>, waiter_wait>);
297   RUN_SECTION("exec: host failure and wait_any<1> / wait",
298               test_failure_host<ExecPtr, create_exec, tester_wait_any<1>, waiter_wait>);
299
300   simgrid::s4u::this_actor::sleep_for(10);
301   assert_cleanup();
302 }