blob: 357dcabdf5ee98c142e0321386ea15a2922cf99e [file] [log] [blame]
Radek Krejci038db942021-02-09 16:18:47 +01001/*
2 * @file test_yangdata.c
3 * @author: Radek Krejci <rkrejci@cesnet.cz>
4 * @brief unit tests for yang-data extensions support
5 *
6 * Copyright (c) 2019-2021 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#define _UTEST_MAIN_
15#include "utests.h"
16
17#include "libyang.h"
18
19static int
20setup(void **state)
21{
22 UTEST_SETUP;
23
24 assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG));
25 assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "ietf-restconf", "2017-01-26", NULL));
26
27 return 0;
28}
29
30static void
31test_schema(void **state)
32{
33 const struct lys_module *mod;
34 struct lysc_ext_instance *e;
35 char *printed = NULL;
36 const char *data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
37 "import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
38 "feature x;"
39 "rc:yang-data template { container x { list l { leaf x { type string;}} leaf y {if-feature x; type string; config false;}}}}";
40 const char *info = "module a {\n"
41 " namespace \"urn:tests:extensions:yangdata:a\";\n"
42 " prefix self;\n\n"
43 " ietf-restconf:yang-data \"template\" {\n"
44 " container x {\n"
45 " status current;\n"
46 " list l {\n" /* no key */
47 " min-elements 0;\n"
48 " max-elements 4294967295;\n"
49 " ordered-by system;\n"
50 " status current;\n"
51 " leaf x {\n"
52 " type string;\n"
53 " status current;\n"
54 " }\n"
55 " }\n"
56 " leaf y {\n" /* config and if-feature are ignored */
57 " type string;\n"
58 " status current;\n"
59 " }\n"
60 " }\n"
61 " }\n"
62 "}\n";
63
64 /* valid data */
65 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, &mod));
66 assert_non_null(e = mod->compiled->exts);
67 assert_int_equal(LY_ARRAY_COUNT(mod->compiled->exts), 1);
68 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0));
69 assert_string_equal(printed, info);
70 free(printed);
71
72 data = "module c {yang-version 1.1; namespace urn:tests:extensions:yangdata:c; prefix self;"
73 "import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
74 "grouping g { choice ch { container a {presence a; config false;} container b {presence b; config true;}}}"
75 "rc:yang-data template { uses g;}}";
76 info = "module c {\n"
77 " namespace \"urn:tests:extensions:yangdata:c\";\n"
78 " prefix self;\n\n"
79 " ietf-restconf:yang-data \"template\" {\n"
80 " choice ch {\n"
81 " status current;\n"
82 " case a {\n"
83 " status current;\n"
84 " container a {\n"
85 " presence \"true\";\n"
86 " status current;\n"
87 " }\n"
88 " }\n"
89 " case b {\n"
90 " status current;\n"
91 " container b {\n"
92 " presence \"true\";\n"
93 " status current;\n"
94 " }\n"
95 " }\n"
96 " }\n"
97 " }\n"
98 "}\n";
99 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, &mod));
100 assert_non_null(e = mod->compiled->exts);
101 assert_int_equal(LY_ARRAY_COUNT(mod->compiled->exts), 1);
102 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0));
103 assert_string_equal(printed, info);
104 free(printed);
105
106 /* ignored - valid with warning */
107 data = "module b {yang-version 1.1; namespace urn:tests:extensions:yangdata:b; prefix self;"
108 "import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
109 "container b { rc:yang-data template { container x { leaf x {type string;}}}}}";
110 info = "module b {\n"
111 " namespace \"urn:tests:extensions:yangdata:b\";\n"
112 " prefix self;\n"
113 " container b {\n"
114 " config true;\n"
115 " status current;\n"
116 " }\n"
117 "}\n";
118 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, &mod));
119 assert_null(mod->compiled->exts);
120 CHECK_LOG_CTX("Extension plugin \"libyang 2 - yang-data, version 1\": "
121 "Extension rc:yang-data is ignored since it appears as a non top-level statement in \"data node\" statement.",
122 "/b:b/{extension='rc:yang-data'}/template");
123 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0));
124 assert_string_equal(printed, info);
125 free(printed);
126
127 /* sama data nodes name, but not conflicting */
128 data = "module d {yang-version 1.1; namespace urn:tests:extensions:yangdata:d; prefix self;"
129 "import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
130 "leaf d { type string;}"
131 "rc:yang-data template1 { container d {presence d;}}"
132 "rc:yang-data template2 { container d {presence d;}}}";
133 info = "module d {\n"
134 " namespace \"urn:tests:extensions:yangdata:d\";\n"
135 " prefix self;\n\n"
136 " ietf-restconf:yang-data \"template1\" {\n"
137 " container d {\n"
138 " presence \"true\";\n"
139 " status current;\n"
140 " }\n"
141 " }\n"
142 " ietf-restconf:yang-data \"template2\" {\n"
143 " container d {\n"
144 " presence \"true\";\n"
145 " status current;\n"
146 " }\n"
147 " }\n"
148 " leaf d {\n"
149 " type string;\n"
150 " config true;\n"
151 " status current;\n"
152 " }\n"
153 "}\n";
154 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, &mod));
155 assert_non_null(e = mod->compiled->exts);
156 assert_int_equal(LY_ARRAY_COUNT(mod->compiled->exts), 2);
157 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0));
158 assert_string_equal(printed, info);
159 free(printed);
160}
161
162static void
163test_schema_invalid(void **state)
164{
165 const char *data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
166 "import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
167 "rc:yang-data template { leaf x {type string;}}}";
168
169 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
170 CHECK_LOG_CTX("Invalid keyword \"leaf\" as a child of \"rc:yang-data template\" extension instance.",
171 "/a:{extension='rc:yang-data'}/template");
172
173 data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
174 "import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
175 "rc:yang-data template { choice x { leaf x {type string;}}}}";
176 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
177 CHECK_LOG_CTX("Extension plugin \"libyang 2 - yang-data, version 1\": "
178 "Extension rc:yang-data is instantiated with leaf top level data node (inside a choice), "
179 "but only a single container data node is allowed.",
180 "/a:{extension='rc:yang-data'}/template");
181
182 data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
183 "import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
184 "rc:yang-data template { choice x { case x { container z {presence ppp;} leaf x {type string;}}}}}";
185 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
186 CHECK_LOG_CTX("Extension plugin \"libyang 2 - yang-data, version 1\": "
187 "Extension rc:yang-data is instantiated with multiple top level data nodes (inside a single choice's case), "
188 "but only a single container data node is allowed.",
189 "/a:{extension='rc:yang-data'}/template");
190
191 data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
192 "import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
193 "rc:yang-data template { container x { leaf x {type string;}} container y { leaf y {type string;}}}}";
194 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
195 CHECK_LOG_CTX("Extension plugin \"libyang 2 - yang-data, version 1\": "
196 "Extension rc:yang-data is instantiated with multiple top level data nodes, "
197 "but only a single container data node is allowed.",
198 "/a:{extension='rc:yang-data'}/template");
199
200 data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
201 "import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
202 "rc:yang-data template;}";
203 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
204 CHECK_LOG_CTX("Extension plugin \"libyang 2 - yang-data, version 1\": "
205 "Extension rc:yang-data is instantiated without any top level data node, "
206 "but exactly one container data node is expected.",
207 "/a:{extension='rc:yang-data'}/template");
208
209 data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
210 "import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
211 "rc:yang-data { container x { leaf x {type string;}}}}";
212 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
213 CHECK_LOG_CTX("Extension plugin \"libyang 2 - yang-data, version 1\": "
214 "Extension rc:yang-data is instantiated without mandatory argument representing YANG data template name.",
215 "/a:{extension='rc:yang-data'}");
216
217 data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
218 "import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
219 "rc:yang-data template { container x { leaf x {type string;}}}"
220 "rc:yang-data template { container y { leaf y {type string;}}}}";
221 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
222 CHECK_LOG_CTX("Extension plugin \"libyang 2 - yang-data, version 1\": "
223 "Extension rc:yang-data is instantiated multiple times.",
224 "/a:{extension='rc:yang-data'}/template");
225
226 data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
227 "import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
228 "grouping t { leaf-list x {type string;}}"
229 "rc:yang-data template { uses t;}}";
230 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
231 CHECK_LOG_CTX("Extension plugin \"libyang 2 - yang-data, version 1\": "
232 "Extension rc:yang-data is instantiated with leaf-list top level data node, "
233 "but only a single container data node is allowed.",
234 "/a:{extension='rc:yang-data'}/template");
235}
236
237int
238main(void)
239{
240 const struct CMUnitTest tests[] = {
241 UTEST(test_schema, setup),
242 UTEST(test_schema_invalid, setup),
243 };
244
245 return cmocka_run_group_tests(tests, NULL, NULL);
246}