test_heap.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2009, Digium, Inc.
  5. *
  6. * Russell Bryant <russell@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*! \file
  19. *
  20. * \brief Heap data structure test module
  21. *
  22. * \author Russell Bryant <russell@digium.com>
  23. */
  24. /*** MODULEINFO
  25. <depend>TEST_FRAMEWORK</depend>
  26. <support_level>extended</support_level>
  27. ***/
  28. #include "asterisk.h"
  29. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  30. #include "asterisk/module.h"
  31. #include "asterisk/utils.h"
  32. #include "asterisk/heap.h"
  33. #include "asterisk/test.h"
  34. struct node {
  35. long val;
  36. size_t index;
  37. };
  38. static int node_cmp(void *_n1, void *_n2)
  39. {
  40. struct node *n1 = _n1;
  41. struct node *n2 = _n2;
  42. if (n1->val < n2->val) {
  43. return -1;
  44. } else if (n1->val == n2->val) {
  45. return 0;
  46. } else {
  47. return 1;
  48. }
  49. }
  50. AST_TEST_DEFINE(heap_test_1)
  51. {
  52. struct ast_heap *h;
  53. struct node *obj;
  54. struct node nodes[3] = {
  55. { 1, } ,
  56. { 2, } ,
  57. { 3, } ,
  58. };
  59. switch (cmd) {
  60. case TEST_INIT:
  61. info->name = "heap_test_1";
  62. info->category = "/main/heap/";
  63. info->summary = "push and pop elements";
  64. info->description = "Push a few elements onto a heap and make sure that they come back off in the right order.";
  65. return AST_TEST_NOT_RUN;
  66. case TEST_EXECUTE:
  67. break;
  68. }
  69. if (!(h = ast_heap_create(8, node_cmp, offsetof(struct node, index)))) {
  70. return AST_TEST_FAIL;
  71. }
  72. ast_heap_push(h, &nodes[0]);
  73. ast_heap_push(h, &nodes[1]);
  74. ast_heap_push(h, &nodes[2]);
  75. obj = ast_heap_pop(h);
  76. if (obj->val != 3) {
  77. ast_test_status_update(test, "expected 3, got %ld\n", obj->val);
  78. return AST_TEST_FAIL;
  79. }
  80. obj = ast_heap_pop(h);
  81. if (obj->val != 2) {
  82. ast_test_status_update(test, "expected 2, got %ld\n", obj->val);
  83. return AST_TEST_FAIL;
  84. }
  85. obj = ast_heap_pop(h);
  86. if (obj->val != 1) {
  87. ast_test_status_update(test, "expected 1, got %ld\n", obj->val);
  88. return AST_TEST_FAIL;
  89. }
  90. obj = ast_heap_pop(h);
  91. if (obj) {
  92. ast_test_status_update(test, "got unexpected object\n");
  93. return AST_TEST_FAIL;
  94. }
  95. h = ast_heap_destroy(h);
  96. return AST_TEST_PASS;
  97. }
  98. AST_TEST_DEFINE(heap_test_2)
  99. {
  100. struct ast_heap *h = NULL;
  101. static const unsigned int total = 100000;
  102. struct node *nodes = NULL;
  103. struct node *node;
  104. unsigned int i = total;
  105. long last = LONG_MAX;
  106. long cur;
  107. enum ast_test_result_state res = AST_TEST_PASS;
  108. switch (cmd) {
  109. case TEST_INIT:
  110. info->name = "heap_test_2";
  111. info->category = "/main/heap/";
  112. info->summary = "load test";
  113. info->description =
  114. "Push one hundred thousand random elements on to a heap, "
  115. "verify that the heap has been properly constructed, "
  116. "and then ensure that the elements are come back off "
  117. "in the proper order.";
  118. return AST_TEST_NOT_RUN;
  119. case TEST_EXECUTE:
  120. break;
  121. }
  122. if (!(nodes = ast_malloc(total * sizeof(*node)))) {
  123. res = AST_TEST_FAIL;
  124. goto return_cleanup;
  125. }
  126. if (!(h = ast_heap_create(20, node_cmp, offsetof(struct node, index)))) {
  127. res = AST_TEST_FAIL;
  128. goto return_cleanup;
  129. }
  130. while (i--) {
  131. nodes[i].val = ast_random();
  132. ast_heap_push(h, &nodes[i]);
  133. }
  134. if (ast_heap_verify(h)) {
  135. res = AST_TEST_FAIL;
  136. goto return_cleanup;
  137. }
  138. i = 0;
  139. while ((node = ast_heap_pop(h))) {
  140. cur = node->val;
  141. if (cur > last) {
  142. ast_test_status_update(test, "i: %u, cur: %ld, last: %ld\n", i, cur, last);
  143. res = AST_TEST_FAIL;
  144. goto return_cleanup;
  145. }
  146. last = cur;
  147. i++;
  148. }
  149. if (i != total) {
  150. ast_test_status_update(test, "Stopped popping off after only getting %u nodes\n", i);
  151. res = AST_TEST_FAIL;
  152. goto return_cleanup;
  153. }
  154. return_cleanup:
  155. if (h) {
  156. h = ast_heap_destroy(h);
  157. }
  158. if (nodes) {
  159. ast_free(nodes);
  160. }
  161. return res;
  162. }
  163. AST_TEST_DEFINE(heap_test_3)
  164. {
  165. struct ast_heap *h = NULL;
  166. struct node *nodes = NULL;
  167. struct node *node;
  168. static const unsigned int test_size = 100000;
  169. unsigned int i = test_size;
  170. long last = LONG_MAX, cur;
  171. int random_index;
  172. enum ast_test_result_state res = AST_TEST_PASS;
  173. switch (cmd) {
  174. case TEST_INIT:
  175. info->name = "heap_test_3";
  176. info->category = "/main/heap/";
  177. info->summary = "random element removal test";
  178. info->description =
  179. "Push a hundred thousand random elements on to a heap, "
  180. "verify that the heap has been properly constructed, "
  181. "randomly remove and re-add 10000 elements, and then "
  182. "ensure that the elements come back off in the proper order.";
  183. return AST_TEST_NOT_RUN;
  184. case TEST_EXECUTE:
  185. break;
  186. }
  187. if (!(nodes = ast_malloc(test_size * sizeof(*node)))) {
  188. ast_test_status_update(test, "memory allocation failure\n");
  189. res = AST_TEST_FAIL;
  190. goto return_cleanup;
  191. }
  192. if (!(h = ast_heap_create(20, node_cmp, offsetof(struct node, index)))) {
  193. ast_test_status_update(test, "Failed to allocate heap\n");
  194. res = AST_TEST_FAIL;
  195. goto return_cleanup;
  196. }
  197. while (i--) {
  198. nodes[i].val = ast_random();
  199. ast_heap_push(h, &nodes[i]);
  200. }
  201. if (ast_heap_verify(h)) {
  202. ast_test_status_update(test, "Failed to verify heap after populating it\n");
  203. res = AST_TEST_FAIL;
  204. goto return_cleanup;
  205. }
  206. i = test_size / 10;
  207. while (i--) {
  208. random_index = ast_random() % test_size;
  209. node = ast_heap_remove(h, &nodes[random_index]);
  210. if (nodes[random_index].val != node->val){
  211. ast_test_status_update(test, "Failed to remove what we expected to\n");
  212. res = AST_TEST_FAIL;
  213. goto return_cleanup;
  214. }
  215. ast_heap_push(h, &nodes[random_index]);
  216. }
  217. if (ast_heap_verify(h)) {
  218. ast_test_status_update(test, "Failed to verify after removals\n");
  219. res = AST_TEST_FAIL;
  220. goto return_cleanup;
  221. }
  222. i = 0;
  223. while ((node = ast_heap_pop(h))) {
  224. cur = node->val;
  225. if (cur > last) {
  226. ast_test_status_update(test, "i: %u, cur: %ld, last: %ld\n", i, cur, last);
  227. res = AST_TEST_FAIL;
  228. goto return_cleanup;
  229. }
  230. last = cur;
  231. i++;
  232. }
  233. if (i != test_size) {
  234. ast_test_status_update(test, "Stopped popping off after only getting %u nodes\n", i);
  235. res = AST_TEST_FAIL;
  236. goto return_cleanup;
  237. }
  238. return_cleanup:
  239. if (h) {
  240. h = ast_heap_destroy(h);
  241. }
  242. if (nodes) {
  243. ast_free(nodes);
  244. }
  245. return res;
  246. }
  247. static int unload_module(void)
  248. {
  249. AST_TEST_UNREGISTER(heap_test_1);
  250. AST_TEST_UNREGISTER(heap_test_2);
  251. AST_TEST_UNREGISTER(heap_test_3);
  252. return 0;
  253. }
  254. static int load_module(void)
  255. {
  256. AST_TEST_REGISTER(heap_test_1);
  257. AST_TEST_REGISTER(heap_test_2);
  258. AST_TEST_REGISTER(heap_test_3);
  259. return AST_MODULE_LOAD_SUCCESS;
  260. }
  261. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Heap test module");