The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
pair_list_perf_test.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program 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
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/** Performance tests for lists of fr_pair_t
18 *
19 * @file src/lib/util/test//pair_list_perf_test.c
20 * @author Nick Porter <nick.porter@networkradius.com>
21 *
22 * @copyright 2021 Network RADIUS SAS (legal@networkradius.com)
23 */
24
25static void pair_list_perf_init(void);
26#define TEST_GLOBAL_INIT pair_list_perf_init()
27
28#include "acutest_common_init.h"
29
30#ifdef WITH_VERIFY_PTR
31#undef WITH_VERIFY_PTR
32#endif
33
34#include <freeradius-devel/util/dict_test.h>
35#include <freeradius-devel/server/base.h>
36
37
38#define TEST_MSG_STATS \
39 do { \
40 TEST_MSG_ALWAYS("\n"); \
41 TEST_MSG_ALWAYS("repetitions = %u", reps); \
42 TEST_MSG_ALWAYS("%% repeated = %u", perc); \
43 TEST_MSG_ALWAYS("list_length = %u", len); \
44 TEST_MSG_ALWAYS("elapsed (ns) = %" PRId64, fr_time_delta_unwrap(used)); \
45 TEST_MSG_ALWAYS("calls/s = %0.0lf", (reps * len)/(fr_time_delta_unwrap(used) / (double)NSEC)); \
46 TEST_MSG_ALWAYS("(ns) / call = %0.0lf", (double) fr_time_delta_unwrap(used) / (double) reps); \
47 } while (0)
48
49/*
50 * Global variables
51 */
53static TALLOC_CTX *autofree;
54
55static char const *test_attrs_0 = \
56 "Test-String-# = \"hello\"," /* 1 */
57 "Test-Octets-# = 0x0102030405060708," /* 2 */
58 "Test-IPv4-Addr-# = 192.168.1.1," /* 3 */
59 "Test-IPv4-Prefix-# = 192.168/16," /* 4 */
60 "Test-IPv6-Addr-# = fd12:3456:789a:1::1," /* 5 */
61 "Test-IPv6-Prefix-# = fd12:3456:789a:1::/64," /* 6 */
62 "Test-Ethernet-# = 11:22:33:44:55:66," /* 7 */
63 "Test-Uint8-# = 255," /* 8 */
64 "Test-Uint16-# = 65535," /* 9 */
65 "Test-Uint32-# = 4294967295," /* 10 */
66 "Test-Uint64-# = 18446744073709551615," /* 11 */
67 "Test-Int8-# = -120," /* 12 */
68 "Test-Int16-# = -4573," /* 13 */
69 "Test-Int32-# = 45645," /* 14 */
70 "Test-Int64-# = 85645," /* 15 */
71 "Test-Float32-# = 1.134," /* 16 */
72 "Test-Float64-# = 1.1345," /* 17 */
73 "Test-Date-# += \"Jan 1 2020 00:00:00 UTC\"," /* 18 */
74 "Test-TLV-#.String = \"nested\"," /* 19 */
75 "Test-Struct-#.uint32 = 1234"; /* 20 */
76
77static char const *test_attrs_25 = \
78 "Test-String-# += \"hello\"," /* 1 */
79 "Test-String-# += \"goodbye\"," /* 2 */
80 "Test-String-# += \"hola\"," /* 3 */
81 "Test-String-# += \"hasta pronto\"," /* 4 */
82 "Test-String-# += \"bonjour\"," /* 5 */
83 "Test-Octets-# += 0x0102030405060708," /* 6 */
84 "Test-IPv4-Addr-# = 192.168.1.1," /* 7 */
85 "Test-IPv4-Prefix-# = 192.168/16," /* 8 */
86 "Test-IPv6-Addr-# = fd12:3456:789a:1::1," /* 9 */
87 "Test-IPv6-Prefix-# = fd12:3456:789a:1::/64," /* 10 */
88 "Test-Ethernet-# = 11:22:33:44:55:66," /* 11 */
89 "Test-Uint8-# = 255," /* 12 */
90 "Test-Uint16-# = 65535," /* 13 */
91 "Test-Uint32-# = 4294967295," /* 14 */
92 "Test-Uint64-# = 18446744073709551615," /* 15 */
93 "Test-Int64-# = 85645," /* 16 */
94 "Test-Float32-# = 1.134," /* 17 */
95 "Test-Date-# += \"Jan 1 2020 00:00:00 UTC\"," /* 18 */
96 "Test-TLV-#.String = \"nested\"," /* 19 */
97 "Test-Struct-#.uint32 = 1234"; /* 20 */
98
99static char const *test_attrs_50 = \
100 "Test-String-# += \"hello\"," /* 1 */
101 "Test-String-# += \"goodbye\"," /* 2 */
102 "Test-String-# += \"hola\"," /* 3 */
103 "Test-String-# += \"hasta pronto\"," /* 4 */
104 "Test-String-# += \"bonjour\"," /* 5 */
105 "Test-String-# += \"au revoir\"," /* 6 */
106 "Test-String-# += \"halo\"," /* 7 */
107 "Test-String-# += \"kwaheri\"," /* 8 */
108 "Test-String-# += \"ciao\"," /* 9 */
109 "Test-String-# += \"arrivederci\"," /* 10 */
110 "Test-IPv4-Addr-# = 192.168.1.1," /* 11 */
111 "Test-IPv4-Prefix-# = 192.168/16," /* 12 */
112 "Test-IPv6-Addr-# = fd12:3456:789a:1::1," /* 13 */
113 "Test-IPv6-Prefix-# = fd12:3456:789a:1::/64," /* 14 */
114 "Test-Ethernet-# = 11:22:33:44:55:66," /* 15 */
115 "Test-Uint8-# = 255," /* 16 */
116 "Test-Int64-# = 85645," /* 17 */
117 "Test-Date-# += \"Jan 1 2020 00:00:00 UTC\"," /* 18 */
118 "Test-TLV-#.String = \"nested\"," /* 19 */
119 "Test-Struct-#.uint32 = 1234"; /* 20 */
120
121static char const *test_attrs_75 = \
122 "Test-String-# += \"hello\"," /* 1 */
123 "Test-String-# += \"goodbye\"," /* 2 */
124 "Test-String-# += \"hola\"," /* 3 */
125 "Test-String-# += \"hasta pronto\"," /* 4 */
126 "Test-String-# += \"bonjour\"," /* 5 */
127 "Test-String-# += \"au revoir\"," /* 6 */
128 "Test-String-# += \"halo\"," /* 7 */
129 "Test-String-# += \"kwaheri\"," /* 8 */
130 "Test-String-# += \"ciao\"," /* 9 */
131 "Test-String-# += \"arrivederci\"," /* 10 */
132 "Test-String-# += \"halo\"," /* 11 */
133 "Test-String-# += \"selamat tinggal\"," /* 12 */
134 "Test-String-# += \"你好\"," /* 13 */
135 "Test-String-# += \"再见\"," /* 14 */
136 "Test-String-# += \"Я люблю сир\"," /* 15 */
137 "Test-Uint8-# = 255," /* 16 */
138 "Test-Int64-# = 85645," /* 17 */
139 "Test-Date-# += \"Jan 1 2020 00:00:00 UTC\"," /* 18 */
140 "Test-TLV-#.String = \"nested\"," /* 19 */
141 "Test-Struct-#.uint32 = 1234"; /* 20 */
142
143static char const *test_attrs_100 = \
144 "Test-String-# += \"hello\"," /* 1 */
145 "Test-String-# += \"goodbye\"," /* 2 */
146 "Test-String-# += \"hola\"," /* 3 */
147 "Test-String-# += \"hasta pronto\"," /* 4 */
148 "Test-String-# += \"bonjour\"," /* 5 */
149 "Test-String-# += \"au revoir\"," /* 6 */
150 "Test-String-# += \"halo\"," /* 7 */
151 "Test-String-# += \"kwaheri\"," /* 8 */
152 "Test-String-# += \"ciao\"," /* 9 */
153 "Test-String-# += \"arrivederci\"," /* 10 */
154 "Test-String-# += \"halo\"," /* 11 */
155 "Test-String-# += \"selamat tinggal\"," /* 12 */
156 "Test-String-# += \"你好\"," /* 13 */
157 "Test-String-# += \"再见\"," /* 14 */
158 "Test-String-# += \"Я люблю сир\"," /* 15 I love cheese */
159 "Test-String-# += \"Найкращий сир - бринза\"," /* 16 The best cheese is brynza */
160 "Test-String-# += \"Сулугуні чудовий на грилі\"," /* 17 Suluguni is wonderful grilled */
161 "Test-String-# += \"Сирники з домашнього сиру\"," /* 18 Syrnyky from homemade cheese */
162 "Test-String-# += \"Карпатська бринза пахне гірськими травами\","/* 19 (Carpathian brynza smells of mountain herbs */
163 "Test-String-# += \"Вареники з сиром найсмачніші\""; /* 20 Varenyky with cheese are the tastiest */
164
165static fr_pair_t **source_vps_0; //!< List with zero duplicate attributes.
166static fr_pair_t **source_vps_25; //!< List with 25% duplicate attributes.
167static fr_pair_t **source_vps_50; //!< List with 50% duplicate attributes.
168static fr_pair_t **source_vps_75; //!< List with 75% duplicate attributes.
169static fr_pair_t **source_vps_100; //!< List with 100% duplicate attributes, i.e. all the same.
170
171/** Duplicate a list of pairs starting at a particular item
172 *
173 * Copy all pairs from 'from' regardless of tag, attribute or vendor, starting at 'item'.
174 *
175 * @param[in] ctx for new #fr_pair_t (s) to be allocated in.
176 * @param[in] to where to copy attributes to.
177 * @param[in] from whence to copy #fr_pair_t (s).
178 * @param[in] start first pair to start copying from.
179 * @return
180 * - >0 the number of attributes copied.
181 * - 0 if no attributes copied.
182 * - -1 on error.
183 */
184static int fr_pair_sublist_copy(TALLOC_CTX *ctx, fr_pair_list_t *to,
185 fr_pair_list_t const *from, fr_pair_t const *start)
186{
187 fr_pair_t const *vp;
188 fr_pair_t *new_vp;
189 unsigned int cnt = 0;
190 fr_pair_list_t list;
191
192 fr_pair_list_init(&list);
193
194 if (!start) start = fr_pair_list_head(from);
195
196 for (vp = start;
197 vp != NULL;
198 vp = fr_pair_list_next(from, vp), cnt++) {
200
201 new_vp = fr_pair_copy(ctx, vp);
202 if (unlikely(!new_vp)) {
203 fr_pair_list_free(&list);
204 return -1;
205 }
206
207 fr_pair_append(&list, new_vp);
208 }
209
210 fr_pair_list_append(to, &list);
211
212 return cnt;
213}
214
215static void pair_list_init(TALLOC_CTX *ctx, fr_pair_t ***out, fr_dict_t const *dict, char const *pairs,
216 int const perc, int const reps)
217{
218 fr_pair_list_t list, full_list, dups;
219 char *prep_pairs, *p;
220 fr_pair_t *vp, *next;
221 int i;
222 size_t j;
223 fr_slen_t slen;
224 fr_pair_t **vp_array;
225 size_t input_count;
226
227 fr_pair_list_init(&list);
228 fr_pair_list_init(&full_list);
229 fr_pair_list_init(&dups);
230
231 prep_pairs = talloc_array(NULL, char, strlen(pairs) + 1);
232
233 /*
234 * Build a list of pairs, repeating the source list 'reps' times
235 * replacing the '#' in the source string with the number of this
236 * repetition.
237 */
238 for (i = 0; i < reps; i++) {
239 fr_pair_parse_t root, relative;
240
241 root = (fr_pair_parse_t) {
242 .ctx = ctx,
243 .da = fr_dict_root(dict),
244 .list = &list,
245 .dict = dict,
246 .internal = fr_dict_internal(),
247 };
248 relative = (fr_pair_parse_t) { };
249
250 strcpy(prep_pairs, pairs);
251 p = prep_pairs;
252 while ((p = strchr(p, '#'))) {
253 *p = (char)(i + 48);
254 }
255 slen = fr_pair_list_afrom_substr(&root, &relative, &FR_SBUFF_IN_STR(prep_pairs));
256 if (slen <= 0) fr_perror("pair_list_perf_tests");
257 TEST_ASSERT(slen > 0);
258
259 input_count = fr_pair_list_num_elements(&list);
260
261 if ((i == 0) && (perc > 0) && (reps > 0)) {
262 fr_pair_t *new_vp;
263 /*
264 * Copy the required number of attributes from the first iteration
265 * to use for duplicating attributes to required percentage.
266 * Duplicates are at the beginning of the source list
267 */
268 vp = fr_pair_list_head(&list);
269 for (j = 0; j < (size_t)(input_count * perc / 100); j++) {
270 new_vp = fr_pair_copy(ctx, vp);
271 fr_pair_append(&dups, new_vp);
272 vp = fr_pair_list_next(&list, vp);
273 }
274 }
275
276 if (i == 0) {
277 /*
278 * On the first iteration, just move the test pairs to the final list
279 */
280 fr_pair_list_append(&full_list, &list);
281 } else {
282 /*
283 * With subsequent iterations, replicate the duplicates from the first
284 * iteration to maintain the percentage of attribute repeats
285 */
286 vp = fr_pair_list_head(&dups);
287 fr_pair_sublist_copy(ctx, &full_list, &dups, vp);
288
289 /*
290 * Walk past equivalent pairs in new source list
291 */
292 vp = fr_pair_list_head(&list);
293 for (j = 0; j < fr_pair_list_num_elements(&dups); j++) vp = fr_pair_list_next(&list, vp);
294
295 /*
296 * Append copy remaining pairs from source list to destination
297 */
298 fr_pair_sublist_copy(ctx, &full_list, &list, vp);
299
300 /*
301 * We copied pairs rather than moving, free the source
302 */
303 fr_pair_list_free(&list);
304 }
305 }
306
307 talloc_free(prep_pairs);
308
309 /*
310 * Move vps to array so we can pick them randomly to populate the test list.
311 */
312 vp_array = talloc_array(ctx, fr_pair_t *, fr_pair_list_num_elements(&full_list));
313 for (vp = fr_pair_list_head(&full_list), i = 0; vp; vp = next, i++) {
314 next = fr_pair_list_next(&full_list, vp);
315 fr_pair_remove(&full_list, vp);
316 vp_array[i] = vp;
317 }
318
319 *out = vp_array;
320}
321
323{
325 if (!autofree) {
326 error:
327 fr_perror("pair_list_perf_tests");
328 fr_exit_now(EXIT_FAILURE);
329 }
330
331 /*
332 * Mismatch between the binary and the libraries it depends on
333 */
334 if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) goto error;
335
336 if (fr_dict_test_init(autofree, &test_dict, NULL) < 0) goto error;
337
338 if (fr_dict_test_attrs_init(test_dict, fr_dict_test_attrs, 100, 1) < 0) goto error;
339 if (fr_dict_test_attrs_init(test_dict, fr_dict_test_attrs, 200, 2) < 0) goto error;
340 if (fr_dict_test_attrs_init(test_dict, fr_dict_test_attrs, 300, 3) < 0) goto error;
341 if (fr_dict_test_attrs_init(test_dict, fr_dict_test_attrs, 400, 4) < 0) goto error;
342
348
350}
351
352static void do_test_fr_pair_append(unsigned int len, unsigned int perc, unsigned int reps, fr_pair_t *source_vps[])
353{
354 fr_pair_list_t test_vps;
355 unsigned int i, j;
356 fr_pair_t *new_vp;
357 fr_time_t start, end;
359 size_t input_count = talloc_array_length(source_vps);
360 fr_fast_rand_t rand_ctx;
361
362 fr_pair_list_init(&test_vps);
363 rand_ctx.a = fr_rand();
364 rand_ctx.b = fr_rand();
365
366 /*
367 * Only use up to the number of pairs needed from the source to maintain ratio
368 * of attribute repeats.
369 */
370 if (input_count > len) input_count = len;
371
372 /*
373 * Insert pairs into the test list, choosing randomly from the source list
374 */
375 for (i = 0; i < reps; i++) {
376 for (j = 0; j < len; j++) {
377 int idx = fr_fast_rand(&rand_ctx) % input_count;
378 new_vp = fr_pair_copy(autofree, source_vps[idx]);
379 start = fr_time();
380 fr_pair_append(&test_vps, new_vp);
381 end = fr_time();
382 used = fr_time_delta_add(used, fr_time_sub(end, start));
383 }
385 fr_pair_list_free(&test_vps);
386 }
388}
389
390static void do_test_fr_pair_find_by_da(unsigned int len, unsigned int perc, unsigned int reps, fr_pair_t *source_vps[])
391{
392 fr_pair_list_t test_vps;
393 unsigned int i, j;
394 fr_pair_t *new_vp;
395 fr_time_t start, end;
397 fr_dict_attr_t const *da;
398 size_t input_count = talloc_array_length(source_vps);
399 fr_fast_rand_t rand_ctx;
400
401 fr_pair_list_init(&test_vps);
402 if (input_count > len) input_count = len;
403 rand_ctx.a = fr_rand();
404 rand_ctx.b = fr_rand();
405
406 /*
407 * Initialise the test list
408 */
409 for (i = 0; i < len; i++) {
410 int idx = fr_fast_rand(&rand_ctx) % input_count;
411 new_vp = fr_pair_copy(autofree, source_vps[idx]);
412 fr_pair_append(&test_vps, new_vp);
413 }
414
415 /*
416 * Find first instance of specific DA
417 */
418 for (i = 0; i < reps; i++) {
419 for (j = 0; j < len; j++) {
420 int idx = fr_fast_rand(&rand_ctx) % input_count;
421 da = source_vps[idx]->da;
422 start = fr_time();
423 (void) fr_pair_find_by_da(&test_vps, NULL, da);
424 end = fr_time();
425 used = fr_time_delta_add(used, fr_time_sub(end, start));
426 }
427 }
428 fr_pair_list_free(&test_vps);
430}
431
432static void do_test_find_nth(unsigned int len, unsigned int perc, unsigned int reps, fr_pair_t *source_vps[])
433{
434 fr_pair_list_t test_vps;
435 unsigned int i, j, nth_item;
436 fr_pair_t *new_vp;
437 fr_time_t start, end;
439 fr_dict_attr_t const *da;
440 size_t input_count = talloc_array_length(source_vps);
441 fr_fast_rand_t rand_ctx;
442
443 fr_pair_list_init(&test_vps);
444 if (input_count > len) input_count = len;
445 rand_ctx.a = fr_rand();
446 rand_ctx.b = fr_rand();
447
448 /*
449 * Initialise the test list
450 */
451 for (i = 0; i < len; i++) {
452 int idx = fr_fast_rand(&rand_ctx) % input_count;
453 new_vp = fr_pair_copy(autofree, source_vps[idx]);
454 fr_pair_append(&test_vps, new_vp);
455 }
456
457 /*
458 * Find nth instance of specific DA. nth is based on the percentage
459 * of attributes which are repeats.
460 */
461 nth_item = perc == 0 ? 1 : (unsigned int)(len * perc / 100);
462 for (i = 0; i < reps; i++) {
463 for (j = 0; j < len; j++) {
464 int idx = fr_fast_rand(&rand_ctx) % input_count;
465
466 da = source_vps[idx]->da;
467 start = fr_time();
468 (void) fr_pair_find_by_da_idx(&test_vps, da, nth_item);
469 end = fr_time();
470 used = fr_time_delta_add(used, fr_time_sub(end, start));
471 }
472 }
473 fr_pair_list_free(&test_vps);
475}
476
477static void do_test_fr_pair_list_free(unsigned int len, unsigned int perc, unsigned int reps, fr_pair_t *source_vps[])
478{
479 fr_pair_list_t test_vps;
480 unsigned int i, j;
481 fr_pair_t *new_vp;
482 fr_time_t start, end;
484 size_t input_count = talloc_array_length(source_vps);
485 fr_fast_rand_t rand_ctx;
486
487 fr_pair_list_init(&test_vps);
488 if (input_count > len) input_count = len;
489 rand_ctx.a = fr_rand();
490 rand_ctx.b = fr_rand();
491
492 for (i = 0; i < reps; i++) {
493 for (j = 0; j < len; j++) {
494 int idx = fr_fast_rand(&rand_ctx) % input_count;
495 new_vp = fr_pair_copy(autofree, source_vps[idx]);
496 fr_pair_append(&test_vps, new_vp);
497 }
498 start = fr_time();
499 fr_pair_list_free(&test_vps);
500 end = fr_time();
501 used = fr_time_delta_add(used, fr_time_sub(end, start));
502 }
503 fr_pair_list_free(&test_vps);
505}
506
507#define test_func(_func, _count, _perc, _source_vps) \
508static void test_ ## _func ## _ ## _count ## _ ## _perc(void)\
509{\
510 do_test_ ## _func(_count, _perc, 10000, _source_vps);\
511}
512
513#define test_funcs(_func, _perc) \
514 test_func(_func, 20, _perc, source_vps_ ## _perc) \
515 test_func(_func, 40, _perc, source_vps_ ## _perc) \
516 test_func(_func, 60, _perc, source_vps_ ## _perc) \
517 test_func(_func, 80, _perc, source_vps_ ## _perc) \
518 test_func(_func, 100, _perc, source_vps_ ## _perc)
519
520#define all_test_funcs(_func) \
521 test_funcs(_func, 0) \
522 test_funcs(_func, 25) \
523 test_funcs(_func, 50) \
524 test_funcs(_func, 75) \
525 test_funcs(_func, 100)
526
529all_test_funcs(find_nth)
531
532#define repetition_tests(_func, _perc) \
533 { #_func "_20_" #_perc, test_ ## _func ## _20_ ## _perc},\
534 { #_func "_40_" #_perc, test_ ## _func ## _40_ ## _perc},\
535 { #_func "_60_" #_perc, test_ ## _func ## _60_ ## _perc},\
536 { #_func "_80_" #_perc, test_ ## _func ## _80_ ## _perc},\
537 { #_func "_100_" #_perc, test_ ## _func ## _100_ ## _perc},\
538
539#define all_repetition_tests(_func) \
540 repetition_tests(_func, 0) \
541 repetition_tests(_func, 25) \
542 repetition_tests(_func, 50) \
543 repetition_tests(_func, 75) \
544 repetition_tests(_func, 100)
545
546TEST_LIST = {
549 all_repetition_tests(find_nth)
551
553};
#define TEST_CHECK(cond)
Definition acutest.h:101
#define TEST_LIST
Definition acutest.h:75
strcpy(log_entry->msg, buffer)
#define TEST_ASSERT(cond)
Definition acutest.h:125
#define TEST_TERMINATOR
Definition acutest.h:77
Common initialisation for acutest binaries.
#define unlikely(_x)
Definition build.h:486
fr_dict_t * dict
Definition common.c:31
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
Definition debug.h:272
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2717
fr_dict_t const * fr_dict_internal(void)
Definition dict_util.c:5065
fr_dict_test_attr_t const fr_dict_test_attrs[]
Definition dict_test.c:86
int fr_dict_test_attrs_init(fr_dict_t *dict, fr_dict_test_attr_t const *test_defs, unsigned int base, int inst)
Add our test attributes to our test dictionary.
Definition dict_test.c:176
int fr_dict_test_init(TALLOC_CTX *ctx, fr_dict_t **dict_p, fr_dict_test_attr_t const *test_defs)
Initialise a test dictionary and add our test_defs to it.
Definition dict_test.c:248
talloc_free(hp)
#define fr_time()
Definition event.c:58
ssize_t fr_slen_t
unsigned long int size_t
static size_t used
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:707
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition pair.c:1297
fr_pair_t * fr_pair_find_by_da_idx(fr_pair_list_t const *list, fr_dict_attr_t const *da, unsigned int idx)
Find a pair with a matching da at a given index.
Definition pair.c:754
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:47
fr_pair_t * fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp)
Copy a single valuepair.
Definition pair.c:500
fr_slen_t fr_pair_list_afrom_substr(fr_pair_parse_t const *root, fr_pair_parse_t *relative, fr_sbuff_t *in)
Parse a fr_pair_list_t from a substring.
TALLOC_CTX * ctx
Definition pair_legacy.h:43
static char const * test_attrs_75
static char const * test_attrs_100
static fr_pair_t ** source_vps_25
List with 25% duplicate attributes.
static fr_pair_t ** source_vps_100
List with 100% duplicate attributes, i.e. all the same.
static fr_pair_t ** source_vps_75
List with 75% duplicate attributes.
#define all_repetition_tests(_func)
static TALLOC_CTX * autofree
static char const * test_attrs_50
#define TEST_MSG_STATS
static void do_test_fr_pair_append(unsigned int len, unsigned int perc, unsigned int reps, fr_pair_t *source_vps[])
static void pair_list_perf_init(void)
static char const * test_attrs_0
static void do_test_find_nth(unsigned int len, unsigned int perc, unsigned int reps, fr_pair_t *source_vps[])
#define all_test_funcs(_func)
static void do_test_fr_pair_list_free(unsigned int len, unsigned int perc, unsigned int reps, fr_pair_t *source_vps[])
static fr_dict_t * test_dict
static char const * test_attrs_25
static fr_pair_t ** source_vps_0
List with zero duplicate attributes.
static void pair_list_init(TALLOC_CTX *ctx, fr_pair_t ***out, fr_dict_t const *dict, char const *pairs, int const perc, int const reps)
static fr_pair_t ** source_vps_50
List with 50% duplicate attributes.
static void do_test_fr_pair_find_by_da(unsigned int len, unsigned int perc, unsigned int reps, fr_pair_t *source_vps[])
static int fr_pair_sublist_copy(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from, fr_pair_t const *start)
Duplicate a list of pairs starting at a particular item.
uint32_t fr_fast_rand(fr_fast_rand_t *ctx)
Definition rand.c:303
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition rand.c:128
uint32_t b
Definition rand.h:55
uint32_t a
Definition rand.h:55
Smaller fast random number generator.
Definition rand.h:54
#define FR_SBUFF_IN_STR(_start)
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
Definition talloc.h:55
int fr_time_start(void)
Initialize the local time.
Definition time.c:157
static fr_time_delta_t fr_time_delta_add(fr_time_delta_t a, fr_time_delta_t b)
Definition time.h:255
#define fr_time_delta_wrap(_time)
Definition time.h:152
#define fr_time_sub(_a, _b)
Subtract one time from another.
Definition time.h:229
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
"server local" time.
Definition time.h:69
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
Definition pair_inline.c:69
fr_pair_t * fr_pair_remove(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list without freeing.
Definition pair_inline.c:93
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
void fr_pair_list_append(fr_pair_list_t *dst, fr_pair_list_t *src)
Appends a list of fr_pair_t from a temporary list to a destination list.
#define PAIR_VERIFY_WITH_LIST(_l, _x)
Definition pair.h:210
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Definition pair_inline.c:42
size_t fr_pair_list_num_elements(fr_pair_list_t const *list)
Get the length of a list of fr_pair_t.
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition strerror.c:737
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
Definition version.c:40
#define RADIUSD_MAGIC_NUMBER
Definition version.h:81
static fr_sbuff_err_t char ** out
Definition value.h:1061
static fr_sbuff_err_t char size_t * len
Definition value.h:1061