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