blob: d21c868238c302560e9e0c9b9ed5c48b805c4fc8 [file] [log] [blame]
Benny Prijono4766ffe2005-11-01 17:56:59 +00001/* $Id$
2 *
3 */
Benny Prijonodd859a62005-11-01 16:42:51 +00004#include "test.h"
5
6#if INCLUDE_RBTREE_TEST
7
8#include <pjlib.h>
9
10#define LOOP 32
11#define MIN_COUNT 64
12#define MAX_COUNT (LOOP * MIN_COUNT)
13#define STRSIZE 16
14#define THIS_FILE "rbtree_test"
15
16typedef struct node_key
17{
18 pj_uint32_t hash;
19 char str[STRSIZE];
20} node_key;
21
22static int compare_node(const node_key *k1, const node_key *k2)
23{
24 if (k1->hash == k2->hash) {
25 return strcmp(k1->str, k2->str);
26 } else {
27 return k1->hash < k2->hash ? -1 : 1;
28 }
29}
30
31void randomize_string(char *str, int len)
32{
33 int i;
34 for (i=0; i<len-1; ++i)
35 str[i] = (char)('a' + pj_rand() % 26);
36 str[len-1] = '\0';
37}
38
39static int test(void)
40{
41 pj_rbtree rb;
42 node_key *key;
43 pj_rbtree_node *node;
44 pj_pool_t *pool;
45 int err=0;
46 int count = MIN_COUNT;
47 int i;
48 unsigned size;
49
50 pj_rbtree_init(&rb, (pj_rbtree_comp*)&compare_node);
51 size = MAX_COUNT*(sizeof(*key)+PJ_RBTREE_NODE_SIZE) +
52 PJ_RBTREE_SIZE + PJ_POOL_SIZE;
53 pool = pj_pool_create( mem, "pool", size, 0, NULL);
54 if (!pool) {
55 PJ_LOG(3,("test", "...error: creating pool of %u bytes", size));
56 return -10;
57 }
58
59 key = (node_key *)pj_pool_alloc(pool, MAX_COUNT*sizeof(*key));
60 if (!key)
61 return -20;
62
63 node = (pj_rbtree_node*)pj_pool_alloc(pool, MAX_COUNT*sizeof(*node));
64 if (!node)
65 return -30;
66
67 for (i=0; i<LOOP; ++i) {
68 int j;
69 pj_rbtree_node *prev, *it;
70 pj_timestamp t1, t2, t_setup, t_insert, t_search, t_erase;
71
72 pj_assert(rb.size == 0);
73
74 t_setup.u32.lo = t_insert.u32.lo = t_search.u32.lo = t_erase.u32.lo = 0;
75
76 for (j=0; j<count; j++) {
77 randomize_string(key[j].str, STRSIZE);
78
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
86 pj_get_timestamp(&t1);
87 pj_rbtree_insert(&rb, &node[j]);
88 pj_get_timestamp(&t2);
89 t_insert.u32.lo += (t2.u32.lo - t1.u32.lo);
90 }
91
92 pj_assert(rb.size == (unsigned)count);
93
94 // Iterate key, make sure they're sorted.
95 prev = NULL;
96 it = pj_rbtree_first(&rb);
97 while (it) {
98 if (prev) {
99 if (compare_node((node_key*)prev->key,(node_key*)it->key)>=0) {
100 ++err;
101 PJ_LOG(3, (THIS_FILE, "Error: %s >= %s",
102 (char*)prev->user_data, (char*)it->user_data));
103 }
104 }
105 prev = it;
106 it = pj_rbtree_next(&rb, it);
107 }
108
109 // Search.
110 for (j=0; j<count; j++) {
111 pj_get_timestamp(&t1);
112 it = pj_rbtree_find(&rb, &key[j]);
113 pj_get_timestamp(&t2);
114 t_search.u32.lo += (t2.u32.lo - t1.u32.lo);
115
116 pj_assert(it != NULL);
117 if (it == NULL)
118 ++err;
119 }
120
121 // Erase node.
122 for (j=0; j<count; j++) {
123 pj_get_timestamp(&t1);
124 it = pj_rbtree_erase(&rb, &node[j]);
125 pj_get_timestamp(&t2);
126 t_erase.u32.lo += (t2.u32.lo - t1.u32.lo);
127 }
128
129 PJ_LOG(4, (THIS_FILE,
130 "...count:%d, setup:%d, insert:%d, search:%d, erase:%d",
131 count,
132 t_setup.u32.lo / count, t_insert.u32.lo / count,
133 t_search.u32.lo / count, t_erase.u32.lo / count));
134
135 count = 2 * count;
136 if (count > MAX_COUNT)
137 break;
138 }
139
140 pj_pool_release(pool);
141 return err;
142}
143
144
145int rbtree_test()
146{
147 return test();
148}
149
150#endif /* INCLUDE_RBTREE_TEST */
151
152