blob: df90385d51c8ad563aa8050af8185b0c775d6b38 [file] [log] [blame]
David Sedlákb1ce3f82019-06-05 14:37:26 +02001/**
2 * @file test_parser_yin.c
3 * @author David Sedlák <xsedla1d@stud.fit.vutbr.cz>
4 * @brief unit tests for functions from parser_yin.c
5 *
6 * Copyright (c) 2015 - 2019 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
David Sedlák3b4db242018-10-19 16:11:01 +020015#include <stdarg.h>
16#include <stddef.h>
17#include <setjmp.h>
18#include <cmocka.h>
19
20#include <stdio.h>
21#include <string.h>
David Sedlák79e50cb2019-06-05 16:33:09 +020022#include <stdbool.h>
David Sedlák3b4db242018-10-19 16:11:01 +020023
David Sedlákecf5eb82019-06-03 14:12:44 +020024#include "../../src/common.h"
25#include "../../src/tree_schema.h"
26#include "../../src/tree_schema_internal.h"
27#include "../../src/parser_yin.h"
David Sedlák8f5bce02019-06-03 16:41:08 +020028#include "../../src/xml.h"
David Sedlák3b4db242018-10-19 16:11:01 +020029
David Sedlák555c7202019-07-04 12:14:12 +020030/* prototypes of static functions */
31void lysp_ext_instance_free(struct ly_ctx *ctx, struct lysp_ext_instance *ext);
David Sedlák986cb412019-07-04 13:10:11 +020032void lysp_ext_free(struct ly_ctx *ctx, struct lysp_ext *ext);
David Sedlák32eee7b2019-07-09 12:38:44 +020033void lysp_when_free(struct ly_ctx *ctx, struct lysp_when *when);
David Sedlák555c7202019-07-04 12:14:12 +020034
David Sedlák68a1af12019-03-08 13:46:54 +010035struct state {
David Sedlák3b4db242018-10-19 16:11:01 +020036 struct ly_ctx *ctx;
David Sedlák3017da42019-02-15 09:48:04 +010037 struct lys_module *mod;
David Sedlák619db942019-07-03 14:47:30 +020038 struct lysp_module *lysp_mod;
David Sedlákda8ffa32019-07-08 14:17:10 +020039 struct yin_parser_ctx *yin_ctx;
David Sedlák79e50cb2019-06-05 16:33:09 +020040 bool finished_correctly;
David Sedlák68a1af12019-03-08 13:46:54 +010041};
David Sedlák872c7b42018-10-26 13:15:20 +020042
David Sedlák79e50cb2019-06-05 16:33:09 +020043#define BUFSIZE 1024
44char logbuf[BUFSIZE] = {0};
45int store = -1; /* negative for infinite logging, positive for limited logging */
46
47/* set to 0 to printing error messages to stderr instead of checking them in code */
48#define ENABLE_LOGGER_CHECKING 1
49
50#if ENABLE_LOGGER_CHECKING
51static void
52logger(LY_LOG_LEVEL level, const char *msg, const char *path)
53{
54 (void) level; /* unused */
55 if (store) {
56 if (path && path[0]) {
57 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
58 } else {
59 strncpy(logbuf, msg, BUFSIZE - 1);
60 }
61 if (store > 0) {
62 --store;
63 }
64 }
65}
66#endif
67
68#if ENABLE_LOGGER_CHECKING
69# define logbuf_assert(str) assert_string_equal(logbuf, str)
70#else
71# define logbuf_assert(str)
72#endif
73
74#define TEST_DUP_GENERIC(PREFIX, MEMBER, VALUE1, VALUE2, FUNC, RESULT, LINE, CLEANUP) \
75 str = PREFIX MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
76 assert_int_equal(LY_EVALID, FUNC(&ctx, &str, RESULT)); \
77 logbuf_assert("Duplicate keyword \""MEMBER"\". Line number "LINE"."); \
78 CLEANUP
79
80
David Sedlák68a1af12019-03-08 13:46:54 +010081static int
82setup_f(void **state)
83{
84 struct state *st = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +020085
David Sedlák79e50cb2019-06-05 16:33:09 +020086#if ENABLE_LOGGER_CHECKING
87 /* setup logger */
88 ly_set_log_clb(logger, 1);
89#endif
90
David Sedlák68a1af12019-03-08 13:46:54 +010091 /* allocate state variable */
92 (*state) = st = calloc(1, sizeof(*st));
93 if (!st) {
94 fprintf(stderr, "Memmory allocation failed");
95 return EXIT_FAILURE;
96 }
David Sedlák872c7b42018-10-26 13:15:20 +020097
David Sedlák68a1af12019-03-08 13:46:54 +010098 /* create new libyang context */
99 ly_ctx_new(NULL, 0, &st->ctx);
David Sedlák872c7b42018-10-26 13:15:20 +0200100
David Sedlák68a1af12019-03-08 13:46:54 +0100101 /* allocate new module */
102 st->mod = calloc(1, sizeof(*st->mod));
103 st->mod->ctx = st->ctx;
104
David Sedlák619db942019-07-03 14:47:30 +0200105 /* allocate new parsed module */
106 st->lysp_mod = calloc(1, sizeof(*st->lysp_mod));
107 st->lysp_mod->mod = calloc(1, sizeof(*st->lysp_mod->mod));
108 st->lysp_mod->mod->ctx = st->ctx;
109
110 /* allocate parser context */
David Sedlákda8ffa32019-07-08 14:17:10 +0200111 st->yin_ctx = calloc(1, sizeof(*st->yin_ctx));
112 st->yin_ctx->xml_ctx.ctx = st->ctx;
113 st->yin_ctx->xml_ctx.line = 1;
David Sedlák8f5bce02019-06-03 16:41:08 +0200114
David Sedlák68a1af12019-03-08 13:46:54 +0100115 return EXIT_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +0200116}
117
118static int
David Sedlák68a1af12019-03-08 13:46:54 +0100119teardown_f(void **state)
120{
121 struct state *st = *(struct state **)state;
David Sedlák619db942019-07-03 14:47:30 +0200122 struct lys_module *temp;
David Sedlák68a1af12019-03-08 13:46:54 +0100123
David Sedlák79e50cb2019-06-05 16:33:09 +0200124#if ENABLE_LOGGER_CHECKING
125 /* teardown logger */
126 if (!st->finished_correctly && logbuf[0] != '\0') {
127 fprintf(stderr, "%s\n", logbuf);
128 }
129#endif
130
David Sedlák619db942019-07-03 14:47:30 +0200131 temp = st->lysp_mod->mod;
132
David Sedlákda8ffa32019-07-08 14:17:10 +0200133 lyxml_context_clear(&st->yin_ctx->xml_ctx);
David Sedlák68a1af12019-03-08 13:46:54 +0100134 lys_module_free(st->mod, NULL);
David Sedlák619db942019-07-03 14:47:30 +0200135 lysp_module_free(st->lysp_mod);
136 lys_module_free(temp, NULL);
David Sedlák68a1af12019-03-08 13:46:54 +0100137 ly_ctx_destroy(st->ctx, NULL);
David Sedlákda8ffa32019-07-08 14:17:10 +0200138 free(st->yin_ctx);
David Sedlák68a1af12019-03-08 13:46:54 +0100139 free(st);
140
141 return EXIT_SUCCESS;
142}
143
David Sedlák392af4f2019-06-04 16:02:42 +0200144static struct state*
145reset_state(void **state)
146{
David Sedlák79e50cb2019-06-05 16:33:09 +0200147 ((struct state *)*state)->finished_correctly = true;
David Sedlák555c7202019-07-04 12:14:12 +0200148 logbuf[0] = '\0';
David Sedlák392af4f2019-06-04 16:02:42 +0200149 teardown_f(state);
150 setup_f(state);
151
152 return *state;
153}
154
David Sedlák79e50cb2019-06-05 16:33:09 +0200155void
156logbuf_clean(void)
157{
158 logbuf[0] = '\0';
159}
160
David Sedlák68a1af12019-03-08 13:46:54 +0100161static void
David Sedlák392af4f2019-06-04 16:02:42 +0200162test_yin_parse_module(void **state)
David Sedlák68a1af12019-03-08 13:46:54 +0100163{
164 LY_ERR ret = LY_SUCCESS;
165 struct state *st = *state;
166
167 ret = yin_parse_module(st->ctx,
David Sedlák2b214ac2019-06-06 16:11:03 +0200168 "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\
169 name=\"example-foo\"\
David Sedlák18730132019-03-15 15:51:34 +0100170 xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\
171 xmlns:foo=\"urn:example:foo\"\
172 xmlns:myext=\"urn:example:extensions\">\
David Sedlákcd0c9512019-03-29 13:23:06 +0100173 <namespace uri=\"urn:example:foo\" xmlns:myext=\"urn:example:extensions\"/>\
David Sedláka7406952019-04-05 10:33:07 +0200174 <prefix xmlns:myxt=\"urn:emple:extensions\" value=\"foo\" xmlns:myext=\"urn:example:extensions\"/>\
David Sedlákd9d3a312019-06-04 09:47:10 +0200175 </module>",
David Sedlák68a1af12019-03-08 13:46:54 +0100176 st->mod);
177
178 assert_int_equal(ret, LY_SUCCESS);
179 assert_string_equal(st->mod->parsed->mod->name, "example-foo");
180 assert_string_equal(st->mod->parsed->mod->prefix, "foo");
David Sedlákcd0c9512019-03-29 13:23:06 +0100181 assert_string_equal(st->mod->parsed->mod->ns, "urn:example:foo");
David Sedlák392af4f2019-06-04 16:02:42 +0200182
183 st = reset_state(state);
184 ret = yin_parse_module(st->ctx,
David Sedlák2b214ac2019-06-06 16:11:03 +0200185 "<module name=\"example-foo\">\
186 <invalid-tag uri=\"urn:example:foo\"\"/>\
187 </module>",
188 st->mod);
David Sedlák392af4f2019-06-04 16:02:42 +0200189 assert_int_equal(ret, LY_EVALID);
190
191 st = reset_state(state);
192 ret = yin_parse_module(st->ctx,
David Sedlák8f7a1172019-06-20 14:42:18 +0200193 "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">\
David Sedlák57715b12019-06-17 13:05:22 +0200194 </module>",
David Sedlák2b214ac2019-06-06 16:11:03 +0200195 st->mod);
David Sedlák392af4f2019-06-04 16:02:42 +0200196 assert_int_equal(ret, LY_EVALID);
David Sedlák882a8072019-07-08 17:51:20 +0200197 logbuf_assert("Missing mandatory attribute name of module element. Line number 1.");
David Sedlák392af4f2019-06-04 16:02:42 +0200198
199 st = reset_state(state);
200 ret = yin_parse_module(st->ctx,
201 "",
202 st->mod);
203 assert_int_equal(ret, LY_EVALID);
David Sedlák79e50cb2019-06-05 16:33:09 +0200204 logbuf_assert("Invalid keyword \"(null)\", expected \"module\" or \"submodule\". Line number 1.");
205 st->finished_correctly = true;
David Sedlák3b4db242018-10-19 16:11:01 +0200206}
207
208static void
David Sedlák1bccdfa2019-06-17 15:55:27 +0200209test_yin_match_keyword(void **state)
David Sedlák3b4db242018-10-19 16:11:01 +0200210{
David Sedlák8f7a1172019-06-20 14:42:18 +0200211 struct state *st = *state;
David Sedlák3b4db242018-10-19 16:11:01 +0200212
David Sedlák8f7a1172019-06-20 14:42:18 +0200213 const char *prefix, *name;
214 struct yin_arg_record *args = NULL;
215 size_t prefix_len, name_len;
216 /* create mock yin namespace in xml context */
217 const char *data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" />";
David Sedlákda8ffa32019-07-08 14:17:10 +0200218 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
219 yin_load_attributes(st->yin_ctx, &data, &args);
David Sedlák8f7a1172019-06-20 14:42:18 +0200220 LY_ARRAY_FREE(args);
221
David Sedlákda8ffa32019-07-08 14:17:10 +0200222 assert_int_equal(yin_match_keyword(st->yin_ctx, "anydatax", strlen("anydatax"), prefix, prefix_len), YANG_NONE);
223 assert_int_equal(yin_match_keyword(st->yin_ctx, "asdasd", strlen("asdasd"), prefix, prefix_len), YANG_NONE);
224 assert_int_equal(yin_match_keyword(st->yin_ctx, "", 0, prefix, prefix_len), YANG_NONE);
225 assert_int_equal(yin_match_keyword(st->yin_ctx, "anydata", strlen("anydata"), prefix, prefix_len), YANG_ANYDATA);
226 assert_int_equal(yin_match_keyword(st->yin_ctx, "anyxml", strlen("anyxml"), prefix, prefix_len), YANG_ANYXML);
227 assert_int_equal(yin_match_keyword(st->yin_ctx, "argument", strlen("argument"), prefix, prefix_len), YANG_ARGUMENT);
228 assert_int_equal(yin_match_keyword(st->yin_ctx, "augment", strlen("augment"), prefix, prefix_len), YANG_AUGMENT);
229 assert_int_equal(yin_match_keyword(st->yin_ctx, "base", strlen("base"), prefix, prefix_len), YANG_BASE);
230 assert_int_equal(yin_match_keyword(st->yin_ctx, "belongs-to", strlen("belongs-to"), prefix, prefix_len), YANG_BELONGS_TO);
231 assert_int_equal(yin_match_keyword(st->yin_ctx, "bit", strlen("bit"), prefix, prefix_len), YANG_BIT);
232 assert_int_equal(yin_match_keyword(st->yin_ctx, "case", strlen("case"), prefix, prefix_len), YANG_CASE);
233 assert_int_equal(yin_match_keyword(st->yin_ctx, "choice", strlen("choice"), prefix, prefix_len), YANG_CHOICE);
234 assert_int_equal(yin_match_keyword(st->yin_ctx, "config", strlen("config"), prefix, prefix_len), YANG_CONFIG);
235 assert_int_equal(yin_match_keyword(st->yin_ctx, "contact", strlen("contact"), prefix, prefix_len), YANG_CONTACT);
236 assert_int_equal(yin_match_keyword(st->yin_ctx, "container", strlen("container"), prefix, prefix_len), YANG_CONTAINER);
237 assert_int_equal(yin_match_keyword(st->yin_ctx, "default", strlen("default"), prefix, prefix_len), YANG_DEFAULT);
238 assert_int_equal(yin_match_keyword(st->yin_ctx, "description", strlen("description"), prefix, prefix_len), YANG_DESCRIPTION);
239 assert_int_equal(yin_match_keyword(st->yin_ctx, "deviate", strlen("deviate"), prefix, prefix_len), YANG_DEVIATE);
240 assert_int_equal(yin_match_keyword(st->yin_ctx, "deviation", strlen("deviation"), prefix, prefix_len), YANG_DEVIATION);
241 assert_int_equal(yin_match_keyword(st->yin_ctx, "enum", strlen("enum"), prefix, prefix_len), YANG_ENUM);
242 assert_int_equal(yin_match_keyword(st->yin_ctx, "error-app-tag", strlen("error-app-tag"), prefix, prefix_len), YANG_ERROR_APP_TAG);
243 assert_int_equal(yin_match_keyword(st->yin_ctx, "error-message", strlen("error-message"), prefix, prefix_len), YANG_ERROR_MESSAGE);
244 assert_int_equal(yin_match_keyword(st->yin_ctx, "extension", strlen("extension"), prefix, prefix_len), YANG_EXTENSION);
245 assert_int_equal(yin_match_keyword(st->yin_ctx, "feature", strlen("feature"), prefix, prefix_len), YANG_FEATURE);
246 assert_int_equal(yin_match_keyword(st->yin_ctx, "fraction-digits", strlen("fraction-digits"), prefix, prefix_len), YANG_FRACTION_DIGITS);
247 assert_int_equal(yin_match_keyword(st->yin_ctx, "grouping", strlen("grouping"), prefix, prefix_len), YANG_GROUPING);
248 assert_int_equal(yin_match_keyword(st->yin_ctx, "identity", strlen("identity"), prefix, prefix_len), YANG_IDENTITY);
249 assert_int_equal(yin_match_keyword(st->yin_ctx, "if-feature", strlen("if-feature"), prefix, prefix_len), YANG_IF_FEATURE);
250 assert_int_equal(yin_match_keyword(st->yin_ctx, "import", strlen("import"), prefix, prefix_len), YANG_IMPORT);
251 assert_int_equal(yin_match_keyword(st->yin_ctx, "include", strlen("include"), prefix, prefix_len), YANG_INCLUDE);
252 assert_int_equal(yin_match_keyword(st->yin_ctx, "input", strlen("input"), prefix, prefix_len), YANG_INPUT);
253 assert_int_equal(yin_match_keyword(st->yin_ctx, "key", strlen("key"), prefix, prefix_len), YANG_KEY);
254 assert_int_equal(yin_match_keyword(st->yin_ctx, "leaf", strlen("leaf"), prefix, prefix_len), YANG_LEAF);
255 assert_int_equal(yin_match_keyword(st->yin_ctx, "leaf-list", strlen("leaf-list"), prefix, prefix_len), YANG_LEAF_LIST);
256 assert_int_equal(yin_match_keyword(st->yin_ctx, "length", strlen("length"), prefix, prefix_len), YANG_LENGTH);
257 assert_int_equal(yin_match_keyword(st->yin_ctx, "list", strlen("list"), prefix, prefix_len), YANG_LIST);
258 assert_int_equal(yin_match_keyword(st->yin_ctx, "mandatory", strlen("mandatory"), prefix, prefix_len), YANG_MANDATORY);
259 assert_int_equal(yin_match_keyword(st->yin_ctx, "max-elements", strlen("max-elements"), prefix, prefix_len), YANG_MAX_ELEMENTS);
260 assert_int_equal(yin_match_keyword(st->yin_ctx, "min-elements", strlen("min-elements"), prefix, prefix_len), YANG_MIN_ELEMENTS);
261 assert_int_equal(yin_match_keyword(st->yin_ctx, "modifier", strlen("modifier"), prefix, prefix_len), YANG_MODIFIER);
262 assert_int_equal(yin_match_keyword(st->yin_ctx, "module", strlen("module"), prefix, prefix_len), YANG_MODULE);
263 assert_int_equal(yin_match_keyword(st->yin_ctx, "must", strlen("must"), prefix, prefix_len), YANG_MUST);
264 assert_int_equal(yin_match_keyword(st->yin_ctx, "namespace", strlen("namespace"), prefix, prefix_len), YANG_NAMESPACE);
265 assert_int_equal(yin_match_keyword(st->yin_ctx, "notification", strlen("notification"), prefix, prefix_len), YANG_NOTIFICATION);
266 assert_int_equal(yin_match_keyword(st->yin_ctx, "ordered-by", strlen("ordered-by"), prefix, prefix_len), YANG_ORDERED_BY);
267 assert_int_equal(yin_match_keyword(st->yin_ctx, "organization", strlen("organization"), prefix, prefix_len), YANG_ORGANIZATION);
268 assert_int_equal(yin_match_keyword(st->yin_ctx, "output", strlen("output"), prefix, prefix_len), YANG_OUTPUT);
269 assert_int_equal(yin_match_keyword(st->yin_ctx, "path", strlen("path"), prefix, prefix_len), YANG_PATH);
270 assert_int_equal(yin_match_keyword(st->yin_ctx, "pattern", strlen("pattern"), prefix, prefix_len), YANG_PATTERN);
271 assert_int_equal(yin_match_keyword(st->yin_ctx, "position", strlen("position"), prefix, prefix_len), YANG_POSITION);
272 assert_int_equal(yin_match_keyword(st->yin_ctx, "prefix", strlen("prefix"), prefix, prefix_len), YANG_PREFIX);
273 assert_int_equal(yin_match_keyword(st->yin_ctx, "presence", strlen("presence"), prefix, prefix_len), YANG_PRESENCE);
274 assert_int_equal(yin_match_keyword(st->yin_ctx, "range", strlen("range"), prefix, prefix_len), YANG_RANGE);
275 assert_int_equal(yin_match_keyword(st->yin_ctx, "reference", strlen("reference"), prefix, prefix_len), YANG_REFERENCE);
276 assert_int_equal(yin_match_keyword(st->yin_ctx, "refine", strlen("refine"), prefix, prefix_len), YANG_REFINE);
277 assert_int_equal(yin_match_keyword(st->yin_ctx, "require-instance", strlen("require-instance"), prefix, prefix_len), YANG_REQUIRE_INSTANCE);
278 assert_int_equal(yin_match_keyword(st->yin_ctx, "revision", strlen("revision"), prefix, prefix_len), YANG_REVISION);
279 assert_int_equal(yin_match_keyword(st->yin_ctx, "revision-date", strlen("revision-date"), prefix, prefix_len), YANG_REVISION_DATE);
280 assert_int_equal(yin_match_keyword(st->yin_ctx, "rpc", strlen("rpc"), prefix, prefix_len), YANG_RPC);
281 assert_int_equal(yin_match_keyword(st->yin_ctx, "status", strlen("status"), prefix, prefix_len), YANG_STATUS);
282 assert_int_equal(yin_match_keyword(st->yin_ctx, "submodule", strlen("submodule"), prefix, prefix_len), YANG_SUBMODULE);
283 assert_int_equal(yin_match_keyword(st->yin_ctx, "type", strlen("type"), prefix, prefix_len), YANG_TYPE);
284 assert_int_equal(yin_match_keyword(st->yin_ctx, "typedef", strlen("typedef"), prefix, prefix_len), YANG_TYPEDEF);
285 assert_int_equal(yin_match_keyword(st->yin_ctx, "unique", strlen("unique"), prefix, prefix_len), YANG_UNIQUE);
286 assert_int_equal(yin_match_keyword(st->yin_ctx, "units", strlen("units"), prefix, prefix_len), YANG_UNITS);
287 assert_int_equal(yin_match_keyword(st->yin_ctx, "uses", strlen("uses"), prefix, prefix_len), YANG_USES);
288 assert_int_equal(yin_match_keyword(st->yin_ctx, "value", strlen("value"), prefix, prefix_len), YANG_VALUE);
289 assert_int_equal(yin_match_keyword(st->yin_ctx, "when", strlen("when"), prefix, prefix_len), YANG_WHEN);
290 assert_int_equal(yin_match_keyword(st->yin_ctx, "yang-version", strlen("yang-version"), prefix, prefix_len), YANG_YANG_VERSION);
291 assert_int_equal(yin_match_keyword(st->yin_ctx, "yin-element", strlen("yin-element"), prefix, prefix_len), YANG_YIN_ELEMENT);
David Sedlák8f7a1172019-06-20 14:42:18 +0200292
293 st->finished_correctly = true;
David Sedlák872c7b42018-10-26 13:15:20 +0200294}
David Sedlák3b4db242018-10-19 16:11:01 +0200295
David Sedlák872c7b42018-10-26 13:15:20 +0200296static void
David Sedlák060b00e2019-06-19 11:12:06 +0200297test_yin_match_argument_name(void **state)
David Sedlák872c7b42018-10-26 13:15:20 +0200298{
David Sedlák68a1af12019-03-08 13:46:54 +0100299 (void)state; /* unused */
David Sedlák872c7b42018-10-26 13:15:20 +0200300
David Sedlák060b00e2019-06-19 11:12:06 +0200301 assert_int_equal(yin_match_argument_name("", 5), YIN_ARG_UNKNOWN);
302 assert_int_equal(yin_match_argument_name("qwertyasd", 5), YIN_ARG_UNKNOWN);
303 assert_int_equal(yin_match_argument_name("conditionasd", 8), YIN_ARG_UNKNOWN);
304 assert_int_equal(yin_match_argument_name("condition", 9), YIN_ARG_CONDITION);
305 assert_int_equal(yin_match_argument_name("date", 4), YIN_ARG_DATE);
306 assert_int_equal(yin_match_argument_name("module", 6), YIN_ARG_MODULE);
307 assert_int_equal(yin_match_argument_name("name", 4), YIN_ARG_NAME);
308 assert_int_equal(yin_match_argument_name("tag", 3), YIN_ARG_TAG);
309 assert_int_equal(yin_match_argument_name("target-node", 11), YIN_ARG_TARGET_NODE);
310 assert_int_equal(yin_match_argument_name("text", 4), YIN_ARG_TEXT);
311 assert_int_equal(yin_match_argument_name("uri", 3), YIN_ARG_URI);
312 assert_int_equal(yin_match_argument_name("value", 5), YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200313}
314
David Sedlák68a1af12019-03-08 13:46:54 +0100315static void
316test_meta(void **state)
317{
318 LY_ERR ret = LY_SUCCESS;
319 struct state *st = *state;
320
David Sedlák2b214ac2019-06-06 16:11:03 +0200321 ret = yin_parse_module(st->ctx,"<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\
322 name=\"example-foo\">\
David Sedlák21f87cd2019-07-03 16:53:23 +0200323 <prefix value=\"foo\">ignored</prefix>\
324 <namespace uri=\"urn:example:foo\" xmlns:myext=\"urn:example:extensions\"/>\
David Sedlák15a92662019-06-18 11:55:15 +0200325 <organization xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"><text>organization...</text></organization>\
326 <contact><text>contact...</text></contact>\
327 <description><text>description...</text></description>\
328 <reference><text>reference...</text></reference>\
David Sedlák68a1af12019-03-08 13:46:54 +0100329 </module>", st->mod);
330
331 assert_int_equal(ret, LY_SUCCESS);
David Sedláka7406952019-04-05 10:33:07 +0200332 assert_string_equal(st->mod->parsed->mod->org, "organization...");
David Sedlák68a1af12019-03-08 13:46:54 +0100333 assert_string_equal(st->mod->parsed->mod->contact, "contact...");
334 assert_string_equal(st->mod->parsed->mod->dsc, "description...");
335 assert_string_equal(st->mod->parsed->mod->ref, "reference...");
David Sedlák68826732019-06-05 10:50:58 +0200336
337 st = reset_state(state);
338 ret = yin_parse_module(st->ctx,"<module name=\"example-foo\">\
339 <organization test=\"invalid-argument\">organization...</organization>\
340 </module>", st->mod);
341 assert_int_equal(ret, LY_EVALID);
David Sedlák79e50cb2019-06-05 16:33:09 +0200342
343 st->finished_correctly = true;
David Sedlák68a1af12019-03-08 13:46:54 +0100344}
345
David Sedlák8f5bce02019-06-03 16:41:08 +0200346static void
David Sedlákda63c082019-06-04 13:52:23 +0200347test_yin_parse_import(void **state)
348{
349 struct state *st = *state;
350 const char *prefix = NULL, *name = NULL;
351 size_t prefix_len = 0, name_len = 0;
352 LY_ERR ret = LY_SUCCESS;
David Sedlák8f7a1172019-06-20 14:42:18 +0200353 struct yin_arg_record *args = NULL;
David Sedlákda63c082019-06-04 13:52:23 +0200354
David Sedlák2b214ac2019-06-06 16:11:03 +0200355 const char *data = "<import xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" module=\"a\">\
David Sedlákda63c082019-06-04 13:52:23 +0200356 <prefix value=\"a_mod\"/>\
David Sedlák00250342019-06-21 14:19:39 +0200357 <revision-date date=\"2015-01-01\"></revision-date>\
David Sedlákb6e65972019-06-19 10:44:13 +0200358 <description><text>import description</text></description>\
359 <reference><text>import reference</text></reference>\
David Sedlákc67dcaa2019-06-04 14:49:05 +0200360 </import>\
361 \
David Sedlák2b214ac2019-06-06 16:11:03 +0200362 <import xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" module=\"a\">\
David Sedlákc67dcaa2019-06-04 14:49:05 +0200363 <prefix value=\"a_mod\"/>\
David Sedlák00250342019-06-21 14:19:39 +0200364 <revision-date date=\"2015-01-01\" />\
David Sedlákda63c082019-06-04 13:52:23 +0200365 </import>";
David Sedlákb6e65972019-06-19 10:44:13 +0200366 /* first import */
David Sedlákda8ffa32019-07-08 14:17:10 +0200367 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
368 yin_load_attributes(st->yin_ctx, &data, &args);
David Sedlák619db942019-07-03 14:47:30 +0200369 st->lysp_mod->mod->prefix = "b-mod";
David Sedlákda8ffa32019-07-08 14:17:10 +0200370 ret = yin_parse_import(st->yin_ctx, &args, &data, st->lysp_mod);
David Sedlákda63c082019-06-04 13:52:23 +0200371 assert_int_equal(ret, LY_SUCCESS);
David Sedlák619db942019-07-03 14:47:30 +0200372 assert_string_equal(st->lysp_mod->imports->name, "a");
373 assert_string_equal(st->lysp_mod->imports->prefix, "a_mod");
374 assert_string_equal(st->lysp_mod->imports->rev, "2015-01-01");
375 assert_string_equal(st->lysp_mod->imports->dsc, "import description");
376 assert_string_equal(st->lysp_mod->imports->ref, "import reference");
David Sedlák8f7a1172019-06-20 14:42:18 +0200377 LY_ARRAY_FREE(args);
David Sedlák8f7a1172019-06-20 14:42:18 +0200378 args = NULL;
David Sedlák619db942019-07-03 14:47:30 +0200379 st = reset_state(state);
David Sedlákc67dcaa2019-06-04 14:49:05 +0200380
David Sedlákb6e65972019-06-19 10:44:13 +0200381 /* second invalid import */
David Sedlákda8ffa32019-07-08 14:17:10 +0200382 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
383 yin_load_attributes(st->yin_ctx, &data, &args);
David Sedlák619db942019-07-03 14:47:30 +0200384 st->lysp_mod->mod->prefix = "a_mod";
David Sedlákda8ffa32019-07-08 14:17:10 +0200385 ret = yin_parse_import(st->yin_ctx, &args, &data, st->lysp_mod);
David Sedlákda63c082019-06-04 13:52:23 +0200386 assert_int_equal(ret, LY_EVALID);
David Sedlák79e50cb2019-06-05 16:33:09 +0200387 logbuf_assert("Prefix \"a_mod\" already used as module prefix. Line number 1.");
David Sedlák8f7a1172019-06-20 14:42:18 +0200388 LY_ARRAY_FREE(args);
David Sedlák8f7a1172019-06-20 14:42:18 +0200389 args = NULL;
390
David Sedlákb6e65972019-06-19 10:44:13 +0200391 st = reset_state(state);
392 /* import with unknown child element */
393 data = "<import xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" module=\"a\">\
394 <what value=\"a_mod\"/>\
395 </import>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200396 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
397 yin_load_attributes(st->yin_ctx, &data, &args);
David Sedlák619db942019-07-03 14:47:30 +0200398 st->lysp_mod->mod->prefix = "invalid_mod";
David Sedlákda8ffa32019-07-08 14:17:10 +0200399 ret = yin_parse_import(st->yin_ctx, &args, &data, st->lysp_mod);
David Sedlákb6e65972019-06-19 10:44:13 +0200400 assert_int_equal(ret, LY_EVALID);
David Sedlák3ffbc522019-07-02 17:49:28 +0200401 logbuf_assert("Unexpected child element \"what\" of import element. Line number 1.");
David Sedlák8f7a1172019-06-20 14:42:18 +0200402 LY_ARRAY_FREE(args);
David Sedlákb6e65972019-06-19 10:44:13 +0200403
404 st->finished_correctly = true;
405}
406
407static void
408test_yin_parse_status(void **state)
409{
410 struct state *st = *state;
411 const char *prefix = NULL, *name = NULL;
412 size_t prefix_len = 0, name_len = 0;
413 LY_ERR ret = LY_SUCCESS;
414 uint16_t flags = 0;
415 struct lysp_ext_instance *exts;
David Sedlák8f7a1172019-06-20 14:42:18 +0200416 struct yin_arg_record *args = NULL;
David Sedlákb6e65972019-06-19 10:44:13 +0200417
418 /* try all valid values */
419 const char *data = "<status value=\"current\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"/>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200420 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
421 yin_load_attributes(st->yin_ctx, &data, &args);
422 ret = yin_parse_status(st->yin_ctx, &args, &data, &flags, &exts);
423 assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
David Sedlákb6e65972019-06-19 10:44:13 +0200424 assert_int_equal(ret, LY_SUCCESS);
425 assert_true(flags & LYS_STATUS_CURR);
David Sedlák8f7a1172019-06-20 14:42:18 +0200426 LY_ARRAY_FREE(args);
427 args = NULL;
David Sedlákb6e65972019-06-19 10:44:13 +0200428
429 st = reset_state(state);
430 flags = 0;
431 data = "<status value=\"deprecated\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"/>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200432 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
433 yin_load_attributes(st->yin_ctx, &data, &args);
434 ret = yin_parse_status(st->yin_ctx, &args, &data, &flags, &exts);
435 assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
David Sedlákb6e65972019-06-19 10:44:13 +0200436 assert_int_equal(ret, LY_SUCCESS);
437 assert_true(flags & LYS_STATUS_DEPRC);
David Sedlák8f7a1172019-06-20 14:42:18 +0200438 LY_ARRAY_FREE(args);
439 args = NULL;
David Sedlákb6e65972019-06-19 10:44:13 +0200440
441 st = reset_state(state);
442 flags = 0;
443 data = "<status value=\"obsolete\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"/>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200444 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
445 yin_load_attributes(st->yin_ctx, &data, &args);
446 ret = yin_parse_status(st->yin_ctx, &args, &data, &flags, &exts);
447 assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
David Sedlákb6e65972019-06-19 10:44:13 +0200448 assert_int_equal(ret, LY_SUCCESS);
449 assert_true(flags & LYS_STATUS_OBSLT);
David Sedlák8f7a1172019-06-20 14:42:18 +0200450 LY_ARRAY_FREE(args);
451 args = NULL;
David Sedlákb6e65972019-06-19 10:44:13 +0200452
453 /* duplicit definition (no reset_state() call) */
454 data = "<status value=\"deprecated\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"/>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200455 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
456 yin_load_attributes(st->yin_ctx, &data, &args);
457 ret = yin_parse_status(st->yin_ctx, &args, &data, &flags, &exts);
David Sedlákb6e65972019-06-19 10:44:13 +0200458 assert_int_equal(ret, LY_EVALID);
459 logbuf_assert("Duplicate element \"status\". Line number 1.");
David Sedlák8f7a1172019-06-20 14:42:18 +0200460 LY_ARRAY_FREE(args);
461 args = NULL;
David Sedlákb6e65972019-06-19 10:44:13 +0200462
463 /* invalid status value */
464 st = reset_state(state);
465 flags = 0;
466 data = "<status value=\"dunno\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"/>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200467 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
468 yin_load_attributes(st->yin_ctx, &data, &args);
469 ret = yin_parse_status(st->yin_ctx, &args, &data, &flags, &exts);
David Sedlákb6e65972019-06-19 10:44:13 +0200470 assert_int_equal(ret, LY_EVALID);
471 logbuf_assert("Invalid value \"dunno\" of \"status\". Line number 1.");
David Sedlák8f7a1172019-06-20 14:42:18 +0200472 LY_ARRAY_FREE(args);
473
David Sedlák79e50cb2019-06-05 16:33:09 +0200474 st->finished_correctly = true;
David Sedlákda63c082019-06-04 13:52:23 +0200475}
476
David Sedlák554e36d2019-06-20 16:00:04 +0200477static void
478test_yin_parse_extension(void **state)
479{
480 struct state *st = *state;
481 const char *prefix = NULL, *name = NULL;
482 size_t prefix_len = 0, name_len = 0;
483 LY_ERR ret = LY_SUCCESS;
484 struct yin_arg_record *args = NULL;
485 struct lysp_ext *exts = NULL, *iter = NULL;
486
487 const char *data = "<extension name=\"b\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">\
David Sedlák9494eb22019-06-21 16:06:53 +0200488 <argument name=\"argname\"></argument>\
David Sedlák554e36d2019-06-20 16:00:04 +0200489 <description><text>desc</text></description>\
490 <reference><text>ref</text></reference>\
491 <status value=\"deprecated\"></status>\
492 </extension>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200493 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
494 yin_load_attributes(st->yin_ctx, &data, &args);
495 ret = yin_parse_extension(st->yin_ctx, &args, &data, &exts);
496 assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
David Sedlák554e36d2019-06-20 16:00:04 +0200497 assert_int_equal(ret, LY_SUCCESS);
498 LY_ARRAY_FOR_ITER(exts, struct lysp_ext, iter) {
499 assert_string_equal(iter->name, "b");
500 assert_string_equal(iter->dsc, "desc");
501 assert_string_equal(iter->ref, "ref");
David Sedlák9494eb22019-06-21 16:06:53 +0200502 assert_string_equal(iter->argument, "argname");
David Sedlák554e36d2019-06-20 16:00:04 +0200503 assert_true(iter->flags & LYS_STATUS_DEPRC);
504 }
David Sedlák288c1472019-06-20 16:09:48 +0200505 lydict_remove(st->ctx, "b");
506 lydict_remove(st->ctx, "desc");
507 lydict_remove(st->ctx, "ref");
David Sedlák9494eb22019-06-21 16:06:53 +0200508 lydict_remove(st->ctx, "argname");
David Sedlák554e36d2019-06-20 16:00:04 +0200509 LY_ARRAY_FREE(args);
David Sedlák288c1472019-06-20 16:09:48 +0200510 LY_ARRAY_FREE(exts);
David Sedlák554e36d2019-06-20 16:00:04 +0200511 st->finished_correctly = true;
512}
513
David Sedlák2721d3d2019-06-21 15:37:41 +0200514static void
515test_yin_parse_yin_element_element(void **state)
516{
517 struct state *st = *state;
518 const char *prefix = NULL, *name = NULL;
519 size_t prefix_len = 0, name_len = 0;
520 LY_ERR ret = LY_SUCCESS;
521 uint16_t flags = 0;
David Sedlák3ffbc522019-07-02 17:49:28 +0200522 struct lysp_ext_instance *exts;
David Sedlák2721d3d2019-06-21 15:37:41 +0200523 struct yin_arg_record *args = NULL;
524
525 /* try all valid values */
526 const char *data = "<yin-element value=\"true\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"/>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200527 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
528 yin_load_attributes(st->yin_ctx, &data, &args);
529 ret = yin_parse_yin_element_element(st->yin_ctx, args, &data, &flags, &exts);
530 assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
David Sedlák2721d3d2019-06-21 15:37:41 +0200531 assert_int_equal(ret, LY_SUCCESS);
532 assert_true(flags & LYS_YINELEM_TRUE);
533 LY_ARRAY_FREE(args);
534 args = NULL;
535
536 st = reset_state(state);
537 flags = 0;
538 data = "<yin-element value=\"false\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"/>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200539 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
540 yin_load_attributes(st->yin_ctx, &data, &args);
541 ret = yin_parse_yin_element_element(st->yin_ctx, args, &data, &flags, &exts);
542 assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
David Sedlák2721d3d2019-06-21 15:37:41 +0200543 assert_int_equal(ret, LY_SUCCESS);
544 assert_true(flags & LYS_YINELEM_FALSE);
545 LY_ARRAY_FREE(args);
546 args = NULL;
547
548 /* invalid value */
549 st = reset_state(state);
550 flags = 0;
551 data = "<yin-element value=\"invalid\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"/>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200552 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
553 yin_load_attributes(st->yin_ctx, &data, &args);
554 ret = yin_parse_yin_element_element(st->yin_ctx, args, &data, &flags, &exts);
David Sedlák2721d3d2019-06-21 15:37:41 +0200555 assert_int_equal(ret, LY_EVALID);
556 LY_ARRAY_FREE(args);
557 args = NULL;
558
559 st->finished_correctly = true;
560}
561
David Sedlákb1a78352019-06-28 16:16:29 +0200562static void
563test_yin_parse_element_generic(void **state)
564{
565 const char *prefix, *name;
566 struct state *st = *state;
567 struct lysp_ext_instance exts;
568 size_t prefix_len, name_len;
569 LY_ERR ret;
570
571 memset(&exts, 0, sizeof(exts));
572
573 const char *data = "<elem attr=\"value\">text_value</elem>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200574 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
575 ret = yin_parse_element_generic(st->yin_ctx, name, name_len, prefix, prefix_len, &data, &exts.child);
David Sedlákb1a78352019-06-28 16:16:29 +0200576 assert_int_equal(ret, LY_SUCCESS);
577 assert_string_equal(exts.child->stmt, "elem");
578 assert_string_equal(exts.child->arg, "text_value");
David Sedlákb1a78352019-06-28 16:16:29 +0200579 assert_string_equal(exts.child->child->stmt, "attr");
580 assert_string_equal(exts.child->child->arg, "value");
581 assert_true(exts.child->child->flags & LYS_YIN_ATTR);
David Sedlákb1a78352019-06-28 16:16:29 +0200582 lysp_ext_instance_free(st->ctx, &exts);
David Sedlák5392a212019-07-01 09:19:10 +0200583 st = reset_state(state);
584
585 data = "<elem></elem>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200586 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
587 ret = yin_parse_element_generic(st->yin_ctx, name, name_len, prefix, prefix_len, &data, &exts.child);
David Sedlák5392a212019-07-01 09:19:10 +0200588 assert_int_equal(ret, LY_SUCCESS);
589 assert_string_equal(exts.child->stmt, "elem");
590 assert_null(exts.child->child);
591 assert_null(exts.child->arg);
David Sedlákda8ffa32019-07-08 14:17:10 +0200592 assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
David Sedlák5392a212019-07-01 09:19:10 +0200593 lysp_ext_instance_free(st->ctx, &exts);
594
David Sedlákb1a78352019-06-28 16:16:29 +0200595 st->finished_correctly = true;
596}
597
598static void
599test_yin_parse_extension_instance(void **state)
600{
601 LY_ERR ret;
602 struct state *st = *state;
603 const char *prefix, *name;
604 size_t prefix_len, name_len;
605 struct yin_arg_record *args = NULL;
606 struct lysp_ext_instance *exts = NULL;
David Sedlákb1a78352019-06-28 16:16:29 +0200607 const char *data = "<ext value1=\"test\" value=\"test2\"><subelem>text</subelem></ext>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200608 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
609 yin_load_attributes(st->yin_ctx, &data, &args);
610 ret = yin_parse_extension_instance(st->yin_ctx, &args, &data, name2fullname(name, prefix_len),
David Sedlák619db942019-07-03 14:47:30 +0200611 namelen2fulllen(name_len, prefix_len), LYEXT_SUBSTMT_CONTACT, 0, &exts);
David Sedlákb1a78352019-06-28 16:16:29 +0200612 assert_int_equal(ret, LY_SUCCESS);
613 assert_string_equal(exts->name, "ext");
614 assert_int_equal(exts->insubstmt_index, 0);
615 assert_true(exts->insubstmt == LYEXT_SUBSTMT_CONTACT);
616 assert_true(exts->yin & LYS_YIN);
617 assert_string_equal(exts->child->stmt, "value1");
618 assert_string_equal(exts->child->arg, "test");
619 assert_null(exts->child->child);
620 assert_true(exts->child->flags & LYS_YIN_ATTR);
621 assert_string_equal(exts->child->next->stmt, "value");
622 assert_string_equal(exts->child->next->arg, "test2");
623 assert_null(exts->child->next->child);
624 assert_true(exts->child->next->flags & LYS_YIN_ATTR);
625
626 assert_string_equal(exts->child->next->next->stmt, "subelem");
627 assert_string_equal(exts->child->next->next->arg, "text");
628 assert_null(exts->child->next->next->child);
629 assert_null(exts->child->next->next->next);
630 assert_false(exts->child->next->next->flags & LYS_YIN_ATTR);
David Sedlákda8ffa32019-07-08 14:17:10 +0200631 assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
David Sedlákb1a78352019-06-28 16:16:29 +0200632 LY_ARRAY_FREE(args);
633 lysp_ext_instance_free(st->ctx, exts);
634 LY_ARRAY_FREE(exts);
David Sedlákf250ecf2019-07-01 11:02:05 +0200635 exts = NULL;
636 args = NULL;
637 st = reset_state(state);
638
639 data = "<extension-elem />";
David Sedlákda8ffa32019-07-08 14:17:10 +0200640 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
641 yin_load_attributes(st->yin_ctx, &data, &args);
642 ret = yin_parse_extension_instance(st->yin_ctx, &args, &data, name, name_len, LYEXT_SUBSTMT_CONTACT, 0, &exts);
David Sedlákf250ecf2019-07-01 11:02:05 +0200643 assert_int_equal(ret, LY_SUCCESS);
644 assert_string_equal(exts->name, "extension-elem");
645 assert_null(exts->argument);
646 assert_null(exts->child);
647 assert_int_equal(exts->insubstmt, LYEXT_SUBSTMT_CONTACT);
648 assert_int_equal(exts->insubstmt_index, 0);
649 assert_true(exts->yin & LYS_YIN);
David Sedlákda8ffa32019-07-08 14:17:10 +0200650 assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
David Sedlákf250ecf2019-07-01 11:02:05 +0200651 LY_ARRAY_FREE(args);
652 lysp_ext_instance_free(st->ctx, exts);
653 LY_ARRAY_FREE(exts);
David Sedlákb1a78352019-06-28 16:16:29 +0200654 st->finished_correctly = true;
655}
656
David Sedlák555c7202019-07-04 12:14:12 +0200657static void
658test_yin_parse_content(void **state)
659{
660 struct state *st = *state;
661 LY_ERR ret = LY_SUCCESS;
662 struct sized_string name, prefix;
663 const char *data = "<prefix value=\"a_mod\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
664 "<custom xmlns=\"my-ext\">"
665 "totally amazing extension"
666 "</custom>"
David Sedlák986cb412019-07-04 13:10:11 +0200667 "<extension name=\"ext\">"
668 "<argument name=\"argname\"></argument>"
669 "<description><text>desc</text></description>"
670 "<reference><text>ref</text></reference>"
671 "<status value=\"deprecated\"></status>"
672 "</extension>"
David Sedlák555c7202019-07-04 12:14:12 +0200673 "<text xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">wsefsdf</text>"
David Sedlák5f8191e2019-07-08 16:35:52 +0200674 "<if-feature value=\"foo\"></if-feature>"
David Sedlák32eee7b2019-07-09 12:38:44 +0200675 "<when condition=\"condition...\">"
676 "<reference><text>when_ref</text></reference>"
677 "<description><text>when_desc</text></description>"
678 "</when>"
David Sedlák555c7202019-07-04 12:14:12 +0200679 "</prefix>";
680 struct lysp_ext_instance *exts = NULL;
David Sedlák5f8191e2019-07-08 16:35:52 +0200681 const char **if_features = NULL;
David Sedlák555c7202019-07-04 12:14:12 +0200682 struct yin_arg_record *attrs = NULL;
683 const char *value;
David Sedlák986cb412019-07-04 13:10:11 +0200684 struct lysp_ext *ext_def = NULL;
David Sedlák32eee7b2019-07-09 12:38:44 +0200685 struct lysp_when *when_p = NULL;
David Sedlák555c7202019-07-04 12:14:12 +0200686
David Sedlákda8ffa32019-07-08 14:17:10 +0200687 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix.value, &prefix.len, &name.value, &name.len);
688 yin_load_attributes(st->yin_ctx, &data, &attrs);
David Sedlák555c7202019-07-04 12:14:12 +0200689
David Sedlák32eee7b2019-07-09 12:38:44 +0200690 struct yin_subelement subelems[5] = {{YANG_EXTENSION, &ext_def, 0},
David Sedlák5f8191e2019-07-08 16:35:52 +0200691 {YANG_IF_FEATURE, &if_features, 0},
David Sedlák32eee7b2019-07-09 12:38:44 +0200692 {YANG_WHEN, &when_p, 0},
David Sedlákb0faad82019-07-04 14:28:59 +0200693 {YANG_CUSTOM, NULL, 0},
694 {YIN_TEXT, &value, 0}};
David Sedlák32eee7b2019-07-09 12:38:44 +0200695 ret = yin_parse_content(st->yin_ctx, subelems, 5, &data, YANG_PREFIX, NULL, &exts);
David Sedlák555c7202019-07-04 12:14:12 +0200696 assert_int_equal(ret, LY_SUCCESS);
697 assert_string_equal(exts->name, "custom");
698 assert_string_equal(exts->argument, "totally amazing extension");
699 assert_string_equal(value, "wsefsdf");
David Sedlák32eee7b2019-07-09 12:38:44 +0200700 assert_string_equal(when_p->cond, "condition...");
701 assert_string_equal(when_p->dsc, "when_desc");
702 assert_string_equal(when_p->ref, "when_ref");
David Sedlák555c7202019-07-04 12:14:12 +0200703 lysp_ext_instance_free(st->ctx, exts);
David Sedlák32eee7b2019-07-09 12:38:44 +0200704 lysp_when_free(st->ctx, when_p);
David Sedlák986cb412019-07-04 13:10:11 +0200705 lysp_ext_free(st->ctx, ext_def);
David Sedlák5f8191e2019-07-08 16:35:52 +0200706 FREE_STRING(st->ctx, *if_features);
707 LY_ARRAY_FREE(if_features);
David Sedlák555c7202019-07-04 12:14:12 +0200708 LY_ARRAY_FREE(exts);
David Sedlák986cb412019-07-04 13:10:11 +0200709 LY_ARRAY_FREE(ext_def);
David Sedlák555c7202019-07-04 12:14:12 +0200710 LY_ARRAY_FREE(attrs);
David Sedlák32eee7b2019-07-09 12:38:44 +0200711 free(when_p);
David Sedlák555c7202019-07-04 12:14:12 +0200712 attrs = NULL;
713 lydict_remove(st->ctx, value);
714 st = reset_state(state);
715
716 /* test unique subelem */
717 const char *prefix_value;
718 struct yin_subelement subelems2[2] = {{YANG_PREFIX, &prefix_value, 0},
719 {YIN_TEXT, &value, YIN_SUBELEM_UNIQUE}};
720 data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
721 "<prefix value=\"inv_mod\" />"
722 "<text xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">wsefsdf</text>"
723 "<text xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">wsefsdf</text>"
724 "</module>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200725 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix.value, &prefix.len, &name.value, &name.len);
726 yin_load_attributes(st->yin_ctx, &data, &attrs);
727 ret = yin_parse_content(st->yin_ctx, subelems2, 2, &data, YANG_MODULE, NULL, &exts);
David Sedlák555c7202019-07-04 12:14:12 +0200728 assert_int_equal(ret, LY_EVALID);
729 logbuf_assert("Redefinition of text element in module element. Line number 1.");
730 lydict_remove(st->ctx, prefix_value);
731 lydict_remove(st->ctx, value);
732 st = reset_state(state);
733 LY_ARRAY_FREE(attrs);
734 attrs = NULL;
735
736 /* test first subelem */
737 data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
738 "<prefix value=\"inv_mod\" />"
739 "<text xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">wsefsdf</text>"
740 "<text xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">wsefsdf</text>"
741 "</module>";
742 struct yin_subelement subelems3[2] = {{YANG_PREFIX, &prefix_value, 0},
743 {YIN_TEXT, &value, YIN_SUBELEM_FIRST}};
David Sedlákda8ffa32019-07-08 14:17:10 +0200744 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix.value, &prefix.len, &name.value, &name.len);
745 yin_load_attributes(st->yin_ctx, &data, &attrs);
746 ret = yin_parse_content(st->yin_ctx, subelems3, 2, &data, YANG_MODULE, NULL, &exts);
David Sedlák555c7202019-07-04 12:14:12 +0200747 assert_int_equal(ret, LY_EVALID);
748 logbuf_assert("Subelement text of module element must be defined as first subelement. Line number 1.");
749 lydict_remove(st->ctx, prefix_value);
750 st = reset_state(state);
751 LY_ARRAY_FREE(attrs);
752 attrs = NULL;
753
754 /* test mandatory subelem */
755 data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
756 "</module>";
757 struct yin_subelement subelems4[1] = {{YANG_PREFIX, &prefix_value, YIN_SUBELEM_MANDATORY}};
David Sedlákda8ffa32019-07-08 14:17:10 +0200758 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix.value, &prefix.len, &name.value, &name.len);
759 yin_load_attributes(st->yin_ctx, &data, &attrs);
760 ret = yin_parse_content(st->yin_ctx, subelems4, 1, &data, YANG_MODULE, NULL, &exts);
David Sedlák555c7202019-07-04 12:14:12 +0200761 assert_int_equal(ret, LY_EVALID);
762 logbuf_assert("Missing mandatory subelement prefix of module element. Line number 1.");
763 LY_ARRAY_FREE(attrs);
764
765 st->finished_correctly = true;
766}
767
David Sedlák92147b02019-07-09 14:01:01 +0200768static void
769test_yin_parse_yangversion(void **state)
770{
771 struct state *st = *state;
772 LY_ERR ret = LY_SUCCESS;
773 struct sized_string name, prefix;
774 struct yin_arg_record *attrs = NULL;
775 uint8_t version;
776
777 const char *data = "<yang-version xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" value=\"1.0\">\n"
778 "</yang-version>";
779 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix.value, &prefix.len, &name.value, &name.len);
780 yin_load_attributes(st->yin_ctx, &data, &attrs);
781 ret = yin_parse_yangversion(st->yin_ctx, attrs, &data, &version, NULL);
782 assert_int_equal(LY_SUCCESS, ret);
783 assert_true(version == LYS_VERSION_1_0);
784 assert_true(st->yin_ctx->mod_version == LYS_VERSION_1_0);
785 LY_ARRAY_FREE(attrs);
786 attrs = NULL;
787 st = reset_state(state);
788
789 data = "<yang-version xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" value=\"1.1\">\n"
790 "</yang-version>";
791 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix.value, &prefix.len, &name.value, &name.len);
792 yin_load_attributes(st->yin_ctx, &data, &attrs);
793 ret = yin_parse_yangversion(st->yin_ctx, attrs, &data, &version, NULL);
794 assert_int_equal(LY_SUCCESS, ret);
795 assert_true(version == LYS_VERSION_1_1);
796 assert_true(st->yin_ctx->mod_version == LYS_VERSION_1_1);
797 LY_ARRAY_FREE(attrs);
798 attrs = NULL;
799 st = reset_state(state);
800
801 data = "<yang-version xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" value=\"randomvalue\">\n"
802 "</yang-version>";
803 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix.value, &prefix.len, &name.value, &name.len);
804 yin_load_attributes(st->yin_ctx, &data, &attrs);
805 ret = yin_parse_yangversion(st->yin_ctx, attrs, &data, &version, NULL);
806 assert_int_equal(ret, LY_EVALID);
807 LY_ARRAY_FREE(attrs);
808 attrs = NULL;
809 logbuf_assert("Invalid value \"randomvalue\" of \"yang-version\". Line number 1.");
810 st->finished_correctly = true;
811}
812
David Sedlák3b4db242018-10-19 16:11:01 +0200813int
814main(void)
815{
816
817 const struct CMUnitTest tests[] = {
David Sedlák392af4f2019-06-04 16:02:42 +0200818 cmocka_unit_test_setup_teardown(test_yin_parse_module, setup_f, teardown_f),
David Sedlák68a1af12019-03-08 13:46:54 +0100819 cmocka_unit_test_setup_teardown(test_meta, setup_f, teardown_f),
David Sedlákda63c082019-06-04 13:52:23 +0200820 cmocka_unit_test_setup_teardown(test_yin_parse_import, setup_f, teardown_f),
David Sedlákb6e65972019-06-19 10:44:13 +0200821 cmocka_unit_test_setup_teardown(test_yin_parse_status, setup_f, teardown_f),
David Sedlák8f7a1172019-06-20 14:42:18 +0200822 cmocka_unit_test_setup_teardown(test_yin_match_keyword, setup_f, teardown_f),
David Sedlák554e36d2019-06-20 16:00:04 +0200823 cmocka_unit_test_setup_teardown(test_yin_parse_extension, setup_f, teardown_f),
David Sedlák2721d3d2019-06-21 15:37:41 +0200824 cmocka_unit_test_setup_teardown(test_yin_parse_yin_element_element, setup_f, teardown_f),
David Sedlákb1a78352019-06-28 16:16:29 +0200825 cmocka_unit_test_setup_teardown(test_yin_parse_element_generic, setup_f, teardown_f),
826 cmocka_unit_test_setup_teardown(test_yin_parse_extension_instance, setup_f, teardown_f),
David Sedlák555c7202019-07-04 12:14:12 +0200827 cmocka_unit_test_setup_teardown(test_yin_parse_content, setup_f, teardown_f),
David Sedlák92147b02019-07-09 14:01:01 +0200828 cmocka_unit_test_setup_teardown(test_yin_parse_yangversion, setup_f, teardown_f),
David Sedlák060b00e2019-06-19 11:12:06 +0200829 cmocka_unit_test(test_yin_match_argument_name),
David Sedlák3b4db242018-10-19 16:11:01 +0200830 };
831
832 return cmocka_run_group_tests(tests, NULL, NULL);
833}