Micro template library A library for building device drivers
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

425 lines
16 KiB

  1. /*!
  2. * \file ring_iterator.cpp
  3. * \brief
  4. * Unit tests for ring_iterator
  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/ring_iterator.h>
  32. #include <gtest/gtest.h>
  33. #include <array>
  34. #include <type_traits>
  35. namespace Tring_iterator {
  36. using namespace utl;
  37. // Test construction
  38. TEST(Tring_iterator, construct) {
  39. int A[10];
  40. //default constructor
  41. ring_iterator<int*, 10> i1;
  42. EXPECT_EQ(nullptr, i1.base());
  43. EXPECT_EQ(nullptr, i1.iter());
  44. EXPECT_EQ(10UL, i1.size());
  45. // implementation specific (you can remove it freely)
  46. EXPECT_EQ(2*sizeof(int*), sizeof(i1));
  47. // basic
  48. ring_iterator<int*, 10> i2(A);
  49. EXPECT_EQ(A, i2.base());
  50. EXPECT_EQ(A, i2.iter());
  51. EXPECT_EQ(10UL, i2.size());
  52. // basic from assignment
  53. ring_iterator<int*, 10> i3 = A;
  54. EXPECT_EQ(A, i3.base());
  55. EXPECT_EQ(A, i3.iter());
  56. EXPECT_EQ(10UL, i3.size());
  57. // basic with offset
  58. ring_iterator<int*, 10> i4(A, 5);
  59. EXPECT_EQ(A, i4.base());
  60. EXPECT_EQ(&A[5], i4.iter());
  61. EXPECT_EQ(10UL, i4.size());
  62. // copy (Legacy iterator)
  63. auto i5 = i2;
  64. EXPECT_EQ(A, i5.base());
  65. EXPECT_EQ(A, i5.iter());
  66. EXPECT_EQ(10UL, i5.size());
  67. // arbitrary type
  68. struct TT { int a,b,c; };
  69. std::array<TT, 10> t;
  70. ring_iterator<TT*, 10> it(t.data(), 2);
  71. EXPECT_EQ(t.begin(), it.base());
  72. EXPECT_EQ(&t[2], it.iter());
  73. EXPECT_EQ(10UL, it.size());
  74. }
  75. // Legacy iterator
  76. TEST(Tring_iterator, LegacyIterator) {
  77. EXPECT_EQ(true, (std::is_same<int, typename ring_iterator<int*, 10>::value_type>::value));
  78. EXPECT_EQ(true, (std::is_same<std::ptrdiff_t, typename ring_iterator<int*, 10>::difference_type>::value));
  79. EXPECT_EQ(true, (std::is_same<int&, typename ring_iterator<int*, 10>::reference>::value));
  80. EXPECT_EQ(true, (std::is_same<int*, typename ring_iterator<int*, 10>::pointer>::value));
  81. EXPECT_EQ(true, (std::is_same<std::random_access_iterator_tag, typename ring_iterator<int*, 10>::iterator_category>::value));
  82. int A[10] {0, 1, 2, 3, 4, 5, 6, 7, 8 , 9};
  83. ring_iterator<int*, 10> i1(A);
  84. // copy constructible/assignable
  85. auto i2 = i1;
  86. EXPECT_EQ(A, i2.base());
  87. EXPECT_EQ(A, i2.iter());
  88. EXPECT_EQ(10UL, i2.size());
  89. // dereferenceable - incrementable
  90. ring_iterator<int*, 10> i3(A);
  91. EXPECT_EQ(true, (std::is_reference<decltype(*i3)>::value));
  92. EXPECT_EQ(true, (std::is_same<ring_iterator<int*, 10>&, decltype(++i3)>::value));
  93. EXPECT_EQ(true, (std::is_reference<decltype((*i3++))>::value));
  94. // more practical
  95. ring_iterator<int*, 10> i4(A);
  96. ring_iterator<int*, 10> i5(A, 9);
  97. EXPECT_EQ(A[0], *i4);
  98. EXPECT_EQ(&A[1], (++i4).iter());
  99. // check loop
  100. EXPECT_EQ(A[9], *i5);
  101. EXPECT_EQ(&A[0], (++i5).iter());
  102. }
  103. // Legacy input iterator
  104. TEST(Tring_iterator, LegacyInputIterator) {
  105. int A[10] {0, 1, 2, 3, 4, 5, 6, 7, 8 , 9};
  106. ring_iterator<int*, 10> i1(A), i2(A), i3(A, 1);
  107. struct T { int m; };
  108. T B[5] { {0}, {1}, {2}, {3}, {4}};
  109. ring_iterator<T*, 5> it(B);
  110. EXPECT_EQ (true, (std::is_same<bool, decltype(i1 == i2)>::value));
  111. EXPECT_EQ (true, (std::is_same<bool, decltype(i1 != i2)>::value));
  112. EXPECT_EQ (true, (std::is_same<int&, decltype(*i1)>::value));
  113. EXPECT_EQ (true, (std::is_same<int, decltype(it->m)>::value));
  114. EXPECT_EQ (true, (std::is_same<ring_iterator<int*, 10>&, decltype(++i1)>::value));
  115. EXPECT_EQ (true, (std::is_same<int&, decltype(*i1++)>::value));
  116. // more practical
  117. EXPECT_EQ (true, i1 == i2);
  118. EXPECT_EQ (true, i1 != i3);
  119. EXPECT_EQ (0, *i1);
  120. EXPECT_EQ (0, it->m);
  121. EXPECT_EQ (true, (++i1 == i3));
  122. EXPECT_EQ (1, *i1++);
  123. EXPECT_EQ (2, *i1);
  124. }
  125. // Legacy input iterator
  126. TEST(Tring_iterator, LegacyOutputIterator) {
  127. int A[10] {0, 1, 2, 3, 4, 5, 6, 7, 8 , 9};
  128. ring_iterator<int*, 10> it(A);
  129. EXPECT_EQ (true, (std::is_assignable<decltype(*it), int>::value));
  130. EXPECT_EQ (true, (std::is_assignable<decltype(*it++), int>::value));
  131. // more practical
  132. *it = 42;
  133. EXPECT_EQ (42, A[0]);
  134. *it++ = 7;
  135. EXPECT_EQ (7, A[0]);
  136. EXPECT_EQ (&A[1], it.iter());
  137. }
  138. // Legacy forward iterator
  139. TEST(Tring_iterator, LegacyForwardIterator)
  140. {
  141. int A[10] {0, 1, 2, 3, 4, 5, 6, 7, 8 , 9};
  142. ring_iterator<int*, 10> it(A);
  143. EXPECT_EQ (0, *it++);
  144. EXPECT_EQ (1, *it);
  145. }
  146. // Legacy bidirectional iterator
  147. TEST(Tring_iterator, LegacyBidirectionalIterator) {
  148. int A[10] {0, 1, 2, 3, 4, 5, 6, 7, 8 , 9};
  149. ring_iterator<int*, 10> it(A);
  150. EXPECT_EQ (true, (std::is_same<ring_iterator<int*, 10>&, decltype(--it)>::value));
  151. EXPECT_EQ (true, (std::is_same<ring_iterator<int*, 10>, decltype(it--)>::value));
  152. EXPECT_EQ (true, (std::is_same<int&, decltype(*it--)>::value));
  153. // more practical
  154. ring_iterator<int*, 10> i1(A), i2(A, 9);
  155. EXPECT_EQ (9, *i2--); // check loop also
  156. EXPECT_EQ (8, *i2);
  157. EXPECT_EQ (0, *i1--); // check loop also
  158. EXPECT_EQ (9, *i1);
  159. }
  160. // Legacy random access iterator
  161. TEST(Tring_iterator, LegacyRandomAccessIterator) {
  162. int A[10] {0, 1, 2, 3, 4, 5, 6, 7, 8 , 9};
  163. ring_iterator<int*, 10> it1(A), it2(A, 7);
  164. EXPECT_EQ (true, (std::is_same<ring_iterator<int*, 10>&, decltype(it1 += 7)>::value));
  165. EXPECT_EQ (true, (std::is_same<ring_iterator<int*, 10>, decltype(it1 + 7)>::value));
  166. EXPECT_EQ (true, (std::is_same<ring_iterator<int*, 10>, decltype(7 + it1)>::value));
  167. EXPECT_EQ (true, (std::is_same<ring_iterator<int*, 10>&, decltype(it1 -= 7)>::value));
  168. EXPECT_EQ (true, (std::is_same<ring_iterator<int*, 10>, decltype(it1 - 7)>::value));
  169. EXPECT_EQ (true, (std::is_same<std::ptrdiff_t, decltype(it1 - it2)>::value));
  170. EXPECT_EQ (true, (std::is_same<int&, decltype(it1[7])>::value));
  171. EXPECT_EQ (true, (std::is_same<bool, decltype(it1 < it2)>::value));
  172. EXPECT_EQ (true, (std::is_same<bool, decltype(it1 > it2)>::value));
  173. EXPECT_EQ (true, (std::is_same<bool, decltype(it1 <= it2)>::value));
  174. EXPECT_EQ (true, (std::is_same<bool, decltype(it1 >= it2)>::value));
  175. // more practical
  176. ring_iterator<int*, 10> i1(A), i2(A);
  177. i1 += 7;
  178. EXPECT_EQ (7, *i1);
  179. i1 -= 7;
  180. EXPECT_EQ (0, *i1);
  181. i1 += 11;
  182. EXPECT_EQ (1, *i1);
  183. i1 -= 2;
  184. EXPECT_EQ (9, *i1);
  185. EXPECT_EQ (7, *(i2+7));
  186. EXPECT_EQ (7, *(7+i2));
  187. EXPECT_EQ (1, *(i2+11));
  188. EXPECT_EQ (1, *(11+i2));
  189. EXPECT_EQ (7, *(i1-2));
  190. EXPECT_EQ (8, *(i2-2));
  191. EXPECT_EQ (9, (i1 - i2));
  192. EXPECT_EQ (1, (i2 - i1)); // loop
  193. }
  194. // Test construction atomic
  195. TEST(Tring_iterator, construct_atomic) {
  196. int A[10];
  197. //default constructor
  198. ring_iterator<int*, 10, true> i1;
  199. EXPECT_EQ(nullptr, i1.base());
  200. EXPECT_EQ(nullptr, i1.iter());
  201. EXPECT_EQ(10UL, i1.size());
  202. // implementation specific (you can remove it freely)
  203. EXPECT_EQ(2*sizeof(int*), sizeof(i1));
  204. // basic
  205. ring_iterator<int*, 10, true> i2(A);
  206. EXPECT_EQ(A, i2.base());
  207. EXPECT_EQ(A, i2.iter());
  208. EXPECT_EQ(10UL, i2.size());
  209. // basic from assignment
  210. ring_iterator<int*, 10, true> i3 = A;
  211. EXPECT_EQ(A, i3.base());
  212. EXPECT_EQ(A, i3.iter());
  213. EXPECT_EQ(10UL, i3.size());
  214. // basic with offset
  215. ring_iterator<int*, 10, true> i4(A, 5);
  216. EXPECT_EQ(A, i4.base());
  217. EXPECT_EQ(&A[5], i4.iter());
  218. EXPECT_EQ(10UL, i4.size());
  219. // copy (Legacy iterator)
  220. auto i5 = i2;
  221. EXPECT_EQ(A, i5.base());
  222. EXPECT_EQ(A, i5.iter());
  223. EXPECT_EQ(10UL, i5.size());
  224. // arbitrary type
  225. struct TT { int a,b,c; };
  226. std::array<TT, 10> t;
  227. ring_iterator<TT*, 10, true> it(t.data(), 2);
  228. EXPECT_EQ(t.begin(), it.base());
  229. EXPECT_EQ(&t[2], it.iter());
  230. EXPECT_EQ(10UL, it.size());
  231. }
  232. // Legacy iterator atomic
  233. TEST(Tring_iterator, LegacyIterator_atomic) {
  234. EXPECT_EQ(true, (std::is_same<int, typename ring_iterator<int*, 10, true>::value_type>::value));
  235. EXPECT_EQ(true, (std::is_same<std::ptrdiff_t, typename ring_iterator<int*, 10, true>::difference_type>::value));
  236. EXPECT_EQ(true, (std::is_same<int&, typename ring_iterator<int*, 10, true>::reference>::value));
  237. EXPECT_EQ(true, (std::is_same<int*, typename ring_iterator<int*, 10, true>::pointer>::value));
  238. EXPECT_EQ(true, (std::is_same<std::random_access_iterator_tag, typename ring_iterator<int*, 10, true>::iterator_category>::value));
  239. int A[10] {0, 1, 2, 3, 4, 5, 6, 7, 8 , 9};
  240. ring_iterator<int*, 10, true> i1(A);
  241. // copy constructible/assignable
  242. auto i2 = i1;
  243. EXPECT_EQ(A, i2.base());
  244. EXPECT_EQ(A, i2.iter());
  245. EXPECT_EQ(10UL, i2.size());
  246. // dereferenceable - incrementable
  247. ring_iterator<int*, 10, true> i3(A);
  248. EXPECT_EQ(true, (std::is_reference<decltype(*i3)>::value));
  249. EXPECT_EQ(true, (std::is_same<ring_iterator<int*, 10, true>&, decltype(++i3)>::value));
  250. EXPECT_EQ(true, (std::is_reference<decltype((*i3++))>::value));
  251. // more practical
  252. ring_iterator<int*, 10, true> i4(A);
  253. ring_iterator<int*, 10, true> i5(A, 9);
  254. EXPECT_EQ(A[0], *i4);
  255. EXPECT_EQ(&A[1], (++i4).iter());
  256. // check loop
  257. EXPECT_EQ(A[9], *i5);
  258. EXPECT_EQ(&A[0], (++i5).iter());
  259. }
  260. // Legacy input iterator atomic
  261. TEST(Tring_iterator, LegacyInputIterator_atomic) {
  262. int A[10] {0, 1, 2, 3, 4, 5, 6, 7, 8 , 9};
  263. ring_iterator<int*, 10, true> i1(A), i2(A), i3(A, 1);
  264. struct T { int m; };
  265. T B[5] { {0}, {1}, {2}, {3}, {4}};
  266. ring_iterator<T*, 5, true> it(B);
  267. EXPECT_EQ (true, (std::is_same<bool, decltype(i1 == i2)>::value));
  268. EXPECT_EQ (true, (std::is_same<bool, decltype(i1 != i2)>::value));
  269. EXPECT_EQ (true, (std::is_same<int&, decltype(*i1)>::value));
  270. EXPECT_EQ (true, (std::is_same<int, decltype(it->m)>::value));
  271. EXPECT_EQ (true, (std::is_same<ring_iterator<int*, 10, true>&, decltype(++i1)>::value));
  272. EXPECT_EQ (true, (std::is_same<int&, decltype(*i1++)>::value));
  273. // more practical
  274. EXPECT_EQ (true, i1 == i2);
  275. EXPECT_EQ (true, i1 != i3);
  276. EXPECT_EQ (0, *i1);
  277. EXPECT_EQ (0, it->m);
  278. EXPECT_EQ (true, (++i1 == i3));
  279. EXPECT_EQ (1, *i1++);
  280. EXPECT_EQ (2, *i1);
  281. }
  282. // Legacy input iterator atomic
  283. TEST(Tring_iterator, LegacyOutputIterator_atomic) {
  284. int A[10] {0, 1, 2, 3, 4, 5, 6, 7, 8 , 9};
  285. ring_iterator<int*, 10, true> it(A);
  286. EXPECT_EQ (true, (std::is_assignable<decltype(*it), int>::value));
  287. EXPECT_EQ (true, (std::is_assignable<decltype(*it++), int>::value));
  288. // more practical
  289. *it = 42;
  290. EXPECT_EQ (42, A[0]);
  291. *it++ = 7;
  292. EXPECT_EQ (7, A[0]);
  293. EXPECT_EQ (&A[1], it.iter());
  294. }
  295. // Legacy forward iterator atomic
  296. TEST(Tring_iterator, LegacyForwardIterator_atomic)
  297. {
  298. int A[10] {0, 1, 2, 3, 4, 5, 6, 7, 8 , 9};
  299. ring_iterator<int*, 10, true> it(A);
  300. EXPECT_EQ (0, *it++);
  301. EXPECT_EQ (1, *it);
  302. }
  303. // Legacy bidirectional iterator atomic
  304. TEST(Tring_iterator, LegacyBidirectionalIterator_atomic) {
  305. int A[10] {0, 1, 2, 3, 4, 5, 6, 7, 8 , 9};
  306. ring_iterator<int*, 10, true> it(A);
  307. EXPECT_EQ (true, (std::is_same<ring_iterator<int*, 10, true>&, decltype(--it)>::value));
  308. EXPECT_EQ (true, (std::is_same<ring_iterator<int*, 10, true>, decltype(it--)>::value));
  309. EXPECT_EQ (true, (std::is_same<int&, decltype(*it--)>::value));
  310. // more practical
  311. ring_iterator<int*, 10, true> i1(A), i2(A, 9);
  312. EXPECT_EQ (9, *i2--); // check loop also
  313. EXPECT_EQ (8, *i2);
  314. EXPECT_EQ (0, *i1--); // check loop also
  315. EXPECT_EQ (9, *i1);
  316. }
  317. // Legacy random access iterator atomic
  318. TEST(Tring_iterator, LegacyRandomAccessIterator_atomic) {
  319. int A[10] {0, 1, 2, 3, 4, 5, 6, 7, 8 , 9};
  320. ring_iterator<int*, 10, true> it1(A), it2(A, 7);
  321. EXPECT_EQ (true, (std::is_same<ring_iterator<int*, 10, true>&, decltype(it1 += 7)>::value));
  322. EXPECT_EQ (true, (std::is_same<ring_iterator<int*, 10, true>, decltype(it1 + 7)>::value));
  323. EXPECT_EQ (true, (std::is_same<ring_iterator<int*, 10, true>, decltype(7 + it1)>::value));
  324. EXPECT_EQ (true, (std::is_same<ring_iterator<int*, 10, true>&, decltype(it1 -= 7)>::value));
  325. EXPECT_EQ (true, (std::is_same<ring_iterator<int*, 10, true>, decltype(it1 - 7)>::value));
  326. EXPECT_EQ (true, (std::is_same<std::ptrdiff_t, decltype(it1 - it2)>::value));
  327. EXPECT_EQ (true, (std::is_same<int&, decltype(it1[7])>::value));
  328. EXPECT_EQ (true, (std::is_same<bool, decltype(it1 < it2)>::value));
  329. EXPECT_EQ (true, (std::is_same<bool, decltype(it1 > it2)>::value));
  330. EXPECT_EQ (true, (std::is_same<bool, decltype(it1 <= it2)>::value));
  331. EXPECT_EQ (true, (std::is_same<bool, decltype(it1 >= it2)>::value));
  332. // more practical
  333. ring_iterator<int*, 10, true> i1(A), i2(A);
  334. i1 += 7;
  335. EXPECT_EQ (7, *i1);
  336. i1 -= 7;
  337. EXPECT_EQ (0, *i1);
  338. i1 += 11;
  339. EXPECT_EQ (1, *i1);
  340. i1 -= 2;
  341. EXPECT_EQ (9, *i1);
  342. EXPECT_EQ (7, *(i2+7));
  343. EXPECT_EQ (7, *(7+i2));
  344. EXPECT_EQ (1, *(i2+11));
  345. EXPECT_EQ (1, *(11+i2));
  346. EXPECT_EQ (7, *(i1-2));
  347. EXPECT_EQ (8, *(i2-2));
  348. EXPECT_EQ (9, (i1 - i2));
  349. EXPECT_EQ (1, (i2 - i1)); // loop
  350. }
  351. }