unittest_mtrie.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. /*
  2. Copyright (c) 2018 Contributors as noted in the AUTHORS file
  3. This file is part of 0MQ.
  4. 0MQ is free software; you can redistribute it and/or modify it under
  5. the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. 0MQ is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "../tests/testutil.hpp"
  16. #if defined(min)
  17. #undef min
  18. #endif
  19. #include <generic_mtrie_impl.hpp>
  20. #include <unity.h>
  21. void setUp ()
  22. {
  23. }
  24. void tearDown ()
  25. {
  26. }
  27. int getlen (const zmq::generic_mtrie_t<int>::prefix_t &data_)
  28. {
  29. return static_cast<int> (strlen (reinterpret_cast<const char *> (data_)));
  30. }
  31. void test_create ()
  32. {
  33. zmq::generic_mtrie_t<int> mtrie;
  34. }
  35. void mtrie_count (int *pipe_, int *count_)
  36. {
  37. LIBZMQ_UNUSED (pipe_);
  38. ++*count_;
  39. }
  40. void test_check_empty_match_nonempty_data ()
  41. {
  42. zmq::generic_mtrie_t<int> mtrie;
  43. const zmq::generic_mtrie_t<int>::prefix_t test_name =
  44. reinterpret_cast<zmq::generic_mtrie_t<int>::prefix_t> ("foo");
  45. int count = 0;
  46. mtrie.match (test_name, getlen (test_name), mtrie_count, &count);
  47. TEST_ASSERT_EQUAL_INT (0, count);
  48. }
  49. void test_check_empty_match_empty_data ()
  50. {
  51. zmq::generic_mtrie_t<int> mtrie;
  52. int count = 0;
  53. mtrie.match (NULL, 0, mtrie_count, &count);
  54. TEST_ASSERT_EQUAL_INT (0, count);
  55. }
  56. void test_add_single_entry_match_exact ()
  57. {
  58. int pipe;
  59. zmq::generic_mtrie_t<int> mtrie;
  60. const zmq::generic_mtrie_t<int>::prefix_t test_name =
  61. reinterpret_cast<zmq::generic_mtrie_t<int>::prefix_t> ("foo");
  62. bool res = mtrie.add (test_name, getlen (test_name), &pipe);
  63. TEST_ASSERT_TRUE (res);
  64. int count = 0;
  65. mtrie.match (test_name, getlen (test_name), mtrie_count, &count);
  66. TEST_ASSERT_EQUAL_INT (1, count);
  67. }
  68. void test_add_single_entry_twice_match_exact ()
  69. {
  70. int pipe;
  71. zmq::generic_mtrie_t<int> mtrie;
  72. const zmq::generic_mtrie_t<int>::prefix_t test_name =
  73. reinterpret_cast<zmq::generic_mtrie_t<int>::prefix_t> ("foo");
  74. bool res = mtrie.add (test_name, getlen (test_name), &pipe);
  75. TEST_ASSERT_TRUE (res);
  76. res = mtrie.add (test_name, getlen (test_name), &pipe);
  77. TEST_ASSERT_FALSE (res);
  78. int count = 0;
  79. mtrie.match (test_name, getlen (test_name), mtrie_count, &count);
  80. TEST_ASSERT_EQUAL_INT (1, count);
  81. }
  82. void test_add_two_entries_with_same_name_match_exact ()
  83. {
  84. int pipe_1, pipe_2;
  85. zmq::generic_mtrie_t<int> mtrie;
  86. const zmq::generic_mtrie_t<int>::prefix_t test_name =
  87. reinterpret_cast<zmq::generic_mtrie_t<int>::prefix_t> ("foo");
  88. bool res = mtrie.add (test_name, getlen (test_name), &pipe_1);
  89. TEST_ASSERT_TRUE (res);
  90. res = mtrie.add (test_name, getlen (test_name), &pipe_2);
  91. TEST_ASSERT_FALSE (res);
  92. int count = 0;
  93. mtrie.match (test_name, getlen (test_name), mtrie_count, &count);
  94. TEST_ASSERT_EQUAL_INT (2, count);
  95. }
  96. void test_add_two_entries_match_prefix_and_exact ()
  97. {
  98. int pipe_1, pipe_2;
  99. zmq::generic_mtrie_t<int> mtrie;
  100. const zmq::generic_mtrie_t<int>::prefix_t test_name_prefix =
  101. reinterpret_cast<zmq::generic_mtrie_t<int>::prefix_t> ("foo");
  102. const zmq::generic_mtrie_t<int>::prefix_t test_name_full =
  103. reinterpret_cast<zmq::generic_mtrie_t<int>::prefix_t> ("foobar");
  104. bool res = mtrie.add (test_name_prefix, getlen (test_name_prefix), &pipe_1);
  105. TEST_ASSERT_TRUE (res);
  106. res = mtrie.add (test_name_full, getlen (test_name_full), &pipe_2);
  107. TEST_ASSERT_TRUE (res);
  108. int count = 0;
  109. mtrie.match (test_name_full, getlen (test_name_full), mtrie_count, &count);
  110. TEST_ASSERT_EQUAL_INT (2, count);
  111. }
  112. void test_add_rm_single_entry_match_exact ()
  113. {
  114. int pipe;
  115. zmq::generic_mtrie_t<int> mtrie;
  116. const zmq::generic_mtrie_t<int>::prefix_t test_name =
  117. reinterpret_cast<zmq::generic_mtrie_t<int>::prefix_t> ("foo");
  118. mtrie.add (test_name, getlen (test_name), &pipe);
  119. zmq::generic_mtrie_t<int>::rm_result res =
  120. mtrie.rm (test_name, getlen (test_name), &pipe);
  121. TEST_ASSERT_EQUAL (zmq::generic_mtrie_t<int>::last_value_removed, res);
  122. int count = 0;
  123. mtrie.match (test_name, getlen (test_name), mtrie_count, &count);
  124. TEST_ASSERT_EQUAL_INT (0, count);
  125. }
  126. void test_rm_nonexistent_0_size_empty ()
  127. {
  128. int pipe;
  129. zmq::generic_mtrie_t<int> mtrie;
  130. zmq::generic_mtrie_t<int>::rm_result res = mtrie.rm (0, 0, &pipe);
  131. TEST_ASSERT_EQUAL (zmq::generic_mtrie_t<int>::not_found, res);
  132. }
  133. void test_rm_nonexistent_empty ()
  134. {
  135. int pipe;
  136. zmq::generic_mtrie_t<int> mtrie;
  137. const zmq::generic_mtrie_t<int>::prefix_t test_name =
  138. reinterpret_cast<zmq::generic_mtrie_t<int>::prefix_t> ("foo");
  139. zmq::generic_mtrie_t<int>::rm_result res =
  140. mtrie.rm (test_name, getlen (test_name), &pipe);
  141. TEST_ASSERT_EQUAL (zmq::generic_mtrie_t<int>::not_found, res);
  142. int count = 0;
  143. mtrie.match (test_name, getlen (test_name), mtrie_count, &count);
  144. TEST_ASSERT_EQUAL_INT (0, count);
  145. }
  146. void test_add_and_rm_other (const char *add_name_, const char *rm_name_)
  147. {
  148. int addpipe, rmpipe;
  149. zmq::generic_mtrie_t<int> mtrie;
  150. const zmq::generic_mtrie_t<int>::prefix_t add_name_data =
  151. reinterpret_cast<zmq::generic_mtrie_t<int>::prefix_t> (add_name_);
  152. const zmq::generic_mtrie_t<int>::prefix_t rm_name_data =
  153. reinterpret_cast<zmq::generic_mtrie_t<int>::prefix_t> (rm_name_);
  154. mtrie.add (add_name_data, getlen (add_name_data), &addpipe);
  155. zmq::generic_mtrie_t<int>::rm_result res =
  156. mtrie.rm (rm_name_data, getlen (rm_name_data), &rmpipe);
  157. TEST_ASSERT_EQUAL (zmq::generic_mtrie_t<int>::not_found, res);
  158. {
  159. int count = 0;
  160. mtrie.match (add_name_data, getlen (add_name_data), mtrie_count,
  161. &count);
  162. TEST_ASSERT_EQUAL_INT (1, count);
  163. }
  164. if (strncmp (add_name_, rm_name_,
  165. std::min (strlen (add_name_), strlen (rm_name_) + 1))
  166. != 0) {
  167. int count = 0;
  168. mtrie.match (rm_name_data, getlen (rm_name_data), mtrie_count, &count);
  169. TEST_ASSERT_EQUAL_INT (0, count);
  170. }
  171. }
  172. void test_rm_nonexistent_nonempty_samename ()
  173. {
  174. // TODO this triggers an assertion
  175. test_add_and_rm_other ("foo", "foo");
  176. }
  177. void test_rm_nonexistent_nonempty_differentname ()
  178. {
  179. test_add_and_rm_other ("foo", "bar");
  180. }
  181. void test_rm_nonexistent_nonempty_prefix ()
  182. {
  183. // TODO here, a test assertion fails
  184. test_add_and_rm_other ("foobar", "foo");
  185. }
  186. void test_rm_nonexistent_nonempty_prefixed ()
  187. {
  188. test_add_and_rm_other ("foo", "foobar");
  189. }
  190. void add_indexed_expect_unique (zmq::generic_mtrie_t<int> &mtrie_,
  191. int *pipes_,
  192. const char **names_,
  193. size_t i_)
  194. {
  195. const zmq::generic_mtrie_t<int>::prefix_t name_data =
  196. reinterpret_cast<zmq::generic_mtrie_t<int>::prefix_t> (names_[i_]);
  197. bool res = mtrie_.add (name_data, getlen (name_data), &pipes_[i_]);
  198. TEST_ASSERT_EQUAL (zmq::generic_mtrie_t<int>::last_value_removed, res);
  199. }
  200. void test_rm_nonexistent_between ()
  201. {
  202. int pipes[3];
  203. const char *names[] = {"foo1", "foo2", "foo3"};
  204. zmq::generic_mtrie_t<int> mtrie;
  205. add_indexed_expect_unique (mtrie, pipes, names, 0);
  206. add_indexed_expect_unique (mtrie, pipes, names, 2);
  207. const zmq::generic_mtrie_t<int>::prefix_t name_data =
  208. reinterpret_cast<zmq::generic_mtrie_t<int>::prefix_t> (names[1]);
  209. zmq::generic_mtrie_t<int>::rm_result res =
  210. mtrie.rm (name_data, getlen (name_data), &pipes[1]);
  211. TEST_ASSERT_EQUAL (zmq::generic_mtrie_t<int>::not_found, res);
  212. }
  213. template <size_t N>
  214. void add_entries (zmq::generic_mtrie_t<int> &mtrie_,
  215. int (&pipes_)[N],
  216. const char *(&names_)[N])
  217. {
  218. for (size_t i = 0; i < N; ++i) {
  219. add_indexed_expect_unique (mtrie_, pipes_, names_, i);
  220. }
  221. }
  222. void test_add_multiple ()
  223. {
  224. int pipes[3];
  225. const char *names[] = {"foo1", "foo2", "foo3"};
  226. zmq::generic_mtrie_t<int> mtrie;
  227. add_entries (mtrie, pipes, names);
  228. for (size_t i = 0; i < sizeof (names) / sizeof (names[0]); ++i) {
  229. const zmq::generic_mtrie_t<int>::prefix_t name_data =
  230. reinterpret_cast<zmq::generic_mtrie_t<int>::prefix_t> (names[i]);
  231. int count = 0;
  232. mtrie.match (name_data, getlen (name_data), mtrie_count, &count);
  233. TEST_ASSERT_EQUAL_INT (1, count);
  234. }
  235. }
  236. void test_add_multiple_reverse ()
  237. {
  238. int pipes[3];
  239. const char *names[] = {"foo1", "foo2", "foo3"};
  240. zmq::generic_mtrie_t<int> mtrie;
  241. for (int i = 2; i >= 0; --i) {
  242. add_indexed_expect_unique (mtrie, pipes, names,
  243. static_cast<size_t> (i));
  244. }
  245. for (size_t i = 0; i < 3; ++i) {
  246. const zmq::generic_mtrie_t<int>::prefix_t name_data =
  247. reinterpret_cast<zmq::generic_mtrie_t<int>::prefix_t> (names[i]);
  248. int count = 0;
  249. mtrie.match (name_data, getlen (name_data), mtrie_count, &count);
  250. TEST_ASSERT_EQUAL_INT (1, count);
  251. }
  252. }
  253. template <size_t N> void add_and_rm_entries (const char *(&names_)[N])
  254. {
  255. int pipes[N];
  256. zmq::generic_mtrie_t<int> mtrie;
  257. add_entries (mtrie, pipes, names_);
  258. for (size_t i = 0; i < N; ++i) {
  259. const zmq::generic_mtrie_t<int>::prefix_t name_data =
  260. reinterpret_cast<zmq::generic_mtrie_t<int>::prefix_t> (names_[i]);
  261. zmq::generic_mtrie_t<int>::rm_result res =
  262. mtrie.rm (name_data, getlen (name_data), &pipes[i]);
  263. TEST_ASSERT_EQUAL (zmq::generic_mtrie_t<int>::last_value_removed, res);
  264. }
  265. }
  266. void test_rm_multiple_in_order ()
  267. {
  268. const char *names[] = {"foo1", "foo2", "foo3"};
  269. add_and_rm_entries (names);
  270. }
  271. void test_rm_multiple_reverse_order ()
  272. {
  273. const char *names[] = {"foo3", "foo2", "foo1"};
  274. add_and_rm_entries (names);
  275. }
  276. void check_name (zmq::generic_mtrie_t<int>::prefix_t data_,
  277. size_t len_,
  278. const char *name_)
  279. {
  280. TEST_ASSERT_EQUAL_UINT (strlen (name_), len_);
  281. TEST_ASSERT_EQUAL_STRING_LEN (name_, data_, len_);
  282. }
  283. template <size_t N> void add_entries_rm_pipes_unique (const char *(&names_)[N])
  284. {
  285. int pipes[N];
  286. zmq::generic_mtrie_t<int> mtrie;
  287. add_entries (mtrie, pipes, names_);
  288. for (size_t i = 0; i < N; ++i) {
  289. mtrie.rm (&pipes[i], check_name, names_[i], false);
  290. }
  291. }
  292. void test_rm_with_callback_multiple_in_order ()
  293. {
  294. const char *names[] = {"foo1", "foo2", "foo3"};
  295. add_entries_rm_pipes_unique (names);
  296. }
  297. void test_rm_with_callback_multiple_reverse_order ()
  298. {
  299. const char *names[] = {"foo3", "foo2", "foo1"};
  300. add_entries_rm_pipes_unique (names);
  301. }
  302. void check_count (zmq::generic_mtrie_t<int>::prefix_t data_,
  303. size_t len_,
  304. int *count_)
  305. {
  306. --(*count_);
  307. TEST_ASSERT_GREATER_OR_EQUAL (0, *count_);
  308. }
  309. void add_duplicate_entry (zmq::generic_mtrie_t<int> &mtrie_, int (&pipes_)[2])
  310. {
  311. const char *name = "foo";
  312. const zmq::generic_mtrie_t<int>::prefix_t name_data =
  313. reinterpret_cast<zmq::generic_mtrie_t<int>::prefix_t> (name);
  314. bool res = mtrie_.add (name_data, getlen (name_data), &pipes_[0]);
  315. TEST_ASSERT_TRUE (res);
  316. res = mtrie_.add (name_data, getlen (name_data), &pipes_[1]);
  317. TEST_ASSERT_FALSE (res);
  318. }
  319. void test_rm_with_callback_duplicate ()
  320. {
  321. int pipes[2];
  322. zmq::generic_mtrie_t<int> mtrie;
  323. add_duplicate_entry (mtrie, pipes);
  324. int count = 1;
  325. mtrie.rm (&pipes[0], check_count, &count, false);
  326. count = 1;
  327. mtrie.rm (&pipes[1], check_count, &count, false);
  328. }
  329. void test_rm_with_callback_duplicate_uniq_only ()
  330. {
  331. int pipes[2];
  332. zmq::generic_mtrie_t<int> mtrie;
  333. add_duplicate_entry (mtrie, pipes);
  334. int count = 0;
  335. mtrie.rm (&pipes[0], check_count, &count, true);
  336. count = 1;
  337. mtrie.rm (&pipes[1], check_count, &count, true);
  338. }
  339. int main (void)
  340. {
  341. setup_test_environment ();
  342. UNITY_BEGIN ();
  343. RUN_TEST (test_create);
  344. RUN_TEST (test_check_empty_match_nonempty_data);
  345. RUN_TEST (test_check_empty_match_empty_data);
  346. RUN_TEST (test_add_single_entry_match_exact);
  347. RUN_TEST (test_add_single_entry_twice_match_exact);
  348. RUN_TEST (test_add_rm_single_entry_match_exact);
  349. RUN_TEST (test_add_two_entries_match_prefix_and_exact);
  350. RUN_TEST (test_add_two_entries_with_same_name_match_exact);
  351. RUN_TEST (test_rm_nonexistent_0_size_empty);
  352. RUN_TEST (test_rm_nonexistent_empty);
  353. RUN_TEST (test_rm_nonexistent_nonempty_samename);
  354. RUN_TEST (test_rm_nonexistent_nonempty_differentname);
  355. RUN_TEST (test_rm_nonexistent_nonempty_prefix);
  356. RUN_TEST (test_rm_nonexistent_nonempty_prefixed);
  357. RUN_TEST (test_rm_nonexistent_between);
  358. RUN_TEST (test_add_multiple);
  359. RUN_TEST (test_add_multiple_reverse);
  360. RUN_TEST (test_rm_multiple_in_order);
  361. RUN_TEST (test_rm_multiple_reverse_order);
  362. RUN_TEST (test_rm_with_callback_multiple_in_order);
  363. RUN_TEST (test_rm_with_callback_multiple_reverse_order);
  364. RUN_TEST (test_rm_with_callback_duplicate);
  365. RUN_TEST (test_rm_with_callback_duplicate_uniq_only);
  366. return UNITY_END ();
  367. }