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::ActivityPtr 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: " << 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 //========== Waiters: wait for the completion of an activity
58 template <typename Activity> using waiter_type = void (*)(const Activity&);
61 template <typename Activity> void waiter_sleep6(const Activity&)
63 simgrid::s4u::this_actor::sleep_for(6.0);
64 XBT_DEBUG("wake up after 6s sleep");
67 // Wait for completion of activity
68 template <typename Activity> void waiter_wait(const Activity& activity)
71 XBT_DEBUG("end of wait()");
74 //========== Finally, the test templates
76 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test> void test_trivial()
78 XBT_INFO("Launch an activity for 5s, and let it proceed before test");
80 simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], []() {
81 assert_exit(true, 6.);
82 Activity activity = Create(5.0);
83 simgrid::s4u::this_actor::sleep_for(6.0);
84 INFO("activity should be terminated now");
85 REQUIRE(Test(activity));
90 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test> void test_basic()
92 XBT_INFO("Launch an activity for 5s, and test while it proceeds");
94 simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], []() {
95 assert_exit(true, 6.);
96 Activity activity = Create(5.0);
97 for (int i = 0; i < 3; i++) {
98 const double timestep = simgrid::s4u::Engine::get_clock() + 2.0;
99 INFO("activity should be still running (i = " << i << ")");
100 REQUIRE(not Test(activity));
101 simgrid::s4u::this_actor::sleep_until(timestep);
103 INFO("activity should be terminated now");
104 REQUIRE(Test(activity));
109 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test> void test_cancel()
111 XBT_INFO("Launch an activity for 5s, and cancel it after 2s");
113 simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], []() {
114 assert_exit(true, 2.);
115 Activity activity = Create(5.0);
116 simgrid::s4u::this_actor::sleep_for(2.0);
118 INFO("activity should be terminated now");
119 REQUIRE(Test(activity));
124 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test, waiter_type<Activity> Wait>
125 void test_failure_actor()
127 XBT_INFO("Launch an activity for 5s, and kill running actor after 2s");
130 simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], [&activity]() {
131 assert_exit(false, 2.);
132 activity = Create(5.0);
134 FAIL("should not be here!");
136 const double timestep = simgrid::s4u::Engine::get_clock() + 2.0;
137 simgrid::s4u::this_actor::sleep_for(1.0);
138 INFO("activity should be still running");
139 REQUIRE(not Test(activity));
140 simgrid::s4u::this_actor::sleep_until(timestep);
142 INFO("activity should be terminated now");
143 REQUIRE(Test(activity));
146 template <typename Activity, creator_type<Activity> Create, tester_type<Activity> Test, waiter_type<Activity> Wait>
147 void test_failure_host()
149 XBT_INFO("Launch an activity for 5s, and shutdown host 2s");
152 simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], [&activity]() {
153 assert_exit(false, 2.);
154 activity = Create(5.0);
156 FAIL("should not be here!");
158 const double timestep = simgrid::s4u::Engine::get_clock() + 2.0;
159 simgrid::s4u::this_actor::sleep_for(1.0);
160 INFO("activity should be still running");
161 REQUIRE(not Test(activity));
162 simgrid::s4u::this_actor::sleep_until(timestep);
163 actor->get_host()->turn_off();
164 actor->get_host()->turn_on();
165 INFO("activity should be terminated now");
166 REQUIRE(Test(activity));
171 using simgrid::s4u::ActivityPtr;
173 TEST_CASE("Activity test/wait: using <tester_test>")
175 XBT_INFO("#####[ launch next test ]#####");
177 RUN_SECTION("exec: run and test once", test_trivial<ActivityPtr, create_exec, tester_test>);
178 RUN_SECTION("exec: run and test many", test_basic<ActivityPtr, create_exec, tester_test>);
179 RUN_SECTION("exec: cancel and test", test_cancel<ActivityPtr, create_exec, tester_test>);
180 RUN_SECTION("exec: actor failure and test / sleep",
181 test_failure_actor<ActivityPtr, create_exec, tester_test, waiter_sleep6>);
182 RUN_SECTION("exec: host failure and test / sleep",
183 test_failure_host<ActivityPtr, create_exec, tester_test, waiter_sleep6>);
184 RUN_SECTION("exec: actor failure and test / wait",
185 test_failure_actor<ActivityPtr, create_exec, tester_test, waiter_wait>);
186 RUN_SECTION("exec: host failure and test / wait",
187 test_failure_host<ActivityPtr, create_exec, tester_test, waiter_wait>);
189 simgrid::s4u::this_actor::sleep_for(10);
193 TEST_CASE("Activity test/wait: using <tester_wait<0>>")
195 XBT_INFO("#####[ launch next test ]#####");
197 RUN_SECTION("exec: run and wait<0> once", test_trivial<ActivityPtr, create_exec, tester_wait<0>>);
198 // exec: run and wait<0> many
199 RUN_SECTION("exec: cancel and wait<0>", test_cancel<ActivityPtr, create_exec, tester_wait<0>>);
200 // exec: actor failure and wait<0> / sleep
201 // exec: host failure and wait<0> / sleep
202 // exec: actor failure and wait<0> / wait
203 // exec: host failure and wait<0> / wait
205 simgrid::s4u::this_actor::sleep_for(10);
209 TEST_CASE("Activity test/wait: using <tester_wait<1>>")
211 XBT_INFO("#####[ launch next test ]#####");
213 RUN_SECTION("exec: run and wait<1> once", test_trivial<ActivityPtr, create_exec, tester_wait<1>>);
214 // exec: run and wait<1> many
215 RUN_SECTION("exec: cancel and wait<1>", test_cancel<ActivityPtr, create_exec, tester_wait<1>>);
216 // exec: actor failure and wait<1> / sleep
217 // exec: host failure and wait<1> / sleep
218 // exec: actor failure and wait<1> / wait
219 // exec: host failure and wait<1> / wait
221 simgrid::s4u::this_actor::sleep_for(10);
225 // FIXME: The tests grouped here are currently failing. Once fixed, they should be put in the right section above.
226 // The tests can be activated with run-time parameter '*' or, more specifically '[failing]'
227 TEST_CASE("Activity test/wait: tests currently failing", "[.][failing]")
229 XBT_INFO("#####[ launch next failing test ]#####");
231 // with tester_wait<0>
232 RUN_SECTION("exec: run and wait<0> many", test_basic<ActivityPtr, create_exec, tester_wait<0>>);
233 RUN_SECTION("exec: actor failure and wait<0> / sleep",
234 test_failure_actor<ActivityPtr, create_exec, tester_wait<0>, waiter_sleep6>);
235 RUN_SECTION("exec: host failure and wait<0> / sleep",
236 test_failure_host<ActivityPtr, create_exec, tester_wait<0>, waiter_sleep6>);
237 RUN_SECTION("exec: actor failure and wait<0> / wait",
238 test_failure_actor<ActivityPtr, create_exec, tester_wait<0>, waiter_wait>);
239 RUN_SECTION("exec: host failure and wait<0> / wait",
240 test_failure_host<ActivityPtr, create_exec, tester_wait<0>, waiter_wait>);
242 // with tester_wait<1>
243 RUN_SECTION("exec: run and wait<1> many", test_basic<ActivityPtr, create_exec, tester_wait<1>>);
244 RUN_SECTION("exec: actor failure and wait<1> / sleep",
245 test_failure_actor<ActivityPtr, create_exec, tester_wait<1>, waiter_sleep6>);
246 RUN_SECTION("exec: host failure and wait<1> / sleep",
247 test_failure_host<ActivityPtr, create_exec, tester_wait<1>, waiter_sleep6>);
248 RUN_SECTION("exec: actor failure and wait<1> / wait",
249 test_failure_actor<ActivityPtr, create_exec, tester_wait<1>, waiter_wait>);
250 RUN_SECTION("exec: host failure and wait<1> / wait",
251 test_failure_host<ActivityPtr, create_exec, tester_wait<1>, waiter_wait>);
253 simgrid::s4u::this_actor::sleep_for(10);