The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
value_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 value box functions
18 *
19 * @file src/lib/util/test/value_tests.c
20 * @copyright 2026 Network RADIUS SAS (legal@networkradius.com)
21 */
22
23static void test_init(void);
24#define TEST_GLOBAL_INIT test_init()
25
26#include "acutest_common_init.h"
27#include "acutest_helpers.h"
28
29#include <freeradius-devel/util/value.h>
30
31static TALLOC_CTX *autofree;
32
33static void test_init(void)
34{
36 if (!autofree) {
37 fr_perror("value_tests");
38 fr_exit_now(EXIT_FAILURE);
39 }
40
42 fr_perror("value_tests");
43 fr_exit_now(EXIT_FAILURE);
44 }
45}
46
47/*
48 * Comparison tests (fr_value_box_cmp)
49 */
50static void test_cmp_uint32_equal(void)
51{
52 fr_value_box_t a, b;
53
54 fr_value_box(&a, (uint32_t) 42, false);
55 fr_value_box(&b, (uint32_t) 42, false);
56
57 TEST_CHECK(fr_value_box_cmp(&a, &b) == 0);
58}
59
60static void test_cmp_uint32_less(void)
61{
62 fr_value_box_t a, b;
63
64 fr_value_box(&a, (uint32_t) 10, false);
65 fr_value_box(&b, (uint32_t) 20, false);
66
67 TEST_CHECK(fr_value_box_cmp(&a, &b) == -1);
68 TEST_CHECK(fr_value_box_cmp(&b, &a) == 1);
69}
70
71static void test_cmp_int32(void)
72{
73 fr_value_box_t a, b;
74
75 fr_value_box(&a, (int32_t) -10, false);
76 fr_value_box(&b, (int32_t) 10, false);
77
78 TEST_CHECK(fr_value_box_cmp(&a, &b) == -1);
79 TEST_CHECK(fr_value_box_cmp(&b, &a) == 1);
80
81 fr_value_box(&b, (int32_t) -10, false);
82 TEST_CHECK(fr_value_box_cmp(&a, &b) == 0);
83}
84
85static void test_cmp_float64(void)
86{
87 fr_value_box_t a, b;
88
89 fr_value_box(&a, (double) 3.14, false);
90 fr_value_box(&b, (double) 2.71, false);
91
92 TEST_CHECK(fr_value_box_cmp(&a, &b) == 1);
93 TEST_CHECK(fr_value_box_cmp(&b, &a) == -1);
94
95 fr_value_box(&b, (double) 3.14, false);
96 TEST_CHECK(fr_value_box_cmp(&a, &b) == 0);
97}
98
99static void test_cmp_string(void)
100{
101 fr_value_box_t a, b;
102
103 fr_value_box_strdup(autofree, &a, NULL, "apple", false);
104 fr_value_box_strdup(autofree, &b, NULL, "banana", false);
105
106 TEST_CHECK(fr_value_box_cmp(&a, &b) == -1);
107 TEST_CHECK(fr_value_box_cmp(&b, &a) == 1);
108
110 fr_value_box_strdup(autofree, &b, NULL, "apple", false);
111 TEST_CHECK(fr_value_box_cmp(&a, &b) == 0);
112
115}
116
117static void test_cmp_octets(void)
118{
119 fr_value_box_t a, b;
120
121 fr_value_box_memdup(autofree, &a, NULL, (uint8_t const *)"\x01\x02", 2, false);
122 fr_value_box_memdup(autofree, &b, NULL, (uint8_t const *)"\x01\x03", 2, false);
123
124 TEST_CHECK(fr_value_box_cmp(&a, &b) == -1);
125 TEST_CHECK(fr_value_box_cmp(&b, &a) == 1);
126
129}
130
131static void test_cmp_octets_length(void)
132{
133 fr_value_box_t a, b;
134
135 /* Same prefix but different length: shorter is "less" */
136 fr_value_box_memdup(autofree, &a, NULL, (uint8_t const *)"\x01", 1, false);
137 fr_value_box_memdup(autofree, &b, NULL, (uint8_t const *)"\x01\x02", 2, false);
138
139 TEST_CHECK(fr_value_box_cmp(&a, &b) == -1);
140 TEST_CHECK(fr_value_box_cmp(&b, &a) == 1);
141
144}
145
146static void test_cmp_bool(void)
147{
148 fr_value_box_t a, b;
149
150 fr_value_box(&a, (bool) true, false);
151 fr_value_box(&b, (bool) false, false);
152
153 TEST_CHECK(fr_value_box_cmp(&a, &b) == 1);
154 TEST_CHECK(fr_value_box_cmp(&b, &a) == -1);
155
156 fr_value_box(&b, (bool) true, false);
157 TEST_CHECK(fr_value_box_cmp(&a, &b) == 0);
158}
159
161{
162 fr_value_box_t a, b;
163
164 fr_value_box(&a, (uint32_t) 42, false);
165 fr_value_box(&b, (uint64_t) 42, false);
166
167 /* Different types are incomparable, both directions return CMP_ERR exactly */
170}
171
172/*
173 * Comparison operator tests (fr_value_box_cmp_op)
174 */
175static void test_cmp_op_eq(void)
176{
177 fr_value_box_t a, b;
178
179 fr_value_box(&a, (uint32_t) 42, false);
180 fr_value_box(&b, (uint32_t) 42, false);
181
183
184 fr_value_box(&b, (uint32_t) 43, false);
186}
187
188static void test_cmp_op_ne(void)
189{
190 fr_value_box_t a, b;
191
192 fr_value_box(&a, (uint32_t) 42, false);
193 fr_value_box(&b, (uint32_t) 43, false);
194
196
197 fr_value_box(&b, (uint32_t) 42, false);
199}
200
201static void test_cmp_op_lt(void)
202{
203 fr_value_box_t a, b;
204
205 fr_value_box(&a, (uint32_t) 10, false);
206 fr_value_box(&b, (uint32_t) 20, false);
207
211}
212
213static void test_cmp_op_gt(void)
214{
215 fr_value_box_t a, b;
216
217 fr_value_box(&a, (uint32_t) 20, false);
218 fr_value_box(&b, (uint32_t) 10, false);
219
222}
223
224static void test_cmp_op_le(void)
225{
226 fr_value_box_t a, b;
227
228 fr_value_box(&a, (uint32_t) 10, false);
229 fr_value_box(&b, (uint32_t) 20, false);
230
233
234 fr_value_box(&b, (uint32_t) 10, false);
236}
237
238static void test_cmp_op_ge(void)
239{
240 fr_value_box_t a, b;
241
242 fr_value_box(&a, (uint32_t) 20, false);
243 fr_value_box(&b, (uint32_t) 10, false);
244
247
248 fr_value_box(&b, (uint32_t) 20, false);
250}
251
252/*
253 * Cast tests (fr_value_box_cast)
254 */
256{
257 fr_value_box_t src, dst;
258
259 fr_value_box(&src, (uint32_t) 42, false);
261
262 TEST_CHECK(fr_value_box_cast(autofree, &dst, FR_TYPE_UINT64, NULL, &src) == 0);
263 TEST_CHECK(dst.type == FR_TYPE_UINT64);
264 TEST_CHECK(dst.vb_uint64 == 42);
265}
266
268{
269 fr_value_box_t src, dst;
270
271 fr_value_box(&src, (uint32_t) 12345, false);
273
274 TEST_CHECK(fr_value_box_cast(autofree, &dst, FR_TYPE_STRING, NULL, &src) == 0);
275 TEST_CHECK(dst.type == FR_TYPE_STRING);
276 TEST_CHECK_STRCMP(dst.vb_strvalue, "12345");
277
278 fr_value_box_clear(&dst);
279}
280
282{
283 fr_value_box_t src, dst;
284
285 fr_value_box_strdup(autofree, &src, NULL, "12345", false);
287
288 TEST_CHECK(fr_value_box_cast(autofree, &dst, FR_TYPE_UINT32, NULL, &src) >= 0);
289 TEST_CHECK(dst.type == FR_TYPE_UINT32);
290 TEST_CHECK(dst.vb_uint32 == 12345);
291 TEST_MSG("Expected 12345, got %u", dst.vb_uint32);
292
293 fr_value_box_clear(&src);
294}
295
297{
298 fr_value_box_t src, dst;
299
300 fr_value_box(&src, (int32_t) -42, false);
302
303 TEST_CHECK(fr_value_box_cast(autofree, &dst, FR_TYPE_INT64, NULL, &src) == 0);
304 TEST_CHECK(dst.type == FR_TYPE_INT64);
305 TEST_CHECK(dst.vb_int64 == -42);
306}
307
309{
310 fr_value_box_t src, dst;
311
312 fr_value_box(&src, (uint8_t) 255, false);
314
315 TEST_CHECK(fr_value_box_cast(autofree, &dst, FR_TYPE_UINT32, NULL, &src) == 0);
316 TEST_CHECK(dst.type == FR_TYPE_UINT32);
317 TEST_CHECK(dst.vb_uint32 == 255);
318}
319
320static void test_cast_same_type(void)
321{
322 fr_value_box_t src, dst;
323
324 fr_value_box(&src, (uint32_t) 42, false);
326
327 TEST_CHECK(fr_value_box_cast(autofree, &dst, FR_TYPE_UINT32, NULL, &src) == 0);
328 TEST_CHECK(dst.type == FR_TYPE_UINT32);
329 TEST_CHECK(dst.vb_uint32 == 42);
330}
331
333{
334 fr_value_box_t src, dst;
335
336 fr_value_box(&src, (bool) true, false);
338
339 TEST_CHECK(fr_value_box_cast(autofree, &dst, FR_TYPE_UINT32, NULL, &src) == 0);
340 TEST_CHECK(dst.vb_uint32 == 1);
341
342 fr_value_box(&src, (bool) false, false);
343 TEST_CHECK(fr_value_box_cast(autofree, &dst, FR_TYPE_UINT32, NULL, &src) == 0);
344 TEST_CHECK(dst.vb_uint32 == 0);
345}
346
348{
349 fr_value_box_t src, dst;
350
351 fr_value_box(&src, (uint32_t) 1, false);
353
354 TEST_CHECK(fr_value_box_cast(autofree, &dst, FR_TYPE_BOOL, NULL, &src) == 0);
355 TEST_CHECK(dst.vb_bool == true);
356
357 fr_value_box(&src, (uint32_t) 0, false);
358 TEST_CHECK(fr_value_box_cast(autofree, &dst, FR_TYPE_BOOL, NULL, &src) == 0);
359 TEST_CHECK(dst.vb_bool == false);
360}
361
362/*
363 * Cast in place tests
364 */
366{
368
369 fr_value_box(&vb, (uint32_t) 42, false);
370
372 TEST_CHECK(vb.type == FR_TYPE_UINT64);
373 TEST_CHECK(vb.vb_uint64 == 42);
374}
375
377{
379
380 fr_value_box(&vb, (uint32_t) 12345, false);
381
383 TEST_CHECK(vb.type == FR_TYPE_STRING);
384 TEST_CHECK_STRCMP(vb.vb_strvalue, "12345");
385
387}
388
389/*
390 * Copy tests
391 */
392static void test_copy_uint32(void)
393{
394 fr_value_box_t src, dst;
395
396 fr_value_box(&src, (uint32_t) 42, false);
398
399 TEST_CHECK(fr_value_box_copy(autofree, &dst, &src) == 0);
400 TEST_CHECK(dst.type == FR_TYPE_UINT32);
401 TEST_CHECK(dst.vb_uint32 == 42);
402}
403
404static void test_copy_string(void)
405{
406 fr_value_box_t src, dst;
407
408 fr_value_box_strdup(autofree, &src, NULL, "hello", false);
410
411 TEST_CHECK(fr_value_box_copy(autofree, &dst, &src) == 0);
412 TEST_CHECK(dst.type == FR_TYPE_STRING);
413 TEST_CHECK_STRCMP(dst.vb_strvalue, "hello");
414
415 /* Deep copy: different pointer */
416 TEST_CHECK(dst.vb_strvalue != src.vb_strvalue);
417
418 fr_value_box_clear(&src);
419 fr_value_box_clear(&dst);
420}
421
422static void test_copy_octets(void)
423{
424 fr_value_box_t src, dst;
425
426 fr_value_box_memdup(autofree, &src, NULL, (uint8_t const *)"\x01\x02\x03", 3, false);
428
429 TEST_CHECK(fr_value_box_copy(autofree, &dst, &src) == 0);
430 TEST_CHECK(dst.type == FR_TYPE_OCTETS);
431 TEST_CHECK(dst.vb_length == 3);
432 TEST_CHECK(memcmp(dst.vb_octets, "\x01\x02\x03", 3) == 0);
433
434 /* Deep copy */
435 TEST_CHECK(dst.vb_octets != src.vb_octets);
436
437 fr_value_box_clear(&src);
438 fr_value_box_clear(&dst);
439}
440
442{
443 fr_value_box_t src, dst;
444
445 fr_value_box(&src, (uint32_t) 42, true);
447
448 TEST_CHECK(fr_value_box_copy(autofree, &dst, &src) == 0);
449 TEST_CHECK(dst.tainted == true);
450}
451
452/*
453 * Safety (safe_for) propagation tests
454 *
455 * Tokens standing in for two different consumers. Any two distinct values other
456 * than FR_VALUE_BOX_SAFE_FOR_NONE and FR_VALUE_BOX_SAFE_FOR_ANY will do.
457 */
458#define SAFE_FOR_X ((fr_value_box_safe_for_t) 0x1000)
459#define SAFE_FOR_Y ((fr_value_box_safe_for_t) 0x2000)
460
462{
463 fr_value_box_t src, dst;
464
465 fr_value_box_strdup(autofree, &src, NULL, "copy me", false);
468
469 TEST_CHECK(fr_value_box_copy(autofree, &dst, &src) == 0);
471
472 fr_value_box_clear(&src);
473 fr_value_box_clear(&dst);
474}
475
477{
478 fr_value_box_t src, dst;
479
480 fr_value_box_memdup(autofree, &src, NULL, (uint8_t const *) "abc", 3, false);
483
484 TEST_CHECK(fr_value_box_cast(autofree, &dst, FR_TYPE_STRING, NULL, &src) == 0);
485 TEST_CHECK(dst.type == FR_TYPE_STRING);
487 TEST_MSG("Expected safe_for %#lx, got %#lx", (unsigned long) SAFE_FOR_X, (unsigned long) dst.vb_safefor);
488
489 fr_value_box_clear(&src);
490 fr_value_box_clear(&dst);
491}
492
494{
495 fr_value_box_t src, dst;
496
497 fr_value_box_strdup(autofree, &src, NULL, "abc", false);
500
501 TEST_CHECK(fr_value_box_cast(autofree, &dst, FR_TYPE_OCTETS, NULL, &src) == 0);
502 TEST_CHECK(dst.type == FR_TYPE_OCTETS);
504 TEST_MSG("Expected safe_for %#lx, got %#lx", (unsigned long) SAFE_FOR_X, (unsigned long) dst.vb_safefor);
505
506 fr_value_box_clear(&src);
507 fr_value_box_clear(&dst);
508}
509
511{
512 fr_value_box_t src, dst;
513
514 fr_value_box(&src, (uint32_t) 12345, false);
517
518 TEST_CHECK(fr_value_box_cast(autofree, &dst, FR_TYPE_STRING, NULL, &src) == 0);
519 TEST_CHECK(dst.type == FR_TYPE_STRING);
520 TEST_CHECK(dst.vb_safefor == FR_VALUE_BOX_SAFE_FOR_NONE);
521 TEST_MSG("Expected safe_for NONE, got %#lx", (unsigned long) dst.vb_safefor);
522
523 fr_value_box_clear(&dst);
524}
525
526/** Build a list of single character string boxes, each marked with the matching token
527 */
528static void safe_for_list_build(fr_value_box_list_t *list, fr_value_box_safe_for_t const tokens[], size_t num)
529{
530 size_t i;
531
532 fr_value_box_list_init(list);
533 for (i = 0; i < num; i++) {
534 fr_value_box_t *vb;
535
537 TEST_ASSERT(vb != NULL);
538 TEST_ASSERT(fr_value_box_strdup(vb, vb, NULL, "x", false) == 0);
539 fr_value_box_mark_safe_for(vb, tokens[i]);
540 fr_value_box_list_insert_tail(list, vb);
541 }
542}
543
544/** Concatenate a list into a separate output box and check the resulting safe_for
545 */
546static void safe_for_concat_check(fr_type_t type, fr_value_box_safe_for_t const tokens[], size_t num,
548{
549 fr_value_box_list_t list;
551
552 safe_for_list_build(&list, tokens, num);
554
556 FR_VALUE_BOX_LIST_FREE, true, SIZE_MAX) == 0);
557 TEST_CHECK(out.type == type);
558 TEST_CHECK(out.vb_length == num);
559 TEST_CHECK(out.vb_safefor == expect);
560 TEST_MSG("Expected safe_for %#lx, got %#lx", (unsigned long) expect, (unsigned long) out.vb_safefor);
561
563}
564
571
572static void test_concat_x_x_is_x(void)
573{
574 fr_value_box_safe_for_t const tokens[] = { SAFE_FOR_X, SAFE_FOR_X };
575
577}
578
585
592
599
606
608{
609 fr_value_box_safe_for_t const tokens[] = { SAFE_FOR_X, SAFE_FOR_X };
610
612}
613
614/** The list head doubles as the output box
615 */
617{
618 fr_value_box_safe_for_t const tokens[] = { SAFE_FOR_X, SAFE_FOR_X };
619 fr_value_box_list_t list;
621
622 safe_for_list_build(&list, tokens, NUM_ELEMENTS(tokens));
623 head = fr_value_box_list_head(&list);
624
626 FR_VALUE_BOX_LIST_FREE, true, SIZE_MAX) == 0);
627 TEST_CHECK(head->vb_length == 2);
629 TEST_MSG("Expected safe_for %#lx, got %#lx", (unsigned long) SAFE_FOR_X, (unsigned long) head->vb_safefor);
630
631 fr_value_box_list_talloc_free(&list);
632}
633
634static void test_list_safety_merge(void)
635{
638 fr_value_box_safe_for_t const x_only[] = { SAFE_FOR_X };
639 fr_value_box_list_t list;
640 fr_value_box_t out, *group;
641
642 TEST_CASE("X and ANY merge to X");
643 safe_for_list_build(&list, x_any, NUM_ELEMENTS(x_any));
647 fr_value_box_list_talloc_free(&list);
648
649 TEST_CASE("X and Y merge to NONE");
650 safe_for_list_build(&list, x_y, NUM_ELEMENTS(x_y));
654 fr_value_box_list_talloc_free(&list);
655
656 TEST_CASE("Group children are merged, the group box itself is not");
657 fr_value_box_list_init(&list);
659 TEST_ASSERT(group != NULL);
660 safe_for_list_build(&group->vb_group, x_only, NUM_ELEMENTS(x_only));
661 fr_value_box_list_insert_tail(&list, group);
665 fr_value_box_list_talloc_free(&list);
666}
667
668/*
669 * String operations
670 */
671static void test_strdup(void)
672{
674
675 TEST_CHECK(fr_value_box_strdup(autofree, &vb, NULL, "hello world", false) == 0);
676 TEST_CHECK(vb.type == FR_TYPE_STRING);
677 TEST_CHECK_STRCMP(vb.vb_strvalue, "hello world");
678 TEST_CHECK(vb.vb_length == 11);
679
681}
682
683static void test_asprintf(void)
684{
686
687 TEST_CHECK(fr_value_box_asprintf(autofree, &vb, NULL, false, "value=%d", 42) == 0);
688 TEST_CHECK(vb.type == FR_TYPE_STRING);
689 TEST_CHECK_STRCMP(vb.vb_strvalue, "value=42");
690
692}
693
694static void test_bstrndup(void)
695{
697
698 /* bstrndup copies exactly len bytes */
699 TEST_CHECK(fr_value_box_bstrndup(autofree, &vb, NULL, "hello\0world", 11, false) == 0);
700 TEST_CHECK(vb.type == FR_TYPE_STRING);
701 TEST_CHECK(vb.vb_length == 11);
702 TEST_CHECK(memcmp(vb.vb_strvalue, "hello\0world", 11) == 0);
703
705}
706
707/*
708 * Memory operations
709 */
710static void test_memdup(void)
711{
713 uint8_t data[] = { 0xde, 0xad, 0xbe, 0xef };
714
715 TEST_CHECK(fr_value_box_memdup(autofree, &vb, NULL, data, sizeof(data), false) == 0);
716 TEST_CHECK(vb.type == FR_TYPE_OCTETS);
717 TEST_CHECK(vb.vb_length == 4);
718 TEST_CHECK(memcmp(vb.vb_octets, data, 4) == 0);
719
721}
722
723/*
724 * Hash tests
725 */
726static void test_hash_same_values(void)
727{
728 fr_value_box_t a, b;
729
730 fr_value_box(&a, (uint32_t) 42, false);
731 fr_value_box(&b, (uint32_t) 42, false);
732
734}
735
737{
738 fr_value_box_t a, b;
739
740 fr_value_box(&a, (uint32_t) 42, false);
741 fr_value_box(&b, (uint32_t) 43, false);
742
744}
745
746static void test_hash_string(void)
747{
748 fr_value_box_t a, b;
749
750 fr_value_box_strdup(autofree, &a, NULL, "hello", false);
751 fr_value_box_strdup(autofree, &b, NULL, "hello", false);
752
754
757}
758
759/*
760 * Truthiness tests (fr_value_box_is_truthy)
761 */
762static void test_truthy_bool(void)
763{
765
766 fr_value_box(&vb, (bool) true, false);
768
769 fr_value_box(&vb, (bool) false, false);
770 TEST_CHECK(fr_value_box_is_truthy(&vb) == false);
771}
772
773static void test_truthy_uint32(void)
774{
776
777 fr_value_box(&vb, (uint32_t) 42, false);
779
780 fr_value_box(&vb, (uint32_t) 0, false);
781 TEST_CHECK(fr_value_box_is_truthy(&vb) == false);
782}
783
784static void test_truthy_string(void)
785{
787
788 fr_value_box_strdup(autofree, &vb, NULL, "hello", false);
791
792 fr_value_box_strdup(autofree, &vb, NULL, "", false);
793 TEST_CHECK(fr_value_box_is_truthy(&vb) == false);
795}
796
797static void test_truthy_octets(void)
798{
800
801 fr_value_box_memdup(autofree, &vb, NULL, (uint8_t const *)"\x01", 1, false);
804
805 fr_value_box_memdup(autofree, &vb, NULL, (uint8_t const *)"", 0, false);
806 TEST_CHECK(fr_value_box_is_truthy(&vb) == false);
808}
809
810/*
811 * Increment tests (fr_value_box_increment)
812 */
813static void test_increment_uint32(void)
814{
816
817 fr_value_box(&vb, (uint32_t) 41, false);
819 TEST_CHECK(vb.vb_uint32 == 42);
820 TEST_MSG("Expected 42, got %u", vb.vb_uint32);
821}
822
824{
826
827 fr_value_box(&vb, (uint8_t) UINT8_MAX, false);
829 TEST_CHECK(vb.vb_uint8 == 0);
830 TEST_MSG("Expected 0 (wrap), got %u", vb.vb_uint8);
831}
832
833static void test_increment_int32(void)
834{
836
837 fr_value_box(&vb, (int32_t) -1, false);
839 TEST_CHECK(vb.vb_int32 == 0);
840 TEST_MSG("Expected 0, got %d", vb.vb_int32);
841}
842
843/*
844 * as_uint64 extraction tests
845 */
846static void test_as_uint64(void)
847{
849
850 fr_value_box(&vb, (uint8_t) 255, false);
852
853 fr_value_box(&vb, (uint16_t) 1000, false);
855
856 fr_value_box(&vb, (uint32_t) 100000, false);
857 TEST_CHECK(fr_value_box_as_uint64(&vb) == 100000);
858
859 fr_value_box(&vb, (uint64_t) UINT64_MAX, false);
860 TEST_CHECK(fr_value_box_as_uint64(&vb) == UINT64_MAX);
861
862 fr_value_box(&vb, (bool) true, false);
864}
865
866/*
867 * Clear tests
868 */
869static void test_clear(void)
870{
872
873 fr_value_box(&vb, (uint32_t) 42, false);
874 TEST_CHECK(vb.type == FR_TYPE_UINT32);
875
877 TEST_CHECK(vb.type == FR_TYPE_NULL);
878}
879
880static void test_clear_string(void)
881{
883
884 fr_value_box_strdup(autofree, &vb, NULL, "hello", false);
885 TEST_CHECK(vb.type == FR_TYPE_STRING);
886
888 TEST_CHECK(vb.type == FR_TYPE_NULL);
889}
890
891/*
892 * Tainted flag tests
893 */
894static void test_tainted_flag(void)
895{
897
898 fr_value_box(&vb, (uint32_t) 42, true);
899 TEST_CHECK(vb.tainted == true);
900
901 fr_value_box(&vb, (uint32_t) 42, false);
902 TEST_CHECK(vb.tainted == false);
903}
904
905/*
906 * Network encode/decode round-trip tests
907 */
908static void test_network_uint32(void)
909{
910 fr_value_box_t src, dst;
911 uint8_t buffer[256] = {};
912 fr_dbuff_t dbuff;
913 ssize_t enc_len, dec_len;
914
915 fr_value_box(&src, (uint32_t) 0x12345678, false);
916
917 /* Encode to network format */
918 dbuff = FR_DBUFF_TMP(buffer, sizeof(buffer));
919 enc_len = fr_value_box_to_network(&dbuff, &src);
920 TEST_CHECK(enc_len == 4);
921
922 /* Verify network byte order (big endian) */
923 TEST_CHECK(buffer[0] == 0x12);
924 TEST_CHECK(buffer[1] == 0x34);
925 TEST_CHECK(buffer[2] == 0x56);
926 TEST_CHECK(buffer[3] == 0x78);
927
928 /* Decode back */
930 dbuff = FR_DBUFF_TMP(buffer, (size_t)enc_len);
931 dec_len = fr_value_box_from_network(NULL, &dst, FR_TYPE_UINT32, NULL, &dbuff, enc_len, false);
932 TEST_CHECK(dec_len == 4);
933 TEST_CHECK(dst.vb_uint32 == 0x12345678);
934 TEST_MSG("Expected 0x12345678, got 0x%08x", dst.vb_uint32);
935}
936
937/** The scope_id of an IPv6 address is one byte on the wire, not the four bytes of fr_ipaddr_t.scope_id
938 *
939 */
941{
942 fr_value_box_t src, dst;
943 uint8_t buffer[256] = {};
944 fr_dbuff_t dbuff;
945 ssize_t enc_len, dec_len;
946
947 fr_value_box_init(&src, FR_TYPE_IPV6_ADDR, NULL, false);
948 src.vb_ip = (fr_ipaddr_t) {
949 .af = AF_INET6,
950 .prefix = 128,
951 .scope_id = 1,
952 .addr.v6.s6_addr = { 0xfe, 0x80, [15] = 0x01 }
953 };
954
955 dbuff = FR_DBUFF_TMP(buffer, sizeof(buffer));
956 enc_len = fr_value_box_to_network(&dbuff, &src);
957 TEST_CHECK(enc_len == 17);
958 TEST_MSG("Expected 17, got %zd", enc_len);
959 TEST_CHECK(buffer[0] == 1);
960 TEST_CHECK(buffer[1] == 0xfe);
961
963 dbuff = FR_DBUFF_TMP(buffer, (size_t)enc_len);
964 dec_len = fr_value_box_from_network(NULL, &dst, FR_TYPE_IPV6_ADDR, NULL, &dbuff, enc_len, false);
965 TEST_CHECK(dec_len == 17);
966 TEST_CHECK(dst.vb_ip.scope_id == 1);
967 TEST_CHECK(memcmp(&dst.vb_ip.addr.v6, &src.vb_ip.addr.v6, sizeof(src.vb_ip.addr.v6)) == 0);
968
969 /*
970 * A scope_id which does not fit in one byte is an error, not a truncation.
971 */
972 src.vb_ip.scope_id = 256;
973 dbuff = FR_DBUFF_TMP(buffer, sizeof(buffer));
974 enc_len = fr_value_box_to_network(&dbuff, &src);
975 TEST_CHECK(enc_len < 0);
976 TEST_MSG("Expected an error, got %zd", enc_len);
977}
978
979static void test_network_uint64(void)
980{
981 fr_value_box_t src, dst;
982 uint8_t buffer[256] = {};
983 fr_dbuff_t dbuff;
984 ssize_t enc_len, dec_len;
985
986 fr_value_box(&src, (uint64_t) 0x0102030405060708ULL, false);
987
988 dbuff = FR_DBUFF_TMP(buffer, sizeof(buffer));
989 enc_len = fr_value_box_to_network(&dbuff, &src);
990 TEST_CHECK(enc_len == 8);
991
992 /* Verify big endian */
993 TEST_CHECK(buffer[0] == 0x01);
994 TEST_CHECK(buffer[7] == 0x08);
995
996 /* Decode back */
998 dbuff = FR_DBUFF_TMP(buffer, (size_t)enc_len);
999 dec_len = fr_value_box_from_network(NULL, &dst, FR_TYPE_UINT64, NULL, &dbuff, enc_len, false);
1000 TEST_CHECK(dec_len == 8);
1001 TEST_CHECK(dst.vb_uint64 == 0x0102030405060708ULL);
1002}
1003
1004static void test_network_int32(void)
1005{
1006 fr_value_box_t src, dst;
1007 uint8_t buffer[256] = {};
1008 fr_dbuff_t dbuff;
1009 ssize_t enc_len, dec_len;
1010
1011 fr_value_box(&src, (int32_t) -1, false);
1012
1013 dbuff = FR_DBUFF_TMP(buffer, sizeof(buffer));
1014 enc_len = fr_value_box_to_network(&dbuff, &src);
1015 TEST_CHECK(enc_len == 4);
1016
1017 /* -1 in two's complement big endian is 0xffffffff */
1018 TEST_CHECK(buffer[0] == 0xff);
1019 TEST_CHECK(buffer[1] == 0xff);
1020 TEST_CHECK(buffer[2] == 0xff);
1021 TEST_CHECK(buffer[3] == 0xff);
1022
1023 /* Decode back */
1025 dbuff = FR_DBUFF_TMP(buffer, (size_t)enc_len);
1026 dec_len = fr_value_box_from_network(NULL, &dst, FR_TYPE_INT32, NULL, &dbuff, enc_len, false);
1027 TEST_CHECK(dec_len == 4);
1028 TEST_CHECK(dst.vb_int32 == -1);
1029}
1030
1031static void test_network_bool(void)
1032{
1033 fr_value_box_t src, dst;
1034 uint8_t buffer[256] = {};
1035 fr_dbuff_t dbuff;
1036 ssize_t enc_len, dec_len;
1037
1038 fr_value_box(&src, (bool) true, false);
1039
1040 dbuff = FR_DBUFF_TMP(buffer, sizeof(buffer));
1041 enc_len = fr_value_box_to_network(&dbuff, &src);
1042 TEST_CHECK(enc_len == 1);
1043 TEST_CHECK(buffer[0] == 1);
1044
1046 dbuff = FR_DBUFF_TMP(buffer, (size_t)enc_len);
1047 dec_len = fr_value_box_from_network(NULL, &dst, FR_TYPE_BOOL, NULL, &dbuff, enc_len, false);
1048 TEST_CHECK(dec_len == 1);
1049 TEST_CHECK(dst.vb_bool == true);
1050}
1051
1052static void test_network_length(void)
1053{
1054 fr_value_box_t vb;
1055
1056 fr_value_box(&vb, (uint8_t) 0, false);
1058
1059 fr_value_box(&vb, (uint16_t) 0, false);
1061
1062 fr_value_box(&vb, (uint32_t) 0, false);
1064
1065 fr_value_box(&vb, (uint64_t) 0, false);
1067}
1068
1069/*
1070 * Print tests (fr_value_box_print)
1071 */
1072static void test_print_uint32(void)
1073{
1074 fr_value_box_t vb;
1075 char buffer[256] = {};
1076 fr_sbuff_t sbuff = FR_SBUFF_OUT(buffer, sizeof(buffer));
1077
1078 fr_value_box(&vb, (uint32_t) 42, false);
1079
1080 TEST_CHECK(fr_value_box_print(&sbuff, &vb, NULL) > 0);
1081 fr_sbuff_terminate(&sbuff);
1083}
1084
1086{
1087 fr_value_box_t vb;
1088 char buffer[256] = {};
1089 fr_sbuff_t sbuff = FR_SBUFF_OUT(buffer, sizeof(buffer));
1090
1091 fr_value_box(&vb, (int32_t) -42, false);
1092
1093 TEST_CHECK(fr_value_box_print(&sbuff, &vb, NULL) > 0);
1094 fr_sbuff_terminate(&sbuff);
1095 TEST_CHECK_STRCMP(buffer, "-42");
1096}
1097
1098static void test_print_string(void)
1099{
1100 fr_value_box_t vb;
1101 char buffer[256] = {};
1102 fr_sbuff_t sbuff = FR_SBUFF_OUT(buffer, sizeof(buffer));
1103
1104 fr_value_box_strdup(autofree, &vb, NULL, "hello", false);
1105
1106 TEST_CHECK(fr_value_box_print(&sbuff, &vb, NULL) > 0);
1107 fr_sbuff_terminate(&sbuff);
1108 TEST_CHECK_STRCMP(buffer, "hello");
1109
1110 fr_value_box_clear(&vb);
1111}
1112
1113static void test_print_bool(void)
1114{
1115 fr_value_box_t vb;
1116 char buffer[256] = {};
1117 fr_sbuff_t sbuff;
1118
1119 fr_value_box(&vb, (bool) true, false);
1120 sbuff = FR_SBUFF_OUT(buffer, sizeof(buffer));
1121 TEST_CHECK(fr_value_box_print(&sbuff, &vb, NULL) > 0);
1122 fr_sbuff_terminate(&sbuff);
1123 TEST_CHECK_STRCMP(buffer, "yes");
1124
1125 fr_value_box(&vb, (bool) false, false);
1126 sbuff = FR_SBUFF_OUT(buffer, sizeof(buffer));
1127 TEST_CHECK(fr_value_box_print(&sbuff, &vb, NULL) > 0);
1128 fr_sbuff_terminate(&sbuff);
1130}
1131
1132static void test_print_octets(void)
1133{
1134 fr_value_box_t vb;
1135 char buffer[256] = {};
1136 fr_sbuff_t sbuff = FR_SBUFF_OUT(buffer, sizeof(buffer));
1137
1138 fr_value_box_memdup(autofree, &vb, NULL, (uint8_t const *)"\xde\xad\xbe\xef", 4, false);
1139
1140 TEST_CHECK(fr_value_box_print(&sbuff, &vb, NULL) > 0);
1141 fr_sbuff_terminate(&sbuff);
1142 TEST_CHECK_STRCMP(buffer, "0xdeadbeef");
1143
1144 fr_value_box_clear(&vb);
1145}
1146
1147/*
1148 * From string parsing tests (fr_value_box_from_str)
1149 */
1150static void test_from_str_uint32(void)
1151{
1152 fr_value_box_t vb;
1153
1155 "12345", strlen("12345"), NULL) > 0);
1156 TEST_CHECK(vb.type == FR_TYPE_UINT32);
1157 TEST_CHECK(vb.vb_uint32 == 12345);
1158 TEST_MSG("Expected 12345, got %u", vb.vb_uint32);
1159}
1160
1161static void test_from_str_int32(void)
1162{
1163 fr_value_box_t vb;
1164
1166 "-42", strlen("-42"), NULL) > 0);
1167 TEST_CHECK(vb.type == FR_TYPE_INT32);
1168 TEST_CHECK(vb.vb_int32 == -42);
1169 TEST_MSG("Expected -42, got %d", vb.vb_int32);
1170}
1171
1172static void test_from_str_bool(void)
1173{
1174 fr_value_box_t vb;
1175
1177 "yes", strlen("yes"), NULL) > 0);
1178 TEST_CHECK(vb.type == FR_TYPE_BOOL);
1179 TEST_CHECK(vb.vb_bool == true);
1180}
1181
1182static void test_from_str_float64(void)
1183{
1184 fr_value_box_t vb;
1185
1187 "3.14", strlen("3.14"), NULL) > 0);
1188 TEST_CHECK(vb.type == FR_TYPE_FLOAT64);
1189 TEST_CHECK((vb.vb_float64 > 3.13) && (vb.vb_float64 < 3.15));
1190 TEST_MSG("Expected ~3.14, got %f", vb.vb_float64);
1191}
1192
1193static void test_from_str_octets(void)
1194{
1195 fr_value_box_t vb;
1196
1198 "0xdeadbeef", strlen("0xdeadbeef"), NULL) > 0);
1199 TEST_CHECK(vb.type == FR_TYPE_OCTETS);
1200 TEST_CHECK(vb.vb_length == 4);
1201 TEST_CHECK(memcmp(vb.vb_octets, "\xde\xad\xbe\xef", 4) == 0);
1202
1203 fr_value_box_clear(&vb);
1204}
1205
1206static void test_from_str_string(void)
1207{
1208 fr_value_box_t vb;
1209
1211 "hello world", strlen("hello world"), NULL) > 0);
1212 TEST_CHECK(vb.type == FR_TYPE_STRING);
1213 TEST_CHECK_STRCMP(vb.vb_strvalue, "hello world");
1214
1215 fr_value_box_clear(&vb);
1216}
1217
1218/*
1219 * Print/parse round-trip tests
1220 */
1221static void test_round_trip_uint32(void)
1222{
1223 fr_value_box_t src, dst;
1224 char buffer[256] = {};
1225 fr_sbuff_t sbuff = FR_SBUFF_OUT(buffer, sizeof(buffer));
1226
1227 fr_value_box(&src, (uint32_t) 42, false);
1228
1229 TEST_CHECK(fr_value_box_print(&sbuff, &src, NULL) > 0);
1230 fr_sbuff_terminate(&sbuff);
1231
1233 buffer, strlen(buffer), NULL) > 0);
1234 TEST_CHECK(dst.vb_uint32 == 42);
1235}
1236
1237static void test_round_trip_int64(void)
1238{
1239 fr_value_box_t src, dst;
1240 char buffer[256] = {};
1241 fr_sbuff_t sbuff = FR_SBUFF_OUT(buffer, sizeof(buffer));
1242
1243 fr_value_box(&src, (int64_t) -9999999, false);
1244
1245 TEST_CHECK(fr_value_box_print(&sbuff, &src, NULL) > 0);
1246 fr_sbuff_terminate(&sbuff);
1247
1249 buffer, strlen(buffer), NULL) > 0);
1250 TEST_CHECK(dst.vb_int64 == -9999999);
1251}
1252
1253static void test_round_trip_bool(void)
1254{
1255 fr_value_box_t src, dst;
1256 char buffer[256] = {};
1257 fr_sbuff_t sbuff;
1258
1259 fr_value_box(&src, (bool) true, false);
1260 sbuff = FR_SBUFF_OUT(buffer, sizeof(buffer));
1261 TEST_CHECK(fr_value_box_print(&sbuff, &src, NULL) > 0);
1262 fr_sbuff_terminate(&sbuff);
1263
1265 buffer, strlen(buffer), NULL) > 0);
1266 TEST_CHECK(dst.vb_bool == true);
1267}
1268
1270{
1271 fr_value_box_t src, dst;
1272 uint8_t buffer[256] = {};
1273 fr_dbuff_t dbuff;
1274 ssize_t enc_len;
1275
1276 fr_value_box(&src, (uint32_t) 0xdeadbeef, false);
1277
1278 /* Encode */
1279 dbuff = FR_DBUFF_TMP(buffer, sizeof(buffer));
1280 enc_len = fr_value_box_to_network(&dbuff, &src);
1281 TEST_CHECK(enc_len == 4);
1282
1283 /* Decode */
1285 dbuff = FR_DBUFF_TMP(buffer, (size_t)enc_len);
1286 TEST_CHECK(fr_value_box_from_network(NULL, &dst, FR_TYPE_UINT32, NULL, &dbuff, enc_len, false) == 4);
1287 TEST_CHECK(dst.vb_uint32 == 0xdeadbeef);
1288}
1289
1290/** Escape function for the in-place escape tests, writes '%' as "%25"
1291 */
1293{
1294 fr_sbuff_t our_out = FR_SBUFF(out);
1295 fr_sbuff_t our_in = FR_SBUFF(in);
1296
1297 while (fr_sbuff_extend(&our_in)) {
1298 char c = *fr_sbuff_current(&our_in);
1299
1300 if (c == '%') {
1301 FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "%25");
1302 } else {
1303 FR_SBUFF_IN_CHAR_RETURN(&our_out, c);
1304 }
1305 fr_sbuff_advance(&our_in, 1);
1306 }
1307
1308 fr_sbuff_set(in, &our_in);
1309 FR_SBUFF_SET_RETURN(out, &our_out);
1310}
1311
1312static void test_bstrndup_replace(void)
1313{
1314 fr_value_box_t *vb;
1315 char const *old;
1316
1317 TEST_CASE("Replacing a string value copies the new bytes and keeps the flags");
1318 vb = fr_value_box_alloc(NULL, FR_TYPE_STRING, NULL);
1319 TEST_ASSERT(vb != NULL);
1320 TEST_ASSERT(fr_value_box_bstrndup(vb, vb, NULL, "before", 6, true) == 0);
1322 old = vb->vb_strvalue;
1323
1324 TEST_CHECK_RET(fr_value_box_bstrndup_replace(vb, vb, "af\0ter", 6), 0);
1325 TEST_CHECK(vb->vb_strvalue != old);
1326 TEST_CHECK_LEN(vb->vb_length, 6);
1327 TEST_CHECK(memcmp(vb->vb_strvalue, "af\0ter", 6) == 0);
1328 TEST_CHECK(vb->vb_strvalue[6] == '\0');
1329 TEST_CHECK(vb->tainted == true);
1331
1332 TEST_CASE("Replacing from an aliased source copies before freeing");
1333 TEST_CHECK_RET(fr_value_box_bstrndup_replace(vb, vb, vb->vb_strvalue + 2, 4), 0);
1334 TEST_CHECK_LEN(vb->vb_length, 4);
1335 TEST_CHECK(memcmp(vb->vb_strvalue, "\0ter", 4) == 0);
1336
1337 talloc_free(vb);
1338}
1339
1341{
1342 fr_value_box_t *vb;
1343
1344 TEST_CASE("String with escapable characters and an embedded NUL");
1345 vb = fr_value_box_alloc(NULL, FR_TYPE_STRING, NULL);
1346 TEST_ASSERT(vb != NULL);
1347 TEST_ASSERT(fr_value_box_bstrndup(vb, vb, NULL, "a%b\0c", 5, true) == 0);
1348
1350 TEST_CHECK_LEN(vb->vb_length, 7);
1351 TEST_CHECK(memcmp(vb->vb_strvalue, "a%25b\0c", 7) == 0);
1352 TEST_CHECK(vb->vb_strvalue[7] == '\0');
1353 TEST_CHECK(vb->tainted == true);
1354
1355 talloc_free(vb);
1356}
1357
1359{
1360 fr_value_box_t *vb;
1361
1362 TEST_CASE("String with nothing to escape is copied as is");
1363 vb = fr_value_box_alloc(NULL, FR_TYPE_STRING, NULL);
1364 TEST_ASSERT(vb != NULL);
1365 TEST_ASSERT(fr_value_box_strdup(vb, vb, NULL, "plain", false) == 0);
1366
1368 TEST_CHECK_STRCMP(vb->vb_strvalue, "plain");
1369 TEST_CHECK_LEN(vb->vb_length, 5);
1370
1371 talloc_free(vb);
1372}
1373
1375{
1376 fr_value_box_t *vb;
1377
1378 TEST_CASE("Non-string input is cast to a string before escaping");
1379 vb = fr_value_box_alloc(NULL, FR_TYPE_UINT32, NULL);
1380 TEST_ASSERT(vb != NULL);
1381 vb->vb_uint32 = 100;
1382
1384 TEST_CHECK(vb->type == FR_TYPE_STRING);
1385 TEST_CHECK_STRCMP(vb->vb_strvalue, "100");
1386
1387 talloc_free(vb);
1388}
1389
1391 /* Value replacement and in place escaping */
1392 { "bstrndup_replace", test_bstrndup_replace },
1393 { "escape_in_place_func_string", test_escape_in_place_func_string },
1394 { "escape_in_place_func_unchanged", test_escape_in_place_func_unchanged },
1395 { "escape_in_place_func_cast", test_escape_in_place_func_cast },
1396
1397 /* Comparison tests */
1398 { "cmp_uint32_equal", test_cmp_uint32_equal },
1399 { "cmp_uint32_less", test_cmp_uint32_less },
1400 { "cmp_int32", test_cmp_int32 },
1401 { "cmp_float64", test_cmp_float64 },
1402 { "cmp_string", test_cmp_string },
1403 { "cmp_octets", test_cmp_octets },
1404 { "cmp_octets_length", test_cmp_octets_length },
1405 { "cmp_bool", test_cmp_bool },
1406 { "cmp_different_types", test_cmp_different_types },
1407
1408 /* Comparison operator tests */
1409 { "cmp_op_eq", test_cmp_op_eq },
1410 { "cmp_op_ne", test_cmp_op_ne },
1411 { "cmp_op_lt", test_cmp_op_lt },
1412 { "cmp_op_gt", test_cmp_op_gt },
1413 { "cmp_op_le", test_cmp_op_le },
1414 { "cmp_op_ge", test_cmp_op_ge },
1415
1416 /* Cast tests */
1417 { "cast_uint32_to_uint64", test_cast_uint32_to_uint64 },
1418 { "cast_uint32_to_string", test_cast_uint32_to_string },
1419 { "cast_string_to_uint32", test_cast_string_to_uint32 },
1420 { "cast_int32_to_int64", test_cast_int32_to_int64 },
1421 { "cast_uint8_to_uint32", test_cast_uint8_to_uint32 },
1422 { "cast_same_type", test_cast_same_type },
1423 { "cast_bool_to_uint32", test_cast_bool_to_uint32 },
1424 { "cast_uint32_to_bool", test_cast_uint32_to_bool },
1425
1426 /* Cast in place */
1427 { "cast_in_place_uint32_to_uint64", test_cast_in_place_uint32_to_uint64 },
1428 { "cast_in_place_uint32_to_string", test_cast_in_place_uint32_to_string },
1429
1430 /* Copy tests */
1431 { "copy_uint32", test_copy_uint32 },
1432 { "copy_string", test_copy_string },
1433 { "copy_octets", test_copy_octets },
1434 { "copy_preserves_tainted", test_copy_preserves_tainted },
1435
1436 /* Safety propagation */
1437 { "copy_preserves_safe_for", test_copy_preserves_safe_for },
1438 { "cast_octets_to_string_preserves_safe_for", test_cast_octets_to_string_preserves_safe_for },
1439 { "cast_string_to_octets_preserves_safe_for", test_cast_string_to_octets_preserves_safe_for },
1440 { "cast_uint32_to_string_clears_safe_for", test_cast_uint32_to_string_clears_safe_for },
1441 { "concat_any_any_is_any", test_concat_any_any_is_any },
1442 { "concat_x_x_is_x", test_concat_x_x_is_x },
1443 { "concat_x_any_is_x", test_concat_x_any_is_x },
1444 { "concat_any_x_is_x", test_concat_any_x_is_x },
1445 { "concat_x_y_is_none", test_concat_x_y_is_none },
1446 { "concat_x_none_is_none", test_concat_x_none_is_none },
1447 { "concat_octets_x_x_is_x", test_concat_octets_x_x_is_x },
1448 { "concat_into_head_x_x_is_x", test_concat_into_head_x_x_is_x },
1449 { "list_safety_merge", test_list_safety_merge },
1450
1451 /* String operations */
1452 { "strdup", test_strdup },
1453 { "asprintf", test_asprintf },
1454 { "bstrndup", test_bstrndup },
1455
1456 /* Memory operations */
1457 { "memdup", test_memdup },
1458
1459 /* Hash tests */
1460 { "hash_same_values", test_hash_same_values },
1461 { "hash_different_values", test_hash_different_values },
1462 { "hash_string", test_hash_string },
1463
1464 /* Truthiness tests */
1465 { "truthy_bool", test_truthy_bool },
1466 { "truthy_uint32", test_truthy_uint32 },
1467 { "truthy_string", test_truthy_string },
1468 { "truthy_octets", test_truthy_octets },
1469
1470 /* Increment tests */
1471 { "increment_uint32", test_increment_uint32 },
1472 { "increment_uint8_overflow", test_increment_uint8_overflow },
1473 { "increment_int32", test_increment_int32 },
1474
1475 /* as_uint64 */
1476 { "as_uint64", test_as_uint64 },
1477
1478 /* Clear tests */
1479 { "clear", test_clear },
1480 { "clear_string", test_clear_string },
1481
1482 /* Tainted flag */
1483 { "tainted_flag", test_tainted_flag },
1484
1485 /* Network encode/decode */
1486 { "network_uint32", test_network_uint32 },
1487 { "network_uint64", test_network_uint64 },
1488 { "network_int32", test_network_int32 },
1489 { "network_bool", test_network_bool },
1490 { "network_length", test_network_length },
1491
1492 /* Print tests */
1493 { "print_uint32", test_print_uint32 },
1494 { "print_int32_negative", test_print_int32_negative },
1495 { "print_string", test_print_string },
1496 { "print_bool", test_print_bool },
1497 { "print_octets", test_print_octets },
1498
1499 /* From string parsing */
1500 { "from_str_uint32", test_from_str_uint32 },
1501 { "from_str_int32", test_from_str_int32 },
1502 { "from_str_bool", test_from_str_bool },
1503 { "from_str_float64", test_from_str_float64 },
1504 { "from_str_octets", test_from_str_octets },
1505 { "from_str_string", test_from_str_string },
1506
1507 /* Round-trip tests */
1508 { "round_trip_uint32", test_round_trip_uint32 },
1509 { "round_trip_int64", test_round_trip_int64 },
1510 { "round_trip_bool", test_round_trip_bool },
1511 { "round_trip_network_uint32", test_round_trip_network_uint32 },
1512 { "network_ipv6addr_scope_id", test_network_ipv6addr_scope_id },
1513
1515};
static int const char char buffer[256]
Definition acutest.h:641
#define TEST_CHECK(cond)
Definition acutest.h:101
#define TEST_CASE(name)
Definition acutest.h:203
#define TEST_ASSERT(cond)
Definition acutest.h:125
#define TEST_TERMINATOR
Definition acutest.h:77
#define TEST_MSG(...)
Definition acutest.h:234
Common initialisation for acutest binaries.
#define TEST_CHECK_LEN(_got, _exp)
#define TEST_CHECK_RET(_got, _exp)
#define TEST_CHECK_STRCMP(_got, _exp)
#define NUM_ELEMENTS(_t)
Definition build.h:437
@ CMP_ERR
comparison failed
Definition build.h:114
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:556
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
Definition debug.h:272
talloc_free(hp)
IPv4/6 prefix.
unsigned short uint16_t
fr_type_t
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_INT64
64 Bit signed integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_GROUP
A grouping of other attributes.
@ FR_TYPE_FLOAT64
Double precision floating point.
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
ssize_t fr_slen_t
#define UINT8_MAX
#define FR_SBUFF_IN_CHAR_RETURN(_sbuff,...)
#define fr_sbuff_set(_dst, _src)
#define fr_sbuff_current(_sbuff_or_marker)
#define FR_SBUFF_IN_STRCPY_LITERAL_RETURN(_sbuff, _str)
#define fr_sbuff_extend(_sbuff_or_marker)
#define FR_SBUFF_SET_RETURN(_dst, _src)
#define FR_SBUFF(_sbuff_or_marker)
#define fr_sbuff_advance(_sbuff_or_marker, _len)
#define FR_SBUFF_OUT(_start, _len_or_end)
fr_aka_sim_id_type_t type
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
Definition talloc.h:55
@ T_OP_NE
Definition token.h:95
@ T_OP_CMP_EQ
Definition token.h:104
@ T_OP_LE
Definition token.h:98
@ T_OP_GE
Definition token.h:96
@ T_OP_GT
Definition token.h:97
@ T_OP_LT
Definition token.h:99
static fr_slen_t head
Definition xlat.h:410
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
fr_cmp_ret_t fr_value_box_cmp(fr_value_box_t const *a, fr_value_box_t const *b)
Compare two values.
Definition value.c:770
fr_slen_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, char const *in, size_t inlen, fr_sbuff_unescape_rules_t const *erules)
Definition value.c:6195
size_t fr_value_box_network_length(fr_value_box_t const *value)
Get the size of the value held by the fr_value_box_t.
Definition value.c:1431
uint32_t fr_value_box_hash(fr_value_box_t const *vb)
Hash the contents of a value box.
Definition value.c:7259
ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules)
Print one boxed value to a string.
Definition value.c:6232
ssize_t fr_value_box_from_network(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t type, fr_dict_attr_t const *enumv, fr_dbuff_t *dbuff, size_t len, bool tainted)
Decode a fr_value_box_t from serialized binary data.
Definition value.c:1942
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
Definition value.c:4015
int fr_value_box_asprintf(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, bool tainted, char const *fmt,...)
Print a formatted string using our internal printf wrapper and assign it to a value box.
Definition value.c:4790
int fr_value_box_escape_in_place_func(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_sbuff_escape_func_t escape)
Escape a value box in place using an sbuff escape function.
Definition value.c:7107
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
Definition value.c:4465
int fr_value_box_cmp_op(fr_token_t op, fr_value_box_t const *a, fr_value_box_t const *b)
Compare two attributes using an operator.
Definition value.c:1017
int fr_value_box_bstrndup_replace(TALLOC_CTX *ctx, fr_value_box_t *vb, char const *src, ssize_t len)
Free the existing buffer (if talloced) associated with the valuebox, and replace it with a copy of a ...
Definition value.c:4848
uint64_t fr_value_box_as_uint64(fr_value_box_t const *vb)
Return a uint64_t from a fr_value_box_t.
Definition value.c:4315
bool fr_value_box_is_truthy(fr_value_box_t const *in)
Check truthiness of values.
Definition value.c:7627
int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
Convert one type of fr_value_box_t to another in place.
Definition value.c:4265
void fr_value_box_increment(fr_value_box_t *vb)
Increment a boxed value.
Definition value.c:5370
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated string to a fr_value_box_t.
Definition value.c:4702
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:4448
ssize_t fr_value_box_to_network(fr_dbuff_t *dbuff, fr_value_box_t const *value)
Encode a single value box, serializing its contents in generic network format.
Definition value.c:1534
void fr_value_box_list_safety_merge(fr_value_box_t *out, fr_value_box_list_t const *list)
Set the safety of out to the most restrictive safety of any leaf box in a list.
Definition value.c:7610
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
Definition value.c:4953
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Copy a buffer to a fr_value_box_t.
Definition value.c:5194
int fr_value_box_list_concat_in_place(TALLOC_CTX *ctx, fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type, fr_value_box_list_action_t proc_action, bool flatten, size_t max_size)
Concatenate a list of value boxes.
Definition value.c:6732
@ FR_VALUE_BOX_LIST_FREE
Definition value.h:267
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
Definition value.h:668
static fr_sbuff_err_t char size_t fr_sbuff_t * in
Definition value.h:1061
#define fr_value_box_mark_safe_for(_box, _safe_for)
Definition value.h:1124
static fr_slen_t data
Definition value.h:1366
#define fr_value_box_is_safe_for_only(_box, _safe_for)
Definition value.h:1132
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
Definition value.h:640
static fr_sbuff_err_t char ** out
Definition value.h:1061
#define fr_value_box(_box, _var, _tainted)
Automagically fill in a box, determining the value type from the type of the C variable.
Definition value.h:935
#define FR_VALUE_BOX_SAFE_FOR_NONE
Definition value.h:177
uintptr_t fr_value_box_safe_for_t
Escaping that's been applied to a value box.
Definition value.h:167
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
Definition value.h:634
#define FR_VALUE_BOX_SAFE_FOR_ANY
Definition value.h:178
static void test_clear(void)
static void test_escape_in_place_func_cast(void)
static void test_cmp_int32(void)
Definition value_tests.c:71
static void test_strdup(void)
static void test_copy_string(void)
static void test_tainted_flag(void)
static void test_from_str_int32(void)
static void test_cast_uint32_to_string_clears_safe_for(void)
TEST_LIST
static void test_cmp_op_ge(void)
static void test_cmp_uint32_equal(void)
Definition value_tests.c:50
static void test_cmp_op_ne(void)
static void test_concat_x_y_is_none(void)
static void test_cmp_octets_length(void)
static void safe_for_list_build(fr_value_box_list_t *list, fr_value_box_safe_for_t const tokens[], size_t num)
Build a list of single character string boxes, each marked with the matching token.
static void test_concat_x_none_is_none(void)
static void test_round_trip_network_uint32(void)
static void test_network_int32(void)
static void test_cast_uint32_to_uint64(void)
static void test_as_uint64(void)
static void test_from_str_float64(void)
static void test_from_str_string(void)
static void test_print_octets(void)
static void test_network_uint32(void)
static TALLOC_CTX * autofree
Definition value_tests.c:31
static void test_round_trip_uint32(void)
static void test_copy_uint32(void)
static void test_network_ipv6addr_scope_id(void)
The scope_id of an IPv6 address is one byte on the wire, not the four bytes of fr_ipaddr_t....
static void test_print_string(void)
static void test_round_trip_int64(void)
static void test_asprintf(void)
static void test_print_uint32(void)
static void test_network_uint64(void)
static void test_network_length(void)
static void test_concat_into_head_x_x_is_x(void)
The list head doubles as the output box.
static void test_cast_uint32_to_string(void)
static void test_cast_octets_to_string_preserves_safe_for(void)
static void test_bstrndup(void)
static void test_print_int32_negative(void)
static void test_increment_uint32(void)
static void test_concat_any_x_is_x(void)
static void test_bstrndup_replace(void)
static void test_cast_int32_to_int64(void)
static void test_round_trip_bool(void)
static void test_cast_in_place_uint32_to_string(void)
static void test_list_safety_merge(void)
static void test_increment_uint8_overflow(void)
static void test_truthy_bool(void)
static void test_hash_different_values(void)
static void test_cast_uint8_to_uint32(void)
static void test_escape_in_place_func_string(void)
static void test_cmp_op_lt(void)
static void test_cast_same_type(void)
static void test_cmp_octets(void)
static void test_copy_preserves_safe_for(void)
static void test_cast_bool_to_uint32(void)
static void test_escape_in_place_func_unchanged(void)
static void test_from_str_bool(void)
static void test_concat_x_any_is_x(void)
static void test_concat_octets_x_x_is_x(void)
static void test_cmp_op_eq(void)
static void test_cast_in_place_uint32_to_uint64(void)
static void test_cast_uint32_to_bool(void)
static void test_copy_preserves_tainted(void)
static void test_cmp_different_types(void)
static void test_concat_any_any_is_any(void)
static void test_concat_x_x_is_x(void)
static void test_cmp_string(void)
Definition value_tests.c:99
static void test_hash_same_values(void)
static fr_slen_t test_percent_escape(fr_sbuff_t *out, fr_sbuff_t *in)
Escape function for the in-place escape tests, writes '' as "%25".
static void test_cmp_float64(void)
Definition value_tests.c:85
static void test_truthy_octets(void)
static void test_from_str_octets(void)
static void test_cast_string_to_uint32(void)
static void test_clear_string(void)
static void test_init(void)
Definition value_tests.c:33
static void test_hash_string(void)
static void test_cmp_op_le(void)
static void test_truthy_uint32(void)
static void test_memdup(void)
static void test_increment_int32(void)
static void test_cmp_op_gt(void)
static void safe_for_concat_check(fr_type_t type, fr_value_box_safe_for_t const tokens[], size_t num, fr_value_box_safe_for_t expect)
Concatenate a list into a separate output box and check the resulting safe_for.
static void test_print_bool(void)
static void test_truthy_string(void)
static void test_cmp_bool(void)
#define SAFE_FOR_Y
static void test_cmp_uint32_less(void)
Definition value_tests.c:60
static void test_cast_string_to_octets_preserves_safe_for(void)
static void test_copy_octets(void)
static void test_from_str_uint32(void)
static void test_network_bool(void)
#define SAFE_FOR_X