1 /**
2  * @file test_when_1.1.c
3  * @author Michal Vasko <mvasko@cesnet.cz>
4  * @brief Cmocka tests for resolving YANG 1.1 when-stmt constraints.
5  *
6  * Copyright (c) 2016 CESNET, z.s.p.o.
7  *
8  * This source code is licensed under BSD 3-Clause License (the "License").
9  * You may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     https://opensource.org/licenses/BSD-3-Clause
13  */
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <setjmp.h>
18 #include <stdarg.h>
19 #include <cmocka.h>
20 
21 #include "tests/config.h"
22 #include "libyang.h"
23 
24 struct state {
25     struct ly_ctx *ctx;
26     const struct lys_module *mod;
27     struct lyd_node *dt;
28     char *xml;
29 };
30 
31 static int
setup_f(void ** state)32 setup_f(void **state)
33 {
34     struct state *st;
35 
36     (*state) = st = calloc(1, sizeof *st);
37     if (!st) {
38         fprintf(stderr, "Memory allocation error");
39         return -1;
40     }
41 
42     /* libyang context */
43     st->ctx = ly_ctx_new(NULL, 0);
44     if (!st->ctx) {
45         fprintf(stderr, "Failed to create context.\n");
46         goto error;
47     }
48 
49     return 0;
50 
51 error:
52     ly_ctx_destroy(st->ctx, NULL);
53     free(st);
54     (*state) = NULL;
55 
56     return -1;
57 }
58 
59 static int
teardown_f(void ** state)60 teardown_f(void **state)
61 {
62     struct state *st = (*state);
63 
64     lyd_free_withsiblings(st->dt);
65     ly_ctx_destroy(st->ctx, NULL);
66     free(st->xml);
67     free(st);
68     (*state) = NULL;
69 
70     return 0;
71 }
72 
73 static void
test_unlink_uses(void ** state)74 test_unlink_uses(void **state)
75 {
76     struct state *st = (struct state *)*state;
77 
78     /* schema */
79     st->mod = lys_parse_path(st->ctx, TESTS_DIR"/data/files/when-unlink.yin", LYS_IN_YIN);
80     assert_ptr_not_equal(st->mod, NULL);
81 
82     st->dt = lyd_new_path(NULL, st->ctx, "/when-unlink:top/e", "val_e", 0, 0);
83     assert_ptr_not_equal(st->dt, NULL);
84 
85     assert_int_equal(lyd_validate(&(st->dt), LYD_OPT_CONFIG, NULL), 0);
86 
87     lyd_print_mem(&(st->xml), st->dt, LYD_XML, LYP_WITHSIBLINGS);
88     assert_string_equal(st->xml, "<top xmlns=\"urn:libyang:tests:when-unlink\"><e>val_e</e></top>");
89 }
90 
91 static void
test_unlink_choice(void ** state)92 test_unlink_choice(void **state)
93 {
94     struct state *st = (struct state *)*state;
95 
96     /* schema */
97     st->mod = lys_parse_path(st->ctx, TESTS_DIR"/data/files/when-unlink.yin", LYS_IN_YIN);
98     assert_ptr_not_equal(st->mod, NULL);
99 
100     st->dt = lyd_new_path(NULL, st->ctx, "/when-unlink:top/cas2", NULL, 0, 0);
101     assert_ptr_not_equal(st->dt, NULL);
102 
103     assert_int_equal(lyd_validate(&(st->dt), LYD_OPT_CONFIG, NULL), 0);
104 
105     lyd_print_mem(&(st->xml), st->dt, LYD_XML, LYP_WITHSIBLINGS);
106     assert_string_equal(st->xml, "<top xmlns=\"urn:libyang:tests:when-unlink\"><cas2/></top>");
107 }
108 
109 static void
test_unlink_case(void ** state)110 test_unlink_case(void **state)
111 {
112     struct state *st = (struct state *)*state;
113     struct lyd_node *node;
114 
115     /* schema */
116     st->mod = lys_parse_path(st->ctx, TESTS_DIR"/data/files/when-unlink.yin", LYS_IN_YIN);
117     assert_ptr_not_equal(st->mod, NULL);
118 
119     st->dt = lyd_new_path(NULL, st->ctx, "/when-unlink:top/a", "val_a", 0, 0);
120     assert_ptr_not_equal(st->dt, NULL);
121     node = lyd_new_path(st->dt, st->ctx, "/when-unlink:top/b", "val_b", 0, 0);
122     assert_ptr_not_equal(node, NULL);
123 
124     assert_int_equal(lyd_validate(&(st->dt), LYD_OPT_CONFIG, NULL), 0);
125 
126     lyd_print_mem(&(st->xml), st->dt, LYD_XML, LYP_WITHSIBLINGS);
127     assert_string_equal(st->xml, "<top xmlns=\"urn:libyang:tests:when-unlink\"><a>val_a</a><b>val_b</b></top>");
128 }
129 
130 static void
test_unlink_augment(void ** state)131 test_unlink_augment(void **state)
132 {
133     struct state *st = (struct state *)*state;
134     struct lyd_node *node;
135 
136     /* schema */
137     st->mod = lys_parse_path(st->ctx, TESTS_DIR"/data/files/when-unlink.yin", LYS_IN_YIN);
138     assert_ptr_not_equal(st->mod, NULL);
139 
140     st->dt = lyd_new_path(NULL, st->ctx, "/when-unlink:top/d", "1", 0, 0);
141     assert_ptr_not_equal(st->dt, NULL);
142     node = lyd_new_path(st->dt, st->ctx, "/when-unlink:top/d", "2", 0, 0);
143     assert_ptr_not_equal(node, NULL);
144 
145     assert_int_equal(lyd_validate(&(st->dt), LYD_OPT_CONFIG, NULL), 0);
146 
147     lyd_print_mem(&(st->xml), st->dt, LYD_XML, LYP_WITHSIBLINGS);
148     assert_string_equal(st->xml, "<top xmlns=\"urn:libyang:tests:when-unlink\"><d>1</d><d>2</d></top>");
149 }
150 
151 static void
test_dummy(void ** state)152 test_dummy(void **state)
153 {
154     struct state *st = (struct state *)*state;
155 
156     /* schema */
157     st->mod = lys_parse_path(st->ctx, TESTS_DIR"/data/files/when-dummy.yin", LYS_IN_YIN);
158     assert_ptr_not_equal(st->mod, NULL);
159 
160     st->dt = lyd_new_path(NULL, st->ctx, "/when-dummy:c", "value", 0, 0);
161     assert_ptr_not_equal(st->dt, NULL);
162 
163     assert_int_equal(lyd_validate(&(st->dt), LYD_OPT_CONFIG, NULL), 1);
164     assert_int_equal(ly_errno, LY_EVALID);
165     assert_int_equal(ly_vecode(st->ctx), LYVE_XPATH_DUMMY);
166 }
167 
168 static void
test_dependency_noautodel(void ** state)169 test_dependency_noautodel(void **state)
170 {
171     struct state *st = (struct state *)*state;
172     struct lyd_node *node;
173 
174     /* schema */
175     st->mod = lys_parse_path(st->ctx, TESTS_DIR"/data/files/when-depend.yin", LYS_IN_YIN);
176     assert_ptr_not_equal(st->mod, NULL);
177 
178     st->dt = lyd_new_path(NULL, st->ctx, "/when-depend:top/a", "val_a", 0, 0);
179     assert_ptr_not_equal(st->dt, NULL);
180     node = lyd_new_path(st->dt, st->ctx, "/when-depend:top/b", "val_b", 0, 0);
181     assert_ptr_not_equal(node, NULL);
182     node = lyd_new_path(st->dt, st->ctx, "/when-depend:top/d", "1", 0, 0);
183     assert_ptr_not_equal(node, NULL);
184     node = lyd_new_path(st->dt, st->ctx, "/when-depend:top/d", "2", 0, 0);
185     assert_ptr_not_equal(node, NULL);
186     node = lyd_new_path(st->dt, st->ctx, "/when-depend:top/e", "val_e", 0, 0);
187     assert_ptr_not_equal(node, NULL);
188 
189     assert_int_equal(lyd_validate(&(st->dt), LYD_OPT_CONFIG | LYD_OPT_WHENAUTODEL, NULL), 1);
190     assert_int_equal(ly_errno, LY_EVALID);
191     assert_int_equal(ly_vecode(st->ctx), LYVE_NOWHEN);
192 }
193 
194 static void
test_dependency_circular(void ** state)195 test_dependency_circular(void **state)
196 {
197     struct state *st = (struct state *)*state;
198     struct lyd_node *node;
199 
200     /* schema */
201     st->mod = lys_parse_path(st->ctx, TESTS_DIR"/data/files/when-circdepend.yin", LYS_IN_YIN);
202     assert_ptr_not_equal(st->mod, NULL);
203 
204     st->dt = lyd_new_path(NULL, st->ctx, "/when-circdepend:top/a", "val_a", 0, 0);
205     assert_ptr_not_equal(st->dt, NULL);
206     node = lyd_new_path(st->dt, st->ctx, "/when-circdepend:top/b", "val_b", 0, 0);
207     assert_ptr_not_equal(node, NULL);
208     node = lyd_new_path(st->dt, st->ctx, "/when-circdepend:top/d", "1", 0, 0);
209     assert_ptr_not_equal(node, NULL);
210     node = lyd_new_path(st->dt, st->ctx, "/when-circdepend:top/d", "2", 0, 0);
211     assert_ptr_not_equal(node, NULL);
212     node = lyd_new_path(st->dt, st->ctx, "/when-circdepend:top/e", "val_e", 0, 0);
213     assert_ptr_not_equal(node, NULL);
214 
215     assert_int_equal(lyd_validate(&(st->dt), LYD_OPT_CONFIG, NULL), 1);
216     assert_int_equal(ly_errno, LY_EVALID);
217     assert_int_equal(ly_vecode(st->ctx), LYVE_INWHEN);
218 }
219 
220 static void
test_unlink_all(void ** state)221 test_unlink_all(void **state)
222 {
223     struct state *st = (struct state *)*state;
224 
225     /* schema */
226     st->mod = lys_parse_path(st->ctx, TESTS_DIR"/data/files/when-unlinkall.yin", LYS_IN_YIN);
227     assert_ptr_not_equal(st->mod, NULL);
228 
229     st->dt = lyd_new_path(NULL, st->ctx, "/when-unlinkall:a", "val_a", 0, 0);
230     assert_ptr_not_equal(st->dt, NULL);
231 
232     assert_int_equal(lyd_validate(&(st->dt), LYD_OPT_CONFIG, NULL), 0);
233 
234     lyd_print_mem(&(st->xml), st->dt, LYD_XML, LYP_WITHSIBLINGS);
235     assert_string_equal(st->xml, "<a xmlns=\"urn:libyang:tests:when-unlinkall\">val_a</a>");
236 }
237 
main(void)238 int main(void)
239 {
240     const struct CMUnitTest tests[] = {
241                     cmocka_unit_test_setup_teardown(test_unlink_uses, setup_f, teardown_f),
242                     cmocka_unit_test_setup_teardown(test_unlink_choice, setup_f, teardown_f),
243                     cmocka_unit_test_setup_teardown(test_unlink_case, setup_f, teardown_f),
244                     cmocka_unit_test_setup_teardown(test_unlink_augment, setup_f, teardown_f),
245                     cmocka_unit_test_setup_teardown(test_dummy, setup_f, teardown_f),
246                     cmocka_unit_test_setup_teardown(test_dependency_noautodel, setup_f, teardown_f),
247                     cmocka_unit_test_setup_teardown(test_dependency_circular, setup_f, teardown_f),
248                     cmocka_unit_test_setup_teardown(test_unlink_all, setup_f, teardown_f)
249     };
250 
251     return cmocka_run_group_tests(tests, NULL, NULL);
252 }
253