Micro template library A library for building device drivers
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

318 lignes
10 KiB

  1. /*!
  2. * \file equeue.cpp
  3. * \brief
  4. * Unit tests for equeue
  5. *
  6. * \copyright Copyright (C) 2020 Christos Choutouridis <christos@choutouridis.net>
  7. *
  8. * <dl class=\"section copyright\"><dt>License</dt><dd>
  9. * The MIT License (MIT)
  10. *
  11. * Permission is hereby granted, free of charge, to any person obtaining a copy
  12. * of this software and associated documentation files (the "Software"), to deal
  13. * in the Software without restriction, including without limitation the rights
  14. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15. * copies of the Software, and to permit persons to whom the Software is
  16. * furnished to do so, subject to the following conditions:
  17. *
  18. * The above copyright notice and this permission notice shall be included in all
  19. * copies or substantial portions of the Software.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  24. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  26. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  27. * SOFTWARE.
  28. * </dd></dl>
  29. *
  30. */
  31. #include <utl/container/equeue.h>
  32. #include <gtest/gtest.h>
  33. namespace Tequeue {
  34. using namespace utl;
  35. int global_flag =0;
  36. // Callable mocks
  37. void vfun(void) { ++global_flag; }
  38. struct vfoo {
  39. void operator() (void) { ++global_flag; }
  40. };
  41. // Test construction
  42. TEST(Tequeue, contruct) {
  43. using Equeue = equeue<int, 8>;
  44. struct T { int a,b; };
  45. int local{};
  46. Equeue e1(Equeue::size_match::GE, 3, [](){
  47. ++global_flag;
  48. });
  49. Equeue e2(Equeue::size_match::GE, 3, [&](){
  50. ++local;
  51. });
  52. Equeue e3(Equeue::size_match::EQ, 7, vfun);
  53. equeue<T, 8> e4(equeue<T, 8>::size_match::EQ, 2, vfoo{});
  54. equeue<int, 8> q1;
  55. equeue<int, 8> q2(equeue<int, 8>::size_match::DISABLED, 0, nullptr);
  56. EXPECT_EQ (8UL, e1.capacity());
  57. EXPECT_EQ (8UL, e2.capacity());
  58. EXPECT_EQ (8UL, e3.capacity());
  59. EXPECT_EQ (8UL, e4.capacity());
  60. EXPECT_EQ (8UL, q1.capacity());
  61. EXPECT_EQ (8UL, q2.capacity());
  62. }
  63. // simple push-pop functionality
  64. TEST(Tequeue, base_class) {
  65. using Equeue = equeue<int, 8>;
  66. Equeue e1(Equeue::size_match::GE, 3, [](){
  67. ++global_flag;
  68. });
  69. // Access of base class functionality
  70. EXPECT_EQ (8UL, e1.capacity());
  71. EXPECT_EQ (0UL, e1.size());
  72. EXPECT_EQ (true, e1.empty());
  73. EXPECT_EQ (false, e1.full());
  74. e1.push(42);
  75. EXPECT_EQ (42, e1.front());
  76. EXPECT_EQ (42, e1.back());
  77. EXPECT_EQ (42, e1.pop());
  78. e1.push(1);
  79. e1.push(2);
  80. e1.push(3);
  81. int check_it=1;
  82. for (auto it = e1.begin() ; it != e1.end() ; ++it)
  83. EXPECT_EQ(*it, check_it++);
  84. EXPECT_EQ(4, check_it); // run through all
  85. }
  86. // trigger functionality
  87. TEST (Tequeue, set_clear_check_trigger) {
  88. using Equeue = equeue<int, 8>;
  89. bool flag{};
  90. Equeue e1(Equeue::size_match::GE, 1, [&](){ flag = true; });
  91. flag = false;
  92. e1.clear_trigger();
  93. EXPECT_EQ (false, flag);
  94. e1.push_back(1); // 1, no-trigger cleared
  95. EXPECT_EQ (false, flag);
  96. flag = false;
  97. e1.clear();
  98. e1.clear_trigger();
  99. EXPECT_EQ (false, flag); // no spurious triggers
  100. e1.push_back(1); // 1
  101. e1.push_back(2); // 2
  102. e1.set_trigger(Equeue::size_match::GE, 1, [&](){ flag = true; });
  103. EXPECT_EQ (false, flag); // no spurious triggers
  104. e1.check_trigger(); // manual trigger
  105. EXPECT_EQ (true, flag);
  106. flag = false;
  107. e1.check_trigger(); // manual trigger attempt
  108. EXPECT_EQ (false, flag); // [SIZE triggers are auto clear]
  109. Equeue e2(Equeue::data_match::MATCH_PUSH, 42, [&](){ flag = true; });
  110. flag = false;
  111. e2.clear_trigger();
  112. EXPECT_EQ (false, flag);
  113. e2.push_back(42); // push 42, no-trigger cleared
  114. EXPECT_EQ (false, flag);
  115. e2.set_trigger(Equeue::data_match::MATCH_PUSH, 42, [&](){ flag = true; });
  116. EXPECT_EQ (false, flag); // no spurious triggers
  117. e2.push_back(42); // push 42, trigger
  118. EXPECT_EQ (true, flag);
  119. flag = false;
  120. e2.push_back(42); // push 42, re-trigger [DATA re-triggers]
  121. EXPECT_EQ (true, flag);
  122. }
  123. // stream push-pop
  124. TEST(Tequeue, stream_push_pop) {
  125. equeue<int, 8> q1;
  126. q1 << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8;
  127. EXPECT_EQ (8UL, q1.capacity());
  128. EXPECT_EQ (8UL, q1.size());
  129. EXPECT_EQ (false, q1.empty());
  130. EXPECT_EQ (true, q1.full());
  131. q1 << 9; // try to insert in full queue
  132. EXPECT_EQ (8UL, q1.capacity());
  133. EXPECT_EQ (8UL, q1.size());
  134. EXPECT_EQ (false, q1.empty());
  135. EXPECT_EQ (true, q1.full());
  136. int check_it=1;
  137. for (auto it = q1.begin() ; it != q1.end() ; ++it)
  138. EXPECT_EQ(*it, check_it++);
  139. EXPECT_EQ(9, check_it); // run through all
  140. for (int i =1 ; i <= 8 ; ++i) {
  141. check_it << q1;
  142. EXPECT_EQ(i, check_it);
  143. }
  144. EXPECT_EQ (8UL, q1.capacity());
  145. EXPECT_EQ (0UL, q1.size());
  146. EXPECT_EQ (true, q1.empty());
  147. EXPECT_EQ (false, q1.full());
  148. q1 >> check_it;
  149. EXPECT_EQ (int{}, check_it);
  150. }
  151. // atomic
  152. // Test construction
  153. TEST(Tequeue, contruct_atomic) {
  154. using Equeue = equeue<int, 8, true>;
  155. struct T { int a,b; };
  156. int local{};
  157. Equeue e1(Equeue::size_match::GE, 3, [](){
  158. ++global_flag;
  159. });
  160. Equeue e2(Equeue::size_match::GE, 3, [&](){
  161. ++local;
  162. });
  163. Equeue e3(Equeue::size_match::EQ, 7, vfun);
  164. equeue<T, 8> e4(equeue<T, 8>::size_match::EQ, 2, vfoo{});
  165. equeue<int, 8, true> q1;
  166. equeue<int, 8, true> q2(equeue<int, 8, true>::size_match::DISABLED, 0, nullptr);
  167. EXPECT_EQ (8UL, e1.capacity());
  168. EXPECT_EQ (8UL, e2.capacity());
  169. EXPECT_EQ (8UL, e3.capacity());
  170. EXPECT_EQ (8UL, e4.capacity());
  171. EXPECT_EQ (8UL, q1.capacity());
  172. EXPECT_EQ (8UL, q2.capacity());
  173. }
  174. // simple push-pop functionality
  175. TEST(Tequeue, base_class_atomic) {
  176. using Equeue = equeue<int, 8, true>;
  177. Equeue e1(Equeue::size_match::GE, 3, [](){
  178. ++global_flag;
  179. });
  180. // Access of base class functionality
  181. EXPECT_EQ (8UL, e1.capacity());
  182. EXPECT_EQ (0UL, e1.size());
  183. EXPECT_EQ (true, e1.empty());
  184. EXPECT_EQ (false, e1.full());
  185. e1.push(42);
  186. EXPECT_EQ (42, e1.front());
  187. EXPECT_EQ (42, e1.back());
  188. EXPECT_EQ (42, e1.pop());
  189. e1.push(1);
  190. e1.push(2);
  191. e1.push(3);
  192. int check_it=1;
  193. for (auto it = e1.begin() ; it != e1.end() ; ++it)
  194. EXPECT_EQ(*it, check_it++);
  195. EXPECT_EQ(4, check_it); // run through all
  196. }
  197. // trigger functionality
  198. TEST (Tequeue, set_clear_check_trigger_atomic) {
  199. using Equeue = equeue<int, 8, true>;
  200. bool flag{};
  201. Equeue e1(Equeue::size_match::GE, 1, [&](){ flag = true; });
  202. flag = false;
  203. e1.clear_trigger();
  204. EXPECT_EQ (false, flag);
  205. e1.push_back(1); // 1, no-trigger cleared
  206. EXPECT_EQ (false, flag);
  207. flag = false;
  208. e1.clear();
  209. e1.clear_trigger();
  210. EXPECT_EQ (false, flag); // no spurious triggers
  211. e1.push_back(1); // 1
  212. e1.push_back(2); // 2
  213. e1.set_trigger(Equeue::size_match::GE, 1, [&](){ flag = true; });
  214. EXPECT_EQ (false, flag); // no spurious triggers
  215. e1.check_trigger(); // manual trigger
  216. EXPECT_EQ (true, flag);
  217. flag = false;
  218. e1.check_trigger(); // manual trigger attempt
  219. EXPECT_EQ (false, flag); // [SIZE triggers are auto clear]
  220. Equeue e2(Equeue::data_match::MATCH_PUSH, 42, [&](){ flag = true; });
  221. flag = false;
  222. e2.clear_trigger();
  223. EXPECT_EQ (false, flag);
  224. e2.push_back(42); // push 42, no-trigger cleared
  225. EXPECT_EQ (false, flag);
  226. e2.set_trigger(Equeue::data_match::MATCH_PUSH, 42, [&](){ flag = true; });
  227. EXPECT_EQ (false, flag); // no spurious triggers
  228. e2.push_back(42); // push 42, trigger
  229. EXPECT_EQ (true, flag);
  230. flag = false;
  231. e2.push_back(42); // push 42, re-trigger [DATA re-triggers]
  232. EXPECT_EQ (true, flag);
  233. }
  234. // stream push-pop
  235. TEST(Tequeue, stream_push_pop_atomic) {
  236. equeue<int, 8, true> q1;
  237. q1 << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8;
  238. EXPECT_EQ (8UL, q1.capacity());
  239. EXPECT_EQ (8UL, q1.size());
  240. EXPECT_EQ (false, q1.empty());
  241. EXPECT_EQ (true, q1.full());
  242. q1 << 9; // try to insert in full queue
  243. EXPECT_EQ (8UL, q1.capacity());
  244. EXPECT_EQ (8UL, q1.size());
  245. EXPECT_EQ (false, q1.empty());
  246. EXPECT_EQ (true, q1.full());
  247. int check_it=1;
  248. for (auto it = q1.begin() ; it != q1.end() ; ++it)
  249. EXPECT_EQ(*it, check_it++);
  250. EXPECT_EQ(9, check_it); // run through all
  251. for (int i =1 ; i <= 8 ; ++i) {
  252. check_it << q1;
  253. EXPECT_EQ(i, check_it);
  254. }
  255. EXPECT_EQ (8UL, q1.capacity());
  256. EXPECT_EQ (0UL, q1.size());
  257. EXPECT_EQ (true, q1.empty());
  258. EXPECT_EQ (false, q1.full());
  259. q1 >> check_it;
  260. EXPECT_EQ (int{}, check_it);
  261. }
  262. }