blob: e19f991ce611f2be36f3fbf3b7b857cd0a9f872f [file] [log] [blame]
Václav Kubernát0d4db442018-07-18 17:18:43 +02001/*
2 * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
3 * Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
4 *
5 * Written by Václav Kubernát <kubervac@fit.cvut.cz>
6 *
7*/
8
9#include "trompeloeil_catch.h"
10#include "yang_schema.hpp"
11
Václav Kubernát4f77a252019-02-19 16:51:30 +010012const char* second_schema = R"(
13module second-schema {
14 namespace "http://example.com/nevim";
15 prefix second;
16
17 import example-schema {
18 prefix "example";
19 }
20
Václav Kubernáteeb38842019-03-20 19:46:05 +010021 identity pineapple {
22 base "example:fruit";
23 }
24
Václav Kubernát4f77a252019-02-19 16:51:30 +010025 augment /example:a {
26 container augmentedContainer {
27 }
28 }
29
30 container bla {
31 container bla2 {
32 }
33 }
34}
35)";
36
37const char* example_schema = R"(
Václav Kubernát0d4db442018-07-18 17:18:43 +020038module example-schema {
Václav Kubernát6a713d62018-10-03 18:47:34 +020039 yang-version 1.1;
Václav Kubernát0d4db442018-07-18 17:18:43 +020040 namespace "http://example.com/example-sports";
41 prefix coze;
42
Václav Kubernáteeb38842019-03-20 19:46:05 +010043 identity drink {
44 }
45
46 identity voda {
47 base "drink";
48 }
49
50 identity food {
51 }
52
53 identity fruit {
54 base "food";
55 }
56
57 identity pizza {
58 base "food";
59 }
60
61 identity hawaii {
62 base "pizza";
63 }
64
Václav Kubernát0d4db442018-07-18 17:18:43 +020065 container a {
66 container a2 {
67 container a3 {
68 presence true;
69 }
70 }
71
72 leaf leafa {
73 type string;
74 }
75 }
76
77 container b {
78 container b2 {
79 presence true;
80 container b3 {
81 }
82 }
83 }
84
85 leaf leafString {
86 type string;
87 }
88
89 leaf leafDecimal {
90 type decimal64 {
91 fraction-digits 5;
92 }
93 }
94
95 leaf leafBool {
96 type boolean;
97 }
98
99 leaf leafInt {
100 type int32;
101 }
102
103 leaf leafUint {
104 type uint32;
105 }
106
107 leaf leafEnum {
108 type enumeration {
109 enum lol;
110 enum data;
111 enum coze;
112 }
113 }
114
Václav Kubernát6a713d62018-10-03 18:47:34 +0200115 typedef enumTypedef {
116 type enumeration {
117 enum lol;
118 enum data;
119 enum coze;
120 }
121 }
122
123 typedef enumTypedefRestricted {
124 type enumTypedef {
125 enum lol;
126 enum data;
127 }
128 }
129
130 leaf leafEnumTypedef {
131 type enumTypedef;
132 }
133
134 leaf leafEnumTypedefRestricted {
135 type enumTypedef {
136 enum data;
137 enum coze;
138 }
139 }
140
141 leaf leafEnumTypedefRestricted2 {
142 type enumTypedefRestricted;
143 }
144
Václav Kubernáteeb38842019-03-20 19:46:05 +0100145 leaf foodIdentLeaf {
146 type identityref {
147 base "food";
148 }
149 }
150
151 leaf pizzaIdentLeaf {
152 type identityref {
153 base "pizza";
154 }
155 }
156
157 leaf foodDrinkIdentLeaf {
158 type identityref {
159 base "food";
160 base "drink";
161 }
162 }
163
Václav Kubernát0d4db442018-07-18 17:18:43 +0200164 list _list {
165 key number;
166
167 leaf number {
168 type int32;
169 }
170
171 container contInList {
172 presence true;
173 }
174 }
175
176 list twoKeyList {
177 key "name number";
178
179 leaf number {
180 type int32;
181 }
182
183 leaf name {
184 type string;
185 }
186 }
187})";
188
189TEST_CASE("yangschema")
190{
Václav Kubernát4f77a252019-02-19 16:51:30 +0100191 using namespace std::string_view_literals;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200192 YangSchema ys;
Václav Kubernát4f77a252019-02-19 16:51:30 +0100193 ys.registerModuleCallback([]([[maybe_unused]] auto modName, auto, auto) {
194 assert("example-schema"sv == modName);
195 return example_schema;
196 });
197 ys.addSchemaString(second_schema);
198
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200199 schemaPath_ path;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200200 ModuleNodePair node;
201
202 SECTION("positive")
203 {
204 SECTION("isContainer")
205 {
206 SECTION("example-schema:a")
207 {
208 node.first = "example-schema";
209 node.second = "a";
210 }
211
212 SECTION("example-schema:a/a2")
213 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200214 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200215 node.second = "a2";
216 }
217
218 REQUIRE(ys.isContainer(path, node));
219 }
220 SECTION("isLeaf")
221 {
222 SECTION("example-schema:leafString")
223 {
224 node.first = "example-schema";
225 node.second = "leafString";
226 }
227
228 SECTION("example-schema:a/leafa")
229 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200230 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200231 node.first = "example-schema";
232 node.second = "leafa";
233 }
234
235 REQUIRE(ys.isLeaf(path, node));
236 }
237 SECTION("isModule")
238 {
239 REQUIRE(ys.isModule(path, "example-schema"));
240 }
241 SECTION("isList")
242 {
243 SECTION("example-schema:_list")
244 {
245 node.first = "example-schema";
246 node.second = "_list";
247 }
248
249 SECTION("example-schema:twoKeyList")
250 {
251 node.first = "example-schema";
252 node.second = "twoKeyList";
253 }
254
255 REQUIRE(ys.isList(path, node));
256 }
257 SECTION("isPresenceContainer")
258 {
259 SECTION("example-schema:a/a2/a3")
260 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200261 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
262 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a2")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200263 node.second = "a3";
264 }
265
266 REQUIRE(ys.isPresenceContainer(path, node));
267 }
268 SECTION("leafEnumHasValue")
269 {
Václav Kubernát0d4db442018-07-18 17:18:43 +0200270 std::string value;
Václav Kubernát6a713d62018-10-03 18:47:34 +0200271 SECTION("leafEnum")
272 {
273 node.first = "example-schema";
274 node.second = "leafEnum";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200275
Václav Kubernát6a713d62018-10-03 18:47:34 +0200276 SECTION("lol")
277 value = "lol";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200278
Václav Kubernát6a713d62018-10-03 18:47:34 +0200279 SECTION("data")
280 value = "data";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200281
Václav Kubernát6a713d62018-10-03 18:47:34 +0200282 SECTION("coze")
283 value = "coze";
284 }
285
286 SECTION("leafEnumTypedef")
287 {
288 node.first = "example-schema";
289 node.second = "leafEnumTypedef";
290
291 SECTION("lol")
292 value = "lol";
293
294 SECTION("data")
295 value = "data";
296
297 SECTION("coze")
298 value = "coze";
299 }
300
301 SECTION("leafEnumTypedefRestricted")
302 {
303 node.first = "example-schema";
304 node.second = "leafEnumTypedefRestricted";
305
306 SECTION("data")
307 value = "data";
308
309 SECTION("coze")
310 value = "coze";
311 }
312
313 SECTION("leafEnumTypedefRestricted2")
314 {
315 node.first = "example-schema";
316 node.second = "leafEnumTypedefRestricted2";
317
318 SECTION("lol")
319 value = "lol";
320
321 SECTION("data")
322 value = "data";
323 }
Václav Kubernát0d4db442018-07-18 17:18:43 +0200324
325 REQUIRE(ys.leafEnumHasValue(path, node, value));
326 }
Václav Kubernáteeb38842019-03-20 19:46:05 +0100327 SECTION("leafIdentityIsValid")
328 {
329 ModuleValuePair value;
330
331 SECTION("foodIdentLeaf")
332 {
333 node.first = "example-schema";
334 node.second = "foodIdentLeaf";
335
336 SECTION("food")
337 {
338 value.second = "food";
339 }
340 SECTION("example-schema:food")
341 {
342 value.first = "example-schema";
343 value.second = "food";
344 }
345 SECTION("pizza")
346 {
347 value.second = "pizza";
348 }
349 SECTION("example-schema:pizza")
350 {
351 value.first = "example-schema";
352 value.second = "pizza";
353 }
354 SECTION("hawaii")
355 {
356 value.second = "hawaii";
357 }
358 SECTION("example-schema:hawaii")
359 {
360 value.first = "example-schema";
361 value.second = "hawaii";
362 }
363 SECTION("fruit")
364 {
365 value.second = "fruit";
366 }
367 SECTION("example-schema:fruit")
368 {
369 value.first = "example-schema";
370 value.second = "fruit";
371 }
372 SECTION("second-schema:pineapple")
373 {
374 value.first = "second-schema";
375 value.second = "pineapple";
376 }
377 }
378
379 SECTION("pizzaIdentLeaf")
380 {
381 node.first = "example-schema";
382 node.second = "pizzaIdentLeaf";
383
384 SECTION("pizza")
385 {
386 value.second = "pizza";
387 }
388 SECTION("example-schema:pizza")
389 {
390 value.first = "example-schema";
391 value.second = "pizza";
392 }
393 SECTION("hawaii")
394 {
395 value.second = "hawaii";
396 }
397 SECTION("example-schema:hawaii")
398 {
399 value.first = "example-schema";
400 value.second = "hawaii";
401 }
402 }
403
404 SECTION("foodDrinkIdentLeaf")
405 {
406 node.first = "example-schema";
407 node.second = "foodDrinkIdentLeaf";
408
409 SECTION("food")
410 {
411 value.second = "food";
412 }
413 SECTION("example-schema:food")
414 {
415 value.first = "example-schema";
416 value.second = "food";
417 }
418 SECTION("drink")
419 {
420 value.second = "drink";
421 }
422 SECTION("example-schema:drink")
423 {
424 value.first = "example-schema";
425 value.second = "drink";
426 }
427 }
428 REQUIRE(ys.leafIdentityIsValid(path, node, value));
429 }
430
Václav Kubernát0d4db442018-07-18 17:18:43 +0200431 SECTION("listHasKey")
432 {
433 std::string key;
434
435 SECTION("_list")
436 {
437 node.first = "example-schema";
438 node.second = "_list";
439 SECTION("number")
440 key = "number";
441 }
442
443 SECTION("twoKeyList")
444 {
445 node.first = "example-schema";
446 node.second = "twoKeyList";
447 SECTION("number")
448 key = "number";
449 SECTION("name")
450 key = "name";
451 }
452
453 REQUIRE(ys.listHasKey(path, node, key));
454 }
455 SECTION("listKeys")
456 {
457 std::set<std::string> set;
458
459 SECTION("_list")
460 {
461 set = {"number"};
462 node.first = "example-schema";
463 node.second = "_list";
464 }
465
466 SECTION("twoKeyList")
467 {
468 set = {"number", "name"};
469 node.first = "example-schema";
470 node.second = "twoKeyList";
471 }
472
473 REQUIRE(ys.listKeys(path, node) == set);
474 }
475 SECTION("leafType")
476 {
477 yang::LeafDataTypes type;
478
479 SECTION("leafString")
480 {
481 node.first = "example-schema";
482 node.second = "leafString";
483 type = yang::LeafDataTypes::String;
484 }
485
486 SECTION("leafDecimal")
487 {
488 node.first = "example-schema";
489 node.second = "leafDecimal";
490 type = yang::LeafDataTypes::Decimal;
491 }
492
493 SECTION("leafBool")
494 {
495 node.first = "example-schema";
496 node.second = "leafBool";
497 type = yang::LeafDataTypes::Bool;
498 }
499
500 SECTION("leafInt")
501 {
502 node.first = "example-schema";
503 node.second = "leafInt";
504 type = yang::LeafDataTypes::Int;
505 }
506
507 SECTION("leafUint")
508 {
509 node.first = "example-schema";
510 node.second = "leafUint";
511 type = yang::LeafDataTypes::Uint;
512 }
513
514 SECTION("leafEnum")
515 {
516 node.first = "example-schema";
517 node.second = "leafEnum";
518 type = yang::LeafDataTypes::Enum;
519 }
520
521 REQUIRE(ys.leafType(path, node) == type);
522 }
523 SECTION("childNodes")
524 {
525 std::set<std::string> set;
526
527 SECTION("<root>")
528 {
529 set = {"example-schema:a", "example-schema:b", "example-schema:leafString",
530 "example-schema:leafDecimal", "example-schema:leafBool", "example-schema:leafInt",
Václav Kubernát6a713d62018-10-03 18:47:34 +0200531 "example-schema:leafUint", "example-schema:leafEnum", "example-schema:leafEnumTypedef",
532 "example-schema:leafEnumTypedefRestricted", "example-schema:leafEnumTypedefRestricted2",
Václav Kubernáteeb38842019-03-20 19:46:05 +0100533 "example-schema:foodIdentLeaf", "example-schema:pizzaIdentLeaf", "example-schema:foodDrinkIdentLeaf",
Václav Kubernát4f77a252019-02-19 16:51:30 +0100534 "example-schema:_list", "example-schema:twoKeyList", "second-schema:bla"};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200535 }
536
Václav Kubernát4f77a252019-02-19 16:51:30 +0100537 SECTION("example-schema:a")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200538 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200539 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát4f77a252019-02-19 16:51:30 +0100540 set = {"a2", "leafa", "second-schema:augmentedContainer"};
541 }
542
543 SECTION("second-schema:bla")
544 {
545 path.m_nodes.push_back(schemaNode_(module_{"second-schema"}, container_("bla")));
546 set = {"bla2"};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200547 }
548
Václav Kubernáte7d4aea2018-09-11 18:15:48 +0200549 REQUIRE(ys.childNodes(path, Recursion::NonRecursive) == set);
Václav Kubernát0d4db442018-07-18 17:18:43 +0200550 }
551 }
552
553 SECTION("negative")
554 {
555 SECTION("nonexistent nodes")
556 {
557 SECTION("example-schema:coze")
558 {
559 node.first = "example-schema";
560 node.second = "coze";
561 }
562
563 SECTION("example-schema:a/nevim")
564 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200565 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200566 node.second = "nevim";
567 }
568
569 SECTION("modul:a/nevim")
570 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200571 path.m_nodes.push_back(schemaNode_(module_{"modul"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200572 node.second = "nevim";
573 }
574
575 REQUIRE(!ys.isPresenceContainer(path, node));
576 REQUIRE(!ys.isList(path, node));
577 REQUIRE(!ys.isLeaf(path, node));
578 REQUIRE(!ys.isContainer(path, node));
579 }
580
581 SECTION("\"is\" methods return false for existing nodes for different nodetypes")
582 {
583 SECTION("example-schema:a")
584 {
585 node.first = "example-schema";
586 node.second = "a";
587 }
588
589 SECTION("example-schema:a/a2")
590 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200591 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200592 node.second = "a2";
593 }
594
595 REQUIRE(!ys.isPresenceContainer(path, node));
596 REQUIRE(!ys.isList(path, node));
597 REQUIRE(!ys.isLeaf(path, node));
598 }
599
600 SECTION("nodetype-specific methods called with different nodetypes")
601 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200602 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200603 node.second = "a2";
604
605 REQUIRE(!ys.leafEnumHasValue(path, node, "haha"));
606 REQUIRE(!ys.listHasKey(path, node, "chacha"));
607 }
608
609 SECTION("nonexistent module")
610 {
611 REQUIRE(!ys.isModule(path, "notAModule"));
612 }
Václav Kubernáteeb38842019-03-20 19:46:05 +0100613
614 SECTION("leafIdentityIsValid")
615 {
616 ModuleValuePair value;
617 SECTION("pizzaIdentLeaf")
618 {
619 node.first = "example-schema";
620 node.second = "pizzaIdentLeaf";
621
622 SECTION("wrong base ident")
623 {
624 SECTION("food")
625 {
626 value.second = "food";
627 }
628 SECTION("fruit")
629 {
630 value.second = "fruit";
631 }
632 }
633 SECTION("non-existent identity")
634 {
635 value.second = "nonexistent";
636 }
637 SECTION("weird module")
638 {
639 value.first = "ahahaha";
640 value.second = "pizza";
641 }
642 }
643 SECTION("different module identity, but withotu prefix")
644 {
645 node.first = "example-schema";
646 node.second = "foodIdentLeaf";
647 value.second = "pineapple";
648 }
649 REQUIRE_FALSE(ys.leafIdentityIsValid(path, node, value));
650 }
Václav Kubernát0d4db442018-07-18 17:18:43 +0200651 }
652}