blob: 0d159db6a036042c015c3b7421092e4030e713cb [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ák32488102019-07-15 17:44:10 +020034void lysp_type_free(struct ly_ctx *ctx, struct lysp_type *type);
David Sedlák555c7202019-07-04 12:14:12 +020035
David Sedlák68a1af12019-03-08 13:46:54 +010036struct state {
David Sedlák3b4db242018-10-19 16:11:01 +020037 struct ly_ctx *ctx;
David Sedlák3017da42019-02-15 09:48:04 +010038 struct lys_module *mod;
David Sedlák619db942019-07-03 14:47:30 +020039 struct lysp_module *lysp_mod;
David Sedlákda8ffa32019-07-08 14:17:10 +020040 struct yin_parser_ctx *yin_ctx;
David Sedlák79e50cb2019-06-05 16:33:09 +020041 bool finished_correctly;
David Sedlák68a1af12019-03-08 13:46:54 +010042};
David Sedlák872c7b42018-10-26 13:15:20 +020043
David Sedlák79e50cb2019-06-05 16:33:09 +020044#define BUFSIZE 1024
45char logbuf[BUFSIZE] = {0};
46int store = -1; /* negative for infinite logging, positive for limited logging */
47
48/* set to 0 to printing error messages to stderr instead of checking them in code */
49#define ENABLE_LOGGER_CHECKING 1
50
51#if ENABLE_LOGGER_CHECKING
52static void
53logger(LY_LOG_LEVEL level, const char *msg, const char *path)
54{
55 (void) level; /* unused */
56 if (store) {
57 if (path && path[0]) {
58 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
59 } else {
60 strncpy(logbuf, msg, BUFSIZE - 1);
61 }
62 if (store > 0) {
63 --store;
64 }
65 }
66}
67#endif
68
69#if ENABLE_LOGGER_CHECKING
70# define logbuf_assert(str) assert_string_equal(logbuf, str)
71#else
72# define logbuf_assert(str)
73#endif
74
75#define TEST_DUP_GENERIC(PREFIX, MEMBER, VALUE1, VALUE2, FUNC, RESULT, LINE, CLEANUP) \
76 str = PREFIX MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
77 assert_int_equal(LY_EVALID, FUNC(&ctx, &str, RESULT)); \
78 logbuf_assert("Duplicate keyword \""MEMBER"\". Line number "LINE"."); \
79 CLEANUP
80
81
David Sedlák68a1af12019-03-08 13:46:54 +010082static int
83setup_f(void **state)
84{
85 struct state *st = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +020086
David Sedlák79e50cb2019-06-05 16:33:09 +020087#if ENABLE_LOGGER_CHECKING
88 /* setup logger */
89 ly_set_log_clb(logger, 1);
90#endif
91
David Sedlák68a1af12019-03-08 13:46:54 +010092 /* allocate state variable */
93 (*state) = st = calloc(1, sizeof(*st));
94 if (!st) {
95 fprintf(stderr, "Memmory allocation failed");
96 return EXIT_FAILURE;
97 }
David Sedlák872c7b42018-10-26 13:15:20 +020098
David Sedlák68a1af12019-03-08 13:46:54 +010099 /* create new libyang context */
100 ly_ctx_new(NULL, 0, &st->ctx);
David Sedlák872c7b42018-10-26 13:15:20 +0200101
David Sedlák68a1af12019-03-08 13:46:54 +0100102 /* allocate new module */
103 st->mod = calloc(1, sizeof(*st->mod));
104 st->mod->ctx = st->ctx;
105
David Sedlák619db942019-07-03 14:47:30 +0200106 /* allocate new parsed module */
107 st->lysp_mod = calloc(1, sizeof(*st->lysp_mod));
108 st->lysp_mod->mod = calloc(1, sizeof(*st->lysp_mod->mod));
109 st->lysp_mod->mod->ctx = st->ctx;
110
111 /* allocate parser context */
David Sedlákda8ffa32019-07-08 14:17:10 +0200112 st->yin_ctx = calloc(1, sizeof(*st->yin_ctx));
113 st->yin_ctx->xml_ctx.ctx = st->ctx;
114 st->yin_ctx->xml_ctx.line = 1;
David Sedlák8f5bce02019-06-03 16:41:08 +0200115
David Sedlák68a1af12019-03-08 13:46:54 +0100116 return EXIT_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +0200117}
118
119static int
David Sedlák68a1af12019-03-08 13:46:54 +0100120teardown_f(void **state)
121{
122 struct state *st = *(struct state **)state;
David Sedlák619db942019-07-03 14:47:30 +0200123 struct lys_module *temp;
David Sedlák68a1af12019-03-08 13:46:54 +0100124
David Sedlák79e50cb2019-06-05 16:33:09 +0200125#if ENABLE_LOGGER_CHECKING
126 /* teardown logger */
127 if (!st->finished_correctly && logbuf[0] != '\0') {
128 fprintf(stderr, "%s\n", logbuf);
129 }
130#endif
131
David Sedlák619db942019-07-03 14:47:30 +0200132 temp = st->lysp_mod->mod;
133
David Sedlákda8ffa32019-07-08 14:17:10 +0200134 lyxml_context_clear(&st->yin_ctx->xml_ctx);
David Sedlák68a1af12019-03-08 13:46:54 +0100135 lys_module_free(st->mod, NULL);
David Sedlák619db942019-07-03 14:47:30 +0200136 lysp_module_free(st->lysp_mod);
137 lys_module_free(temp, NULL);
David Sedlák68a1af12019-03-08 13:46:54 +0100138 ly_ctx_destroy(st->ctx, NULL);
David Sedlákda8ffa32019-07-08 14:17:10 +0200139 free(st->yin_ctx);
David Sedlák68a1af12019-03-08 13:46:54 +0100140 free(st);
141
142 return EXIT_SUCCESS;
143}
144
David Sedlák392af4f2019-06-04 16:02:42 +0200145static struct state*
146reset_state(void **state)
147{
David Sedlák79e50cb2019-06-05 16:33:09 +0200148 ((struct state *)*state)->finished_correctly = true;
David Sedlák555c7202019-07-04 12:14:12 +0200149 logbuf[0] = '\0';
David Sedlák392af4f2019-06-04 16:02:42 +0200150 teardown_f(state);
151 setup_f(state);
152
153 return *state;
154}
155
David Sedlák79e50cb2019-06-05 16:33:09 +0200156void
157logbuf_clean(void)
158{
159 logbuf[0] = '\0';
160}
161
David Sedlák68a1af12019-03-08 13:46:54 +0100162static void
David Sedlák392af4f2019-06-04 16:02:42 +0200163test_yin_parse_module(void **state)
David Sedlák68a1af12019-03-08 13:46:54 +0100164{
165 LY_ERR ret = LY_SUCCESS;
166 struct state *st = *state;
167
168 ret = yin_parse_module(st->ctx,
David Sedlák2b214ac2019-06-06 16:11:03 +0200169 "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\
170 name=\"example-foo\"\
David Sedlák18730132019-03-15 15:51:34 +0100171 xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\
172 xmlns:foo=\"urn:example:foo\"\
173 xmlns:myext=\"urn:example:extensions\">\
David Sedlákcd0c9512019-03-29 13:23:06 +0100174 <namespace uri=\"urn:example:foo\" xmlns:myext=\"urn:example:extensions\"/>\
David Sedláka7406952019-04-05 10:33:07 +0200175 <prefix xmlns:myxt=\"urn:emple:extensions\" value=\"foo\" xmlns:myext=\"urn:example:extensions\"/>\
David Sedlákd9d3a312019-06-04 09:47:10 +0200176 </module>",
David Sedlák68a1af12019-03-08 13:46:54 +0100177 st->mod);
178
179 assert_int_equal(ret, LY_SUCCESS);
180 assert_string_equal(st->mod->parsed->mod->name, "example-foo");
181 assert_string_equal(st->mod->parsed->mod->prefix, "foo");
David Sedlákcd0c9512019-03-29 13:23:06 +0100182 assert_string_equal(st->mod->parsed->mod->ns, "urn:example:foo");
David Sedlák392af4f2019-06-04 16:02:42 +0200183
184 st = reset_state(state);
185 ret = yin_parse_module(st->ctx,
David Sedlák2b214ac2019-06-06 16:11:03 +0200186 "<module name=\"example-foo\">\
187 <invalid-tag uri=\"urn:example:foo\"\"/>\
188 </module>",
189 st->mod);
David Sedlák392af4f2019-06-04 16:02:42 +0200190 assert_int_equal(ret, LY_EVALID);
191
192 st = reset_state(state);
193 ret = yin_parse_module(st->ctx,
David Sedlák8f7a1172019-06-20 14:42:18 +0200194 "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">\
David Sedlák57715b12019-06-17 13:05:22 +0200195 </module>",
David Sedlák2b214ac2019-06-06 16:11:03 +0200196 st->mod);
David Sedlák392af4f2019-06-04 16:02:42 +0200197 assert_int_equal(ret, LY_EVALID);
David Sedlák882a8072019-07-08 17:51:20 +0200198 logbuf_assert("Missing mandatory attribute name of module element. Line number 1.");
David Sedlák392af4f2019-06-04 16:02:42 +0200199
200 st = reset_state(state);
201 ret = yin_parse_module(st->ctx,
202 "",
203 st->mod);
204 assert_int_equal(ret, LY_EVALID);
David Sedlák79e50cb2019-06-05 16:33:09 +0200205 logbuf_assert("Invalid keyword \"(null)\", expected \"module\" or \"submodule\". Line number 1.");
206 st->finished_correctly = true;
David Sedlák3b4db242018-10-19 16:11:01 +0200207}
208
209static void
David Sedlák1bccdfa2019-06-17 15:55:27 +0200210test_yin_match_keyword(void **state)
David Sedlák3b4db242018-10-19 16:11:01 +0200211{
David Sedlák8f7a1172019-06-20 14:42:18 +0200212 struct state *st = *state;
David Sedlák3b4db242018-10-19 16:11:01 +0200213
David Sedlák8f7a1172019-06-20 14:42:18 +0200214 const char *prefix, *name;
215 struct yin_arg_record *args = NULL;
216 size_t prefix_len, name_len;
217 /* create mock yin namespace in xml context */
218 const char *data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" />";
David Sedlákda8ffa32019-07-08 14:17:10 +0200219 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
220 yin_load_attributes(st->yin_ctx, &data, &args);
David Sedlák8f7a1172019-06-20 14:42:18 +0200221 LY_ARRAY_FREE(args);
222
David Sedlákc1771b12019-07-10 15:55:46 +0200223 assert_int_equal(yin_match_keyword(st->yin_ctx, "anydatax", strlen("anydatax"), prefix, prefix_len, YANG_NONE), YANG_NONE);
224 assert_int_equal(yin_match_keyword(st->yin_ctx, "asdasd", strlen("asdasd"), prefix, prefix_len, YANG_NONE), YANG_NONE);
225 assert_int_equal(yin_match_keyword(st->yin_ctx, "", 0, prefix, prefix_len, YANG_NONE), YANG_NONE);
226 assert_int_equal(yin_match_keyword(st->yin_ctx, "anydata", strlen("anydata"), prefix, prefix_len, YANG_NONE), YANG_ANYDATA);
227 assert_int_equal(yin_match_keyword(st->yin_ctx, "anyxml", strlen("anyxml"), prefix, prefix_len, YANG_NONE), YANG_ANYXML);
228 assert_int_equal(yin_match_keyword(st->yin_ctx, "argument", strlen("argument"), prefix, prefix_len, YANG_NONE), YANG_ARGUMENT);
229 assert_int_equal(yin_match_keyword(st->yin_ctx, "augment", strlen("augment"), prefix, prefix_len, YANG_NONE), YANG_AUGMENT);
230 assert_int_equal(yin_match_keyword(st->yin_ctx, "base", strlen("base"), prefix, prefix_len, YANG_NONE), YANG_BASE);
231 assert_int_equal(yin_match_keyword(st->yin_ctx, "belongs-to", strlen("belongs-to"), prefix, prefix_len, YANG_NONE), YANG_BELONGS_TO);
232 assert_int_equal(yin_match_keyword(st->yin_ctx, "bit", strlen("bit"), prefix, prefix_len, YANG_NONE), YANG_BIT);
233 assert_int_equal(yin_match_keyword(st->yin_ctx, "case", strlen("case"), prefix, prefix_len, YANG_NONE), YANG_CASE);
234 assert_int_equal(yin_match_keyword(st->yin_ctx, "choice", strlen("choice"), prefix, prefix_len, YANG_NONE), YANG_CHOICE);
235 assert_int_equal(yin_match_keyword(st->yin_ctx, "config", strlen("config"), prefix, prefix_len, YANG_NONE), YANG_CONFIG);
236 assert_int_equal(yin_match_keyword(st->yin_ctx, "contact", strlen("contact"), prefix, prefix_len, YANG_NONE), YANG_CONTACT);
237 assert_int_equal(yin_match_keyword(st->yin_ctx, "container", strlen("container"), prefix, prefix_len, YANG_NONE), YANG_CONTAINER);
238 assert_int_equal(yin_match_keyword(st->yin_ctx, "default", strlen("default"), prefix, prefix_len, YANG_NONE), YANG_DEFAULT);
239 assert_int_equal(yin_match_keyword(st->yin_ctx, "description", strlen("description"), prefix, prefix_len, YANG_NONE), YANG_DESCRIPTION);
240 assert_int_equal(yin_match_keyword(st->yin_ctx, "deviate", strlen("deviate"), prefix, prefix_len, YANG_NONE), YANG_DEVIATE);
241 assert_int_equal(yin_match_keyword(st->yin_ctx, "deviation", strlen("deviation"), prefix, prefix_len, YANG_NONE), YANG_DEVIATION);
242 assert_int_equal(yin_match_keyword(st->yin_ctx, "enum", strlen("enum"), prefix, prefix_len, YANG_NONE), YANG_ENUM);
243 assert_int_equal(yin_match_keyword(st->yin_ctx, "error-app-tag", strlen("error-app-tag"), prefix, prefix_len, YANG_NONE), YANG_ERROR_APP_TAG);
244 assert_int_equal(yin_match_keyword(st->yin_ctx, "error-message", strlen("error-message"), prefix, prefix_len, YANG_NONE), YANG_ERROR_MESSAGE);
245 assert_int_equal(yin_match_keyword(st->yin_ctx, "extension", strlen("extension"), prefix, prefix_len, YANG_NONE), YANG_EXTENSION);
246 assert_int_equal(yin_match_keyword(st->yin_ctx, "feature", strlen("feature"), prefix, prefix_len, YANG_NONE), YANG_FEATURE);
247 assert_int_equal(yin_match_keyword(st->yin_ctx, "fraction-digits", strlen("fraction-digits"), prefix, prefix_len, YANG_NONE), YANG_FRACTION_DIGITS);
248 assert_int_equal(yin_match_keyword(st->yin_ctx, "grouping", strlen("grouping"), prefix, prefix_len, YANG_NONE), YANG_GROUPING);
249 assert_int_equal(yin_match_keyword(st->yin_ctx, "identity", strlen("identity"), prefix, prefix_len, YANG_NONE), YANG_IDENTITY);
250 assert_int_equal(yin_match_keyword(st->yin_ctx, "if-feature", strlen("if-feature"), prefix, prefix_len, YANG_NONE), YANG_IF_FEATURE);
251 assert_int_equal(yin_match_keyword(st->yin_ctx, "import", strlen("import"), prefix, prefix_len, YANG_NONE), YANG_IMPORT);
252 assert_int_equal(yin_match_keyword(st->yin_ctx, "include", strlen("include"), prefix, prefix_len, YANG_NONE), YANG_INCLUDE);
253 assert_int_equal(yin_match_keyword(st->yin_ctx, "input", strlen("input"), prefix, prefix_len, YANG_NONE), YANG_INPUT);
254 assert_int_equal(yin_match_keyword(st->yin_ctx, "key", strlen("key"), prefix, prefix_len, YANG_NONE), YANG_KEY);
255 assert_int_equal(yin_match_keyword(st->yin_ctx, "leaf", strlen("leaf"), prefix, prefix_len, YANG_NONE), YANG_LEAF);
256 assert_int_equal(yin_match_keyword(st->yin_ctx, "leaf-list", strlen("leaf-list"), prefix, prefix_len, YANG_NONE), YANG_LEAF_LIST);
257 assert_int_equal(yin_match_keyword(st->yin_ctx, "length", strlen("length"), prefix, prefix_len, YANG_NONE), YANG_LENGTH);
258 assert_int_equal(yin_match_keyword(st->yin_ctx, "list", strlen("list"), prefix, prefix_len, YANG_NONE), YANG_LIST);
259 assert_int_equal(yin_match_keyword(st->yin_ctx, "mandatory", strlen("mandatory"), prefix, prefix_len, YANG_NONE), YANG_MANDATORY);
260 assert_int_equal(yin_match_keyword(st->yin_ctx, "max-elements", strlen("max-elements"), prefix, prefix_len, YANG_NONE), YANG_MAX_ELEMENTS);
261 assert_int_equal(yin_match_keyword(st->yin_ctx, "min-elements", strlen("min-elements"), prefix, prefix_len, YANG_NONE), YANG_MIN_ELEMENTS);
262 assert_int_equal(yin_match_keyword(st->yin_ctx, "modifier", strlen("modifier"), prefix, prefix_len, YANG_NONE), YANG_MODIFIER);
263 assert_int_equal(yin_match_keyword(st->yin_ctx, "module", strlen("module"), prefix, prefix_len, YANG_NONE), YANG_MODULE);
264 assert_int_equal(yin_match_keyword(st->yin_ctx, "must", strlen("must"), prefix, prefix_len, YANG_NONE), YANG_MUST);
265 assert_int_equal(yin_match_keyword(st->yin_ctx, "namespace", strlen("namespace"), prefix, prefix_len, YANG_NONE), YANG_NAMESPACE);
266 assert_int_equal(yin_match_keyword(st->yin_ctx, "notification", strlen("notification"), prefix, prefix_len, YANG_NONE), YANG_NOTIFICATION);
267 assert_int_equal(yin_match_keyword(st->yin_ctx, "ordered-by", strlen("ordered-by"), prefix, prefix_len, YANG_NONE), YANG_ORDERED_BY);
268 assert_int_equal(yin_match_keyword(st->yin_ctx, "organization", strlen("organization"), prefix, prefix_len, YANG_NONE), YANG_ORGANIZATION);
269 assert_int_equal(yin_match_keyword(st->yin_ctx, "output", strlen("output"), prefix, prefix_len, YANG_NONE), YANG_OUTPUT);
270 assert_int_equal(yin_match_keyword(st->yin_ctx, "path", strlen("path"), prefix, prefix_len, YANG_NONE), YANG_PATH);
271 assert_int_equal(yin_match_keyword(st->yin_ctx, "pattern", strlen("pattern"), prefix, prefix_len, YANG_NONE), YANG_PATTERN);
272 assert_int_equal(yin_match_keyword(st->yin_ctx, "position", strlen("position"), prefix, prefix_len, YANG_NONE), YANG_POSITION);
273 assert_int_equal(yin_match_keyword(st->yin_ctx, "prefix", strlen("prefix"), prefix, prefix_len, YANG_NONE), YANG_PREFIX);
274 assert_int_equal(yin_match_keyword(st->yin_ctx, "presence", strlen("presence"), prefix, prefix_len, YANG_NONE), YANG_PRESENCE);
275 assert_int_equal(yin_match_keyword(st->yin_ctx, "range", strlen("range"), prefix, prefix_len, YANG_NONE), YANG_RANGE);
276 assert_int_equal(yin_match_keyword(st->yin_ctx, "reference", strlen("reference"), prefix, prefix_len, YANG_NONE), YANG_REFERENCE);
277 assert_int_equal(yin_match_keyword(st->yin_ctx, "refine", strlen("refine"), prefix, prefix_len, YANG_NONE), YANG_REFINE);
278 assert_int_equal(yin_match_keyword(st->yin_ctx, "require-instance", strlen("require-instance"), prefix, prefix_len, YANG_NONE), YANG_REQUIRE_INSTANCE);
279 assert_int_equal(yin_match_keyword(st->yin_ctx, "revision", strlen("revision"), prefix, prefix_len, YANG_NONE), YANG_REVISION);
280 assert_int_equal(yin_match_keyword(st->yin_ctx, "revision-date", strlen("revision-date"), prefix, prefix_len, YANG_NONE), YANG_REVISION_DATE);
281 assert_int_equal(yin_match_keyword(st->yin_ctx, "rpc", strlen("rpc"), prefix, prefix_len, YANG_NONE), YANG_RPC);
282 assert_int_equal(yin_match_keyword(st->yin_ctx, "status", strlen("status"), prefix, prefix_len, YANG_NONE), YANG_STATUS);
283 assert_int_equal(yin_match_keyword(st->yin_ctx, "submodule", strlen("submodule"), prefix, prefix_len, YANG_NONE), YANG_SUBMODULE);
284 assert_int_equal(yin_match_keyword(st->yin_ctx, "type", strlen("type"), prefix, prefix_len, YANG_NONE), YANG_TYPE);
285 assert_int_equal(yin_match_keyword(st->yin_ctx, "typedef", strlen("typedef"), prefix, prefix_len, YANG_NONE), YANG_TYPEDEF);
286 assert_int_equal(yin_match_keyword(st->yin_ctx, "unique", strlen("unique"), prefix, prefix_len, YANG_NONE), YANG_UNIQUE);
287 assert_int_equal(yin_match_keyword(st->yin_ctx, "units", strlen("units"), prefix, prefix_len, YANG_NONE), YANG_UNITS);
288 assert_int_equal(yin_match_keyword(st->yin_ctx, "uses", strlen("uses"), prefix, prefix_len, YANG_NONE), YANG_USES);
289 assert_int_equal(yin_match_keyword(st->yin_ctx, "value", strlen("value"), prefix, prefix_len, YANG_NONE), YANG_VALUE);
290 assert_int_equal(yin_match_keyword(st->yin_ctx, "when", strlen("when"), prefix, prefix_len, YANG_NONE), YANG_WHEN);
291 assert_int_equal(yin_match_keyword(st->yin_ctx, "yang-version", strlen("yang-version"), prefix, prefix_len, YANG_NONE), YANG_YANG_VERSION);
292 assert_int_equal(yin_match_keyword(st->yin_ctx, "yin-element", strlen("yin-element"), prefix, prefix_len, YANG_NONE), YANG_YIN_ELEMENT);
David Sedlák8f7a1172019-06-20 14:42:18 +0200293
294 st->finished_correctly = true;
David Sedlák872c7b42018-10-26 13:15:20 +0200295}
David Sedlák3b4db242018-10-19 16:11:01 +0200296
David Sedlák872c7b42018-10-26 13:15:20 +0200297static void
David Sedlák060b00e2019-06-19 11:12:06 +0200298test_yin_match_argument_name(void **state)
David Sedlák872c7b42018-10-26 13:15:20 +0200299{
David Sedlák68a1af12019-03-08 13:46:54 +0100300 (void)state; /* unused */
David Sedlák872c7b42018-10-26 13:15:20 +0200301
David Sedlák060b00e2019-06-19 11:12:06 +0200302 assert_int_equal(yin_match_argument_name("", 5), YIN_ARG_UNKNOWN);
303 assert_int_equal(yin_match_argument_name("qwertyasd", 5), YIN_ARG_UNKNOWN);
304 assert_int_equal(yin_match_argument_name("conditionasd", 8), YIN_ARG_UNKNOWN);
305 assert_int_equal(yin_match_argument_name("condition", 9), YIN_ARG_CONDITION);
306 assert_int_equal(yin_match_argument_name("date", 4), YIN_ARG_DATE);
307 assert_int_equal(yin_match_argument_name("module", 6), YIN_ARG_MODULE);
308 assert_int_equal(yin_match_argument_name("name", 4), YIN_ARG_NAME);
309 assert_int_equal(yin_match_argument_name("tag", 3), YIN_ARG_TAG);
310 assert_int_equal(yin_match_argument_name("target-node", 11), YIN_ARG_TARGET_NODE);
311 assert_int_equal(yin_match_argument_name("text", 4), YIN_ARG_TEXT);
312 assert_int_equal(yin_match_argument_name("uri", 3), YIN_ARG_URI);
313 assert_int_equal(yin_match_argument_name("value", 5), YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200314}
315
David Sedlák68a1af12019-03-08 13:46:54 +0100316static void
David Sedlákb1a78352019-06-28 16:16:29 +0200317test_yin_parse_element_generic(void **state)
318{
319 const char *prefix, *name;
320 struct state *st = *state;
321 struct lysp_ext_instance exts;
322 size_t prefix_len, name_len;
323 LY_ERR ret;
324
325 memset(&exts, 0, sizeof(exts));
326
327 const char *data = "<elem attr=\"value\">text_value</elem>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200328 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
329 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 +0200330 assert_int_equal(ret, LY_SUCCESS);
David Sedlák1fdb2522019-07-09 16:22:57 +0200331 assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
David Sedlákb1a78352019-06-28 16:16:29 +0200332 assert_string_equal(exts.child->stmt, "elem");
333 assert_string_equal(exts.child->arg, "text_value");
David Sedlákb1a78352019-06-28 16:16:29 +0200334 assert_string_equal(exts.child->child->stmt, "attr");
335 assert_string_equal(exts.child->child->arg, "value");
336 assert_true(exts.child->child->flags & LYS_YIN_ATTR);
David Sedlákb1a78352019-06-28 16:16:29 +0200337 lysp_ext_instance_free(st->ctx, &exts);
David Sedlák5392a212019-07-01 09:19:10 +0200338 st = reset_state(state);
339
340 data = "<elem></elem>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200341 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
342 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 +0200343 assert_int_equal(ret, LY_SUCCESS);
344 assert_string_equal(exts.child->stmt, "elem");
345 assert_null(exts.child->child);
346 assert_null(exts.child->arg);
David Sedlákda8ffa32019-07-08 14:17:10 +0200347 assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
David Sedlák5392a212019-07-01 09:19:10 +0200348 lysp_ext_instance_free(st->ctx, &exts);
349
David Sedlákb1a78352019-06-28 16:16:29 +0200350 st->finished_correctly = true;
351}
352
353static void
354test_yin_parse_extension_instance(void **state)
355{
356 LY_ERR ret;
357 struct state *st = *state;
358 const char *prefix, *name;
359 size_t prefix_len, name_len;
360 struct yin_arg_record *args = NULL;
361 struct lysp_ext_instance *exts = NULL;
David Sedlákb1a78352019-06-28 16:16:29 +0200362 const char *data = "<ext value1=\"test\" value=\"test2\"><subelem>text</subelem></ext>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200363 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
364 yin_load_attributes(st->yin_ctx, &data, &args);
David Sedlák1f90d252019-07-10 17:09:32 +0200365 ret = yin_parse_extension_instance(st->yin_ctx, args, &data, name2fullname(name, prefix_len),
David Sedlák619db942019-07-03 14:47:30 +0200366 namelen2fulllen(name_len, prefix_len), LYEXT_SUBSTMT_CONTACT, 0, &exts);
David Sedlákb1a78352019-06-28 16:16:29 +0200367 assert_int_equal(ret, LY_SUCCESS);
368 assert_string_equal(exts->name, "ext");
369 assert_int_equal(exts->insubstmt_index, 0);
370 assert_true(exts->insubstmt == LYEXT_SUBSTMT_CONTACT);
371 assert_true(exts->yin & LYS_YIN);
372 assert_string_equal(exts->child->stmt, "value1");
373 assert_string_equal(exts->child->arg, "test");
374 assert_null(exts->child->child);
375 assert_true(exts->child->flags & LYS_YIN_ATTR);
376 assert_string_equal(exts->child->next->stmt, "value");
377 assert_string_equal(exts->child->next->arg, "test2");
378 assert_null(exts->child->next->child);
379 assert_true(exts->child->next->flags & LYS_YIN_ATTR);
380
381 assert_string_equal(exts->child->next->next->stmt, "subelem");
382 assert_string_equal(exts->child->next->next->arg, "text");
383 assert_null(exts->child->next->next->child);
384 assert_null(exts->child->next->next->next);
385 assert_false(exts->child->next->next->flags & LYS_YIN_ATTR);
David Sedlákda8ffa32019-07-08 14:17:10 +0200386 assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
David Sedlákb1a78352019-06-28 16:16:29 +0200387 LY_ARRAY_FREE(args);
388 lysp_ext_instance_free(st->ctx, exts);
389 LY_ARRAY_FREE(exts);
David Sedlákf250ecf2019-07-01 11:02:05 +0200390 exts = NULL;
391 args = NULL;
392 st = reset_state(state);
393
394 data = "<extension-elem />";
David Sedlákda8ffa32019-07-08 14:17:10 +0200395 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
396 yin_load_attributes(st->yin_ctx, &data, &args);
David Sedlák1f90d252019-07-10 17:09:32 +0200397 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 +0200398 assert_int_equal(ret, LY_SUCCESS);
399 assert_string_equal(exts->name, "extension-elem");
400 assert_null(exts->argument);
401 assert_null(exts->child);
402 assert_int_equal(exts->insubstmt, LYEXT_SUBSTMT_CONTACT);
403 assert_int_equal(exts->insubstmt_index, 0);
404 assert_true(exts->yin & LYS_YIN);
David Sedlákda8ffa32019-07-08 14:17:10 +0200405 assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
David Sedlákf250ecf2019-07-01 11:02:05 +0200406 LY_ARRAY_FREE(args);
407 lysp_ext_instance_free(st->ctx, exts);
408 LY_ARRAY_FREE(exts);
David Sedlákb1a78352019-06-28 16:16:29 +0200409 st->finished_correctly = true;
410}
411
David Sedlák555c7202019-07-04 12:14:12 +0200412static void
413test_yin_parse_content(void **state)
414{
415 struct state *st = *state;
416 LY_ERR ret = LY_SUCCESS;
417 struct sized_string name, prefix;
418 const char *data = "<prefix value=\"a_mod\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
419 "<custom xmlns=\"my-ext\">"
420 "totally amazing extension"
421 "</custom>"
David Sedlák986cb412019-07-04 13:10:11 +0200422 "<extension name=\"ext\">"
423 "<argument name=\"argname\"></argument>"
424 "<description><text>desc</text></description>"
425 "<reference><text>ref</text></reference>"
426 "<status value=\"deprecated\"></status>"
427 "</extension>"
David Sedlák555c7202019-07-04 12:14:12 +0200428 "<text xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">wsefsdf</text>"
David Sedlák32488102019-07-15 17:44:10 +0200429 "<if-feature name=\"foo\"></if-feature>"
David Sedlák32eee7b2019-07-09 12:38:44 +0200430 "<when condition=\"condition...\">"
431 "<reference><text>when_ref</text></reference>"
432 "<description><text>when_desc</text></description>"
433 "</when>"
David Sedláke1a30302019-07-10 13:49:38 +0200434 "<config value=\"true\"/>"
David Sedlákc1771b12019-07-10 15:55:46 +0200435 "<error-message>"
436 "<value>error-msg</value>"
437 "</error-message>"
David Sedlák2ce1be62019-07-10 16:15:09 +0200438 "<error-app-tag value=\"err-app-tag\"/>"
David Sedláka5b1d382019-07-10 16:31:09 +0200439 "<units name=\"radians\"></units>"
David Sedláke7084ce2019-07-10 16:44:15 +0200440 "<default value=\"default-value\"/>"
David Sedlák5545f5d2019-07-11 11:55:16 +0200441 "<position value=\"25\"></position>"
442 "<value value=\"-5\"/>"
David Sedlákcf5569a2019-07-11 13:31:34 +0200443 "<require-instance value=\"true\"></require-instance>"
David Sedlákb7296dd2019-07-11 14:58:38 +0200444 "<range value=\"5..10\" />"
David Sedlák438ae432019-07-11 15:36:54 +0200445 "<length value=\"baf\"/>"
David Sedlákd3983112019-07-12 11:20:56 +0200446 "<pattern value='pattern'>"
447 "<modifier value='invert-match'/>"
448 "</pattern>"
David Sedlákfd5b9c32019-07-12 15:33:13 +0200449 "<enum name=\"yay\">"
450 "</enum>"
David Sedlák555c7202019-07-04 12:14:12 +0200451 "</prefix>";
452 struct lysp_ext_instance *exts = NULL;
David Sedlák5f8191e2019-07-08 16:35:52 +0200453 const char **if_features = NULL;
David Sedlák555c7202019-07-04 12:14:12 +0200454 struct yin_arg_record *attrs = NULL;
David Sedláke7084ce2019-07-10 16:44:15 +0200455 const char *value, *err_msg, *app_tag, *units, *def;
David Sedlák986cb412019-07-04 13:10:11 +0200456 struct lysp_ext *ext_def = NULL;
David Sedlák32eee7b2019-07-09 12:38:44 +0200457 struct lysp_when *when_p = NULL;
David Sedlákcf5569a2019-07-11 13:31:34 +0200458 struct lysp_type_enum pos_enum = {}, val_enum = {};
David Sedlákfd5b9c32019-07-12 15:33:13 +0200459 struct lysp_type req_type = {}, range_type = {}, len_type = {}, patter_type = {}, enum_type = {};
David Sedláke1a30302019-07-10 13:49:38 +0200460 uint8_t config = 0;
David Sedlák555c7202019-07-04 12:14:12 +0200461
David Sedlákda8ffa32019-07-08 14:17:10 +0200462 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix.value, &prefix.len, &name.value, &name.len);
463 yin_load_attributes(st->yin_ctx, &data, &attrs);
David Sedlák555c7202019-07-04 12:14:12 +0200464
David Sedlákfd5b9c32019-07-12 15:33:13 +0200465 struct yin_subelement subelems[17] = {
David Sedlák438ae432019-07-11 15:36:54 +0200466 {YANG_CONFIG, &config, 0},
467 {YANG_DEFAULT, &def, 0},
David Sedlákfd5b9c32019-07-12 15:33:13 +0200468 {YANG_ENUM, &enum_type, 0},
David Sedlák438ae432019-07-11 15:36:54 +0200469 {YANG_ERROR_APP_TAG, &app_tag, 0},
470 {YANG_ERROR_MESSAGE, &err_msg, 0},
471 {YANG_EXTENSION, &ext_def, 0},
472 {YANG_IF_FEATURE, &if_features, 0},
473 {YANG_LENGTH, &len_type, 0},
David Sedlákd3983112019-07-12 11:20:56 +0200474 {YANG_PATTERN, &patter_type, 0},
David Sedlák438ae432019-07-11 15:36:54 +0200475 {YANG_POSITION, &pos_enum, 0},
476 {YANG_RANGE, &range_type, 0},
477 {YANG_REQUIRE_INSTANCE, &req_type, 0},
478 {YANG_UNITS, &units, 0},
479 {YANG_VALUE, &val_enum, 0},
480 {YANG_WHEN, &when_p, 0},
481 {YANG_CUSTOM, NULL, 0},
482 {YIN_TEXT, &value, 0}
David Sedlákd3983112019-07-12 11:20:56 +0200483 };
David Sedlákfd5b9c32019-07-12 15:33:13 +0200484 ret = yin_parse_content(st->yin_ctx, subelems, 17, &data, YANG_PREFIX, NULL, &exts);
David Sedlák555c7202019-07-04 12:14:12 +0200485 assert_int_equal(ret, LY_SUCCESS);
David Sedlák1fdb2522019-07-09 16:22:57 +0200486 assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
David Sedlák2ce1be62019-07-10 16:15:09 +0200487 /* check parsed values */
David Sedláke7084ce2019-07-10 16:44:15 +0200488 assert_string_equal(def, "default-value");
David Sedlák555c7202019-07-04 12:14:12 +0200489 assert_string_equal(exts->name, "custom");
490 assert_string_equal(exts->argument, "totally amazing extension");
491 assert_string_equal(value, "wsefsdf");
David Sedláka5b1d382019-07-10 16:31:09 +0200492 assert_string_equal(units, "radians");
David Sedlák32eee7b2019-07-09 12:38:44 +0200493 assert_string_equal(when_p->cond, "condition...");
494 assert_string_equal(when_p->dsc, "when_desc");
495 assert_string_equal(when_p->ref, "when_ref");
David Sedláke1a30302019-07-10 13:49:38 +0200496 assert_int_equal(config, LYS_CONFIG_W);
David Sedlák5545f5d2019-07-11 11:55:16 +0200497 assert_int_equal(pos_enum.value, 25);
498 assert_true(pos_enum.flags | LYS_SET_VALUE);
499 assert_int_equal(val_enum.value, -5);
500 assert_true(val_enum.flags | LYS_SET_VALUE);
David Sedlákcf5569a2019-07-11 13:31:34 +0200501 assert_int_equal(req_type.require_instance, 1);
502 assert_true(req_type.flags |= LYS_SET_REQINST);
David Sedlákb7296dd2019-07-11 14:58:38 +0200503 assert_string_equal(range_type.range->arg, "5..10");
504 assert_true(range_type.flags | LYS_SET_RANGE);
David Sedlákc1771b12019-07-10 15:55:46 +0200505 assert_string_equal(err_msg, "error-msg");
David Sedlák2ce1be62019-07-10 16:15:09 +0200506 assert_string_equal(app_tag, "err-app-tag");
David Sedlákfd5b9c32019-07-12 15:33:13 +0200507 assert_string_equal(enum_type.enums->name, "yay");
David Sedlák438ae432019-07-11 15:36:54 +0200508 assert_string_equal(len_type.length->arg, "baf");
509 assert_true(len_type.flags | LYS_SET_LENGTH);
David Sedlákd3983112019-07-12 11:20:56 +0200510 assert_string_equal(patter_type.patterns->arg, "\x015pattern");
511 assert_true(patter_type.flags | LYS_SET_PATTERN);
David Sedlák2ce1be62019-07-10 16:15:09 +0200512 /* cleanup */
David Sedlák555c7202019-07-04 12:14:12 +0200513 lysp_ext_instance_free(st->ctx, exts);
David Sedlák32eee7b2019-07-09 12:38:44 +0200514 lysp_when_free(st->ctx, when_p);
David Sedlák986cb412019-07-04 13:10:11 +0200515 lysp_ext_free(st->ctx, ext_def);
David Sedlák5f8191e2019-07-08 16:35:52 +0200516 FREE_STRING(st->ctx, *if_features);
David Sedlákc1771b12019-07-10 15:55:46 +0200517 FREE_STRING(st->ctx, err_msg);
David Sedlák2ce1be62019-07-10 16:15:09 +0200518 FREE_STRING(st->ctx, app_tag);
David Sedláka5b1d382019-07-10 16:31:09 +0200519 FREE_STRING(st->ctx, units);
David Sedlákd3983112019-07-12 11:20:56 +0200520 FREE_STRING(st->ctx, patter_type.patterns->arg);
David Sedláke7084ce2019-07-10 16:44:15 +0200521 FREE_STRING(st->ctx, def);
David Sedlákb7296dd2019-07-11 14:58:38 +0200522 FREE_STRING(st->ctx, range_type.range->arg);
David Sedlák438ae432019-07-11 15:36:54 +0200523 FREE_STRING(st->ctx, len_type.length->arg);
David Sedlákfd5b9c32019-07-12 15:33:13 +0200524 FREE_STRING(st->ctx, enum_type.enums->name);
David Sedlákb7296dd2019-07-11 14:58:38 +0200525 FREE_STRING(st->ctx, value);
David Sedlák5f8191e2019-07-08 16:35:52 +0200526 LY_ARRAY_FREE(if_features);
David Sedlák555c7202019-07-04 12:14:12 +0200527 LY_ARRAY_FREE(exts);
David Sedlák986cb412019-07-04 13:10:11 +0200528 LY_ARRAY_FREE(ext_def);
David Sedlák555c7202019-07-04 12:14:12 +0200529 LY_ARRAY_FREE(attrs);
David Sedlákd3983112019-07-12 11:20:56 +0200530 LY_ARRAY_FREE(patter_type.patterns);
David Sedlákfd5b9c32019-07-12 15:33:13 +0200531 LY_ARRAY_FREE(enum_type.enums);
David Sedlák32eee7b2019-07-09 12:38:44 +0200532 free(when_p);
David Sedlákb7296dd2019-07-11 14:58:38 +0200533 free(range_type.range);
David Sedlák438ae432019-07-11 15:36:54 +0200534 free(len_type.length);
David Sedlák555c7202019-07-04 12:14:12 +0200535 attrs = NULL;
David Sedlák555c7202019-07-04 12:14:12 +0200536 st = reset_state(state);
537
538 /* test unique subelem */
539 const char *prefix_value;
540 struct yin_subelement subelems2[2] = {{YANG_PREFIX, &prefix_value, 0},
541 {YIN_TEXT, &value, YIN_SUBELEM_UNIQUE}};
542 data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
543 "<prefix value=\"inv_mod\" />"
544 "<text xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">wsefsdf</text>"
545 "<text xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">wsefsdf</text>"
546 "</module>";
David Sedlákda8ffa32019-07-08 14:17:10 +0200547 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix.value, &prefix.len, &name.value, &name.len);
548 yin_load_attributes(st->yin_ctx, &data, &attrs);
549 ret = yin_parse_content(st->yin_ctx, subelems2, 2, &data, YANG_MODULE, NULL, &exts);
David Sedlák555c7202019-07-04 12:14:12 +0200550 assert_int_equal(ret, LY_EVALID);
551 logbuf_assert("Redefinition of text element in module element. Line number 1.");
552 lydict_remove(st->ctx, prefix_value);
553 lydict_remove(st->ctx, value);
554 st = reset_state(state);
555 LY_ARRAY_FREE(attrs);
556 attrs = NULL;
557
558 /* test first subelem */
559 data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
560 "<prefix value=\"inv_mod\" />"
561 "<text xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">wsefsdf</text>"
562 "<text xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">wsefsdf</text>"
563 "</module>";
564 struct yin_subelement subelems3[2] = {{YANG_PREFIX, &prefix_value, 0},
565 {YIN_TEXT, &value, YIN_SUBELEM_FIRST}};
David Sedlákda8ffa32019-07-08 14:17:10 +0200566 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix.value, &prefix.len, &name.value, &name.len);
567 yin_load_attributes(st->yin_ctx, &data, &attrs);
568 ret = yin_parse_content(st->yin_ctx, subelems3, 2, &data, YANG_MODULE, NULL, &exts);
David Sedlák555c7202019-07-04 12:14:12 +0200569 assert_int_equal(ret, LY_EVALID);
570 logbuf_assert("Subelement text of module element must be defined as first subelement. Line number 1.");
571 lydict_remove(st->ctx, prefix_value);
572 st = reset_state(state);
573 LY_ARRAY_FREE(attrs);
574 attrs = NULL;
575
576 /* test mandatory subelem */
577 data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
578 "</module>";
579 struct yin_subelement subelems4[1] = {{YANG_PREFIX, &prefix_value, YIN_SUBELEM_MANDATORY}};
David Sedlákda8ffa32019-07-08 14:17:10 +0200580 lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix.value, &prefix.len, &name.value, &name.len);
581 yin_load_attributes(st->yin_ctx, &data, &attrs);
582 ret = yin_parse_content(st->yin_ctx, subelems4, 1, &data, YANG_MODULE, NULL, &exts);
David Sedlák555c7202019-07-04 12:14:12 +0200583 assert_int_equal(ret, LY_EVALID);
584 logbuf_assert("Missing mandatory subelement prefix of module element. Line number 1.");
585 LY_ARRAY_FREE(attrs);
586
587 st->finished_correctly = true;
588}
589
David Sedlák92147b02019-07-09 14:01:01 +0200590static void
David Sedlák4a650532019-07-10 11:55:18 +0200591test_validate_value(void **state)
592{
593 struct state *st = *state;
594 assert_int_equal(yin_validate_value(st->yin_ctx, Y_IDENTIF_ARG, "#invalid", 8), LY_EVALID);
595 logbuf_assert("Invalid identifier character '#'. Line number 1.");
596 assert_int_equal(yin_validate_value(st->yin_ctx, Y_STR_ARG, "", 0), LY_SUCCESS);
597 assert_int_equal(yin_validate_value(st->yin_ctx, Y_IDENTIF_ARG, "pre:b", 5), LY_EVALID);
598 assert_int_equal(yin_validate_value(st->yin_ctx, Y_PREF_IDENTIF_ARG, "pre:b", 5), LY_SUCCESS);
599 assert_int_equal(yin_validate_value(st->yin_ctx, Y_PREF_IDENTIF_ARG, "pre:pre:b", 9), LY_EVALID);
600
601 st->finished_correctly = true;
602}
603
David Sedlák32488102019-07-15 17:44:10 +0200604static int
605setup_element_test(void **state)
606{
607 struct state *st = NULL;
608
609#if ENABLE_LOGGER_CHECKING
610 /* setup logger */
611 ly_set_log_clb(logger, 1);
612#endif
613
614 /* reset logbuf */
615 logbuf[0] = '\0';
616 /* allocate state variable */
617 (*state) = st = calloc(1, sizeof(*st));
618 if (!st) {
619 fprintf(stderr, "Memmory allocation failed");
620 return EXIT_FAILURE;
621 }
622
623 /* create new libyang context */
624 ly_ctx_new(NULL, 0, &st->ctx);
625
626 /* allocate parser context */
627 st->yin_ctx = calloc(1, sizeof(*st->yin_ctx));
628 st->yin_ctx->xml_ctx.ctx = st->ctx;
629 st->yin_ctx->xml_ctx.line = 1;
630
631 return EXIT_SUCCESS;
632}
633
634static int
635teardown_element_test(void **state)
636{
637 struct state *st = *(struct state **)state;
638
639#if ENABLE_LOGGER_CHECKING
640 /* teardown logger */
641 if (!st->finished_correctly && logbuf[0] != '\0') {
642 fprintf(stderr, "%s\n", logbuf);
643 }
644#endif
645
646 lyxml_context_clear(&st->yin_ctx->xml_ctx);
647 ly_ctx_destroy(st->ctx, NULL);
648 free(st->yin_ctx);
649 free(st);
650
651 return EXIT_SUCCESS;
652}
653
654#define ELEMENT_WRAPPER_START "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
655#define ELEMENT_WRAPPER_END "</module>"
656
657/* helper function to simplify unit test of each element using parse_content function */
658LY_ERR
659test_element_helper(struct state *st, const char **data, void *dest, const char **text,
660 struct lysp_ext_instance **exts, bool valid)
661{
662 struct yin_arg_record *attrs = NULL;
663 struct sized_string name, prefix;
664 LY_ERR ret = LY_SUCCESS;
665 struct yin_subelement subelems[71] = {
666 {YANG_ACTION, dest, 0},
667 {YANG_ANYDATA, dest, 0},
668 {YANG_ANYXML, dest, 0},
669 {YANG_ARGUMENT,dest, 0},
670 {YANG_AUGMENT, dest, 0},
671 {YANG_BASE, dest, 0},
672 {YANG_BELONGS_TO, dest, 0},
673 {YANG_BIT, dest, 0},
674 {YANG_CASE, dest, 0},
675 {YANG_CHOICE, dest, 0},
676 {YANG_CONFIG, dest, 0},
677 {YANG_CONTACT, dest, 0},
678 {YANG_CONTAINER, dest, 0},
679 {YANG_DEFAULT, dest, 0},
680 {YANG_DESCRIPTION, dest, 0},
681 {YANG_DEVIATE, dest, 0},
682 {YANG_DEVIATION, dest, 0},
683 {YANG_ENUM, dest, 0},
684 {YANG_ERROR_APP_TAG, dest, 0},
685 {YANG_ERROR_MESSAGE, dest, 0},
686 {YANG_EXTENSION, dest, 0},
687 {YANG_FEATURE, dest, 0},
688 {YANG_FRACTION_DIGITS, dest, 0},
689 {YANG_GROUPING, dest, 0},
690 {YANG_IDENTITY, dest, 0},
691 {YANG_IF_FEATURE, dest, 0},
692 {YANG_IMPORT, dest, 0},
693 {YANG_INCLUDE, dest, 0},
694 {YANG_INPUT, dest, 0},
695 {YANG_KEY, dest, 0},
696 {YANG_LEAF, dest, 0},
697 {YANG_LEAF_LIST, dest, 0},
698 {YANG_LENGTH, dest, 0},
699 {YANG_LIST, dest, 0},
700 {YANG_MANDATORY, dest, 0},
701 {YANG_MAX_ELEMENTS, dest, 0},
702 {YANG_MIN_ELEMENTS, dest, 0},
703 {YANG_MODIFIER, dest, 0},
704 {YANG_MODULE, dest, 0},
705 {YANG_MUST, dest, 0},
706 {YANG_NAMESPACE, dest, 0},
707 {YANG_NOTIFICATION, dest, 0},
708 {YANG_ORDERED_BY, dest, 0},
709 {YANG_ORGANIZATION, dest, 0},
710 {YANG_OUTPUT, dest, 0},
711 {YANG_PATH, dest, 0},
712 {YANG_PATTERN, dest, 0},
713 {YANG_POSITION, dest, 0},
714 {YANG_PREFIX, dest, 0},
715 {YANG_PRESENCE, dest, 0},
716 {YANG_RANGE, dest, 0},
717 {YANG_REFERENCE, dest, 0},
718 {YANG_REFINE, dest, 0},
719 {YANG_REQUIRE_INSTANCE, dest, 0},
720 {YANG_REVISION, dest, 0},
721 {YANG_REVISION_DATE, dest, 0},
722 {YANG_RPC, dest, 0},
723 {YANG_STATUS, dest, 0},
724 {YANG_SUBMODULE, dest, 0},
725 {YANG_TYPE, dest, 0},
726 {YANG_TYPEDEF, dest, 0},
727 {YANG_UNIQUE, dest, 0},
728 {YANG_UNITS, dest, 0},
729 {YANG_USES, dest, 0},
730 {YANG_VALUE, dest, 0},
731 {YANG_WHEN, dest, 0},
732 {YANG_YANG_VERSION, dest, 0},
733 {YANG_YIN_ELEMENT, dest, 0},
734 {YANG_CUSTOM, dest, 0},
735 {YIN_TEXT, dest, 0},
736 {YIN_VALUE, dest, 0}
737 };
738 LY_CHECK_RET(lyxml_get_element(&st->yin_ctx->xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len));\
739 LY_CHECK_RET(yin_load_attributes(st->yin_ctx, data, &attrs));\
740 ret = yin_parse_content(st->yin_ctx, subelems, 71, data, YANG_MODULE, text, exts);
741 LY_ARRAY_FREE(attrs);
742 if (valid) {
743 assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
744 }
745 /* reset status */
746 st->yin_ctx->xml_ctx.status = LYXML_ELEMENT;
747 return ret;
748}
749
750static void
751test_enum_bit_elem(void **state)
752{
753 /* yin_parse_enum_bit is function that is being mainly tested by this test */
754 struct state *st = *state;
755 struct lysp_type type = {};
756 const char *data;
757 data = ELEMENT_WRAPPER_START
758 "<enum name=\"enum-name\">"
759 "<if-feature name=\"feature\" />"
760 "<value value=\"55\" />"
761 "<status value=\"deprecated\" />"
762 "<description><text>desc...</text></description>"
763 "<reference><text>ref...</text></reference>"
764 "</enum>"
765 ELEMENT_WRAPPER_END;
766 assert_int_equal(test_element_helper(st, &data, &type, NULL, NULL, true), LY_SUCCESS);
767 assert_string_equal(*type.enums->iffeatures, "feature");
768 assert_int_equal(type.enums->value, 55);
769 assert_true(type.enums->flags | LYS_STATUS_DEPRC && type.enums->flags | LYS_SET_VALUE);
770 assert_string_equal(type.enums->dsc, "desc...");
771 assert_string_equal(type.enums->ref, "ref...");
772 lysp_type_free(st->ctx, &type);
773 memset(&type, 0, sizeof type);
774
775 /* todo bit element test */
776 st->finished_correctly = true;
777}
778
779static void
780test_meta_elem(void **state)
781{
782 struct state *st = *state;
783 char *value = NULL;
784 const char *data;
785
786 /* organization element */
787 data = ELEMENT_WRAPPER_START
788 "<organization><text>organization...</text></organization>"
789 ELEMENT_WRAPPER_END;
790 assert_int_equal(test_element_helper(st, &data, &value, NULL, NULL, true), LY_SUCCESS);
791 assert_string_equal(value, "organization...");
792 FREE_STRING(st->ctx, value);
793 value = NULL;
794 /* contact element */
795 data = ELEMENT_WRAPPER_START
796 "<contact><text>contact...</text></contact>"
797 ELEMENT_WRAPPER_END;
798 assert_int_equal(test_element_helper(st, &data, &value, NULL, NULL, true), LY_SUCCESS);
799 assert_string_equal(value, "contact...");
800 FREE_STRING(st->ctx, value);
801 value = NULL;
802 /* description element */
803 data = ELEMENT_WRAPPER_START
804 "<description><text>description...</text></description>"
805 ELEMENT_WRAPPER_END;
806 assert_int_equal(test_element_helper(st, &data, &value, NULL, NULL, true), LY_SUCCESS);
807 assert_string_equal(value, "description...");
808 FREE_STRING(st->ctx, value);
809 value = NULL;
810 /* reference element */
811 data = ELEMENT_WRAPPER_START
812 "<reference><text>reference...</text></reference>"
813 ELEMENT_WRAPPER_END;
814 assert_int_equal(test_element_helper(st, &data, &value, NULL, NULL, true), LY_SUCCESS);
815 assert_string_equal(value, "reference...");
816 FREE_STRING(st->ctx, value);
817 value = NULL;
818
819 /* missing text subelement */
820 data = ELEMENT_WRAPPER_START
821 "<reference>reference...</reference>"
822 ELEMENT_WRAPPER_END;
823 assert_int_equal(test_element_helper(st, &data, &value, NULL, NULL, false), LY_EVALID);
824 logbuf_assert("Missing mandatory subelement text of reference element. Line number 1.");
825
826 st->finished_correctly = true;
827}
828
829static void
830test_import_elem(void **state)
831{
832 struct state *st = *state;
833 const char *data;
834 struct lys_module *lys_mod = calloc(1, sizeof *lys_mod);
835 struct lysp_module *lysp_mod = calloc(1, sizeof *lysp_mod);
836 lys_mod->ctx = st->ctx;
837 lysp_mod->mod = lys_mod;
838
839 /* max subelems */
840 data = ELEMENT_WRAPPER_START
841 "<import module=\"a\">"
842 "<prefix value=\"a_mod\"/>"
843 "<revision-date date=\"2015-01-01\"></revision-date>"
844 "<description><text>import description</text></description>"
845 "<reference><text>import reference</text></reference>"
846 "</import>"
847 ELEMENT_WRAPPER_END;
848 assert_int_equal(test_element_helper(st, &data, lysp_mod, NULL, NULL, true), LY_SUCCESS);
849 assert_string_equal(lysp_mod->imports->name, "a");
850 assert_string_equal(lysp_mod->imports->prefix, "a_mod");
851 assert_string_equal(lysp_mod->imports->rev, "2015-01-01");
852 assert_string_equal(lysp_mod->imports->dsc, "import description");
853 assert_string_equal(lysp_mod->imports->ref, "import reference");
854 lysp_module_free(lysp_mod);
855 lys_module_free(lys_mod, NULL);
856
857 /* min subelems */
858 lys_mod = calloc(1, sizeof *lys_mod);
859 lysp_mod = calloc(1, sizeof *lysp_mod);
860 lys_mod->ctx = st->ctx;
861 lysp_mod->mod = lys_mod;
862 data = ELEMENT_WRAPPER_START
863 "<import module=\"a\">"
864 "<prefix value=\"a_mod\"/>"
865 "</import>"
866 ELEMENT_WRAPPER_END;
867 assert_int_equal(test_element_helper(st, &data, lysp_mod, NULL, NULL, true), LY_SUCCESS);
868 assert_string_equal(lysp_mod->imports->prefix, "a_mod");
869 lysp_module_free(lysp_mod);
870 lys_module_free(lys_mod, NULL);
871
872 /* invalid (missing prefix) */
873 lys_mod = calloc(1, sizeof *lys_mod);
874 lysp_mod = calloc(1, sizeof *lysp_mod);
875 lys_mod->ctx = st->ctx;
876 lysp_mod->mod = lys_mod;
877 data = ELEMENT_WRAPPER_START "<import module=\"a\">""</import>" ELEMENT_WRAPPER_END;
878 assert_int_equal(test_element_helper(st, &data, lysp_mod, NULL, NULL, false), LY_EVALID);
879 logbuf_assert("Missing mandatory subelement prefix of import element. Line number 1.");
880 lysp_module_free(lysp_mod);
881 lys_module_free(lys_mod, NULL);
882
883 /* invalid reused prefix */
884 lys_mod = calloc(1, sizeof *lys_mod);
885 lysp_mod = calloc(1, sizeof *lysp_mod);
886 lys_mod->ctx = st->ctx;
887 lysp_mod->mod = lys_mod;
888 data = ELEMENT_WRAPPER_START
889 "<import module=\"a\">"
890 "<prefix value=\"a_mod\"/>"
891 "</import>"
892 "<import module=\"a\">"
893 "<prefix value=\"a_mod\"/>"
894 "</import>"
895 ELEMENT_WRAPPER_END;
896 assert_int_equal(test_element_helper(st, &data, lysp_mod, NULL, NULL, false), LY_EVALID);
897 logbuf_assert("Prefix \"a_mod\" already used to import \"a\" module. Line number 1.");
898 lysp_module_free(lysp_mod);
899 lys_module_free(lys_mod, NULL);
900
901 st->finished_correctly = true;
902}
903
904static void
905test_status_elem(void **state)
906{
907 struct state *st = *state;
908 const char *data;
909 uint16_t flags = 0;
910
911 /* test valid values */
912 data = ELEMENT_WRAPPER_START "<status value=\"current\" />" ELEMENT_WRAPPER_END;
913 assert_int_equal(test_element_helper(st, &data, &flags, NULL, NULL, true), LY_SUCCESS);
914 assert_true(flags | LYS_STATUS_CURR);
915
916 data = ELEMENT_WRAPPER_START "<status value=\"deprecated\" />" ELEMENT_WRAPPER_END;
917 assert_int_equal(test_element_helper(st, &data, &flags, NULL, NULL, true), LY_SUCCESS);
918 assert_true(flags | LYS_STATUS_DEPRC);
919
920 data = ELEMENT_WRAPPER_START "<status value=\"obsolete\"></status>" ELEMENT_WRAPPER_END;
921 assert_int_equal(test_element_helper(st, &data, &flags, NULL, NULL, true), LY_SUCCESS);
922 assert_true(flags | LYS_STATUS_OBSLT);
923
924 /* test invalid value */
925 data = ELEMENT_WRAPPER_START "<status value=\"invalid\"></status>" ELEMENT_WRAPPER_END;
926 assert_int_equal(test_element_helper(st, &data, &flags, NULL, NULL, false), LY_EVALID);
927 logbuf_assert("Invalid value \"invalid\" of \"status\". Line number 1.");
928 st->finished_correctly = true;
929}
930
931static void
932test_ext_elem(void **state)
933{
934 struct state *st = *state;
935 const char *data;
936 struct lysp_ext *ext = NULL;
937
938 /* max subelems */
939 data = ELEMENT_WRAPPER_START
940 "<extension name=\"ext_name\">"
941 "<argument name=\"arg\"></argument>"
942 "<status value=\"current\"/>"
943 "<description><text>ext_desc</text></description>"
944 "<reference><text>ext_ref</text></reference>"
945 "</extension>"
946 ELEMENT_WRAPPER_END;
947 assert_int_equal(test_element_helper(st, &data, &ext, NULL, NULL, true), LY_SUCCESS);
948 assert_string_equal(ext->name, "ext_name");
949 assert_string_equal(ext->argument, "arg");
950 assert_true(ext->flags | LYS_STATUS_CURR);
951 assert_string_equal(ext->dsc, "ext_desc");
952 assert_string_equal(ext->ref, "ext_ref");
953 lysp_ext_free(st->ctx, ext);
954 LY_ARRAY_FREE(ext);
955 ext = NULL;
956
957 /* min subelems */
958 data = ELEMENT_WRAPPER_START "<extension name=\"ext_name\"></extension>" ELEMENT_WRAPPER_END;
959 assert_int_equal(test_element_helper(st, &data, &ext, NULL, NULL, true), LY_SUCCESS);
960 assert_string_equal(ext->name, "ext_name");
961 lysp_ext_free(st->ctx, ext);
962 LY_ARRAY_FREE(ext);
963 ext = NULL;
964
965 st->finished_correctly = true;
966}
967
968static void
969test_yin_element_elem(void **state)
970{
971 struct state *st = *state;
972 const char *data;
973 uint16_t flags = 0;
974
975 data = ELEMENT_WRAPPER_START "<yin-element value=\"true\" />" ELEMENT_WRAPPER_END;
976 assert_int_equal(test_element_helper(st, &data, &flags, NULL, NULL, true), LY_SUCCESS);
977 assert_true(flags | LYS_YINELEM_TRUE);
978
979 data = ELEMENT_WRAPPER_START "<yin-element value=\"false\" />" ELEMENT_WRAPPER_END;
980 assert_int_equal(test_element_helper(st, &data, &flags, NULL, NULL, true), LY_SUCCESS);
981 assert_true(flags | LYS_YINELEM_TRUE);
982
983 data = ELEMENT_WRAPPER_START "<yin-element value=\"invalid\" />" ELEMENT_WRAPPER_END;
984 assert_int_equal(test_element_helper(st, &data, &flags, NULL, NULL, false), LY_EVALID);
985 assert_true(flags | LYS_YINELEM_TRUE);
986 logbuf_assert("Invalid value \"invalid\" of \"yin-element\". Line number 1.");
987 st->finished_correctly = true;
988}
989
990static void
991test_yangversion_elem(void **state)
992{
993 struct state *st = *state;
994 const char *data;
995 uint8_t version = 0;
996
997 /* valid values */
998 data = ELEMENT_WRAPPER_START "<yang-version value=\"1.0\" />" ELEMENT_WRAPPER_END;
999 assert_int_equal(test_element_helper(st, &data, &version, NULL, NULL, true), LY_SUCCESS);
1000 assert_true(version | LYS_VERSION_1_0);
1001 assert_int_equal(st->yin_ctx->mod_version, LYS_VERSION_1_0);
1002
1003 data = ELEMENT_WRAPPER_START "<yang-version value=\"1.1\" />" ELEMENT_WRAPPER_END;
1004 assert_int_equal(test_element_helper(st, &data, &version, NULL, NULL, true), LY_SUCCESS);
1005 assert_true(version | LYS_VERSION_1_1);
1006 assert_int_equal(st->yin_ctx->mod_version, LYS_VERSION_1_1);
1007
1008 /* invalid value */
1009 data = ELEMENT_WRAPPER_START "<yang-version value=\"version\" />" ELEMENT_WRAPPER_END;
1010 assert_int_equal(test_element_helper(st, &data, &version, NULL, NULL, false), LY_EVALID);
1011 logbuf_assert("Invalid value \"version\" of \"yang-version\". Line number 1.");
1012
1013 st->finished_correctly = true;
1014}
1015
1016static void
1017test_mandatory_elem(void **state)
1018{
1019 struct state *st = *state;
1020 const char *data;
1021 uint16_t man = 0;
1022
1023 /* valid values */
1024 data = ELEMENT_WRAPPER_START "<mandatory value=\"true\" />" ELEMENT_WRAPPER_END;
1025 assert_int_equal(test_element_helper(st, &data, &man, NULL, NULL, true), LY_SUCCESS);
1026 assert_int_equal(man, LYS_MAND_TRUE);
1027 man = 0;
1028
1029 data = ELEMENT_WRAPPER_START "<mandatory value=\"false\" />" ELEMENT_WRAPPER_END;
1030 assert_int_equal(test_element_helper(st, &data, &man, NULL, NULL, true), LY_SUCCESS);
1031 assert_int_equal(man, LYS_MAND_FALSE);
1032
1033 data = ELEMENT_WRAPPER_START "<mandatory value=\"invalid\" />" ELEMENT_WRAPPER_END;
1034 assert_int_equal(test_element_helper(st, &data, &man, NULL, NULL, false), LY_EVALID);
1035 logbuf_assert("Invalid value \"invalid\" of \"mandatory\". Line number 1.");
1036
1037 st->finished_correctly = true;
1038}
1039
1040
David Sedlák3b4db242018-10-19 16:11:01 +02001041int
1042main(void)
1043{
1044
1045 const struct CMUnitTest tests[] = {
David Sedlák392af4f2019-06-04 16:02:42 +02001046 cmocka_unit_test_setup_teardown(test_yin_parse_module, setup_f, teardown_f),
David Sedlák8f7a1172019-06-20 14:42:18 +02001047 cmocka_unit_test_setup_teardown(test_yin_match_keyword, setup_f, teardown_f),
David Sedlákb1a78352019-06-28 16:16:29 +02001048 cmocka_unit_test_setup_teardown(test_yin_parse_element_generic, setup_f, teardown_f),
1049 cmocka_unit_test_setup_teardown(test_yin_parse_extension_instance, setup_f, teardown_f),
David Sedlák555c7202019-07-04 12:14:12 +02001050 cmocka_unit_test_setup_teardown(test_yin_parse_content, setup_f, teardown_f),
David Sedlák4a650532019-07-10 11:55:18 +02001051 cmocka_unit_test_setup_teardown(test_validate_value, setup_f, teardown_f),
David Sedlák060b00e2019-06-19 11:12:06 +02001052 cmocka_unit_test(test_yin_match_argument_name),
David Sedlák32488102019-07-15 17:44:10 +02001053
1054 cmocka_unit_test_setup_teardown(test_enum_bit_elem, setup_element_test, teardown_element_test),
1055 cmocka_unit_test_setup_teardown(test_meta_elem, setup_element_test, teardown_element_test),
1056 cmocka_unit_test_setup_teardown(test_import_elem, setup_element_test, teardown_element_test),
1057 cmocka_unit_test_setup_teardown(test_status_elem, setup_element_test, teardown_element_test),
1058 cmocka_unit_test_setup_teardown(test_ext_elem, setup_element_test, teardown_element_test),
1059 cmocka_unit_test_setup_teardown(test_yin_element_elem, setup_element_test, teardown_element_test),
1060 cmocka_unit_test_setup_teardown(test_yangversion_elem, setup_element_test, teardown_element_test),
1061 cmocka_unit_test_setup_teardown(test_mandatory_elem, setup_element_test, teardown_element_test),
David Sedlák3b4db242018-10-19 16:11:01 +02001062 };
1063
1064 return cmocka_run_group_tests(tests, NULL, NULL);
1065}