The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rbmonkey.c
Go to the documentation of this file.
1#include <stdlib.h>
2#include <stdio.h>
3#include <netdb.h>
4
5#include <freeradius-devel/util/rb.c>
6#include <freeradius-devel/util/rand.h>
7
8typedef struct {
9 uint32_t num;
10 fr_rb_node_t node;
12
13static int8_t comp(void const *a, void const *b)
14{
15 fr_rb_tree_test_node_t const *our_a = a, *our_b = b;
16
17 return CMP(our_a->num, our_b->num);
18}
19
20static int qsort_comp(void const *a, void const *b)
21{
22 return comp(a, b);
23}
24
25
26#if 0
27static int print_cb(void *i, UNUSED void *uctx)
28{
29 fprintf(stderr, "%i\n", (fr_rb_tree_test_node_t *)i->num);
30 return 0;
31}
32#endif
33
34#define MAXSIZE 1024
35
36static int cb_stored = 0;
38
40
41static int filter_cb(void *i, void *uctx)
42{
43 if ((((fr_rb_tree_test_node_t *)i)->num & mask) == (((fr_rb_tree_test_node_t *)uctx)->num & mask)) {
44 return 2;
45 }
46 return 0;
47}
48
49/*
50 * Returns the count of BLACK nodes from root to child leaves, or a
51 * negative number indicating which RED-BLACK rule was broken.
52 */
53static int rbcount(fr_rb_tree_t *t)
54{
56 int count, count_expect;
57
58 count_expect = -1;
59 n = t->root;
60 if (!n || n == NIL) {
61 return 0;
62 }
63 if (n->colour != BLACK) {
64 return -2; /* root not BLACK */
65 }
66 count = 0;
67descend:
68 while (n->left != NIL) {
69 if (n->colour == RED) {
70 if (n->left->colour != BLACK || n->right->colour != BLACK) {
71 return -4; /* Children of RED nodes must be BLACK */
72 }
73 }
74 else {
75 count++;
76 }
77 n = n->left;
78 }
79 if (n->right != NIL) {
80 if (n->colour == RED) {
81 if (n->left->colour != BLACK || n->right->colour != BLACK) {
82 return -4; /* Children of RED nodes must be BLACK */
83 }
84 }
85 else {
86 count++;
87 }
88 n = n->right;
89 }
90 if ((n->left != NIL) || (n->right != NIL)) {
91 goto descend;
92 }
93 if (count_expect < 0) {
94 count_expect = count + (n->colour == BLACK);
95 }
96 else {
97 if (count_expect != count + (n->colour == BLACK)) {
98 fprintf(stderr,"Expected %i got %i\n", count_expect, count);
99 return -5; /* All paths must traverse the same number of BLACK nodes. */
100 }
101 }
102ascend:
103 if (n->parent == NIL) return count_expect;
104 while (n->parent->right == n) {
105 n = n->parent;
106 if (!n->parent) return count_expect;
107 if (n->colour == BLACK) {
108 count--;
109 }
110 }
111 if (n->parent->left == n) {
112 if (n->parent->right != NIL) {
113 n = n->parent->right;
114 goto descend;
115 }
116 n = n->parent;
117 if (!n->parent) return count_expect;
118 if (n->colour == BLACK) {
119 count--;
120 }
121 }
122 goto ascend;
123}
124
125#define REPS 10
126
127static void freenode(void *data)
128{
130}
131
132int main(UNUSED int argc, UNUSED char *argv[])
133{
134 fr_rb_tree_t *t;
135 int i, j;
136 fr_rb_tree_test_node_t thresh = {};
137 int n, rep;
140 fr_rb_tree_test_node_t const *node;
141
142 memset(&vals, 0, sizeof(vals));
143
144 /* TODO: make starting seed and repetitions a CLI option */
145 rep = REPS;
146
147again:
148 if (!--rep) return 0;
149
150 thresh.num = fr_rand();
151 mask = 0xff >> (fr_rand() & 7);
152 thresh.num &= mask;
153 n = (fr_rand() % MAXSIZE) + 1;
154
155 fprintf(stderr, "filter = %x mask = %x n = %i\n", thresh.num, mask, n);
156
158 for (i = 0; i < n; i++) {
160
161 p = talloc(t, fr_rb_tree_test_node_t); /* Do not use talloc_zero, rbcode should initialise fr_rb_node_t */
162 p->num = fr_rand();
163 vals[i].num = p->num;
164 fr_rb_insert(t, p);
165 }
166
167 i = rbcount(t);
168 fprintf(stderr,"After insert rbcount is %i\n", i);
169 if (i < 0) return i;
170
171 qsort(vals, n, sizeof(fr_rb_tree_test_node_t), qsort_comp);
172
173 /*
174 * For testing deletebydata instead
175
176 for (i = 0; i < n; i++) {
177 if (filter_cb(&vals[i], &thresh) == 2) fr_rb_delete(t, &vals[i]);
178 }
179
180 *
181 */
182 for (node = fr_rb_iter_init_inorder(&iter, t);
183 node;
184 node = fr_rb_iter_next_inorder(&iter)) {
185 if ((node->num & mask) == (thresh.num & mask)) fr_rb_iter_delete_inorder(&iter);
186 }
187 i = rbcount(t);
188 fprintf(stderr,"After delete rbcount is %i\n", i);
189 if (i < 0) return i;
190
191 cb_stored = 0;
192 for (node = fr_rb_iter_init_inorder(&iter, t);
193 node;
194 node = fr_rb_iter_next_inorder(&iter)) {
195 rvals[cb_stored++].num = node->num;
196 }
197
198 for (j = i = 0; i < n; i++) {
199 if (i && (vals[i-1].num == vals[i].num)) continue;
200 if (!filter_cb(&thresh, &vals[i])) {
201 if (vals[i].num != rvals[j].num) goto bad;
202 j++;
203 }
204 }
205 fprintf(stderr,"matched OK\n");
206 talloc_free(t);
207 goto again;
208
209bad:
210 for (j = i = 0; i < n; i++) {
211 if (i && vals[i-1].num == vals[i].num) continue;
212 if (!filter_cb(&thresh, &vals[i])) {
213 fprintf(stderr, "%i: %x %x\n", j, vals[i].num, rvals[j].num);
214 j++;
215 } else {
216 fprintf(stderr, "skipped %x\n", vals[i].num);
217 }
218 }
219 return EXIT_FAILURE;
220}
221
int n
Definition acutest.h:577
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:112
#define UNUSED
Definition build.h:315
talloc_free(reap)
unsigned int uint32_t
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition rand.c:105
void * fr_rb_iter_init_inorder(fr_rb_iter_inorder_t *iter, fr_rb_tree_t *tree)
Initialise an in-order iterator.
Definition rb.c:824
#define NIL
Definition rb.c:29
void fr_rb_iter_delete_inorder(fr_rb_iter_inorder_t *iter)
Remove the current node from the tree.
Definition rb.c:898
void * fr_rb_iter_next_inorder(fr_rb_iter_inorder_t *iter)
Return the next node.
Definition rb.c:850
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
Definition rb.c:626
fr_rb_node_t * left
Left child.
Definition rb.h:43
@ BLACK
Definition rb.h:37
@ RED
Definition rb.h:38
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
Definition rb.h:271
fr_rb_node_t * right
Right child.
Definition rb.h:44
fr_rb_node_t * root
Root of the rbtree.
Definition rb.h:78
Iterator structure for in-order traversal of an rbtree.
Definition rb.h:321
The main red black tree structure.
Definition rb.h:73
static int filter_cb(void *i, void *uctx)
Definition rbmonkey.c:41
#define REPS
Definition rbmonkey.c:125
#define MAXSIZE
Definition rbmonkey.c:34
static int8_t comp(void const *a, void const *b)
Definition rbmonkey.c:13
static fr_rb_tree_test_node_t rvals[MAXSIZE]
Definition rbmonkey.c:37
static int qsort_comp(void const *a, void const *b)
Definition rbmonkey.c:20
int main(UNUSED int argc, UNUSED char *argv[])
Definition rbmonkey.c:132
static int cb_stored
Definition rbmonkey.c:36
static void freenode(void *data)
Definition rbmonkey.c:127
static uint32_t mask
Definition rbmonkey.c:39
static int rbcount(fr_rb_tree_t *t)
Definition rbmonkey.c:53
return count
Definition module.c:163
static fr_slen_t data
Definition value.h:1265