1 /* Copyright (c) 2010-2021. 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 "activity-lifecycle.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 std::vector<Activity> activities = {activity};
64 XBT_DEBUG("calling wait_any_for(%f)", duration);
65 ssize_t index = Activity::element_type::wait_any_for(activities, duration);
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));
72 XBT_DEBUG("wait_any_for() returned index %zd", index);
76 } catch (const simgrid::Exception& e) {
77 XBT_DEBUG("wait_any_for() threw an exception: %s", e.what());
80 INFO("wait_any_for() should return before timeout expiration at date: " << timeout);
81 REQUIRE(simgrid::s4u::Engine::get_clock() <= Approx(timeout));
85 //========== Waiters: wait for the completion of an activity
87 template <typename Activity> using waiter_type = void (*)(const Activity&);
90 template <typename Activity> void waiter_sleep6(const Activity&)
92 simgrid::s4u::this_actor::sleep_for(6.0);
93 XBT_DEBUG("wake up after 6s sleep");
96 // Wait for completion of activity
97 template <typename Activity> void waiter_wait(const Activity& activity)
100 XBT_DEBUG("end of wait()");
103 //========== Finally, the test templates
105 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test> void test_trivial()
107 XBT_INFO("Launch an activity for 5s, and let it proceed before test");
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));
119 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test> void test_basic()
121 XBT_INFO("Launch an activity for 5s, and test while it proceeds");
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);
132 INFO("activity should be terminated now");
133 REQUIRE(Test(activity));
138 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test> void test_cancel()
140 XBT_INFO("Launch an activity for 5s, and cancel it after 2s");
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);
147 INFO("activity should be terminated now");
148 REQUIRE(Test(activity));
153 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test, waiter_type<Activity> Wait>
154 void test_failure_actor()
156 XBT_INFO("Launch an activity for 5s, and kill running actor after 2s");
159 simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], [&activity]() {
160 assert_exit(false, 2.);
161 activity = Create(5.0);
163 FAIL("should not be here!");
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);
171 INFO("activity should be terminated now");
172 REQUIRE(Test(activity));
175 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test, waiter_type<Activity> Wait>
176 void test_failure_host()
178 XBT_INFO("Launch an activity for 5s, and shutdown host 2s");
181 simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], [&activity]() {
182 assert_exit(false, 2.);
183 activity = Create(5.0);
185 FAIL("should not be here!");
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));
200 using simgrid::s4u::ExecPtr;
202 TEST_CASE("Activity test/wait: using <tester_test>")
204 XBT_INFO("#####[ launch next test ]#####");
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>);
218 simgrid::s4u::this_actor::sleep_for(10);
222 TEST_CASE("Activity test/wait: using <tester_wait<0>>")
224 XBT_INFO("#####[ launch next test ]#####");
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>);
238 simgrid::s4u::this_actor::sleep_for(10);
242 TEST_CASE("Activity test/wait: using <tester_wait<1>>")
244 XBT_INFO("#####[ launch next test ]#####");
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>);
258 simgrid::s4u::this_actor::sleep_for(10);
262 TEST_CASE("Activity test/wait: using <tester_wait_any<0>>")
264 XBT_INFO("#####[ launch next test ]#####");
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>);
278 simgrid::s4u::this_actor::sleep_for(10);
282 TEST_CASE("Activity test/wait: using <tester_wait_any<1>>")
284 XBT_INFO("#####[ launch next test ]#####");
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>);
298 simgrid::s4u::this_actor::sleep_for(10);