rbtree.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
  3. * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. #include "test.h"
  20. #if INCLUDE_RBTREE_TEST
  21. #include <pjlib.h>
  22. #define LOOP 32
  23. #define MIN_COUNT 64
  24. #define MAX_COUNT (LOOP * MIN_COUNT)
  25. #define STRSIZE 16
  26. #define THIS_FILE "rbtree_test"
  27. typedef struct node_key
  28. {
  29. pj_uint32_t hash;
  30. char str[STRSIZE];
  31. } node_key;
  32. static int compare_node(const node_key *k1, const node_key *k2)
  33. {
  34. if (k1->hash == k2->hash) {
  35. return strcmp(k1->str, k2->str);
  36. } else {
  37. return k1->hash < k2->hash ? -1 : 1;
  38. }
  39. }
  40. void randomize_string(char *str, int len)
  41. {
  42. int i;
  43. for (i=0; i<len-1; ++i)
  44. str[i] = (char)('a' + pj_rand() % 26);
  45. str[len-1] = '\0';
  46. }
  47. static int test(void)
  48. {
  49. pj_rbtree rb;
  50. node_key *key;
  51. pj_rbtree_node *node;
  52. pj_pool_t *pool;
  53. int err=0;
  54. int count = MIN_COUNT;
  55. int i;
  56. unsigned size;
  57. pj_rbtree_init(&rb, (pj_rbtree_comp*)&compare_node);
  58. size = MAX_COUNT*(sizeof(*key)+PJ_RBTREE_NODE_SIZE) +
  59. PJ_RBTREE_SIZE + PJ_POOL_SIZE;
  60. pool = pj_pool_create( mem, "pool", size, 0, NULL);
  61. if (!pool) {
  62. PJ_LOG(3,("test", "...error: creating pool of %u bytes", size));
  63. return -10;
  64. }
  65. key = (node_key *)pj_pool_alloc(pool, MAX_COUNT*sizeof(*key));
  66. if (!key)
  67. return -20;
  68. node = (pj_rbtree_node*)pj_pool_alloc(pool, MAX_COUNT*sizeof(*node));
  69. if (!node)
  70. return -30;
  71. for (i=0; i<LOOP; ++i) {
  72. int j;
  73. pj_rbtree_node *prev, *it;
  74. pj_timestamp t1, t2, t_setup, t_insert, t_search, t_erase;
  75. pj_assert(rb.size == 0);
  76. t_setup.u32.lo = t_insert.u32.lo = t_search.u32.lo = t_erase.u32.lo = 0;
  77. for (j=0; j<count; j++) {
  78. randomize_string(key[j].str, STRSIZE);
  79. pj_get_timestamp(&t1);
  80. node[j].key = &key[j];
  81. node[j].user_data = key[j].str;
  82. key[j].hash = pj_hash_calc(0, key[j].str, PJ_HASH_KEY_STRING);
  83. pj_get_timestamp(&t2);
  84. t_setup.u32.lo += (t2.u32.lo - t1.u32.lo);
  85. pj_get_timestamp(&t1);
  86. pj_rbtree_insert(&rb, &node[j]);
  87. pj_get_timestamp(&t2);
  88. t_insert.u32.lo += (t2.u32.lo - t1.u32.lo);
  89. }
  90. pj_assert(rb.size == (unsigned)count);
  91. // Iterate key, make sure they're sorted.
  92. prev = NULL;
  93. it = pj_rbtree_first(&rb);
  94. while (it) {
  95. if (prev) {
  96. if (compare_node((node_key*)prev->key,(node_key*)it->key)>=0) {
  97. ++err;
  98. PJ_LOG(3, (THIS_FILE, "Error: %s >= %s",
  99. (char*)prev->user_data, (char*)it->user_data));
  100. }
  101. }
  102. prev = it;
  103. it = pj_rbtree_next(&rb, it);
  104. }
  105. // Search.
  106. for (j=0; j<count; j++) {
  107. pj_get_timestamp(&t1);
  108. it = pj_rbtree_find(&rb, &key[j]);
  109. pj_get_timestamp(&t2);
  110. t_search.u32.lo += (t2.u32.lo - t1.u32.lo);
  111. pj_assert(it != NULL);
  112. if (it == NULL)
  113. ++err;
  114. }
  115. // Erase node.
  116. for (j=0; j<count; j++) {
  117. pj_get_timestamp(&t1);
  118. it = pj_rbtree_erase(&rb, &node[j]);
  119. pj_get_timestamp(&t2);
  120. t_erase.u32.lo += (t2.u32.lo - t1.u32.lo);
  121. }
  122. PJ_LOG(4, (THIS_FILE,
  123. "...count:%d, setup:%d, insert:%d, search:%d, erase:%d",
  124. count,
  125. t_setup.u32.lo / count, t_insert.u32.lo / count,
  126. t_search.u32.lo / count, t_erase.u32.lo / count));
  127. count = 2 * count;
  128. if (count > MAX_COUNT)
  129. break;
  130. }
  131. pj_pool_release(pool);
  132. return err;
  133. }
  134. int rbtree_test()
  135. {
  136. return test();
  137. }
  138. #endif /* INCLUDE_RBTREE_TEST */