The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
edit_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 a AVP manipulation and search API.
18 *
19 * @file src/lib/util/edit_tests.c
20 * @author Alan DeKok (aland@networkradius.com)
21 * @copyright 2021 Network RADIUS SAS (legal@networkradius.com)
22 */
23
24/**
25 * The 'TEST_INIT' macro provided by 'acutest.h' allowing to register a function to be called
26 * before call the unit tests. Therefore, It calls the function ALL THE TIME causing an overhead.
27 * That is why we are initializing test_init() by "__attribute__((constructor));" reducing the
28 * test execution by 50% of the time.
29 */
30#define USE_CONSTRUCTOR
31
32/*
33 * It should be declared before include the "acutest.h"
34 */
35#ifdef USE_CONSTRUCTOR
36static void test_init(void) __attribute__((constructor));
37#else
38static void test_init(void);
39# define TEST_INIT test_init()
40#endif
41
42#include <freeradius-devel/util/acutest.h>
43#include <freeradius-devel/util/acutest_helpers.h>
44#include <freeradius-devel/util/pair_test_helpers.h>
45
46#include <freeradius-devel/util/conf.h>
47#include <freeradius-devel/util/dict.h>
48#include <freeradius-devel/util/edit.h>
49
50#ifdef HAVE_GPERFTOOLS_PROFILER_H
51# include <gperftools/profiler.h>
52#endif
53
54static TALLOC_CTX *autofree;
56static fr_dict_t *test_dict;
57
58/** Global initialisation
59 */
60static void test_init(void)
61{
63 if (!autofree) {
64 error:
65 fr_perror("edit_tests");
66 fr_exit_now(EXIT_FAILURE);
67 }
68
69 /*
70 * Mismatch between the binary and the libraries it depends on
71 */
72 if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) goto error;
73
74 if (fr_dict_test_init(autofree, &test_dict, NULL) < 0) goto error;
75
76 /* Initialize the "test_pairs" list */
78
79 if (fr_pair_test_list_alloc(autofree, &test_pairs, NULL) < 0) goto error;
80}
81
83{
84 int count;
86
88
90 TEST_CHECK(vp != NULL);
91 if (!vp) return;
93
95 TEST_CHECK(vp != NULL);
96 if (!vp) return;
98
100 TEST_CHECK(vp != NULL);
101 if (!vp) return;
103
105 TEST_CASE("Expected (count == 3)");
106 TEST_CHECK(count == 3);
107}
108
110{
111 int count;
112 fr_pair_t *vp;
113
115 TEST_CASE("Expected (count == 3) after undoing the edits");
116 TEST_CHECK(count == 3);
117
120
123
125}
126
127/*
128 * Tests functions
129 */
130static void test_pair_delete_head(void)
131{
132 fr_pair_t *vp;
134 size_t count;
136 int rcode;
137
138 TEST_CASE("Add 3 pairs and delete the first one");
139
141
143
144 el = fr_edit_list_alloc(NULL, 5, NULL);
145 fr_assert(el != NULL);
146
148 TEST_CHECK(rcode == 0);
149
151
153 TEST_CASE("Expected (count == 2) after deleting the head");
154 TEST_CHECK(count == 2);
155
157 TEST_CASE("head is now what was the second pair");
159
161}
162
164{
165 fr_pair_t *vp;
167 size_t count;
169 int rcode;
170
171 TEST_CASE("Add 3 pairs and delete the first one");
172
174
176
177 el = fr_edit_list_alloc(NULL, 5, NULL);
178 fr_assert(el != NULL);
179
181 TEST_CHECK(rcode == 0);
182
184 TEST_CASE("Expected (count == 2) after deleting the head");
185 TEST_CHECK(count == 2);
186
187 /*
188 * Abort the edit
189 */
191
193}
194
195static void test_pair_delete_middle(void)
196{
197 fr_pair_t *vp;
199 size_t count;
201 int rcode;
202
203 TEST_CASE("Add 3 pairs and delete the middle one");
204
206
209 fr_assert(vp != NULL);
210
211 el = fr_edit_list_alloc(NULL, 5, NULL);
212 fr_assert(el != NULL);
213
215 TEST_CHECK(rcode == 0);
216
218
219 /* let's count */
221 TEST_CASE("Expected (count == 2) after deleting the middle");
222 TEST_CHECK(count == 2);
223
226
229
231}
232
234{
235 fr_pair_t *vp, *middle;
237 size_t count;
239 int rcode;
240
241 TEST_CASE("Add 3 pairs and delete the middle one, then abort");
242
244
246 middle = fr_pair_list_next(&local_pairs, vp);
247 fr_assert(middle != NULL);
249
250 el = fr_edit_list_alloc(NULL, 5, NULL);
251 fr_assert(el != NULL);
252
253 rcode = fr_edit_list_pair_delete(el, &local_pairs, middle);
254 TEST_CHECK(rcode == 0);
255
257 TEST_CASE("Expected (count == 2) after deleting the middle");
258 TEST_CHECK(count == 2);
259
262
265
266 /*
267 * Abort the edit
268 */
270
272}
273
275{
276 fr_pair_t *vp;
278 size_t count;
280 int rcode;
281
282 TEST_CASE("Add 3 pairs and delete the last 2");
283
285
288 fr_assert(vp != NULL);
289
290 el = fr_edit_list_alloc(NULL, 5, NULL);
291 fr_assert(el != NULL);
292
293 rcode = fr_edit_list_pair_delete(el, &local_pairs, vp); /* middle */
294 TEST_CHECK(rcode == 0);
295
297 fr_assert(vp != NULL);
298
299 rcode = fr_edit_list_pair_delete(el, &local_pairs, vp); /* tail */
300 TEST_CHECK(rcode == 0);
301
303
305 TEST_CASE("Expected (count == 1) after deleting the last 2");
306 TEST_CHECK(count == 1);
307
310
312 TEST_CHECK(vp->da == fr_dict_attr_test_uint32); /* head == tail */
313
315}
316
318{
319 fr_pair_t *vp;
321 size_t count;
323 int rcode;
324
325 TEST_CASE("Add 3 pairs and delete the last two, then abort");
326
328
330 fr_assert(vp != NULL);
332 fr_assert(vp != NULL);
334
335 el = fr_edit_list_alloc(NULL, 5, NULL);
336 fr_assert(el != NULL);
337
338 rcode = fr_edit_list_pair_delete(el, &local_pairs, vp); /* middle */
339 TEST_CHECK(rcode == 0);
340
342 fr_assert(vp != NULL);
343
344 rcode = fr_edit_list_pair_delete(el, &local_pairs, vp); /* tail */
345 TEST_CHECK(rcode == 0);
346
348 TEST_CASE("Expected (count == 1) after deleting the last 2");
349 TEST_CHECK(count == 1);
350
353
356
357 /*
358 * Abort the edit
359 */
361
363}
364
365
366static void test_pair_edit_value(void)
367{
368 fr_pair_t *vp;
371 int rcode;
372
373 TEST_CASE("Add 3 pairs and change the value of the first one");
374
376
378 fr_assert(vp != NULL);
379
380 el = fr_edit_list_alloc(NULL, 5, NULL);
381 fr_assert(el != NULL);
382
384 TEST_CHECK(rcode == 0);
385
386 TEST_CHECK(vp->vp_uint32 == 0);
387
388 vp->vp_uint32 = 1;
389 TEST_CHECK(vp->vp_uint32 == 1);
390
392
395 TEST_CHECK(vp->vp_uint32 == 1);
396
398}
399
401{
402 fr_pair_t *vp;
405 int rcode;
406
407 TEST_CASE("Add 3 pairs and change the value of the first one, then abort");
408
410
412 fr_assert(vp != NULL);
413
414 el = fr_edit_list_alloc(NULL, 5, NULL);
415 fr_assert(el != NULL);
416
418 TEST_CHECK(rcode == 0);
419
420 TEST_CHECK(vp->vp_uint32 == 0);
421
422 vp->vp_uint32 = 1;
423 TEST_CHECK(vp->vp_uint32 == 1);
424
425 /*
426 * Abort the edit
427 */
429
432 TEST_CHECK(vp->vp_uint32 == 0);
433
435}
436
438{
439 fr_pair_t *vp;
441 size_t count;
443 int rcode;
444
445 TEST_CASE("Add 3 pairs and insert a new one at the head");
446
448
449 el = fr_edit_list_alloc(NULL, 5, NULL);
450 fr_assert(el != NULL);
451
453
455 TEST_CHECK(rcode == 0);
456
458
460 TEST_CASE("Expected (count == 4) after inserting a new one");
461 TEST_CHECK(count == 4);
462
464 TEST_CASE("head is now what was the second pair");
466
468}
469
471{
472 fr_pair_t *vp;
474 size_t count;
476 int rcode;
477
478 TEST_CASE("Add 3 pairs and insert a new one at the head, then abort");
479
481
482 el = fr_edit_list_alloc(NULL, 5, NULL);
483 fr_assert(el != NULL);
484
486
488 TEST_CHECK(rcode == 0);
489
491 TEST_CASE("Expected (count == 4) after inserting a new one");
492 TEST_CHECK(count == 4);
493
494 /*
495 * Abort the edit
496 */
498
500}
501
503{
504 fr_pair_t *vp, *middle;
506 size_t count;
508 int rcode;
509
510 TEST_CASE("Add 3 pairs and insert a new one at the head");
511
513
515 middle = fr_pair_list_next(&local_pairs, vp);
516 fr_assert(middle != NULL);
517
518 el = fr_edit_list_alloc(NULL, 5, NULL);
519 fr_assert(el != NULL);
520
522
524 TEST_CHECK(rcode == 0);
525
527
529 TEST_CASE("Expected (count == 4) after inserting a new one");
530 TEST_CHECK(count == 4);
531
533}
534
536{
537 fr_pair_t *vp, *middle;
539 size_t count;
541 int rcode;
542
543 TEST_CASE("Add 3 pairs and insert a new one at the head, then abort");
544
546
548 middle = fr_pair_list_next(&local_pairs, vp);
549 fr_assert(middle != NULL);
550
551 el = fr_edit_list_alloc(NULL, 5, NULL);
552 fr_assert(el != NULL);
553
555
557 TEST_CHECK(rcode == 0);
558
560 TEST_CASE("Expected (count == 4) after inserting a new one");
561 TEST_CHECK(count == 4);
562
563 /*
564 * Abort the edit
565 */
567
569}
570
572{
573 fr_pair_t *vp;
576 int rcode, count;
577
578 TEST_CASE("Add 3 pairs, change the value of the first one, and delete it");
579
581
583 fr_assert(vp != NULL);
584
585 el = fr_edit_list_alloc(NULL, 5, NULL);
586 fr_assert(el != NULL);
587
589 TEST_CHECK(rcode == 0);
590
591 TEST_CHECK(vp->vp_uint32 == 0);
592
593 vp->vp_uint32 = 1;
594 TEST_CHECK(vp->vp_uint32 == 1);
595
597 TEST_CHECK(rcode == 0);
598
600
603
605 TEST_CASE("Expected (count == 2) after deleting the edited pair");
606 TEST_CHECK(count == 2);
607}
608
610{
611 fr_pair_t *vp;
614 int rcode;
615
616 TEST_CASE("Add 3 pairs, change the value of the first one, and delete it, then abort");
617
619
621 fr_assert(vp != NULL);
622
623 el = fr_edit_list_alloc(NULL, 5, NULL);
624 fr_assert(el != NULL);
625
627 TEST_CHECK(rcode == 0);
628
629 TEST_CHECK(vp->vp_uint32 == 0);
630
631 vp->vp_uint32 = 1;
632 TEST_CHECK(vp->vp_uint32 == 1);
633
635 TEST_CHECK(rcode == 0);
636
637 /*
638 * Abort the edit
639 */
641
644 TEST_CHECK(vp->vp_uint32 == 0);
645
647}
648
650{
651 fr_pair_t *vp;
653 size_t count;
655 int rcode;
656
657 TEST_CASE("Add 3 pairs and insert a new one at the head, and delete it");
658
660
661 el = fr_edit_list_alloc(NULL, 5, NULL);
662 fr_assert(el != NULL);
663
665
667 TEST_CHECK(rcode == 0);
668
670 TEST_CASE("Expected (count == 4) after inserting a new one");
671 TEST_CHECK(count == 4);
672
674 TEST_CHECK(rcode == 0);
675
677 TEST_CASE("Expected (count == 3) after deleting the just inserted on");
678 TEST_CHECK(count == 3);
679
681
683}
684
686{
687 fr_pair_t *vp;
689 size_t count;
691 int rcode;
692
693 TEST_CASE("Add 3 pairs and insert a new one at the head and delete it, then abort");
694
696
697 el = fr_edit_list_alloc(NULL, 5, NULL);
698 fr_assert(el != NULL);
699
701
703 TEST_CHECK(rcode == 0);
704
706 TEST_CASE("Expected (count == 4) after inserting a new one");
707 TEST_CHECK(count == 4);
708
709 /*
710 * Abort the edit
711 */
713
715}
716
717
719{
720 fr_pair_t *vp;
722 fr_edit_list_t *el, *child;
723 int rcode;
724
725 TEST_CASE("Add 3 pairs and change the value of the first one in a child transaction");
726
728
730 fr_assert(vp != NULL);
731
732 el = fr_edit_list_alloc(NULL, 5, NULL);
733 fr_assert(el != NULL);
734
736 TEST_CHECK(rcode == 0);
737
738 TEST_CHECK(vp->vp_uint32 == 0);
739
740 vp->vp_uint32 = 1;
741 TEST_CHECK(vp->vp_uint32 == 1);
742
743 child = fr_edit_list_alloc(NULL, 5, el);
744 fr_assert(child != NULL);
745
746 rcode = fr_edit_list_save_pair_value(child, vp); /* CHILD */
747 TEST_CHECK(rcode == 0);
748
749 TEST_CHECK(vp->vp_uint32 == 1);
750
751 vp->vp_uint32 = 2;
752 TEST_CHECK(vp->vp_uint32 == 2);
753
754 fr_edit_list_commit(child); /* should do nothing */
755
756 TEST_CHECK(vp->vp_uint32 == 2);
757
759
762 TEST_CHECK(vp->vp_uint32 == 2);
763
765}
766
768{
769 fr_pair_t *vp;
771 fr_edit_list_t *el, *child;
772 int rcode;
773
774 TEST_CASE("Add 3 pairs and change the value of the first one, then abort");
775
777
779 fr_assert(vp != NULL);
780
781 el = fr_edit_list_alloc(NULL, 5, NULL);
782 fr_assert(el != NULL);
783
785 TEST_CHECK(rcode == 0);
786
787 TEST_CHECK(vp->vp_uint32 == 0);
788
789 vp->vp_uint32 = 1;
790 TEST_CHECK(vp->vp_uint32 == 1);
791
792 child = fr_edit_list_alloc(NULL, 5, el);
793 fr_assert(child != NULL);
794
795 rcode = fr_edit_list_save_pair_value(child, vp); /* CHILD */
796 TEST_CHECK(rcode == 0);
797
798 TEST_CHECK(vp->vp_uint32 == 1);
799
800 vp->vp_uint32 = 2;
801 TEST_CHECK(vp->vp_uint32 == 2);
802
803 fr_edit_list_abort(child); /* CHILD */
804
805 TEST_CHECK(vp->vp_uint32 == 1);
806
808
811 TEST_CHECK(vp->vp_uint32 == 1);
812
814}
815
817 /*
818 * Deletion.
819 */
820 { "pair_delete_head", test_pair_delete_head },
821 { "pair_delete_head_abort", test_pair_delete_head_abort },
822
823 { "pair_delete_middle", test_pair_delete_middle },
824 { "pair_delete_middle_abort", test_pair_delete_middle_abort },
825
826 { "pair_delete_multiple", test_pair_delete_multiple },
827 { "pair_delete_multiple_abort", test_pair_delete_multiple_abort },
828
829 /*
830 * Insert after
831 */
832 { "pair_insert_after_head", test_pair_insert_after_head },
833 { "pair_insert_after_head_abort", test_pair_insert_after_head_abort },
834
835 { "pair_insert_after_middle", test_pair_insert_after_middle },
836 { "pair_insert_after_middle_abort", test_pair_insert_after_middle_abort },
837
838 /*
839 * Value modification
840 */
841 { "pair_edit_value", test_pair_edit_value },
842 { "pair_edit_value_abort", test_pair_edit_value_abort },
843
844 /*
845 * Value modification, then deletion
846 */
847 { "pair_edit_value_delete", test_pair_edit_value_delete },
848 { "pair_edit_value_delete_abort", test_pair_edit_value_delete_abort },
849
850 /*
851 * Insert after, then delete
852 */
853 { "pair_insert_after_head_delete", test_pair_insert_after_head_delete },
854 { "pair_insert_after_head_delete_abort", test_pair_insert_after_head_delete_abort },
855
856 /*
857 * Value modification in child list
858 */
859 { "pair_edit_child_value", test_pair_edit_child_value },
860 { "pair_edit_child_value_abort", test_pair_edit_child_value_abort },
861
862 { NULL }
863};
#define TEST_CHECK(cond)
Definition acutest.h:85
#define TEST_CASE(name)
Definition acutest.h:184
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
Definition debug.h:234
fr_dict_attr_t const * fr_dict_attr_test_tlv
Definition dict_test.c:64
fr_dict_attr_t const * fr_dict_attr_test_uint32
Definition dict_test.c:47
fr_dict_attr_t const * fr_dict_attr_test_octets
Definition dict_test.c:31
fr_dict_attr_t const * fr_dict_attr_test_string
Definition dict_test.c:30
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
static void test_pair_delete_multiple(void)
Definition edit_tests.c:274
static void test_pair_delete_head(void)
Definition edit_tests.c:130
TEST_LIST
Definition edit_tests.c:816
static void test_pair_delete_head_abort(void)
Definition edit_tests.c:163
static void test_pair_delete_multiple_abort(void)
Definition edit_tests.c:317
static void test_pair_edit_value_delete_abort(void)
Definition edit_tests.c:609
static void test_pair_insert_after_head_delete_abort(void)
Definition edit_tests.c:685
static void test_pair_delete_middle_abort(void)
Definition edit_tests.c:233
static void expect3(fr_pair_list_t *local_pairs)
Definition edit_tests.c:109
static void test_pair_edit_value(void)
Definition edit_tests.c:366
static void test_pair_insert_after_middle(void)
Definition edit_tests.c:502
static void test_pair_edit_child_value(void)
Definition edit_tests.c:718
static void add_pairs(fr_pair_list_t *local_pairs)
Definition edit_tests.c:82
static void test_pair_insert_after_head_abort(void)
Definition edit_tests.c:470
static void test_pair_insert_after_head(void)
Definition edit_tests.c:437
static void test_pair_insert_after_head_delete(void)
Definition edit_tests.c:649
static void test_pair_edit_child_value_abort(void)
Definition edit_tests.c:767
static void test_pair_delete_middle(void)
Definition edit_tests.c:195
static void test_pair_edit_value_delete(void)
Definition edit_tests.c:571
static void test_init(void)
Global initialisation.
Definition edit_tests.c:36
static void test_pair_edit_value_abort(void)
Definition edit_tests.c:400
static void test_pair_insert_after_middle_abort(void)
Definition edit_tests.c:535
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:1345
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition pair.c:283
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:46
static fr_pair_list_t test_pairs
static fr_dict_t * test_dict
static int fr_pair_test_list_alloc(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_test_attr_t const *test_defs)
#define fr_assert(_expr)
Definition rad_assert.h:38
static TALLOC_CTX * autofree
#define local_pairs
Convenience macro for accessing the state list.
Definition request.h:134
return count
Definition module.c:163
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:51
static fr_event_list_t * el
int fr_edit_list_pair_delete(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *vp)
Delete a VP.
Definition edit.c:575
void fr_edit_list_commit(fr_edit_list_t *el)
Commit an edit list.
Definition edit.c:841
int fr_edit_list_insert_pair_after(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *pos, fr_pair_t *vp)
Insert a new VP after an existing one.
Definition edit.c:562
int fr_edit_list_save_pair_value(fr_edit_list_t *el, fr_pair_t *vp)
Record the value of a leaf fr_value_box_t.
Definition edit.c:622
void fr_edit_list_abort(fr_edit_list_t *el)
Abort the entries in an edit list.
Definition edit.c:194
fr_edit_list_t * fr_edit_list_alloc(TALLOC_CTX *ctx, int hint, fr_edit_list_t *parent)
Allocate an edit list.
Definition edit.c:790
Track a series of edits.
Definition edit.c:102
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
fr_pair_t * fr_pair_list_tail(fr_pair_list_t const *list)
Get the tail of a valuepair list.
Definition pair_inline.c:56
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
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
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: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