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 // Create a new async execution with given duration
11 static simgrid::s4u::ActivityPtr create_exec(double duration)
13 double speed = simgrid::s4u::this_actor::get_host()->get_speed();
14 return simgrid::s4u::this_actor::exec_async(speed * duration);
17 // TODO: check other kinds of activities too (Io, Comm, ...)
19 using creator_type = decltype(create_exec);
21 //========== Testers: test the completion of an activity
23 // Calls activity->test() and returns its result
24 static bool tester_test(const simgrid::s4u::ActivityPtr& activity)
26 return activity->test();
29 // Calls activity->wait_for(Duration / 128.0) and returns true when activity is terminated, just like test()
30 template <int Duration> bool tester_wait(const simgrid::s4u::ActivityPtr& activity)
32 constexpr double duration = Duration / 128.0;
33 const double timeout = simgrid::s4u::Engine::get_clock() + duration;
36 XBT_DEBUG("calling wait_for(%f)", duration);
37 activity->wait_for(duration);
38 XBT_DEBUG("wait_for() returned normally");
40 } catch (const simgrid::TimeoutException& e) {
41 XBT_DEBUG("wait_for() timed out (%s)", e.what());
42 INFO("wait_for() timeout should expire at expected date: " << timeout);
43 REQUIRE(simgrid::s4u::Engine::get_clock() == Approx(timeout));
45 } catch (const simgrid::Exception& e) {
46 XBT_DEBUG("wait_for() threw an exception: %s", e.what());
49 INFO("wait_for() should return before timeout expiration at date: " << timeout);
50 REQUIRE(simgrid::s4u::Engine::get_clock() <= Approx(timeout));
54 using tester_type = decltype(tester_test);
56 //========== Waiters: wait for the completion of an activity
59 static void waiter_sleep6(const simgrid::s4u::ActivityPtr&)
61 simgrid::s4u::this_actor::sleep_for(6.0);
62 XBT_DEBUG("wake up after 6s sleep");
65 // Wait for completion of activity
66 static void waiter_wait(const simgrid::s4u::ActivityPtr& activity)
69 XBT_DEBUG("end of wait()");
72 using waiter_type = decltype(waiter_wait);
74 //========== Finally, the test templates
76 template <creator_type Create, tester_type 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 simgrid::s4u::ActivityPtr 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 <creator_type Create, tester_type 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 simgrid::s4u::ActivityPtr 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 <creator_type Create, tester_type 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 simgrid::s4u::ActivityPtr 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 <creator_type Create, tester_type Test, waiter_type Wait> void test_failure_actor()
126 XBT_INFO("Launch an activity for 5s, and kill running actor after 2s");
128 simgrid::s4u::ActivityPtr activity;
129 simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], [&activity]() {
130 assert_exit(false, 2.);
131 activity = Create(5.0);
133 FAIL("should not be here!");
135 const double timestep = simgrid::s4u::Engine::get_clock() + 2.0;
136 simgrid::s4u::this_actor::sleep_for(1.0);
137 INFO("activity should be still running");
138 REQUIRE(not Test(activity));
139 simgrid::s4u::this_actor::sleep_until(timestep);
141 INFO("activity should be terminated now");
142 REQUIRE(Test(activity));
145 template <creator_type Create, tester_type Test, waiter_type Wait> void test_failure_host()
147 XBT_INFO("Launch an activity for 5s, and shutdown host 2s");
149 simgrid::s4u::ActivityPtr activity;
150 simgrid::s4u::ActorPtr actor = simgrid::s4u::Actor::create("actor", all_hosts[1], [&activity]() {
151 assert_exit(false, 2.);
152 activity = Create(5.0);
154 FAIL("should not be here!");
156 const double timestep = simgrid::s4u::Engine::get_clock() + 2.0;
157 simgrid::s4u::this_actor::sleep_for(1.0);
158 INFO("activity should be still running");
159 REQUIRE(not Test(activity));
160 simgrid::s4u::this_actor::sleep_until(timestep);
161 actor->get_host()->turn_off();
162 actor->get_host()->turn_on();
163 INFO("activity should be terminated now");
164 REQUIRE(Test(activity));
169 TEST_CASE("Activity test/wait: using <tester_test>")
171 XBT_INFO("#####[ launch next test ]#####");
173 RUN_SECTION("exec: run and test once", test_trivial<create_exec, tester_test>);
174 RUN_SECTION("exec: run and test many", test_basic<create_exec, tester_test>);
175 RUN_SECTION("exec: cancel and test", test_cancel<create_exec, tester_test>);
176 RUN_SECTION("exec: actor failure and test / sleep", test_failure_actor<create_exec, tester_test, waiter_sleep6>);
177 RUN_SECTION("exec: host failure and test / sleep", test_failure_host<create_exec, tester_test, waiter_sleep6>);
178 RUN_SECTION("exec: actor failure and test / wait", test_failure_actor<create_exec, tester_test, waiter_wait>);
179 RUN_SECTION("exec: host failure and test / wait", test_failure_host<create_exec, tester_test, waiter_wait>);
181 simgrid::s4u::this_actor::sleep_for(10);
185 TEST_CASE("Activity test/wait: using <tester_wait<0>>")
187 XBT_INFO("#####[ launch next test ]#####");
189 RUN_SECTION("exec: run and wait<0> once", test_trivial<create_exec, tester_wait<0>>);
190 // exec: run and wait<0> many
191 RUN_SECTION("exec: cancel and wait<0>", test_cancel<create_exec, tester_wait<0>>);
192 // exec: actor failure and wait<0> / sleep
193 // exec: host failure and wait<0> / sleep
194 // exec: actor failure and wait<0> / wait
195 // exec: host failure and wait<0> / wait
197 simgrid::s4u::this_actor::sleep_for(10);
201 TEST_CASE("Activity test/wait: using <tester_wait<1>>")
203 XBT_INFO("#####[ launch next test ]#####");
205 RUN_SECTION("exec: run and wait<1> once", test_trivial<create_exec, tester_wait<1>>);
206 // exec: run and wait<1> many
207 RUN_SECTION("exec: cancel and wait<1>", test_cancel<create_exec, tester_wait<1>>);
208 // exec: actor failure and wait<1> / sleep
209 // exec: host failure and wait<1> / sleep
210 // exec: actor failure and wait<1> / wait
211 // exec: host failure and wait<1> / wait
213 simgrid::s4u::this_actor::sleep_for(10);
217 // FIXME: The tests grouped here are currently failing. Once fixed, they should be put in the right section above.
218 // The tests can be activated with run-time parameter '*' or, more specifically '[failing]'
219 TEST_CASE("Activity test/wait: tests currently failing", "[.][failing]")
221 XBT_INFO("#####[ launch next failing test ]#####");
223 // with tester_wait<0>
224 RUN_SECTION("exec: run and wait<0> many", test_basic<create_exec, tester_wait<0>>);
225 RUN_SECTION("exec: actor failure and wait<0> / sleep", test_failure_actor<create_exec, tester_wait<0>, waiter_sleep6>);
226 RUN_SECTION("exec: host failure and wait<0> / sleep", test_failure_host<create_exec, tester_wait<0>, waiter_sleep6>);
227 RUN_SECTION("exec: actor failure and wait<0> / wait", test_failure_actor<create_exec, tester_wait<0>, waiter_wait>);
228 RUN_SECTION("exec: host failure and wait<0> / wait", test_failure_host<create_exec, tester_wait<0>, waiter_wait>);
230 // with tester_test<1>
231 RUN_SECTION("exec: run and wait<1> many", test_basic<create_exec, tester_wait<1>>);
232 RUN_SECTION("exec: actor failure and wait<1> / sleep", test_failure_actor<create_exec, tester_wait<1>, waiter_sleep6>);
233 RUN_SECTION("exec: host failure and wait<1> / sleep", test_failure_host<create_exec, tester_wait<1>, waiter_sleep6>);
234 RUN_SECTION("exec: actor failure and wait<1> / wait", test_failure_actor<create_exec, tester_wait<1>, waiter_wait>);
235 RUN_SECTION("exec: host failure and wait<1> / wait", test_failure_host<create_exec, tester_wait<1>, waiter_wait>);
237 simgrid::s4u::this_actor::sleep_for(10);