blob: 9c440082df28dd079e9adeb085b9caac07fa58f1 [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
Jan Kundráta33cf082019-03-28 11:55:57 +01009#include "trompeloeil_doctest.h"
Václav Kubernát0d4db442018-07-18 17:18:43 +020010#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
Ivona Oboňová88c78ca2019-07-02 18:40:07 +020099 leaf leafInt8 {
100 type int8;
101 }
102
103 leaf leafUint8 {
104 type uint8;
105 }
106
107 leaf leafInt16 {
108 type int16;
109 }
110
111 leaf leafUint16 {
112 type uint16;
113 }
114
115 leaf leafInt32 {
Václav Kubernát0d4db442018-07-18 17:18:43 +0200116 type int32;
117 }
118
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200119 leaf leafUint32 {
Václav Kubernát0d4db442018-07-18 17:18:43 +0200120 type uint32;
121 }
122
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200123 leaf leafInt64 {
124 type int64;
125 }
126
127 leaf leafUint64 {
128 type uint64;
129 }
130
Václav Kubernát0d4db442018-07-18 17:18:43 +0200131 leaf leafEnum {
132 type enumeration {
133 enum lol;
134 enum data;
135 enum coze;
136 }
137 }
138
Václav Kubernát6a713d62018-10-03 18:47:34 +0200139 typedef enumTypedef {
140 type enumeration {
141 enum lol;
142 enum data;
143 enum coze;
144 }
145 }
146
147 typedef enumTypedefRestricted {
148 type enumTypedef {
149 enum lol;
150 enum data;
151 }
152 }
153
154 leaf leafEnumTypedef {
155 type enumTypedef;
156 }
157
158 leaf leafEnumTypedefRestricted {
159 type enumTypedef {
160 enum data;
161 enum coze;
162 }
163 }
164
165 leaf leafEnumTypedefRestricted2 {
166 type enumTypedefRestricted;
167 }
168
Václav Kubernáteeb38842019-03-20 19:46:05 +0100169 leaf foodIdentLeaf {
170 type identityref {
171 base "food";
172 }
173 }
174
175 leaf pizzaIdentLeaf {
176 type identityref {
177 base "pizza";
178 }
179 }
180
181 leaf foodDrinkIdentLeaf {
182 type identityref {
183 base "food";
184 base "drink";
185 }
186 }
187
Václav Kubernát0d4db442018-07-18 17:18:43 +0200188 list _list {
189 key number;
190
191 leaf number {
192 type int32;
193 }
194
195 container contInList {
196 presence true;
197 }
198 }
199
200 list twoKeyList {
201 key "name number";
202
203 leaf number {
204 type int32;
205 }
206
207 leaf name {
208 type string;
209 }
210 }
Václav Kubernát7d82da72019-04-11 15:16:38 +0200211
212 grouping arithmeticFlags {
213 leaf carry {
214 type boolean;
215 }
216 leaf zero {
217 type boolean;
218 }
219 }
220
221 grouping flags {
222 leaf direction {
223 type boolean;
224 }
225 leaf interrupt {
226 type boolean;
227 }
228
229 uses arithmeticFlags;
230 }
231
232 uses flags;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200233})";
234
235TEST_CASE("yangschema")
236{
Václav Kubernát4f77a252019-02-19 16:51:30 +0100237 using namespace std::string_view_literals;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200238 YangSchema ys;
Václav Kubernát4f77a252019-02-19 16:51:30 +0100239 ys.registerModuleCallback([]([[maybe_unused]] auto modName, auto, auto) {
240 assert("example-schema"sv == modName);
241 return example_schema;
242 });
243 ys.addSchemaString(second_schema);
244
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200245 schemaPath_ path;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200246 ModuleNodePair node;
247
248 SECTION("positive")
249 {
250 SECTION("isContainer")
251 {
252 SECTION("example-schema:a")
253 {
254 node.first = "example-schema";
255 node.second = "a";
256 }
257
258 SECTION("example-schema:a/a2")
259 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200260 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200261 node.second = "a2";
262 }
263
264 REQUIRE(ys.isContainer(path, node));
265 }
266 SECTION("isLeaf")
267 {
268 SECTION("example-schema:leafString")
269 {
270 node.first = "example-schema";
271 node.second = "leafString";
272 }
273
274 SECTION("example-schema:a/leafa")
275 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200276 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200277 node.first = "example-schema";
278 node.second = "leafa";
279 }
280
Václav Kubernát7d82da72019-04-11 15:16:38 +0200281 SECTION("example-schema:carry")
282 {
283 node.first = "example-schema";
284 node.second = "carry";
285 }
286
287 SECTION("example-schema:zero")
288 {
289 node.first = "example-schema";
290 node.second = "zero";
291 }
292
293 SECTION("example-schema:direction")
294 {
295 node.first = "example-schema";
296 node.second = "direction";
297 }
298
299 SECTION("example-schema:interrupt")
300 {
301 node.first = "example-schema";
302 node.second = "interrupt";
303 }
304
Václav Kubernát0d4db442018-07-18 17:18:43 +0200305 REQUIRE(ys.isLeaf(path, node));
306 }
307 SECTION("isModule")
308 {
309 REQUIRE(ys.isModule(path, "example-schema"));
310 }
311 SECTION("isList")
312 {
313 SECTION("example-schema:_list")
314 {
315 node.first = "example-schema";
316 node.second = "_list";
317 }
318
319 SECTION("example-schema:twoKeyList")
320 {
321 node.first = "example-schema";
322 node.second = "twoKeyList";
323 }
324
325 REQUIRE(ys.isList(path, node));
326 }
327 SECTION("isPresenceContainer")
328 {
329 SECTION("example-schema:a/a2/a3")
330 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200331 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
332 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a2")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200333 node.second = "a3";
334 }
335
336 REQUIRE(ys.isPresenceContainer(path, node));
337 }
338 SECTION("leafEnumHasValue")
339 {
Václav Kubernát0d4db442018-07-18 17:18:43 +0200340 std::string value;
Václav Kubernát6a713d62018-10-03 18:47:34 +0200341 SECTION("leafEnum")
342 {
343 node.first = "example-schema";
344 node.second = "leafEnum";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200345
Václav Kubernát6a713d62018-10-03 18:47:34 +0200346 SECTION("lol")
347 value = "lol";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200348
Václav Kubernát6a713d62018-10-03 18:47:34 +0200349 SECTION("data")
350 value = "data";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200351
Václav Kubernát6a713d62018-10-03 18:47:34 +0200352 SECTION("coze")
353 value = "coze";
354 }
355
356 SECTION("leafEnumTypedef")
357 {
358 node.first = "example-schema";
359 node.second = "leafEnumTypedef";
360
361 SECTION("lol")
362 value = "lol";
363
364 SECTION("data")
365 value = "data";
366
367 SECTION("coze")
368 value = "coze";
369 }
370
371 SECTION("leafEnumTypedefRestricted")
372 {
373 node.first = "example-schema";
374 node.second = "leafEnumTypedefRestricted";
375
376 SECTION("data")
377 value = "data";
378
379 SECTION("coze")
380 value = "coze";
381 }
382
383 SECTION("leafEnumTypedefRestricted2")
384 {
385 node.first = "example-schema";
386 node.second = "leafEnumTypedefRestricted2";
387
388 SECTION("lol")
389 value = "lol";
390
391 SECTION("data")
392 value = "data";
393 }
Václav Kubernát0d4db442018-07-18 17:18:43 +0200394
395 REQUIRE(ys.leafEnumHasValue(path, node, value));
396 }
Václav Kubernáteeb38842019-03-20 19:46:05 +0100397 SECTION("leafIdentityIsValid")
398 {
399 ModuleValuePair value;
400
401 SECTION("foodIdentLeaf")
402 {
403 node.first = "example-schema";
404 node.second = "foodIdentLeaf";
405
406 SECTION("food")
407 {
408 value.second = "food";
409 }
410 SECTION("example-schema:food")
411 {
412 value.first = "example-schema";
413 value.second = "food";
414 }
415 SECTION("pizza")
416 {
417 value.second = "pizza";
418 }
419 SECTION("example-schema:pizza")
420 {
421 value.first = "example-schema";
422 value.second = "pizza";
423 }
424 SECTION("hawaii")
425 {
426 value.second = "hawaii";
427 }
428 SECTION("example-schema:hawaii")
429 {
430 value.first = "example-schema";
431 value.second = "hawaii";
432 }
433 SECTION("fruit")
434 {
435 value.second = "fruit";
436 }
437 SECTION("example-schema:fruit")
438 {
439 value.first = "example-schema";
440 value.second = "fruit";
441 }
442 SECTION("second-schema:pineapple")
443 {
444 value.first = "second-schema";
445 value.second = "pineapple";
446 }
447 }
448
449 SECTION("pizzaIdentLeaf")
450 {
451 node.first = "example-schema";
452 node.second = "pizzaIdentLeaf";
453
454 SECTION("pizza")
455 {
456 value.second = "pizza";
457 }
458 SECTION("example-schema:pizza")
459 {
460 value.first = "example-schema";
461 value.second = "pizza";
462 }
463 SECTION("hawaii")
464 {
465 value.second = "hawaii";
466 }
467 SECTION("example-schema:hawaii")
468 {
469 value.first = "example-schema";
470 value.second = "hawaii";
471 }
472 }
473
474 SECTION("foodDrinkIdentLeaf")
475 {
476 node.first = "example-schema";
477 node.second = "foodDrinkIdentLeaf";
478
479 SECTION("food")
480 {
481 value.second = "food";
482 }
483 SECTION("example-schema:food")
484 {
485 value.first = "example-schema";
486 value.second = "food";
487 }
488 SECTION("drink")
489 {
490 value.second = "drink";
491 }
492 SECTION("example-schema:drink")
493 {
494 value.first = "example-schema";
495 value.second = "drink";
496 }
497 }
498 REQUIRE(ys.leafIdentityIsValid(path, node, value));
499 }
500
Václav Kubernát0d4db442018-07-18 17:18:43 +0200501 SECTION("listHasKey")
502 {
503 std::string key;
504
505 SECTION("_list")
506 {
507 node.first = "example-schema";
508 node.second = "_list";
509 SECTION("number")
510 key = "number";
511 }
512
513 SECTION("twoKeyList")
514 {
515 node.first = "example-schema";
516 node.second = "twoKeyList";
517 SECTION("number")
518 key = "number";
519 SECTION("name")
520 key = "name";
521 }
522
523 REQUIRE(ys.listHasKey(path, node, key));
524 }
525 SECTION("listKeys")
526 {
527 std::set<std::string> set;
528
529 SECTION("_list")
530 {
531 set = {"number"};
532 node.first = "example-schema";
533 node.second = "_list";
534 }
535
536 SECTION("twoKeyList")
537 {
538 set = {"number", "name"};
539 node.first = "example-schema";
540 node.second = "twoKeyList";
541 }
542
543 REQUIRE(ys.listKeys(path, node) == set);
544 }
545 SECTION("leafType")
546 {
547 yang::LeafDataTypes type;
548
549 SECTION("leafString")
550 {
551 node.first = "example-schema";
552 node.second = "leafString";
553 type = yang::LeafDataTypes::String;
554 }
555
556 SECTION("leafDecimal")
557 {
558 node.first = "example-schema";
559 node.second = "leafDecimal";
560 type = yang::LeafDataTypes::Decimal;
561 }
562
563 SECTION("leafBool")
564 {
565 node.first = "example-schema";
566 node.second = "leafBool";
567 type = yang::LeafDataTypes::Bool;
568 }
569
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200570 SECTION("leafInt8")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200571 {
572 node.first = "example-schema";
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200573 node.second = "leafInt8";
574 type = yang::LeafDataTypes::Int8;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200575 }
576
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200577 SECTION("leafUint8")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200578 {
579 node.first = "example-schema";
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200580 node.second = "leafUint8";
581 type = yang::LeafDataTypes::Uint8;
582 }
583
584 SECTION("leafInt15")
585 {
586 node.first = "example-schema";
587 node.second = "leafInt16";
588 type = yang::LeafDataTypes::Int16;
589 }
590
591 SECTION("leafUint16")
592 {
593 node.first = "example-schema";
594 node.second = "leafUint16";
595 type = yang::LeafDataTypes::Uint16;
596 }
597
598 SECTION("leafInt32")
599 {
600 node.first = "example-schema";
601 node.second = "leafInt32";
602 type = yang::LeafDataTypes::Int32;
603 }
604
605 SECTION("leafUint32")
606 {
607 node.first = "example-schema";
608 node.second = "leafUint32";
609 type = yang::LeafDataTypes::Uint32;
610 }
611
612 SECTION("leafInt64")
613 {
614 node.first = "example-schema";
615 node.second = "leafInt64";
616 type = yang::LeafDataTypes::Int64;
617 }
618
619 SECTION("leafUint64")
620 {
621 node.first = "example-schema";
622 node.second = "leafUint64";
623 type = yang::LeafDataTypes::Uint64;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200624 }
625
626 SECTION("leafEnum")
627 {
628 node.first = "example-schema";
629 node.second = "leafEnum";
630 type = yang::LeafDataTypes::Enum;
631 }
632
633 REQUIRE(ys.leafType(path, node) == type);
634 }
635 SECTION("childNodes")
636 {
637 std::set<std::string> set;
638
639 SECTION("<root>")
640 {
641 set = {"example-schema:a", "example-schema:b", "example-schema:leafString",
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200642 "example-schema:leafDecimal", "example-schema:leafBool",
643 "example-schema:leafInt8", "example-schema:leafUint8",
644 "example-schema:leafInt16", "example-schema:leafUint16",
645 "example-schema:leafInt32", "example-schema:leafUint32",
646 "example-schema:leafInt64", "example-schema:leafUint64",
647 "example-schema:leafEnum", "example-schema:leafEnumTypedef",
Václav Kubernát6a713d62018-10-03 18:47:34 +0200648 "example-schema:leafEnumTypedefRestricted", "example-schema:leafEnumTypedefRestricted2",
Václav Kubernáteeb38842019-03-20 19:46:05 +0100649 "example-schema:foodIdentLeaf", "example-schema:pizzaIdentLeaf", "example-schema:foodDrinkIdentLeaf",
Václav Kubernát7d82da72019-04-11 15:16:38 +0200650 "example-schema:_list", "example-schema:twoKeyList", "second-schema:bla",
651 "example-schema:carry", "example-schema:zero", "example-schema:direction",
652 "example-schema:interrupt"};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200653 }
654
Václav Kubernát4f77a252019-02-19 16:51:30 +0100655 SECTION("example-schema:a")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200656 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200657 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát4f77a252019-02-19 16:51:30 +0100658 set = {"a2", "leafa", "second-schema:augmentedContainer"};
659 }
660
661 SECTION("second-schema:bla")
662 {
663 path.m_nodes.push_back(schemaNode_(module_{"second-schema"}, container_("bla")));
664 set = {"bla2"};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200665 }
666
Václav Kubernáte7d4aea2018-09-11 18:15:48 +0200667 REQUIRE(ys.childNodes(path, Recursion::NonRecursive) == set);
Václav Kubernát0d4db442018-07-18 17:18:43 +0200668 }
669 }
670
671 SECTION("negative")
672 {
673 SECTION("nonexistent nodes")
674 {
675 SECTION("example-schema:coze")
676 {
677 node.first = "example-schema";
678 node.second = "coze";
679 }
680
681 SECTION("example-schema:a/nevim")
682 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200683 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200684 node.second = "nevim";
685 }
686
687 SECTION("modul:a/nevim")
688 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200689 path.m_nodes.push_back(schemaNode_(module_{"modul"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200690 node.second = "nevim";
691 }
692
693 REQUIRE(!ys.isPresenceContainer(path, node));
694 REQUIRE(!ys.isList(path, node));
695 REQUIRE(!ys.isLeaf(path, node));
696 REQUIRE(!ys.isContainer(path, node));
697 }
698
699 SECTION("\"is\" methods return false for existing nodes for different nodetypes")
700 {
701 SECTION("example-schema:a")
702 {
703 node.first = "example-schema";
704 node.second = "a";
705 }
706
707 SECTION("example-schema:a/a2")
708 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200709 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200710 node.second = "a2";
711 }
712
713 REQUIRE(!ys.isPresenceContainer(path, node));
714 REQUIRE(!ys.isList(path, node));
715 REQUIRE(!ys.isLeaf(path, node));
716 }
717
718 SECTION("nodetype-specific methods called with different nodetypes")
719 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200720 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200721 node.second = "a2";
722
723 REQUIRE(!ys.leafEnumHasValue(path, node, "haha"));
724 REQUIRE(!ys.listHasKey(path, node, "chacha"));
725 }
726
727 SECTION("nonexistent module")
728 {
729 REQUIRE(!ys.isModule(path, "notAModule"));
730 }
Václav Kubernáteeb38842019-03-20 19:46:05 +0100731
732 SECTION("leafIdentityIsValid")
733 {
734 ModuleValuePair value;
735 SECTION("pizzaIdentLeaf")
736 {
737 node.first = "example-schema";
738 node.second = "pizzaIdentLeaf";
739
740 SECTION("wrong base ident")
741 {
742 SECTION("food")
743 {
744 value.second = "food";
745 }
746 SECTION("fruit")
747 {
748 value.second = "fruit";
749 }
750 }
751 SECTION("non-existent identity")
752 {
753 value.second = "nonexistent";
754 }
755 SECTION("weird module")
756 {
757 value.first = "ahahaha";
758 value.second = "pizza";
759 }
760 }
761 SECTION("different module identity, but withotu prefix")
762 {
763 node.first = "example-schema";
764 node.second = "foodIdentLeaf";
765 value.second = "pineapple";
766 }
767 REQUIRE_FALSE(ys.leafIdentityIsValid(path, node, value));
768 }
Václav Kubernát7d82da72019-04-11 15:16:38 +0200769
770 SECTION("grouping is not a node")
771 {
772 SECTION("example-schema:arithmeticFlags")
773 {
774 node.first = "example-schema";
775 node.second = "arithmeticFlags";
776 }
777
778 SECTION("example-schema:flags")
779 {
780 node.first = "example-schema";
781 node.second = "startAndStop";
782 }
783
784 REQUIRE(!ys.isPresenceContainer(path, node));
785 REQUIRE(!ys.isList(path, node));
786 REQUIRE(!ys.isLeaf(path, node));
787 REQUIRE(!ys.isContainer(path, node));
788 }
Václav Kubernát0d4db442018-07-18 17:18:43 +0200789 }
790}