blob: 00e8677b348f2e5c5ac4d2eaf763d0a56d9a3a5e [file] [log] [blame]
Michal Vaskoedb0fa52022-10-04 10:36:00 +02001/**
2 * @file test_structure.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief unit tests for structure extensions support
5 *
6 * Copyright (c) 2022 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 void
20test_schema(void **state)
21{
22 struct lys_module *mod;
23 struct lysc_ext_instance *e;
24 char *printed = NULL;
Michal Vasko0b50f6b2022-10-05 15:07:55 +020025 const char *data, *info;
26
27 /* valid data */
28 data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix a;"
Michal Vaskoedb0fa52022-10-04 10:36:00 +020029 "import ietf-yang-structure-ext {prefix sx;}"
30 "sx:structure struct {"
31 " must \"/n2/l\";"
32 " status deprecated;"
33 " description desc;"
34 " reference no-ref;"
35 " typedef my-type {type string;}"
36 " grouping my-grp {leaf gl {type my-type;}}"
Michal Vaskoedb0fa52022-10-04 10:36:00 +020037 " container n1 {leaf l {config false; type uint32;}}"
38 " list n2 {leaf l {type leafref {path /n1/l;}}}"
39 " uses my-grp;"
Michal Vaskoedb0fa52022-10-04 10:36:00 +020040 "}}";
Michal Vasko0b50f6b2022-10-05 15:07:55 +020041
Michal Vasko193dacd2022-10-13 08:43:05 +020042 UTEST_ADD_MODULE(data, LYS_IN_YANG, NULL, &mod);
Michal Vasko0b50f6b2022-10-05 15:07:55 +020043 assert_non_null(e = mod->compiled->exts);
44 assert_int_equal(LY_ARRAY_COUNT(mod->compiled->exts), 1);
45
46 /* valid augment data */
47 data = "module b {yang-version 1.1; namespace urn:tests:extensions:structure:b; prefix b;"
48 "import ietf-yang-structure-ext {prefix sx;}"
49 "import a {prefix a;}"
50 "sx:augment-structure \"/a:struct/a:n1\" {"
51 " status obsolete;"
52 " reference none;"
53 " leaf aug-leaf {type string;}"
54 "}}";
55
Michal Vasko193dacd2022-10-13 08:43:05 +020056 UTEST_ADD_MODULE(data, LYS_IN_YANG, NULL, &mod);
Michal Vasko0b50f6b2022-10-05 15:07:55 +020057 assert_non_null(e = mod->compiled->exts);
58 assert_int_equal(LY_ARRAY_COUNT(mod->compiled->exts), 1);
59
60 /* yang compiled print */
61 info = "module a {\n"
Michal Vaskoedb0fa52022-10-04 10:36:00 +020062 " namespace \"urn:tests:extensions:structure:a\";\n"
Michal Vasko0b50f6b2022-10-05 15:07:55 +020063 " prefix a;\n"
Michal Vaskoedb0fa52022-10-04 10:36:00 +020064 "\n"
65 " ietf-yang-structure-ext:structure \"struct\" {\n"
66 " must \"/n2/l\";\n"
67 " status deprecated;\n"
68 " description\n"
69 " \"desc\";\n"
70 " reference\n"
71 " \"no-ref\";\n"
72 " container n1 {\n"
73 " status deprecated;\n"
74 " leaf l {\n"
75 " type uint32;\n"
76 " status deprecated;\n"
77 " }\n"
78 " }\n"
79 " list n2 {\n"
80 " min-elements 0;\n"
81 " max-elements 4294967295;\n"
82 " ordered-by user;\n"
83 " status deprecated;\n"
84 " leaf l {\n"
85 " type leafref {\n"
86 " path \"/n1/l\";\n"
87 " require-instance true;\n"
88 " type uint32;\n"
89 " }\n"
90 " status deprecated;\n"
91 " }\n"
Michal Vasko0b50f6b2022-10-05 15:07:55 +020092 " leaf aug-leaf {\n"
93 " type string;\n"
94 " status obsolete;\n"
95 " }\n"
Michal Vaskoedb0fa52022-10-04 10:36:00 +020096 " }\n"
97 " leaf gl {\n"
98 " type string;\n"
99 " status deprecated;\n"
100 " }\n"
Michal Vaskoedb0fa52022-10-04 10:36:00 +0200101 " }\n"
102 "}\n";
103
Michal Vasko0b50f6b2022-10-05 15:07:55 +0200104 assert_non_null(mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "a"));
105 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0));
106 assert_string_equal(printed, info);
107 free(printed);
108
109 info = "module b {\n"
110 " namespace \"urn:tests:extensions:structure:b\";\n"
111 " prefix b;\n"
112 "\n"
113 " ietf-yang-structure-ext:augment-structure \"/a:struct/a:n1\" {\n"
114 " status obsolete;\n"
115 " reference\n"
116 " \"none\";\n"
117 " }\n"
118 "}\n";
119
120 assert_non_null(mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "b"));
Michal Vaskoedb0fa52022-10-04 10:36:00 +0200121 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0));
122 assert_string_equal(printed, info);
123 free(printed);
124
125 /* no substatements */
Michal Vasko0b50f6b2022-10-05 15:07:55 +0200126 data = "module c {yang-version 1.1; namespace urn:tests:extensions:structure:c; prefix c;"
Michal Vaskoedb0fa52022-10-04 10:36:00 +0200127 "import ietf-yang-structure-ext {prefix sx;}"
128 "sx:structure struct;}";
Michal Vasko0b50f6b2022-10-05 15:07:55 +0200129 info = "module c {\n"
130 " namespace \"urn:tests:extensions:structure:c\";\n"
131 " prefix c;\n"
Michal Vaskoedb0fa52022-10-04 10:36:00 +0200132 "\n"
133 " ietf-yang-structure-ext:structure \"struct\";\n"
134 "}\n";
Michal Vasko193dacd2022-10-13 08:43:05 +0200135
136 UTEST_ADD_MODULE(data, LYS_IN_YANG, NULL, &mod);
Michal Vaskoedb0fa52022-10-04 10:36:00 +0200137 assert_non_null(e = mod->compiled->exts);
138 assert_int_equal(LY_ARRAY_COUNT(mod->compiled->exts), 1);
139 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0));
140 assert_string_equal(printed, info);
141 free(printed);
142}
143
144static void
145test_schema_invalid(void **state)
146{
147 const char *data;
148
149 data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix self;"
150 "import ietf-yang-structure-ext {prefix sx;}"
151 "sx:structure struct {import yang;}}";
Michal Vasko193dacd2022-10-13 08:43:05 +0200152 UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID);
Michal Vaskoedb0fa52022-10-04 10:36:00 +0200153 CHECK_LOG_CTX("Invalid keyword \"import\" as a child of \"sx:structure struct\" extension instance.",
154 "/a:{extension='sx:structure'}/struct");
155
156 data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix self;"
157 "import ietf-yang-structure-ext {prefix sx;}"
158 "container b { sx:structure struct { container x { leaf x {type string;}}}}}";
Michal Vasko193dacd2022-10-13 08:43:05 +0200159 UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID);
160 CHECK_LOG_CTX("Ext plugin \"ly2 structure v1\": "
Michal Vaskoedb0fa52022-10-04 10:36:00 +0200161 "Extension sx:structure must not be used as a non top-level statement in \"container\" statement.",
162 "/a:b/{extension='sx:structure'}/struct");
163
164 data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix self;"
165 "import ietf-yang-structure-ext {prefix sx;}"
166 "sx:structure { container x { leaf x {type string;}}}}";
Michal Vasko193dacd2022-10-13 08:43:05 +0200167 UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID);
168 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
169 "Extension instance \"sx:structure\" missing argument element \"name\".", NULL);
Michal Vaskoedb0fa52022-10-04 10:36:00 +0200170
171 data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix self;"
172 "import ietf-yang-structure-ext {prefix sx;}"
173 "sx:structure struct { container x { leaf x {type string;}}}"
174 "sx:structure struct { container y { leaf y {type string;}}}}";
Michal Vasko193dacd2022-10-13 08:43:05 +0200175 UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID);
176 CHECK_LOG_CTX("Ext plugin \"ly2 structure v1\": Extension sx:structure is instantiated multiple times.",
Michal Vaskoedb0fa52022-10-04 10:36:00 +0200177 "/a:{extension='sx:structure'}/struct");
178
179 data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix self;"
180 "import ietf-yang-structure-ext {prefix sx;}"
181 "sx:structure struct { container x { leaf x {type string;}}}"
182 "choice struct { container y { leaf y {type string;}}}}";
Michal Vasko193dacd2022-10-13 08:43:05 +0200183 UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID);
184 CHECK_LOG_CTX("Ext plugin \"ly2 structure v1\": Extension sx:structure collides with a choice with the same identifier.",
Michal Vaskoedb0fa52022-10-04 10:36:00 +0200185 "/a:{extension='sx:structure'}/struct");
186}
187
188static void
189test_parse(void **state)
190{
191 struct lys_module *mod;
192 struct lysc_ext_instance *e;
193 struct lyd_node *tree = NULL;
194 const char *schema = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix self;"
195 "import ietf-yang-structure-ext {prefix sx;}"
196 "sx:structure struct { container x { leaf x { type string;}}}}";
197 const char *xml = "<x xmlns=\"urn:tests:extensions:structure:a\"><x>test</x></x>";
198 const char *json = "{\"a:x\":{\"x\":\"test\"}}";
199
Michal Vasko193dacd2022-10-13 08:43:05 +0200200 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
Michal Vaskoedb0fa52022-10-04 10:36:00 +0200201 assert_non_null(e = mod->compiled->exts);
202
203 assert_int_equal(LY_SUCCESS, ly_in_new_memory(xml, &UTEST_IN));
204 assert_int_equal(LY_SUCCESS, lyd_parse_ext_data(e, NULL, UTEST_IN, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
205 CHECK_LYD_STRING_PARAM(tree, xml, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS);
206 lyd_free_all(tree);
207
208 ly_in_memory(UTEST_IN, json);
209 assert_int_equal(LY_SUCCESS, lyd_parse_ext_data(e, NULL, UTEST_IN, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
210 CHECK_LYD_STRING_PARAM(tree, json, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS);
211
212 lyd_free_all(tree);
213}
214
215int
216main(void)
217{
218 const struct CMUnitTest tests[] = {
219 UTEST(test_schema),
220 UTEST(test_schema_invalid),
221 UTEST(test_parse),
222 };
223
224 return cmocka_run_group_tests(tests, NULL, NULL);
225}