The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rb_tests.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/** Tests for rbtrees
18 *
19 * @file src/lib/util/rb_tests.c
20 *
21 * @copyright 2021 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
22 */
23#include <freeradius-devel/util/acutest.h>
24#include <freeradius-devel/util/acutest_helpers.h>
25#include <freeradius-devel/util/rand.h>
26#include <freeradius-devel/util/rb.h>
27
28#define MAXSIZE 128
29
34
35static int8_t fr_rb_tree_test_cmp(void const *one, void const *two)
36{
37 fr_rb_tree_test_node_t const *a = one, *b = two;
38 return CMP(a->num, b->num);
39}
40
41static int fr_rb_qsort_cmp(void const *one, void const *two)
42{
43 fr_rb_tree_test_node_t const *a = one, *b = two;
44 return CMP(a->num, b->num);
45}
46
47static void test_fr_rb_iter_inorder(void)
48{
49 fr_rb_tree_t *t;
52 size_t n, i;
54
55 TEST_CASE("in-order iterator");
57 TEST_CHECK(t != NULL);
58
59 n = (fr_rand() % MAXSIZE) + 1;
60
61 /*
62 * Initialise the test nodes
63 * with random numbers.
64 */
65 for (i = 0; i < n; i++) {
66 p = talloc(t, fr_rb_tree_test_node_t);
67 p->num = fr_rand();
68 sorted[i].num = p->num;
69 fr_rb_insert(t, p);
70 }
71
72 qsort(sorted, n, sizeof(fr_rb_tree_test_node_t), fr_rb_qsort_cmp);
73
74 for (p = fr_rb_iter_init_inorder(&iter, t), i = 0;
75 p;
76 p = fr_rb_iter_next_inorder(&iter), i++) {
77 TEST_MSG("Checking sorted[%zu] s = %u vs n = %u", i, sorted[i].num, p->num);
78 TEST_CHECK(sorted[i].num == p->num);
79 }
80
81 talloc_free(t);
82}
83
84/*
85 * There's no natural test for pre- and post-order traversal
86 * as there is for in-order, so we must content ourselves
87 * with static test data.
88 */
89static uint32_t pre_post_input[] = {0, 15, 256, 49, 3, 8192, 144, 4, 4096, 25194};
90static uint32_t pre_output[] = {15, 3, 0, 4, 256, 49, 144, 8192, 4096, 25194};
91static uint32_t post_output[] = {0, 4, 3, 144, 49, 4096, 25194, 8192, 256, 15};
92
93static void test_fr_rb_iter_preorder(void)
94{
95 fr_rb_tree_t *t;
97 size_t i;
99
100 TEST_CASE("pre-order iterator");
101 /*
102 * Build a tree from pre_post_input.
103 */
105 TEST_CHECK(t != NULL);
106
107 for (i = 0; i < sizeof(pre_post_input) / sizeof(uint32_t); i++) {
108 p = talloc(t, fr_rb_tree_test_node_t);
109 p->num = pre_post_input[i];
110 fr_rb_insert(t, p);
111 }
112
113 for (p = fr_rb_iter_init_preorder(&iter, t), i = 0;
114 p;
115 p = fr_rb_iter_next_preorder(&iter), i++) {
116 TEST_MSG("Checking pre_output[%zu] = %u vs n = %u", i, pre_output[i], p->num);
117 TEST_CHECK(pre_output[i] == p->num);
118 }
119
120 talloc_free(t);
121}
122
124{
125 fr_rb_tree_t *t;
127 size_t i;
129
130 TEST_CASE("post-order iterator");
131 /*
132 * Build a tree from pre_post_input.
133 */
135 TEST_CHECK(t != NULL);
136
137 for (i = 0; i < sizeof(pre_post_input) / sizeof(uint32_t); i++) {
138 p = talloc(t, fr_rb_tree_test_node_t);
139 p->num = pre_post_input[i];
140 fr_rb_insert(t, p);
141 }
142
143 for (p = fr_rb_iter_init_postorder(&iter, t), i = 0;
144 p;
145 p = fr_rb_iter_next_postorder(&iter), i++) {
146 TEST_MSG("Checking post_output[%zu] s = %u vs n = %u", i, post_output[i], p->num);
147 TEST_CHECK(post_output[i] == p->num);
148 }
149
150 talloc_free(t);
151}
152
153/*
154 * primality test used in fr_rb_delete_iter() test.
155 */
156static bool is_prime(uint32_t n)
157{
158 uint32_t i, q;
159
160 if (n < 2) return false;
161
162 for (i = 2; (q = n / i) >= i; i++) {
163 if (i * q == n) return false;
164 }
165 return true;
166}
167
168static uint32_t non_primes[] = { 1, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25, 26, 27, 28,
169 30, 32, 33, 34, 35, 36, 38, 39, 40, 42, 44, 45, 46, 48, 49, 50};
170
171static void test_fr_rb_iter_delete(void)
172{
173 fr_rb_tree_t *t;
174 size_t i;
177
179 TEST_CHECK(t != NULL);
180
181 /*
182 * Initialise the test nodes
183 * with integers from 1 to 50.
184 */
185 for (i = 1; i <= 50; i++) {
186 p = talloc(t, fr_rb_tree_test_node_t);
187 p->num = i;
188 fr_rb_insert(t, p);
189 }
190
191 /*
192 * Remove the primes.
193 */
194 for (p = fr_rb_iter_init_inorder(&iter, t);
195 p;
196 p = fr_rb_iter_next_inorder(&iter)) {
197 if (is_prime(p->num)) fr_rb_iter_delete_inorder(&iter);
198 }
199
200 /*
201 * Check that all the non-primes are still there.
202 */
203 for (p = fr_rb_iter_init_inorder(&iter, t), i = 0;
204 p;
205 p = fr_rb_iter_next_inorder(&iter), i++) {
206 TEST_MSG("Checking non_primes[%zu] = %u vs p->num = %u", i, non_primes[i], p->num);
207 TEST_CHECK(non_primes[i] == p->num);
208 }
209
210 talloc_free(t);
211}
212
214 { "fr_rb_iter_inorder", test_fr_rb_iter_inorder },
215 { "fr_rb_iter_preorder", test_fr_rb_iter_preorder },
216 { "fr_rb_iter_postorder", test_fr_rb_iter_postorder },
217 { "fr_rb_iter_delete", test_fr_rb_iter_delete },
218
219 { NULL }
220};
#define TEST_CHECK(cond)
Definition acutest.h:85
int n
Definition acutest.h:577
#define TEST_CASE(name)
Definition acutest.h:184
#define TEST_MSG(...)
Definition acutest.h:215
#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
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
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_preorder(fr_rb_iter_preorder_t *iter)
Return the next node.
Definition rb.c:941
void * fr_rb_iter_init_preorder(fr_rb_iter_preorder_t *iter, fr_rb_tree_t *tree)
Initialise a pre-order iterator.
Definition rb.c:917
void * fr_rb_iter_init_postorder(fr_rb_iter_postorder_t *iter, fr_rb_tree_t *tree)
Initialise a post-order iterator.
Definition rb.c:994
void * fr_rb_iter_next_inorder(fr_rb_iter_inorder_t *iter)
Return the next node.
Definition rb.c:850
void * fr_rb_iter_next_postorder(fr_rb_iter_postorder_t *iter)
Return the next node.
Definition rb.c:1025
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
Definition rb.c:626
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
Definition rb.h:271
Iterator structure for in-order traversal of an rbtree.
Definition rb.h:321
Iterator structure for post-order traversal of an rbtree.
Definition rb.h:356
Iterator structure for pre-order traversal of an rbtree.
Definition rb.h:340
The main red black tree structure.
Definition rb.h:73
static int8_t fr_rb_tree_test_cmp(void const *one, void const *two)
Definition rb_tests.c:35
TEST_LIST
Definition rb_tests.c:213
static void test_fr_rb_iter_postorder(void)
Definition rb_tests.c:123
static uint32_t non_primes[]
Definition rb_tests.c:168
static uint32_t pre_output[]
Definition rb_tests.c:90
static void test_fr_rb_iter_inorder(void)
Definition rb_tests.c:47
#define MAXSIZE
Definition rb_tests.c:28
static int fr_rb_qsort_cmp(void const *one, void const *two)
Definition rb_tests.c:41
static uint32_t pre_post_input[]
Definition rb_tests.c:89
static bool is_prime(uint32_t n)
Definition rb_tests.c:156
static void test_fr_rb_iter_delete(void)
Definition rb_tests.c:171
static void test_fr_rb_iter_preorder(void)
Definition rb_tests.c:93
static uint32_t post_output[]
Definition rb_tests.c:91
fr_rb_node_t node
Definition rb_tests.c:32