1 /* Copyright (c) 2010-2023. The SimGrid Team. All rights reserved. */
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. */
6 #include "teshsuite/catch_simgrid.hpp"
8 //========== Creators: create an async activity
10 template <typename Activity> using creator_type = Activity (*)(double);
12 // Create a new async execution with given duration
13 static simgrid::s4u::ExecPtr create_exec(double duration)
15 double speed = simgrid::s4u::this_actor::get_host()->get_speed();
16 return simgrid::s4u::this_actor::exec_async(speed * duration);
19 // TODO: check other kinds of activities too (Io, Comm, ...)
21 //========== Testers: test the completion of an activity
23 template <typename Activity> using tester_type = bool (*)(const Activity&);
25 // Calls activity->test() and returns its result
26 template <typename Activity> bool tester_test(const Activity& activity)
28 return activity->test();
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)
34 constexpr double duration = Duration / 128.0;
35 const double timeout = simgrid::s4u::Engine::get_clock() + duration;
38 XBT_DEBUG("calling wait_for(%f)", duration);
39 activity->wait_for(duration);
40 XBT_DEBUG("wait_for() returned normally");
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));
47 } catch (const simgrid::Exception& e) {
48 XBT_DEBUG("wait_for() threw an exception: %s", e.what());
51 INFO("wait_for() should return before timeout expiration at date: " << timeout);
52 REQUIRE(simgrid::s4u::Engine::get_clock() <= Approx(timeout));
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)
59 constexpr double duration = Duration / 128.0;
60 const double timeout = simgrid::s4u::Engine::get_clock() + duration;
63 simgrid::s4u::ActivitySet set;
66 XBT_DEBUG("calling wait_any_for(%f)", duration);
67 auto waited_activity = set.wait_any_for(duration);
69 XBT_DEBUG("wait_any_for() returned activity %p", waited_activity.get());
70 REQUIRE(waited_activity.get() == activity);
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));
78 } catch (const simgrid::Exception& e) {
79 XBT_DEBUG("wait_any_for() threw an exception: %s", e.what());
82 INFO("wait_any_for() should return before timeout expiration at date: " << timeout);
83 REQUIRE(simgrid::s4u::Engine::get_clock() <= Approx(timeout));
87 //========== Waiters: wait for the completion of an activity
89 template <typename Activity> using waiter_type = void (*)(const Activity&);
92 template <typename Activity> void waiter_sleep6(const Activity&)
94 simgrid::s4u::this_actor::sleep_for(6.0);
95 XBT_DEBUG("wake up after 6s sleep");
98 // Wait for completion of activity
99 template <typename Activity> void waiter_wait(const Activity& activity)
102 XBT_DEBUG("end of wait()");
105 //========== Finally, the test templates
107 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test> void test_trivial()
109 XBT_INFO("Launch an activity for 5s, and let it proceed before test");
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));
121 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test> void test_basic()
123 XBT_INFO("Launch an activity for 5s, and test while it proceeds");
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);
134 INFO("activity should be terminated now");
135 REQUIRE(Test(activity));
140 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test> void test_cancel()
142 XBT_INFO("Launch an activity for 5s, and cancel it after 2s");
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);
149 INFO("activity should be terminated now");
150 REQUIRE(Test(activity));
155 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test, waiter_type<Activity> Wait>
156 void test_failure_actor()
158 XBT_INFO("Launch an activity for 5s, and kill running actor after 2s");
161 simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], [&activity]() {
162 assert_exit(false, 2.);
163 activity = Create(5.0);
165 FAIL("should not be here!");
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);
173 INFO("activity should be terminated now");
174 REQUIRE(Test(activity));
177 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test, waiter_type<Activity> Wait>
178 void test_failure_host()
180 XBT_INFO("Launch an activity for 5s, and shutdown host 2s");
183 simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], [&activity]() {
184 assert_exit(false, 2.);
185 activity = Create(5.0);
187 FAIL("should not be here!");
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));
202 using simgrid::s4u::ExecPtr;
204 TEST_CASE("Activity test/wait: using <tester_test>")
206 XBT_INFO("#####[ launch next test ]#####");
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>);
220 simgrid::s4u::this_actor::sleep_for(10);
224 TEST_CASE("Activity test/wait: using <tester_wait<0>>")
226 XBT_INFO("#####[ launch next test ]#####");
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>);
240 simgrid::s4u::this_actor::sleep_for(10);
244 TEST_CASE("Activity test/wait: using <tester_wait<1>>")
246 XBT_INFO("#####[ launch next test ]#####");
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>);
260 simgrid::s4u::this_actor::sleep_for(10);
264 TEST_CASE("Activity test/wait: using <tester_wait_any<0>>")
266 XBT_INFO("#####[ launch next test ]#####");
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>);
280 simgrid::s4u::this_actor::sleep_for(10);
284 TEST_CASE("Activity test/wait: using <tester_wait_any<1>>")
286 XBT_INFO("#####[ launch next test ]#####");
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>);
300 simgrid::s4u::this_actor::sleep_for(10);