timer_test.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /**
  2. * The MIT License (MIT)
  3. *
  4. * Copyright (c) 2015 Michael Egli
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. *
  24. * \author Michael Egli
  25. * \copyright Michael Egli
  26. * \date 11-Jul-2015
  27. *
  28. * \file timer_test.cpp
  29. *
  30. * Tests for cpptime component. Compile with
  31. *
  32. * ~~~
  33. * g++ -g -std=c++11 -Wall -Wextra -o run_tests timer_test.cpp -l pthread
  34. * ~~~
  35. *
  36. */
  37. #define CATCH_CONFIG_MAIN
  38. // Includes
  39. #include <thread>
  40. #include <chrono>
  41. #include "catch.hpp"
  42. #include "../cpptime.h"
  43. using namespace std::chrono;
  44. TEST_CASE("Test start and stop.")
  45. {
  46. {
  47. CppTime::Timer t;
  48. }
  49. }
  50. TEST_CASE("Tests with two argument add")
  51. {
  52. CppTime::Timer t;
  53. SECTION("Test uint64_t timeout argument")
  54. {
  55. int i = 0;
  56. t.add(100000, [&](CppTime::timer_id) { i = 42; });
  57. std::this_thread::sleep_for(milliseconds(120));
  58. REQUIRE(i == 42);
  59. }
  60. SECTION("Test duration timeout argument")
  61. {
  62. int i = 0;
  63. t.add(milliseconds(100), [&](CppTime::timer_id) { i = 43; });
  64. std::this_thread::sleep_for(milliseconds(120));
  65. REQUIRE(i == 43);
  66. }
  67. SECTION("Test time_point timeout argument")
  68. {
  69. int i = 0;
  70. t.add(CppTime::clock::now() + milliseconds(100), [&](CppTime::timer_id) { i = 44; });
  71. std::this_thread::sleep_for(milliseconds(120));
  72. REQUIRE(i == 44);
  73. }
  74. }
  75. TEST_CASE("Tests with three argument add")
  76. {
  77. CppTime::Timer t;
  78. SECTION("Test uint64_t timeout argument")
  79. {
  80. size_t count = 0;
  81. auto id = t.add(100000, [&](CppTime::timer_id) { ++count; }, 10000);
  82. std::this_thread::sleep_for(milliseconds(125));
  83. t.remove(id);
  84. REQUIRE(count == 3);
  85. }
  86. SECTION("Test duration timeout argument")
  87. {
  88. size_t count = 0;
  89. auto id =
  90. t.add(milliseconds(100), [&](CppTime::timer_id) { ++count; }, microseconds(10000));
  91. std::this_thread::sleep_for(milliseconds(135));
  92. t.remove(id);
  93. REQUIRE(count == 4);
  94. }
  95. }
  96. TEST_CASE("Test delete timer in callback")
  97. {
  98. CppTime::Timer t;
  99. SECTION("Delete one timer")
  100. {
  101. size_t count = 0;
  102. auto id = t.add(milliseconds(10), [&](CppTime::timer_id id) {
  103. ++count;
  104. t.remove(id);
  105. }, milliseconds(10));
  106. std::this_thread::sleep_for(milliseconds(50));
  107. REQUIRE(count == 1);
  108. }
  109. SECTION("Ensure that the correct timer is freed and reused")
  110. {
  111. auto id1 = t.add(milliseconds(40), [](CppTime::timer_id) {});
  112. auto id2 = t.add(milliseconds(10), [&](CppTime::timer_id id) { t.remove(id); });
  113. std::this_thread::sleep_for(milliseconds(30));
  114. auto id3 = t.add(microseconds(100), [](CppTime::timer_id) {});
  115. auto id4 = t.add(microseconds(100), [](CppTime::timer_id) {});
  116. REQUIRE(id3 == id2);
  117. REQUIRE(id4 != id1);
  118. REQUIRE(id4 != id2);
  119. std::this_thread::sleep_for(milliseconds(20));
  120. }
  121. SECTION("Ensure that the correct timer is freed and reused - different ordering")
  122. {
  123. auto id1 = t.add(milliseconds(10), [&](CppTime::timer_id id) { t.remove(id); });
  124. auto id2 = t.add(milliseconds(40), [](CppTime::timer_id) {});
  125. std::this_thread::sleep_for(milliseconds(30));
  126. auto id3 = t.add(microseconds(100), [](CppTime::timer_id) {});
  127. auto id4 = t.add(microseconds(100), [](CppTime::timer_id) {});
  128. REQUIRE(id3 == id1);
  129. REQUIRE(id4 != id1);
  130. REQUIRE(id4 != id2);
  131. std::this_thread::sleep_for(milliseconds(20));
  132. }
  133. }
  134. TEST_CASE("Test two identical timeouts")
  135. {
  136. int i = 0;
  137. int j = 0;
  138. CppTime::Timer t;
  139. CppTime::timestamp ts = CppTime::clock::now() + milliseconds(40);
  140. t.add(ts, [&](CppTime::timer_id) { i = 42; });
  141. t.add(ts, [&](CppTime::timer_id) { j = 43; });
  142. std::this_thread::sleep_for(milliseconds(50));
  143. REQUIRE(i == 42);
  144. REQUIRE(j == 43);
  145. }
  146. TEST_CASE("Test timeouts from the past.")
  147. {
  148. CppTime::Timer t;
  149. SECTION("Test negative timeouts")
  150. {
  151. int i = 0;
  152. int j = 0;
  153. CppTime::timestamp ts1 = CppTime::clock::now() - milliseconds(10);
  154. CppTime::timestamp ts2 = CppTime::clock::now() - milliseconds(20);
  155. t.add(ts1, [&](CppTime::timer_id) { i = 42; });
  156. t.add(ts2, [&](CppTime::timer_id) { j = 43; });
  157. std::this_thread::sleep_for(microseconds(10));
  158. REQUIRE(i == 42);
  159. REQUIRE(j == 43);
  160. }
  161. SECTION("Test time overflow when blocking timer thread.")
  162. {
  163. int i = 0;
  164. CppTime::timestamp ts1 = CppTime::clock::now() + milliseconds(10);
  165. CppTime::timestamp ts2 = CppTime::clock::now() + milliseconds(20);
  166. t.add(ts1, [&](CppTime::timer_id) { std::this_thread::sleep_for(milliseconds(20)); });
  167. t.add(ts2, [&](CppTime::timer_id) { i = 42; });
  168. std::this_thread::sleep_for(milliseconds(50));
  169. REQUIRE(i == 42);
  170. }
  171. }
  172. TEST_CASE("Test order of multiple timeouts")
  173. {
  174. int i = 0;
  175. CppTime::Timer t;
  176. t.add(10000, [&](CppTime::timer_id) { i = 42; });
  177. t.add(20000, [&](CppTime::timer_id) { i = 43; });
  178. t.add(30000, [&](CppTime::timer_id) { i = 44; });
  179. t.add(40000, [&](CppTime::timer_id) { i = 45; });
  180. std::this_thread::sleep_for(milliseconds(50));
  181. REQUIRE(i == 45);
  182. }
  183. TEST_CASE("Test with multiple timers")
  184. {
  185. int i = 0;
  186. CppTime::Timer t1;
  187. CppTime::Timer t2;
  188. SECTION("Update the same value at different times with different timers")
  189. {
  190. t1.add(milliseconds(20), [&](CppTime::timer_id) { i = 42; });
  191. t1.add(milliseconds(40), [&](CppTime::timer_id) { i = 43; });
  192. std::this_thread::sleep_for(milliseconds(30));
  193. REQUIRE(i == 42);
  194. std::this_thread::sleep_for(milliseconds(20));
  195. REQUIRE(i == 43);
  196. }
  197. SECTION("Remove one timer without affecting the other")
  198. {
  199. auto id1 = t1.add(milliseconds(20), [&](CppTime::timer_id) { i = 42; });
  200. t1.add(milliseconds(40), [&](CppTime::timer_id) { i = 43; });
  201. std::this_thread::sleep_for(milliseconds(10));
  202. t1.remove(id1);
  203. std::this_thread::sleep_for(milliseconds(20));
  204. REQUIRE(i == 0);
  205. std::this_thread::sleep_for(milliseconds(20));
  206. REQUIRE(i == 43);
  207. }
  208. }