blob: a5c153be1a0e7005fb831de28906bce59f241c63 [file] [log] [blame]
Radek Krejciad5963b2019-09-06 16:03:05 +02001/*
2 * @file test_metadata.c
3 * @author: Radek Krejci <rkrejci@cesnet.cz>
4 * @brief unit tests for Metadata extension (annotation) support
5 *
6 * Copyright (c) 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
Radek Krejcib4ac5a92020-11-23 17:54:33 +010015#include "utests.h"
Radek Krejciad5963b2019-09-06 16:03:05 +020016
Radek Krejci70593c12020-06-13 20:48:09 +020017#include "libyang.h"
18#include "plugins_exts_metadata.h"
Radek Krejciad5963b2019-09-06 16:03:05 +020019
20#define BUFSIZE 1024
21char logbuf[BUFSIZE] = {0};
22int store = -1; /* negative for infinite logging, positive for limited logging */
23
24struct state_s {
25 void *func;
26 struct ly_ctx *ctx;
27};
28
29/* set to 0 to printing error messages to stderr instead of checking them in code */
30#define ENABLE_LOGGER_CHECKING 1
31
32#if ENABLE_LOGGER_CHECKING
33static void
34logger(LY_LOG_LEVEL level, const char *msg, const char *path)
35{
36 (void) level; /* unused */
37 if (store) {
38 if (path && path[0]) {
39 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
40 } else {
41 strncpy(logbuf, msg, BUFSIZE - 1);
42 }
43 if (store > 0) {
44 --store;
45 }
46 }
47}
Radek Krejcib4ac5a92020-11-23 17:54:33 +010048
Radek Krejciad5963b2019-09-06 16:03:05 +020049#endif
50
51static int
52setup(void **state)
53{
54 struct state_s *s;
55
56 s = calloc(1, sizeof *s);
57 assert_non_null(s);
58
59#if ENABLE_LOGGER_CHECKING
60 ly_set_log_clb(logger, 1);
61#endif
62
63 assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &s->ctx));
64 *state = s;
65
66 return 0;
67}
68
69static int
70teardown(void **state)
71{
Radek Krejcib4ac5a92020-11-23 17:54:33 +010072 struct state_s *s = (struct state_s *)(*state);
Radek Krejciad5963b2019-09-06 16:03:05 +020073
74#if ENABLE_LOGGER_CHECKING
75 if (s->func) {
76 fprintf(stderr, "%s\n", logbuf);
77 }
78#endif
79
80 ly_ctx_destroy(s->ctx, NULL);
81 free(s);
82
83 return 0;
84}
85
86void
87logbuf_clean(void)
88{
89 logbuf[0] = '\0';
90}
91
92#if ENABLE_LOGGER_CHECKING
93# define logbuf_assert(str) assert_string_equal(logbuf, str)
94#else
95# define logbuf_assert(str)
96#endif
97
98static void
99test_yang(void **state)
100{
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100101 struct state_s *s = (struct state_s *)(*state);
102
Radek Krejciad5963b2019-09-06 16:03:05 +0200103 s->func = test_yang;
104
Michal Vasko3a41dff2020-07-15 14:30:28 +0200105 const struct lys_module *mod;
Radek Krejciad5963b2019-09-06 16:03:05 +0200106 struct lysc_ext_instance *e;
107 struct lyext_metadata *ant;
Michal Vasko7b1ad1a2020-11-02 15:41:27 +0100108 struct ly_in *in;
Radek Krejciad5963b2019-09-06 16:03:05 +0200109
110 const char *data = "module a {yang-version 1.1; namespace urn:tests:extensions:metadata:a; prefix a;"
111 "import ietf-yang-metadata {prefix md;}"
112 "feature f;"
113 "md:annotation x {"
114 " description \"test\";"
115 " if-feature f;"
116 " reference \"test\";"
117 " status \"current\";"
118 " type uint8;"
119 " units meters;"
120 "}}";
Michal Vasko7b1ad1a2020-11-02 15:41:27 +0100121 const char *feats[] = {"f", NULL};
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100122
Michal Vasko7b1ad1a2020-11-02 15:41:27 +0100123 assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
124 assert_int_equal(LY_SUCCESS, lys_parse(s->ctx, in, LYS_IN_YANG, feats, &mod));
125 ly_in_free(in, 0);
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200126 assert_int_equal(1, LY_ARRAY_COUNT(mod->compiled->exts));
Radek Krejciad5963b2019-09-06 16:03:05 +0200127 e = &mod->compiled->exts[0];
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100128 assert_non_null(ant = (struct lyext_metadata *)e->data);
Radek Krejciad5963b2019-09-06 16:03:05 +0200129 assert_string_equal("meters", ant->units);
130
131 /* invalid */
132 /* missing mandatory type substatement */
133 data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
134 "import ietf-yang-metadata {prefix md;}"
135 "md:annotation aa;}";
Michal Vasko3a41dff2020-07-15 14:30:28 +0200136 assert_int_equal(LY_EVALID, lys_parse_mem(s->ctx, data, LYS_IN_YANG, NULL));
Radek Krejciad5963b2019-09-06 16:03:05 +0200137 logbuf_assert("Missing mandatory keyword \"type\" as a child of \"md:annotation aa\". /aa:{extension='md:annotation'}/aa");
138
139 /* not allowed substatement */
140 data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
141 "import ietf-yang-metadata {prefix md;}"
142 "md:annotation aa {default x;}}";
Michal Vasko3a41dff2020-07-15 14:30:28 +0200143 assert_int_equal(LY_EVALID, lys_parse_mem(s->ctx, data, LYS_IN_YANG, NULL));
Radek Krejciad5963b2019-09-06 16:03:05 +0200144 logbuf_assert("Invalid keyword \"default\" as a child of \"md:annotation aa\" extension instance. /aa:{extension='md:annotation'}/aa");
145
146 /* invalid cardinality of units substatement */
147 data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
148 "import ietf-yang-metadata {prefix md;}"
149 "md:annotation aa {type string; units x; units y;}}";
Michal Vasko3a41dff2020-07-15 14:30:28 +0200150 assert_int_equal(LY_EVALID, lys_parse_mem(s->ctx, data, LYS_IN_YANG, NULL));
Radek Krejciad5963b2019-09-06 16:03:05 +0200151 logbuf_assert("Duplicate keyword \"units\". /aa:{extension='md:annotation'}/aa");
152
153 /* invalid cardinality of status substatement */
154 data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
155 "import ietf-yang-metadata {prefix md;}"
156 "md:annotation aa {type string; status current; status obsolete;}}";
Michal Vasko3a41dff2020-07-15 14:30:28 +0200157 assert_int_equal(LY_EVALID, lys_parse_mem(s->ctx, data, LYS_IN_YANG, NULL));
Radek Krejciad5963b2019-09-06 16:03:05 +0200158 logbuf_assert("Duplicate keyword \"status\". /aa:{extension='md:annotation'}/aa");
159
160 /* invalid cardinality of status substatement */
161 data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
162 "import ietf-yang-metadata {prefix md;}"
163 "md:annotation aa {type string; type uint8;}}";
Michal Vasko3a41dff2020-07-15 14:30:28 +0200164 assert_int_equal(LY_EVALID, lys_parse_mem(s->ctx, data, LYS_IN_YANG, NULL));
Radek Krejciad5963b2019-09-06 16:03:05 +0200165 logbuf_assert("Duplicate keyword \"type\". /aa:{extension='md:annotation'}/aa");
166
167 /* duplication of the same annotation */
168 data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
169 "import ietf-yang-metadata {prefix md;}"
170 "md:annotation aa {type string;} md:annotation aa {type uint8;}}";
Michal Vasko3a41dff2020-07-15 14:30:28 +0200171 assert_int_equal(LY_EVALID, lys_parse_mem(s->ctx, data, LYS_IN_YANG, NULL));
Radek Krejciad5963b2019-09-06 16:03:05 +0200172 logbuf_assert("Extension plugin \"libyang 2 - metadata, version 1\": "
173 "Extension md:annotation is instantiated multiple times.) /aa:{extension='md:annotation'}/aa");
174
175 s->func = NULL;
176}
177
Radek Krejci7c960162019-09-18 14:16:12 +0200178static void
179test_yin(void **state)
180{
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100181 struct state_s *s = (struct state_s *)(*state);
182
Radek Krejci7c960162019-09-18 14:16:12 +0200183 s->func = test_yin;
184
Michal Vasko3a41dff2020-07-15 14:30:28 +0200185 const struct lys_module *mod;
Radek Krejci7c960162019-09-18 14:16:12 +0200186 struct lysc_ext_instance *e;
187 struct lyext_metadata *ant;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200188 const char *data;
Radek Krejci7c960162019-09-18 14:16:12 +0200189
Michal Vasko7f45cf22020-10-01 12:49:44 +0200190 /* TODO yin-extension-prefix-compilation-bug
191 data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"a\">\n"
Radek Krejci7c960162019-09-18 14:16:12 +0200192 "<yang-version value=\"1.1\"/><namespace uri=\"urn:tests:extensions:metadata:a\"/><prefix value=\"a\"/>\n"
193 "<import module=\"ietf-yang-metadata\"><prefix value=\"md\"/></import>\n"
194 "<feature name=\"f\"/>\n"
195 "<md:annotation name=\"x\">\n"
196 " <description><text>test</text></description>\n"
197 " <reference><text>test</text></reference>\n"
198 " <if-feature name=\"f\"/>\n"
199 " <status value=\"current\"/>\n"
200 " <type name=\"uint8\"/>\n"
201 " <units name=\"meters\"/>\n"
202 "</md:annotation></module>";
Michal Vasko3a41dff2020-07-15 14:30:28 +0200203 assert_int_equal(LY_SUCCESS, lys_parse_mem(s->ctx, data, LYS_IN_YIN, &mod));
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200204 assert_int_equal(1, LY_ARRAY_COUNT(mod->compiled->exts));
Radek Krejci7c960162019-09-18 14:16:12 +0200205 e = &mod->compiled->exts[0];
206 assert_non_null(ant = (struct lyext_metadata*)e->data);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200207 assert_string_equal("meters", ant->units);*/
Radek Krejci7c960162019-09-18 14:16:12 +0200208
209 /* invalid */
210 /* missing mandatory type substatement */
211 data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
212 "<yang-version value=\"1.1\"/><namespace uri=\"urn:tests:extensions:metadata:aa\"/><prefix value=\"aa\"/>\n"
213 "<import module=\"ietf-yang-metadata\"><prefix value=\"md\"/></import>\n"
214 "<md:annotation name=\"aa\"/>\n"
215 "</module>";
Michal Vasko3a41dff2020-07-15 14:30:28 +0200216 assert_int_equal(LY_EVALID, lys_parse_mem(s->ctx, data, LYS_IN_YIN, NULL));
Radek Krejci7c960162019-09-18 14:16:12 +0200217 logbuf_assert("Missing mandatory keyword \"type\" as a child of \"md:annotation aa\". /aa:{extension='md:annotation'}/aa");
218
219 /* not allowed substatement */
220 data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
221 "<yang-version value=\"1.1\"/><namespace uri=\"urn:tests:extensions:metadata:aa\"/><prefix value=\"aa\"/>\n"
222 "<import module=\"ietf-yang-metadata\"><prefix value=\"md\"/></import>\n"
223 "<md:annotation name=\"aa\">\n"
224 " <default value=\"x\"/>\n"
225 "</md:annotation></module>";
Michal Vasko3a41dff2020-07-15 14:30:28 +0200226 assert_int_equal(LY_EVALID, lys_parse_mem(s->ctx, data, LYS_IN_YIN, NULL));
Radek Krejci7c960162019-09-18 14:16:12 +0200227 logbuf_assert("Invalid keyword \"default\" as a child of \"md:annotation aa\" extension instance. /aa:{extension='md:annotation'}/aa");
228
229 /* invalid cardinality of units substatement */
230 data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
231 "<yang-version value=\"1.1\"/><namespace uri=\"urn:tests:extensions:metadata:aa\"/><prefix value=\"aa\"/>\n"
232 "<import module=\"ietf-yang-metadata\"><prefix value=\"md\"/></import>\n"
233 "<md:annotation name=\"aa\">\n"
234 " <type name=\"string\"/>\n"
235 " <units name=\"x\"/>\n"
236 " <units name=\"y\"/>\n"
237 "</md:annotation></module>";
Michal Vasko3a41dff2020-07-15 14:30:28 +0200238 assert_int_equal(LY_EVALID, lys_parse_mem(s->ctx, data, LYS_IN_YIN, NULL));
Radek Krejci7c960162019-09-18 14:16:12 +0200239 logbuf_assert("Duplicate keyword \"units\". /aa:{extension='md:annotation'}/aa");
240
241 /* invalid cardinality of status substatement */
242 data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
243 "<yang-version value=\"1.1\"/><namespace uri=\"urn:tests:extensions:metadata:aa\"/><prefix value=\"aa\"/>\n"
244 "<import module=\"ietf-yang-metadata\"><prefix value=\"md\"/></import>\n"
245 "<md:annotation name=\"aa\">\n"
246 " <type name=\"string\"/>\n"
247 " <status value=\"current\"/>\n"
248 " <status value=\"obsolete\"/>\n"
249 "</md:annotation></module>";
Michal Vasko3a41dff2020-07-15 14:30:28 +0200250 assert_int_equal(LY_EVALID, lys_parse_mem(s->ctx, data, LYS_IN_YIN, NULL));
Radek Krejci7c960162019-09-18 14:16:12 +0200251 logbuf_assert("Duplicate keyword \"status\". /aa:{extension='md:annotation'}/aa");
252
253 /* invalid cardinality of status substatement */
254 data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
255 "<yang-version value=\"1.1\"/><namespace uri=\"urn:tests:extensions:metadata:aa\"/><prefix value=\"aa\"/>\n"
256 "<import module=\"ietf-yang-metadata\"><prefix value=\"md\"/></import>\n"
257 "<md:annotation name=\"aa\">\n"
258 " <type name=\"string\"/>\n"
259 " <type name=\"uint8\"/>\n"
260 "</md:annotation></module>";
Michal Vasko3a41dff2020-07-15 14:30:28 +0200261 assert_int_equal(LY_EVALID, lys_parse_mem(s->ctx, data, LYS_IN_YIN, NULL));
Radek Krejci7c960162019-09-18 14:16:12 +0200262 logbuf_assert("Duplicate keyword \"type\". /aa:{extension='md:annotation'}/aa");
263
264 /* duplication of the same annotation */
265 data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
266 "<yang-version value=\"1.1\"/><namespace uri=\"urn:tests:extensions:metadata:aa\"/><prefix value=\"aa\"/>\n"
267 "<import module=\"ietf-yang-metadata\"><prefix value=\"md\"/></import>\n"
268 "<md:annotation name=\"aa\">\n"
269 " <type name=\"string\"/>\n"
270 "</md:annotation><md:annotation name=\"aa\">\n"
271 " <type name=\"uint8\"/>\n"
272 "</md:annotation></module>";
Michal Vasko3a41dff2020-07-15 14:30:28 +0200273 assert_int_equal(LY_EVALID, lys_parse_mem(s->ctx, data, LYS_IN_YIN, NULL));
Radek Krejci7c960162019-09-18 14:16:12 +0200274 logbuf_assert("Extension plugin \"libyang 2 - metadata, version 1\": "
275 "Extension md:annotation is instantiated multiple times.) /aa:{extension='md:annotation'}/aa");
276 s->func = NULL;
277}
278
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100279int
280main(void)
Radek Krejciad5963b2019-09-06 16:03:05 +0200281{
282 const struct CMUnitTest tests[] = {
283 cmocka_unit_test_setup_teardown(test_yang, setup, teardown),
Radek Krejci7c960162019-09-18 14:16:12 +0200284 cmocka_unit_test_setup_teardown(test_yin, setup, teardown),
Radek Krejciad5963b2019-09-06 16:03:05 +0200285 };
286
287 return cmocka_run_group_tests(tests, NULL, NULL);
288}