Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
c6409090e16dfc2903ad95ed04c820bc516e929b
[simgrid.git] / teshsuite / s4u / activity-test-wait / activity-test-wait.cpp
1 /* Copyright (c) 2010-2020. 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 #define CATCH_CONFIG_RUNNER // we supply our own main()
7
8 #include "../../src/include/catch.hpp"
9
10 #include "simgrid/s4u.hpp"
11 #include <xbt/config.hpp>
12
13 XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_test, "Messages specific for this s4u example");
14
15 std::vector<simgrid::s4u::Host*> all_hosts;
16
17 /* Helper function easing the testing of actor's ending condition */
18 static void assert_exit(bool exp_success, double duration)
19 {
20   double expected_time = simgrid::s4u::Engine::get_clock() + duration;
21   simgrid::s4u::this_actor::on_exit([exp_success, expected_time](bool got_failed) {
22     INFO("Check exit status. Expected: " << exp_success);
23     REQUIRE(exp_success == not got_failed);
24     INFO("Check date at exit. Expected: " << expected_time);
25     REQUIRE(simgrid::s4u::Engine::get_clock() == Approx(expected_time));
26     XBT_VERB("Checks on exit successful");
27   });
28 }
29
30 /* Helper function in charge of doing some sanity checks after each test */
31 static void assert_cleanup()
32 {
33   /* Check that no actor remain (but on host[0], where main_dispatcher lives */
34   for (unsigned int i = 0; i < all_hosts.size(); i++) {
35     std::vector<simgrid::s4u::ActorPtr> all_actors = all_hosts[i]->get_all_actors();
36     unsigned int expected_count = (i == 0) ? 1 : 0; // host[0] contains main_dispatcher, all other are empty
37     if (all_actors.size() != expected_count) {
38       INFO("Host " << all_hosts[i]->get_cname() << " contains " << all_actors.size() << " actors but " << expected_count
39                    << " are expected (i=" << i << "). Existing actors: ");
40       for (auto act : all_actors)
41         UNSCOPED_INFO(" - " << act->get_cname());
42       FAIL("This is wrong");
43     }
44   }
45   // TODO: Check that all LMM are empty
46 }
47
48 /**
49  ** Each tests
50  **/
51
52 //========== Creators: create an async activity
53
54 // Create a new async execution with given duration
55 static simgrid::s4u::ActivityPtr create_exec(double duration)
56 {
57   double speed = simgrid::s4u::this_actor::get_host()->get_speed();
58   return simgrid::s4u::this_actor::exec_async(speed * duration);
59 }
60
61 // TODO: check other kinds of activities too (Io, Comm, ...)
62
63 using creator_type = decltype(create_exec);
64
65 //========== Testers: test the completion of an activity
66
67 // Calls exec->test() and returns its result
68 static bool tester_test(const simgrid::s4u::ActivityPtr& exec)
69 {
70   return exec->test();
71 }
72
73 // Calls exec->wait_for(Duration * 0.0125) and returns true when exec is terminated, just like test()
74 template <int Duration> bool tester_wait(const simgrid::s4u::ActivityPtr& exec)
75 {
76   bool ret;
77   try {
78     exec->wait_for(Duration * 0.0125);
79     XBT_DEBUG("wait_for() returned normally");
80     ret = true;
81   } catch (const simgrid::TimeoutException& e) {
82     XBT_DEBUG("wait_for() timed out (%s)", e.what());
83     ret = false;
84   } catch (const simgrid::Exception& e) {
85     XBT_DEBUG("wait_for() threw an exception: %s", e.what());
86     ret = true;
87   }
88   return ret;
89 }
90
91 using tester_type = decltype(tester_test);
92
93 //========== Waiters: wait for the completion of an activity
94
95 // Wait for 6s
96 static void waiter_sleep6(const simgrid::s4u::ActivityPtr&)
97 {
98   simgrid::s4u::this_actor::sleep_for(6.0);
99   XBT_DEBUG("wake up after 6s sleep");
100 }
101
102 // Wait for completion of exec
103 static void waiter_wait(const simgrid::s4u::ActivityPtr& exec)
104 {
105   exec->wait();
106   XBT_DEBUG("end of wait()");
107 }
108
109 using waiter_type = decltype(waiter_wait);
110
111 //========== Finally, the test templates
112
113 template <creator_type Create, tester_type Test> void test_trivial()
114 {
115   XBT_INFO("Launch an activity for 5s, and let it proceed before test");
116
117   simgrid::s4u::ActorPtr exec5 = simgrid::s4u::Actor::create("exec5", all_hosts[1], []() {
118     assert_exit(true, 6.);
119     simgrid::s4u::ActivityPtr activity = Create(5.0);
120     simgrid::s4u::this_actor::sleep_for(6.0);
121     INFO("activity should be terminated now");
122     REQUIRE(Test(activity));
123   });
124   exec5->join();
125 }
126
127 template <creator_type Create, tester_type Test> void test_basic()
128 {
129   XBT_INFO("Launch an activity for 5s, and test while it proceeds");
130
131   simgrid::s4u::ActorPtr exec5 = simgrid::s4u::Actor::create("exec5", all_hosts[1], []() {
132     assert_exit(true, 6.);
133     simgrid::s4u::ActivityPtr activity = Create(5.0);
134     for (int i = 0; i < 3; i++) {
135       INFO("activity should be still running (i = " << i << ")");
136       REQUIRE(not Test(activity));
137       simgrid::s4u::this_actor::sleep_for(2.0);
138     }
139     INFO("activity should be terminated now");
140     REQUIRE(Test(activity));
141   });
142   exec5->join();
143 }
144
145 template <creator_type Create, tester_type Test> void test_cancel()
146 {
147   XBT_INFO("Launch an activity for 5s, and cancel it after 2s");
148
149   simgrid::s4u::ActorPtr exec5 = simgrid::s4u::Actor::create("exec5", all_hosts[1], []() {
150     assert_exit(true, 2.);
151     simgrid::s4u::ActivityPtr activity = Create(5.0);
152     simgrid::s4u::this_actor::sleep_for(2.0);
153     activity->cancel();
154     INFO("activity should be terminated now");
155     REQUIRE(Test(activity));
156   });
157   exec5->join();
158 }
159
160 template <creator_type Create, tester_type Test, waiter_type Wait> void test_failure_actor()
161 {
162   XBT_INFO("Launch an activity for 5s, and kill running actor after 2s");
163
164   simgrid::s4u::ActivityPtr activity;
165   simgrid::s4u::ActorPtr exec5 = simgrid::s4u::Actor::create("exec5", all_hosts[1], [&activity]() {
166     assert_exit(false, 2.);
167     activity = Create(5.0);
168     Wait(activity);
169     FAIL("should not be here!");
170   });
171   simgrid::s4u::this_actor::sleep_for(2.0);
172   INFO("activity should be still running");
173   REQUIRE(not Test(activity));
174   exec5->kill();
175   INFO("activity should be terminated now");
176   REQUIRE(Test(activity));
177 }
178
179 template <creator_type Create, tester_type Test, waiter_type Wait> void test_failure_host()
180 {
181   XBT_INFO("Launch an activity for 5s, and shutdown host 2s");
182
183   simgrid::s4u::ActivityPtr activity;
184   simgrid::s4u::ActorPtr exec5 = simgrid::s4u::Actor::create("exec5", all_hosts[1], [&activity]() {
185     assert_exit(false, 2.);
186     activity = Create(5.0);
187     Wait(activity);
188     FAIL("should not be here!");
189   });
190   simgrid::s4u::this_actor::sleep_for(2.0);
191   INFO("activity should be still running");
192   REQUIRE(not Test(activity));
193   exec5->get_host()->turn_off();
194   exec5->get_host()->turn_on();
195   INFO("activity should be terminated now");
196   REQUIRE(Test(activity));
197 }
198
199 //==========
200
201 /* We need an extra actor here, so that it can sleep until the end of each test */
202 #define RUN_SECTION(descr, ...) SECTION(descr) { simgrid::s4u::Actor::create(descr, all_hosts[0], __VA_ARGS__); }
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<create_exec, tester_test>);
209   RUN_SECTION("exec: run and test many", test_basic<create_exec, tester_test>);
210   RUN_SECTION("exec: cancel and test", test_cancel<create_exec, tester_test>);
211   // exec: actor failure and test / sleep
212   // exec: host failure and test / sleep
213   RUN_SECTION("exec: actor failure and test / wait", test_failure_actor<create_exec, tester_test, waiter_wait>);
214   RUN_SECTION("exec: host failure and test / wait", test_failure_host<create_exec, tester_test, waiter_wait>);
215
216   simgrid::s4u::this_actor::sleep_for(10);
217   assert_cleanup();
218 }
219
220 TEST_CASE("Activity test/wait: using <tester_wait<0>>")
221 {
222   XBT_INFO("#####[ launch next test ]#####");
223
224   RUN_SECTION("exec: run and wait<0> once", test_trivial<create_exec, tester_wait<0>>);
225   // exec: run and wait<0> many
226   RUN_SECTION("exec: cancel and wait<0>", test_cancel<create_exec, tester_wait<0>>);
227   // exec: actor failure and wait<0> / sleep
228   // exec: host failure and wait<0> / sleep
229   // exec: actor failure and wait<0> / wait
230   // exec: host failure and wait<0> / wait
231
232   simgrid::s4u::this_actor::sleep_for(10);
233   assert_cleanup();
234 }
235
236 TEST_CASE("Activity test/wait: using <tester_wait<1>>")
237 {
238   XBT_INFO("#####[ launch next test ]#####");
239
240   RUN_SECTION("exec: run and wait<1> once", test_trivial<create_exec, tester_wait<1>>);
241   // exec: run and wait<1> many
242   RUN_SECTION("exec: cancel and wait<1>", test_cancel<create_exec, tester_wait<1>>);
243   // exec: actor failure and wait<1> / sleep
244   // exec: host failure and wait<1> / sleep
245   // exec: actor failure and wait<1> / wait
246   // exec: host failure and wait<1> / wait
247
248   simgrid::s4u::this_actor::sleep_for(10);
249   assert_cleanup();
250 }
251
252 // FIXME: The tests grouped here are currently failing. Once fixed, they should be put in the right section above.
253 //        The tests can be activated with run-time parameter '*' or, more specifically '[failing]'
254 TEST_CASE("Activity test/wait: tests currently failing", "[.][failing]")
255 {
256   XBT_INFO("#####[ launch next failing test ]#####");
257
258   // with tester_test
259   RUN_SECTION("exec: actor failure and test / sleep", test_failure_actor<create_exec, tester_test, waiter_sleep6>);
260   RUN_SECTION("exec: host failure and test / sleep", test_failure_host<create_exec, tester_test, waiter_sleep6>);
261
262   // with tester_wait<0>
263   RUN_SECTION("exec: run and wait<0> many", test_basic<create_exec, tester_wait<0>>);
264   RUN_SECTION("exec: actor failure and wait<0> / sleep", test_failure_actor<create_exec, tester_wait<0>, waiter_sleep6>);
265   RUN_SECTION("exec: host failure and wait<0> / sleep", test_failure_host<create_exec, tester_wait<0>, waiter_sleep6>);
266   RUN_SECTION("exec: actor failure and wait<0> / wait", test_failure_actor<create_exec, tester_wait<0>, waiter_wait>);
267   RUN_SECTION("exec: host failure and wait<0> / wait", test_failure_host<create_exec, tester_wait<0>, waiter_wait>);
268
269   // with tester_test<1>
270   RUN_SECTION("exec: run and wait<1> many", test_basic<create_exec, tester_wait<1>>);
271   RUN_SECTION("exec: actor failure and wait<1> / sleep", test_failure_actor<create_exec, tester_wait<1>, waiter_sleep6>);
272   RUN_SECTION("exec: host failure and wait<1> / sleep", test_failure_host<create_exec, tester_wait<1>, waiter_sleep6>);
273   RUN_SECTION("exec: actor failure and wait<1> / wait", test_failure_actor<create_exec, tester_wait<1>, waiter_wait>);
274   RUN_SECTION("exec: host failure and wait<1> / wait", test_failure_host<create_exec, tester_wait<1>, waiter_wait>);
275
276   simgrid::s4u::this_actor::sleep_for(10);
277   assert_cleanup();
278 }
279
280 int main(int argc, char* argv[])
281 {
282   simgrid::config::set_value("help-nostop", true);
283   simgrid::s4u::Engine e(&argc, argv);
284
285   std::string platf;
286   if (argc > 1) {
287     platf   = argv[1];
288     argv[1] = argv[0];
289     argv++;
290     argc--;
291   } else {
292     XBT_WARN("No platform file provided. Using './testing_platform.xml'");
293     platf = "./testing_platform.xml";
294   }
295   e.load_platform(platf);
296
297   int status = 42;
298   all_hosts = e.get_all_hosts();
299   simgrid::s4u::Actor::create("main_dispatcher", all_hosts[0],
300                               [&argc, &argv, &status]() { status = Catch::Session().run(argc, argv); });
301
302   e.run();
303   XBT_INFO("Simulation done");
304   return status;
305 }