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