The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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/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 
25 /**
26  * The 'TEST_INIT' macro provided by 'acutest.h' allows registering a function to be called
27  * before call the unit tests. Therefore, It calls the function ALL THE TIME causing an overhead.
28  * That is why we are initializing pair_list_perf_init() by "__attribute__((constructor));" reducing the
29  * test execution by 50% of the time.
30  */
31 #define USE_CONSTRUCTOR
32 
33 /*
34  * It should be declared before including "acutest.h"
35  */
36 #ifdef USE_CONSTRUCTOR
37 static void pair_list_perf_init(void) __attribute__((constructor));
38 #else
39 static void pair_list_perf_init(void);
40 #define TEST_INIT pair_list_perf_init()
41 #endif
42 
43 #include <freeradius-devel/util/acutest.h>
44 
45 #ifdef WITH_VERIFY_PTR
46 #undef WITH_VERIFY_PTR
47 #endif
48 
49 #include <freeradius-devel/util/dict_test.h>
50 #include <freeradius-devel/server/base.h>
51 #include <freeradius-devel/util/rand.h>
52 
53 /*
54  * Global variables
55  */
56 
57 static fr_dict_t *test_dict;
58 static TALLOC_CTX *autofree;
59 
60 static char const *test_attrs_0 = \
61  "Test-String-# = \"hello\"," /* 1 */
62  "Test-Octets-# = 0x0102030405060708," /* 2 */
63  "Test-IPv4-Addr-# = 192.168.1.1," /* 3 */
64  "Test-IPv4-Prefix-# = 192.168/16," /* 4 */
65  "Test-IPv6-Addr-# = fd12:3456:789a:1::1," /* 5 */
66  "Test-IPv6-Prefix-# = fd12:3456:789a:1::/64," /* 6 */
67  "Test-Ethernet-# = 11:22:33:44:55:66," /* 7 */
68  "Test-Uint8-# = 255," /* 8 */
69  "Test-Uint16-# = 65535," /* 9 */
70  "Test-Uint32-# = 4294967295," /* 10 */
71  "Test-Uint64-# = 18446744073709551615," /* 11 */
72  "Test-Int8-# = -120," /* 12 */
73  "Test-Int16-# = -4573," /* 13 */
74  "Test-Int32-# = 45645," /* 14 */
75  "Test-Int64-# = 85645," /* 15 */
76  "Test-Float32-# = 1.134," /* 16 */
77  "Test-Float64-# = 1.1345," /* 17 */
78  "Test-Date-# += \"Jan 1 2020 00:00:00 UTC\"," /* 18 */
79  "Test-TLV-#.String = \"nested\"," /* 19 */
80  "Test-Struct-#.uint32 = 1234"; /* 20 */
81 
82 static char const *test_attrs_25 = \
83  "Test-String-# += \"hello\"," /* 1 */
84  "Test-String-# += \"goodbye\"," /* 2 */
85  "Test-String-# += \"hola\"," /* 3 */
86  "Test-String-# += \"hasta pronto\"," /* 4 */
87  "Test-String-# += \"bonjour\"," /* 5 */
88  "Test-Octets-# += 0x0102030405060708," /* 6 */
89  "Test-IPv4-Addr-# = 192.168.1.1," /* 7 */
90  "Test-IPv4-Prefix-# = 192.168/16," /* 8 */
91  "Test-IPv6-Addr-# = fd12:3456:789a:1::1," /* 9 */
92  "Test-IPv6-Prefix-# = fd12:3456:789a:1::/64," /* 10 */
93  "Test-Ethernet-# = 11:22:33:44:55:66," /* 11 */
94  "Test-Uint8-# = 255," /* 12 */
95  "Test-Uint16-# = 65535," /* 13 */
96  "Test-Uint32-# = 4294967295," /* 14 */
97  "Test-Uint64-# = 18446744073709551615," /* 15 */
98  "Test-Int64-# = 85645," /* 16 */
99  "Test-Float32-# = 1.134," /* 17 */
100  "Test-Date-# += \"Jan 1 2020 00:00:00 UTC\"," /* 18 */
101  "Test-TLV-#.String = \"nested\"," /* 19 */
102  "Test-Struct-#.uint32 = 1234"; /* 20 */
103 
104 static char const *test_attrs_50 = \
105  "Test-String-# += \"hello\"," /* 1 */
106  "Test-String-# += \"goodbye\"," /* 2 */
107  "Test-String-# += \"hola\"," /* 3 */
108  "Test-String-# += \"hasta pronto\"," /* 4 */
109  "Test-String-# += \"bonjour\"," /* 5 */
110  "Test-String-# += \"au revoir\"," /* 6 */
111  "Test-String-# += \"halo\"," /* 7 */
112  "Test-String-# += \"kwaheri\"," /* 8 */
113  "Test-String-# += \"ciao\"," /* 9 */
114  "Test-String-# += \"arrivederci\"," /* 10 */
115  "Test-IPv4-Addr-# = 192.168.1.1," /* 11 */
116  "Test-IPv4-Prefix-# = 192.168/16," /* 12 */
117  "Test-IPv6-Addr-# = fd12:3456:789a:1::1," /* 13 */
118  "Test-IPv6-Prefix-# = fd12:3456:789a:1::/64," /* 14 */
119  "Test-Ethernet-# = 11:22:33:44:55:66," /* 15 */
120  "Test-Uint8-# = 255," /* 16 */
121  "Test-Int64-# = 85645," /* 17 */
122  "Test-Date-# += \"Jan 1 2020 00:00:00 UTC\"," /* 18 */
123  "Test-TLV-#.String = \"nested\"," /* 19 */
124  "Test-Struct-#.uint32 = 1234"; /* 20 */
125 
126 static char const *test_attrs_75 = \
127  "Test-String-# += \"hello\"," /* 1 */
128  "Test-String-# += \"goodbye\"," /* 2 */
129  "Test-String-# += \"hola\"," /* 3 */
130  "Test-String-# += \"hasta pronto\"," /* 4 */
131  "Test-String-# += \"bonjour\"," /* 5 */
132  "Test-String-# += \"au revoir\"," /* 6 */
133  "Test-String-# += \"halo\"," /* 7 */
134  "Test-String-# += \"kwaheri\"," /* 8 */
135  "Test-String-# += \"ciao\"," /* 9 */
136  "Test-String-# += \"arrivederci\"," /* 10 */
137  "Test-String-# += \"halo\"," /* 11 */
138  "Test-String-# += \"selamat tinggal\"," /* 12 */
139  "Test-String-# += \"你好\"," /* 13 */
140  "Test-String-# += \"再见\"," /* 14 */
141  "Test-String-# += \"Привет\"," /* 15 */
142  "Test-Uint8-# = 255," /* 16 */
143  "Test-Int64-# = 85645," /* 17 */
144  "Test-Date-# += \"Jan 1 2020 00:00:00 UTC\"," /* 18 */
145  "Test-TLV-#.String = \"nested\"," /* 19 */
146  "Test-Struct-#.uint32 = 1234"; /* 20 */
147 
148 static char const *test_attrs_100 = \
149  "Test-String-# += \"hello\"," /* 1 */
150  "Test-String-# += \"goodbye\"," /* 2 */
151  "Test-String-# += \"hola\"," /* 3 */
152  "Test-String-# += \"hasta pronto\"," /* 4 */
153  "Test-String-# += \"bonjour\"," /* 5 */
154  "Test-String-# += \"au revoir\"," /* 6 */
155  "Test-String-# += \"halo\"," /* 7 */
156  "Test-String-# += \"kwaheri\"," /* 8 */
157  "Test-String-# += \"ciao\"," /* 9 */
158  "Test-String-# += \"arrivederci\"," /* 10 */
159  "Test-String-# += \"halo\"," /* 11 */
160  "Test-String-# += \"selamat tinggal\"," /* 12 */
161  "Test-String-# += \"你好\"," /* 13 */
162  "Test-String-# += \"再见\"," /* 14 */
163  "Test-String-# += \"Привет\"," /* 15 */
164  "Test-String-# += \"до свидания\"," /* 16 */
165  "Test-String-# += \"вся слава советской россии\"," /* 17 */
166  "Test-String-# += \"у нас есть видео с мочой\"," /* 18 */
167  "Test-String-# += \"Байден заплатит за\"," /* 19 */
168  "Test-String-# += \"приставание к бурундукам\""; /* 20 */
169 
170 static fr_pair_t **source_vps_0; //!< List with zero duplicate attributes.
171 static fr_pair_t **source_vps_25; //!< List with 25% duplicate attributes.
172 static fr_pair_t **source_vps_50; //!< List with 50% duplicate attributes.
173 static fr_pair_t **source_vps_75; //!< List with 75% duplicate attributes.
174 static fr_pair_t **source_vps_100; //!< List with 100% duplicate attributes, i.e. all the same.
175 
176 static void pair_list_init(TALLOC_CTX *ctx, fr_pair_t ***out, fr_dict_t const *dict, char const *pairs,
177  int const perc, int const reps)
178 {
179  fr_pair_list_t list, full_list, dups;
180  char *prep_pairs, *p;
181  fr_pair_t *vp, *next;
182  int i;
183  size_t j;
184  ssize_t slen;
185  fr_pair_t **vp_array;
186  size_t input_count;
187 
188  fr_pair_list_init(&list);
189  fr_pair_list_init(&full_list);
190  fr_pair_list_init(&dups);
191 
192  prep_pairs = talloc_array(NULL, char, strlen(pairs) + 1);
193 
194  /*
195  * Build a list of pairs, repeating the source list 'reps' times
196  * replacing the '#' in the source string with the number of this
197  * repetition.
198  */
199  for (i = 0; i < reps; i++) {
200  fr_pair_parse_t root, relative;
201 
202  root = (fr_pair_parse_t) {
203  .ctx = ctx,
204  .da = fr_dict_root(dict),
205  .list = &list,
206  };
207  relative = (fr_pair_parse_t) { };
208 
209  strcpy(prep_pairs, pairs);
210  p = prep_pairs;
211  while ((p = strchr(p, '#'))) {
212  *p = (char)(i + 48);
213  }
214  slen = fr_pair_list_afrom_substr(&root, &relative, &FR_SBUFF_IN(prep_pairs, strlen(prep_pairs)));
215  if (slen <= 0) fr_perror("pair_list_perf_tests");
216  TEST_ASSERT(slen > 0);
217 
218  input_count = fr_pair_list_num_elements(&list);
219 
220  if ((i == 0) && (perc > 0) && (reps > 0)) {
221  fr_pair_t *new_vp;
222  /*
223  * Copy the required number of attributes from the first iteration
224  * to use for duplicating attributes to required percentage.
225  * Duplicates are at the beginning of the source list
226  */
227  /* coverity[dereference] */
228  vp = fr_pair_list_head(&list);
229  for (j = 0; j < (size_t)(input_count * perc / 100); j++) {
230  /* coverity[dereference] */
231  new_vp = fr_pair_copy(ctx, vp);
232  fr_pair_append(&dups, new_vp);
233  /* coverity[dereference] */
234  vp = fr_pair_list_next(&list, vp);
235  }
236  }
237 
238  if (i == 0) {
239  /*
240  * On the first iteration, just move the test pairs to the final list
241  */
242  fr_pair_list_append(&full_list, &list);
243  } else {
244  /*
245  * With subsequent iterations, replicate the duplicates from the first
246  * iteration to maintain the percentage of attribute repeats
247  */
248  vp = fr_pair_list_head(&dups);
249  fr_pair_sublist_copy(ctx, &full_list, &dups, vp, 0);
250 
251  /*
252  * Walk past equivalent pairs in new source list
253  */
254  vp = fr_pair_list_head(&list);
255  for (j = 0; j < fr_pair_list_num_elements(&dups); j++) vp = fr_pair_list_next(&list, vp);
256 
257  /*
258  * Append copy remaining pairs from source list to destination
259  */
260  fr_pair_sublist_copy(ctx, &full_list, &list, vp, 0);
261 
262  /*
263  * We copied pairs rather than moving, free the source
264  */
265  fr_pair_list_free(&list);
266  }
267  }
268 
269  talloc_free(prep_pairs);
270 
271  /*
272  * Move vps to array so we can pick them randomly to populate the test list.
273  */
274  vp_array = talloc_array(ctx, fr_pair_t *, fr_pair_list_num_elements(&full_list));
275  for (vp = fr_pair_list_head(&full_list), i = 0; vp; vp = next, i++) {
276  next = fr_pair_list_next(&full_list, vp);
277  fr_pair_remove(&full_list, vp);
278  vp_array[i] = vp;
279  }
280 
281  *out = vp_array;
282 }
283 
284 void pair_list_perf_init(void)
285 {
287  if (!autofree) {
288  error:
289  fr_perror("pair_list_perf_tests");
290  fr_exit_now(EXIT_FAILURE);
291  }
292 
293  /*
294  * Mismatch between the binary and the libraries it depends on
295  */
296  if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) goto error;
297 
298  if (fr_dict_test_init(autofree, &test_dict, NULL) < 0) goto error;
299 
300  if (fr_dict_test_attrs_init(test_dict, fr_dict_test_attrs, 100, 1) < 0) goto error;
301  if (fr_dict_test_attrs_init(test_dict, fr_dict_test_attrs, 200, 2) < 0) goto error;
302  if (fr_dict_test_attrs_init(test_dict, fr_dict_test_attrs, 300, 3) < 0) goto error;
303  if (fr_dict_test_attrs_init(test_dict, fr_dict_test_attrs, 400, 4) < 0) goto error;
304 
305  pair_list_init(autofree, &source_vps_0, test_dict, test_attrs_0, 0, 5);
306  pair_list_init(autofree, &source_vps_25, test_dict, test_attrs_25, 25, 5);
307  pair_list_init(autofree, &source_vps_50, test_dict, test_attrs_50, 50, 5);
308  pair_list_init(autofree, &source_vps_75, test_dict, test_attrs_75, 75, 5);
309  pair_list_init(autofree, &source_vps_100, test_dict, test_attrs_100, 100, 5);
310 
311  fr_time_start();
312 }
313 
314 static void do_test_fr_pair_append(unsigned int len, unsigned int perc, unsigned int reps, fr_pair_t *source_vps[])
315 {
316  fr_pair_list_t test_vps;
317  unsigned int i, j;
318  fr_pair_t *new_vp;
319  fr_time_t start, end;
321  size_t input_count = talloc_array_length(source_vps);
322  fr_fast_rand_t rand_ctx;
323 
324  fr_pair_list_init(&test_vps);
325  rand_ctx.a = fr_rand();
326  rand_ctx.b = fr_rand();
327 
328  /*
329  * Only use up to the number of pairs needed from the source to maintain ratio
330  * of attribute repeats.
331  */
332  if (input_count > len) input_count = len;
333 
334  /*
335  * Insert pairs into the test list, choosing randomly from the source list
336  */
337  for (i = 0; i < reps; i++) {
338  for (j = 0; j < len; j++) {
339  int idx = fr_fast_rand(&rand_ctx) % input_count;
340  new_vp = fr_pair_copy(autofree, source_vps[idx]);
341  start = fr_time();
342  fr_pair_append(&test_vps, new_vp);
343  end = fr_time();
344  used = fr_time_delta_add(used, fr_time_sub(end, start));
345  }
346  TEST_CHECK(fr_pair_list_num_elements(&test_vps) == len);
347  fr_pair_list_free(&test_vps);
348  }
349  TEST_MSG_ALWAYS("repetitions=%d", reps);
350  TEST_MSG_ALWAYS("perc_rep=%d", perc);
351  TEST_MSG_ALWAYS("list_length=%d", len);
352  TEST_MSG_ALWAYS("used=%"PRId64, fr_time_delta_unwrap(used));
353  TEST_MSG_ALWAYS("per_sec=%0.0lf", (reps * len)/(fr_time_delta_unwrap(used) / (double)NSEC));
354 }
355 
356 static void do_test_fr_pair_find_by_da_idx(unsigned int len, unsigned int perc, unsigned int reps, fr_pair_t *source_vps[])
357 {
358  fr_pair_list_t test_vps;
359  unsigned int i, j;
360  fr_pair_t *new_vp;
361  fr_time_t start, end;
363  fr_dict_attr_t const *da;
364  size_t input_count = talloc_array_length(source_vps);
365  fr_fast_rand_t rand_ctx;
366 
367  fr_pair_list_init(&test_vps);
368  if (input_count > len) input_count = len;
369  rand_ctx.a = fr_rand();
370  rand_ctx.b = fr_rand();
371 
372  /*
373  * Initialise the test list
374  */
375  for (i = 0; i < len; i++) {
376  int idx = fr_fast_rand(&rand_ctx) % input_count;
377  new_vp = fr_pair_copy(autofree, source_vps[idx]);
378  fr_pair_append(&test_vps, new_vp);
379  }
380 
381  /*
382  * Find first instance of specific DA
383  */
384  for (i = 0; i < reps; i++) {
385  for (j = 0; j < len; j++) {
386  int idx = fr_fast_rand(&rand_ctx) % input_count;
387  da = source_vps[idx]->da;
388  start = fr_time();
389  (void) fr_pair_find_by_da(&test_vps, NULL, da);
390  end = fr_time();
391  used = fr_time_delta_add(used, fr_time_sub(end, start));
392  }
393  }
394  fr_pair_list_free(&test_vps);
395  TEST_MSG_ALWAYS("repetitions=%d", reps);
396  TEST_MSG_ALWAYS("perc_rep=%d", perc);
397  TEST_MSG_ALWAYS("list_length=%d", len);
398  TEST_MSG_ALWAYS("used=%"PRId64, fr_time_delta_unwrap(used));
399  TEST_MSG_ALWAYS("per_sec=%0.0lf", (reps * len)/(fr_time_delta_unwrap(used) / (double)NSEC));
400 }
401 
402 static void do_test_find_nth(unsigned int len, unsigned int perc, unsigned int reps, fr_pair_t *source_vps[])
403 {
404  fr_pair_list_t test_vps;
405  unsigned int i, j, nth_item;
406  fr_pair_t *new_vp;
407  fr_time_t start, end;
409  fr_dict_attr_t const *da;
410  size_t input_count = talloc_array_length(source_vps);
411  fr_fast_rand_t rand_ctx;
412 
413  fr_pair_list_init(&test_vps);
414  if (input_count > len) input_count = len;
415  rand_ctx.a = fr_rand();
416  rand_ctx.b = fr_rand();
417 
418  /*
419  * Initialise the test list
420  */
421  for (i = 0; i < len; i++) {
422  int idx = fr_fast_rand(&rand_ctx) % input_count;
423  new_vp = fr_pair_copy(autofree, source_vps[idx]);
424  fr_pair_append(&test_vps, new_vp);
425  }
426 
427  /*
428  * Find nth instance of specific DA. nth is based on the percentage
429  * of attributes which are repeats.
430  */
431  nth_item = perc == 0 ? 1 : (unsigned int)(len * perc / 100);
432  for (i = 0; i < reps; i++) {
433  for (j = 0; j < len; j++) {
434  int idx = fr_fast_rand(&rand_ctx) % input_count;
435 
436  da = source_vps[idx]->da;
437  start = fr_time();
438  (void) fr_pair_find_by_da_idx(&test_vps, da, nth_item);
439  end = fr_time();
440  used = fr_time_delta_add(used, fr_time_sub(end, start));
441  }
442  }
443  fr_pair_list_free(&test_vps);
444  TEST_MSG_ALWAYS("repetitions=%d", reps);
445  TEST_MSG_ALWAYS("perc_rep=%d", perc);
446  TEST_MSG_ALWAYS("list_length=%d", len);
447  TEST_MSG_ALWAYS("used=%"PRId64, fr_time_delta_unwrap(used));
448  TEST_MSG_ALWAYS("per_sec=%0.0lf", (reps * len)/(fr_time_delta_unwrap(used) / (double)NSEC));
449 }
450 
451 static void do_test_fr_pair_list_free(unsigned int len, unsigned int perc, unsigned int reps, fr_pair_t *source_vps[])
452 {
453  fr_pair_list_t test_vps;
454  unsigned int i, j;
455  fr_pair_t *new_vp;
456  fr_time_t start, end;
458  size_t input_count = talloc_array_length(source_vps);
459  fr_fast_rand_t rand_ctx;
460 
461  fr_pair_list_init(&test_vps);
462  if (input_count > len) input_count = len;
463  rand_ctx.a = fr_rand();
464  rand_ctx.b = fr_rand();
465 
466  for (i = 0; i < reps; i++) {
467  for (j = 0; j < len; j++) {
468  int idx = fr_fast_rand(&rand_ctx) % input_count;
469  new_vp = fr_pair_copy(autofree, source_vps[idx]);
470  fr_pair_append(&test_vps, new_vp);
471  }
472  start = fr_time();
473  fr_pair_list_free(&test_vps);
474  end = fr_time();
475  used = fr_time_delta_add(used, fr_time_sub(end, start));
476  }
477  fr_pair_list_free(&test_vps);
478  TEST_MSG_ALWAYS("repetitions=%d", reps);
479  TEST_MSG_ALWAYS("perc_rep=%d", perc);
480  TEST_MSG_ALWAYS("list_length=%d", len);
481  TEST_MSG_ALWAYS("used=%"PRId64, fr_time_delta_unwrap(used));
482  TEST_MSG_ALWAYS("per_sec=%0.0lf", (reps * len)/(fr_time_delta_unwrap(used) / (double)NSEC));
483 }
484 
485 #define test_func(_func, _count, _perc, _source_vps) \
486 static void test_ ## _func ## _ ## _count ## _ ## _perc(void)\
487 {\
488  do_test_ ## _func(_count, _perc, 10000, _source_vps);\
489 }
490 
491 #define test_funcs(_func, _perc) \
492  test_func(_func, 20, _perc, source_vps_ ## _perc) \
493  test_func(_func, 40, _perc, source_vps_ ## _perc) \
494  test_func(_func, 60, _perc, source_vps_ ## _perc) \
495  test_func(_func, 80, _perc, source_vps_ ## _perc) \
496  test_func(_func, 100, _perc, source_vps_ ## _perc)
497 
498 #define all_test_funcs(_func) \
499  test_funcs(_func, 0) \
500  test_funcs(_func, 25) \
501  test_funcs(_func, 50) \
502  test_funcs(_func, 75) \
503  test_funcs(_func, 100)
504 
507 all_test_funcs(find_nth)
509 
510 #define repetition_tests(_func, _perc) \
511  { #_func "_20_" #_perc, test_ ## _func ## _20_ ## _perc},\
512  { #_func "_40_" #_perc, test_ ## _func ## _40_ ## _perc},\
513  { #_func "_60_" #_perc, test_ ## _func ## _60_ ## _perc},\
514  { #_func "_80_" #_perc, test_ ## _func ## _80_ ## _perc},\
515  { #_func "_100_" #_perc, test_ ## _func ## _100_ ## _perc},\
516 
517 #define all_repetition_tests(_func) \
518  repetition_tests(_func, 0) \
519  repetition_tests(_func, 25) \
520  repetition_tests(_func, 50) \
521  repetition_tests(_func, 75) \
522  repetition_tests(_func, 100)
523 
524 TEST_LIST = {
527  all_repetition_tests(find_nth)
529 
530  { NULL }
531 };
#define TEST_MSG_ALWAYS(...)
Definition: acutest.h:222
#define TEST_CHECK(cond)
Definition: acutest.h:85
#define TEST_LIST
Definition: acutest.h:62
strcpy(log_entry->msg, buffer)
#define TEST_ASSERT(cond)
Definition: acutest.h:108
typedef __attribute__
static fr_dict_t * dict
Definition: fuzzer.c:46
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
Definition: debug.h:232
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition: dict_util.c:1997
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(reap)
long int ssize_t
Definition: merged_model.c:24
unsigned long int size_t
Definition: merged_model.c:25
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:688
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:1340
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition: pair.c:46
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:736
int fr_pair_sublist_copy(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from, fr_pair_t const *start, unsigned int count)
Duplicate a list of pairs starting at a particular item.
Definition: pair.c:2505
fr_pair_t * fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp)
Copy a single valuepair.
Definition: pair.c:484
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.
Definition: pair_legacy.c:150
struct fr_pair_parse_s fr_pair_parse_t
TALLOC_CTX * ctx
Definition: pair_legacy.h:43
static void do_test_fr_pair_find_by_da_idx(unsigned int len, unsigned int perc, unsigned int reps, fr_pair_t *source_vps[])
#define all_repetition_tests(_func)
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 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 TALLOC_CTX * autofree
Definition: radclient-ng.c:104
uint32_t fr_fast_rand(fr_fast_rand_t *ctx)
Definition: rand.c:280
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition: rand.c:106
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(_start, _len_or_end)
fr_pair_t * vp
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition: state_test.c:8
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:51
int fr_time_start(void)
Initialize the local time.
Definition: time.c:150
static fr_time_delta_t fr_time_delta_add(fr_time_delta_t a, fr_time_delta_t b)
Definition: time.h:255
static int64_t fr_time_delta_unwrap(fr_time_delta_t time)
Definition: time.h:154
#define fr_time_delta_wrap(_time)
Definition: time.h:152
#define NSEC
Definition: time.h:377
#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_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Definition: pair_inline.c:43
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:94
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:70
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
Definition: pair_inline.c:113
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.
Definition: pair_inline.c:182
size_t fr_pair_list_num_elements(fr_pair_list_t const *list)
Get the length of a list of fr_pair_t.
Definition: pair_inline.c:151
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition: strerror.c:733
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 size_t char ** out
Definition: value.h:984