blob: 5f2f0c3387dc9b5edbc7cc858883707b5346e2ce [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
Václav Kubernát47a3f672019-11-08 15:42:43 +01009#include <experimental/iterator>
Václav Kubernát1e09bd62020-02-17 15:13:38 +010010#include "pretty_printers.hpp"
Václav Kubernát26b56082020-02-03 18:28:56 +010011#include "trompeloeil_doctest.hpp"
Václav Kubernát0d4db442018-07-18 17:18:43 +020012#include "yang_schema.hpp"
13
Václav Kubernát4f77a252019-02-19 16:51:30 +010014const char* second_schema = R"(
15module second-schema {
16 namespace "http://example.com/nevim";
17 prefix second;
18
19 import example-schema {
20 prefix "example";
21 }
22
Václav Kubernáteeb38842019-03-20 19:46:05 +010023 identity pineapple {
24 base "example:fruit";
25 }
26
Václav Kubernát4f77a252019-02-19 16:51:30 +010027 augment /example:a {
28 container augmentedContainer {
29 }
30 }
31
32 container bla {
33 container bla2 {
34 }
35 }
36}
37)";
38
39const char* example_schema = R"(
Václav Kubernát0d4db442018-07-18 17:18:43 +020040module example-schema {
Václav Kubernát6a713d62018-10-03 18:47:34 +020041 yang-version 1.1;
Václav Kubernát0d4db442018-07-18 17:18:43 +020042 namespace "http://example.com/example-sports";
43 prefix coze;
44
Václav Kubernáteeb38842019-03-20 19:46:05 +010045 identity drink {
46 }
47
48 identity voda {
49 base "drink";
50 }
51
52 identity food {
53 }
54
55 identity fruit {
56 base "food";
57 }
58
59 identity pizza {
60 base "food";
61 }
62
63 identity hawaii {
64 base "pizza";
65 }
66
Václav Kubernát0d4db442018-07-18 17:18:43 +020067 container a {
68 container a2 {
69 container a3 {
70 presence true;
71 }
72 }
73
74 leaf leafa {
75 type string;
76 }
77 }
78
79 container b {
80 container b2 {
81 presence true;
82 container b3 {
83 }
84 }
85 }
86
87 leaf leafString {
88 type string;
89 }
90
91 leaf leafDecimal {
92 type decimal64 {
93 fraction-digits 5;
94 }
95 }
96
97 leaf leafBool {
98 type boolean;
99 }
100
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200101 leaf leafInt8 {
102 type int8;
103 }
104
105 leaf leafUint8 {
106 type uint8;
107 }
108
109 leaf leafInt16 {
110 type int16;
111 }
112
113 leaf leafUint16 {
114 type uint16;
115 }
116
117 leaf leafInt32 {
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100118 description "A 32-bit integer leaf.";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200119 type int32;
120 }
121
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200122 leaf leafUint32 {
Václav Kubernát0d4db442018-07-18 17:18:43 +0200123 type uint32;
124 }
125
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200126 leaf leafInt64 {
127 type int64;
128 }
129
130 leaf leafUint64 {
131 type uint64;
132 }
133
Václav Kubernát0d4db442018-07-18 17:18:43 +0200134 leaf leafEnum {
135 type enumeration {
136 enum lol;
137 enum data;
138 enum coze;
139 }
140 }
141
Václav Kubernát6a713d62018-10-03 18:47:34 +0200142 typedef enumTypedef {
143 type enumeration {
144 enum lol;
145 enum data;
146 enum coze;
147 }
148 }
149
150 typedef enumTypedefRestricted {
151 type enumTypedef {
152 enum lol;
153 enum data;
154 }
155 }
156
157 leaf leafEnumTypedef {
158 type enumTypedef;
159 }
160
161 leaf leafEnumTypedefRestricted {
162 type enumTypedef {
163 enum data;
164 enum coze;
165 }
166 }
167
168 leaf leafEnumTypedefRestricted2 {
169 type enumTypedefRestricted;
170 }
171
Václav Kubernáteeb38842019-03-20 19:46:05 +0100172 leaf foodIdentLeaf {
173 type identityref {
174 base "food";
175 }
176 }
177
178 leaf pizzaIdentLeaf {
179 type identityref {
180 base "pizza";
181 }
182 }
183
184 leaf foodDrinkIdentLeaf {
185 type identityref {
186 base "food";
187 base "drink";
188 }
189 }
190
Václav Kubernát0d4db442018-07-18 17:18:43 +0200191 list _list {
192 key number;
193
194 leaf number {
195 type int32;
196 }
197
198 container contInList {
199 presence true;
200 }
201 }
202
203 list twoKeyList {
204 key "name number";
205
206 leaf number {
207 type int32;
208 }
209
210 leaf name {
211 type string;
212 }
213 }
Václav Kubernát7d82da72019-04-11 15:16:38 +0200214
215 grouping arithmeticFlags {
216 leaf carry {
217 type boolean;
218 }
219 leaf zero {
220 type boolean;
221 }
222 }
223
224 grouping flags {
225 leaf direction {
226 type boolean;
227 }
228 leaf interrupt {
229 type boolean;
230 }
231
232 uses arithmeticFlags;
233 }
234
235 uses flags;
Václav Kubernát280df4a2019-11-01 14:46:34 +0100236
237 choice interface {
238 case caseLoopback {
239 container loopback {
240 leaf ip {
241 type string;
242 }
243 }
244 }
245
246 case caseEthernet {
247 container ethernet {
248 leaf ip {
249 type string;
250 }
251 }
252 }
253 }
254
Václav Kubernáta38d4172019-11-04 12:36:39 +0100255 feature bigPizzas;
256
257 leaf pizzaSize {
258 type enumeration {
259 enum large {
260 if-feature "bigPizzas";
261 }
262 enum medium;
263 enum small;
264 }
265 }
266
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100267 leaf length {
268 type int32;
269 units "m";
270 }
271
272 leaf wavelength {
273 type decimal64 {
274 fraction-digits 10;
275 }
276 units "nm";
277 }
278
279 typedef seconds {
280 type int32;
281 units "s";
282 }
283
284 leaf duration {
285 type seconds;
286 }
287
288 leaf another-duration {
289 type seconds;
290 units "vt";
291 }
292
Václav Kubernát0d4db442018-07-18 17:18:43 +0200293})";
294
Václav Kubernát47a3f672019-11-08 15:42:43 +0100295namespace std {
296std::ostream& operator<<(std::ostream& s, const std::set<std::string> set)
297{
298 s << std::endl << "{";
299 std::copy(set.begin(), set.end(), std::experimental::make_ostream_joiner(s, ", "));
300 s << "}" << std::endl;
301 return s;
302}
303}
304
Václav Kubernát0d4db442018-07-18 17:18:43 +0200305TEST_CASE("yangschema")
306{
Václav Kubernát4f77a252019-02-19 16:51:30 +0100307 using namespace std::string_view_literals;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200308 YangSchema ys;
Václav Kubernátb52dc252019-12-04 13:03:39 +0100309 ys.registerModuleCallback([]([[maybe_unused]] auto modName, auto, auto, auto) {
Václav Kubernát4f77a252019-02-19 16:51:30 +0100310 assert("example-schema"sv == modName);
311 return example_schema;
312 });
313 ys.addSchemaString(second_schema);
314
Václav Kubernátefcac932020-01-10 15:26:32 +0100315 schemaPath_ path{Scope::Absolute, {}};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200316 ModuleNodePair node;
317
318 SECTION("positive")
319 {
320 SECTION("isContainer")
321 {
322 SECTION("example-schema:a")
323 {
324 node.first = "example-schema";
325 node.second = "a";
326 }
327
328 SECTION("example-schema:a/a2")
329 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200330 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200331 node.second = "a2";
332 }
333
Václav Kubernát280df4a2019-11-01 14:46:34 +0100334 SECTION("example-schema:ethernet")
335 {
336 node.first = "example-schema";
337 node.second = "ethernet";
338 }
339
340 SECTION("example-schema:loopback")
341 {
342 node.first = "example-schema";
343 node.second = "loopback";
344 }
345
Václav Kubernát0d4db442018-07-18 17:18:43 +0200346 REQUIRE(ys.isContainer(path, node));
347 }
348 SECTION("isLeaf")
349 {
350 SECTION("example-schema:leafString")
351 {
352 node.first = "example-schema";
353 node.second = "leafString";
354 }
355
356 SECTION("example-schema:a/leafa")
357 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200358 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200359 node.first = "example-schema";
360 node.second = "leafa";
361 }
362
Václav Kubernát7d82da72019-04-11 15:16:38 +0200363 SECTION("example-schema:carry")
364 {
365 node.first = "example-schema";
366 node.second = "carry";
367 }
368
369 SECTION("example-schema:zero")
370 {
371 node.first = "example-schema";
372 node.second = "zero";
373 }
374
375 SECTION("example-schema:direction")
376 {
377 node.first = "example-schema";
378 node.second = "direction";
379 }
380
381 SECTION("example-schema:interrupt")
382 {
383 node.first = "example-schema";
384 node.second = "interrupt";
385 }
386
Václav Kubernát0d4db442018-07-18 17:18:43 +0200387 REQUIRE(ys.isLeaf(path, node));
388 }
389 SECTION("isModule")
390 {
Václav Kubernát75877de2019-11-20 17:43:02 +0100391 REQUIRE(ys.isModule("example-schema"));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200392 }
393 SECTION("isList")
394 {
395 SECTION("example-schema:_list")
396 {
397 node.first = "example-schema";
398 node.second = "_list";
399 }
400
401 SECTION("example-schema:twoKeyList")
402 {
403 node.first = "example-schema";
404 node.second = "twoKeyList";
405 }
406
407 REQUIRE(ys.isList(path, node));
408 }
409 SECTION("isPresenceContainer")
410 {
411 SECTION("example-schema:a/a2/a3")
412 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200413 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
414 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a2")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200415 node.second = "a3";
416 }
417
418 REQUIRE(ys.isPresenceContainer(path, node));
419 }
420 SECTION("leafEnumHasValue")
421 {
Václav Kubernát0d4db442018-07-18 17:18:43 +0200422 std::string value;
Václav Kubernát6a713d62018-10-03 18:47:34 +0200423 SECTION("leafEnum")
424 {
425 node.first = "example-schema";
426 node.second = "leafEnum";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200427
Václav Kubernát6a713d62018-10-03 18:47:34 +0200428 SECTION("lol")
429 value = "lol";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200430
Václav Kubernát6a713d62018-10-03 18:47:34 +0200431 SECTION("data")
432 value = "data";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200433
Václav Kubernát6a713d62018-10-03 18:47:34 +0200434 SECTION("coze")
435 value = "coze";
436 }
437
438 SECTION("leafEnumTypedef")
439 {
440 node.first = "example-schema";
441 node.second = "leafEnumTypedef";
442
443 SECTION("lol")
444 value = "lol";
445
446 SECTION("data")
447 value = "data";
448
449 SECTION("coze")
450 value = "coze";
451 }
452
453 SECTION("leafEnumTypedefRestricted")
454 {
455 node.first = "example-schema";
456 node.second = "leafEnumTypedefRestricted";
457
458 SECTION("data")
459 value = "data";
460
461 SECTION("coze")
462 value = "coze";
463 }
464
465 SECTION("leafEnumTypedefRestricted2")
466 {
467 node.first = "example-schema";
468 node.second = "leafEnumTypedefRestricted2";
469
470 SECTION("lol")
471 value = "lol";
472
473 SECTION("data")
474 value = "data";
475 }
Václav Kubernát0d4db442018-07-18 17:18:43 +0200476
Václav Kubernáta38d4172019-11-04 12:36:39 +0100477 SECTION("pizzaSize")
478 {
479 node.first = "example-schema";
480 node.second = "pizzaSize";
481
482 SECTION("small")
483 {
484 value = "small";
Václav Kubernáta38d4172019-11-04 12:36:39 +0100485 }
486 SECTION("medium")
487 {
488 value = "medium";
489 }
490
491 SECTION("large")
492 {
493 ys.enableFeature("example-schema", "bigPizzas");
494 value = "large";
495 }
496 }
497
Václav Kubernát0d4db442018-07-18 17:18:43 +0200498 REQUIRE(ys.leafEnumHasValue(path, node, value));
499 }
Václav Kubernáteeb38842019-03-20 19:46:05 +0100500 SECTION("leafIdentityIsValid")
501 {
502 ModuleValuePair value;
503
504 SECTION("foodIdentLeaf")
505 {
506 node.first = "example-schema";
507 node.second = "foodIdentLeaf";
508
509 SECTION("food")
510 {
511 value.second = "food";
512 }
513 SECTION("example-schema:food")
514 {
515 value.first = "example-schema";
516 value.second = "food";
517 }
518 SECTION("pizza")
519 {
520 value.second = "pizza";
521 }
522 SECTION("example-schema:pizza")
523 {
524 value.first = "example-schema";
525 value.second = "pizza";
526 }
527 SECTION("hawaii")
528 {
529 value.second = "hawaii";
530 }
531 SECTION("example-schema:hawaii")
532 {
533 value.first = "example-schema";
534 value.second = "hawaii";
535 }
536 SECTION("fruit")
537 {
538 value.second = "fruit";
539 }
540 SECTION("example-schema:fruit")
541 {
542 value.first = "example-schema";
543 value.second = "fruit";
544 }
545 SECTION("second-schema:pineapple")
546 {
547 value.first = "second-schema";
548 value.second = "pineapple";
549 }
550 }
551
552 SECTION("pizzaIdentLeaf")
553 {
554 node.first = "example-schema";
555 node.second = "pizzaIdentLeaf";
556
557 SECTION("pizza")
558 {
559 value.second = "pizza";
560 }
561 SECTION("example-schema:pizza")
562 {
563 value.first = "example-schema";
564 value.second = "pizza";
565 }
566 SECTION("hawaii")
567 {
568 value.second = "hawaii";
569 }
570 SECTION("example-schema:hawaii")
571 {
572 value.first = "example-schema";
573 value.second = "hawaii";
574 }
575 }
576
577 SECTION("foodDrinkIdentLeaf")
578 {
579 node.first = "example-schema";
580 node.second = "foodDrinkIdentLeaf";
581
582 SECTION("food")
583 {
584 value.second = "food";
585 }
586 SECTION("example-schema:food")
587 {
588 value.first = "example-schema";
589 value.second = "food";
590 }
591 SECTION("drink")
592 {
593 value.second = "drink";
594 }
595 SECTION("example-schema:drink")
596 {
597 value.first = "example-schema";
598 value.second = "drink";
599 }
600 }
601 REQUIRE(ys.leafIdentityIsValid(path, node, value));
602 }
603
Václav Kubernát0d4db442018-07-18 17:18:43 +0200604 SECTION("listHasKey")
605 {
606 std::string key;
607
608 SECTION("_list")
609 {
610 node.first = "example-schema";
611 node.second = "_list";
612 SECTION("number")
613 key = "number";
614 }
615
616 SECTION("twoKeyList")
617 {
618 node.first = "example-schema";
619 node.second = "twoKeyList";
620 SECTION("number")
621 key = "number";
622 SECTION("name")
623 key = "name";
624 }
625
626 REQUIRE(ys.listHasKey(path, node, key));
627 }
628 SECTION("listKeys")
629 {
630 std::set<std::string> set;
631
632 SECTION("_list")
633 {
634 set = {"number"};
635 node.first = "example-schema";
636 node.second = "_list";
637 }
638
639 SECTION("twoKeyList")
640 {
641 set = {"number", "name"};
642 node.first = "example-schema";
643 node.second = "twoKeyList";
644 }
645
646 REQUIRE(ys.listKeys(path, node) == set);
647 }
648 SECTION("leafType")
649 {
650 yang::LeafDataTypes type;
651
652 SECTION("leafString")
653 {
654 node.first = "example-schema";
655 node.second = "leafString";
656 type = yang::LeafDataTypes::String;
657 }
658
659 SECTION("leafDecimal")
660 {
661 node.first = "example-schema";
662 node.second = "leafDecimal";
663 type = yang::LeafDataTypes::Decimal;
664 }
665
666 SECTION("leafBool")
667 {
668 node.first = "example-schema";
669 node.second = "leafBool";
670 type = yang::LeafDataTypes::Bool;
671 }
672
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200673 SECTION("leafInt8")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200674 {
675 node.first = "example-schema";
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200676 node.second = "leafInt8";
677 type = yang::LeafDataTypes::Int8;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200678 }
679
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200680 SECTION("leafUint8")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200681 {
682 node.first = "example-schema";
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200683 node.second = "leafUint8";
684 type = yang::LeafDataTypes::Uint8;
685 }
686
687 SECTION("leafInt15")
688 {
689 node.first = "example-schema";
690 node.second = "leafInt16";
691 type = yang::LeafDataTypes::Int16;
692 }
693
694 SECTION("leafUint16")
695 {
696 node.first = "example-schema";
697 node.second = "leafUint16";
698 type = yang::LeafDataTypes::Uint16;
699 }
700
701 SECTION("leafInt32")
702 {
703 node.first = "example-schema";
704 node.second = "leafInt32";
705 type = yang::LeafDataTypes::Int32;
706 }
707
708 SECTION("leafUint32")
709 {
710 node.first = "example-schema";
711 node.second = "leafUint32";
712 type = yang::LeafDataTypes::Uint32;
713 }
714
715 SECTION("leafInt64")
716 {
717 node.first = "example-schema";
718 node.second = "leafInt64";
719 type = yang::LeafDataTypes::Int64;
720 }
721
722 SECTION("leafUint64")
723 {
724 node.first = "example-schema";
725 node.second = "leafUint64";
726 type = yang::LeafDataTypes::Uint64;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200727 }
728
729 SECTION("leafEnum")
730 {
731 node.first = "example-schema";
732 node.second = "leafEnum";
733 type = yang::LeafDataTypes::Enum;
734 }
735
736 REQUIRE(ys.leafType(path, node) == type);
737 }
738 SECTION("childNodes")
739 {
740 std::set<std::string> set;
741
742 SECTION("<root>")
743 {
744 set = {"example-schema:a", "example-schema:b", "example-schema:leafString",
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200745 "example-schema:leafDecimal", "example-schema:leafBool",
746 "example-schema:leafInt8", "example-schema:leafUint8",
747 "example-schema:leafInt16", "example-schema:leafUint16",
748 "example-schema:leafInt32", "example-schema:leafUint32",
749 "example-schema:leafInt64", "example-schema:leafUint64",
750 "example-schema:leafEnum", "example-schema:leafEnumTypedef",
Václav Kubernát6a713d62018-10-03 18:47:34 +0200751 "example-schema:leafEnumTypedefRestricted", "example-schema:leafEnumTypedefRestricted2",
Václav Kubernáteeb38842019-03-20 19:46:05 +0100752 "example-schema:foodIdentLeaf", "example-schema:pizzaIdentLeaf", "example-schema:foodDrinkIdentLeaf",
Václav Kubernát7d82da72019-04-11 15:16:38 +0200753 "example-schema:_list", "example-schema:twoKeyList", "second-schema:bla",
754 "example-schema:carry", "example-schema:zero", "example-schema:direction",
Václav Kubernát280df4a2019-11-01 14:46:34 +0100755 "example-schema:interrupt",
Václav Kubernáta38d4172019-11-04 12:36:39 +0100756 "example-schema:ethernet", "example-schema:loopback",
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100757 "example-schema:pizzaSize",
758 "example-schema:length", "example-schema:wavelength",
759 "example-schema:duration", "example-schema:another-duration"};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200760 }
761
Václav Kubernát4f77a252019-02-19 16:51:30 +0100762 SECTION("example-schema:a")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200763 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200764 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát4f77a252019-02-19 16:51:30 +0100765 set = {"a2", "leafa", "second-schema:augmentedContainer"};
766 }
767
768 SECTION("second-schema:bla")
769 {
770 path.m_nodes.push_back(schemaNode_(module_{"second-schema"}, container_("bla")));
771 set = {"bla2"};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200772 }
773
Václav Kubernát47a3f672019-11-08 15:42:43 +0100774 SECTION("example-schema:ethernet")
775 {
776 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("ethernet")));
777 set = {"ip"};
778 }
779
Václav Kubernáte7d4aea2018-09-11 18:15:48 +0200780 REQUIRE(ys.childNodes(path, Recursion::NonRecursive) == set);
Václav Kubernát0d4db442018-07-18 17:18:43 +0200781 }
Václav Kubernát34ee85a2020-02-18 17:12:12 +0100782 SECTION("nodeType")
783 {
784 yang::NodeTypes expected;
785 SECTION("leafInt32")
786 {
787 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
788 expected = yang::NodeTypes::Leaf;
789 }
790
791 SECTION("a")
792 {
793 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
794 expected = yang::NodeTypes::Container;
795 }
796
797 SECTION("a/a2/a3")
798 {
799 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
800 path.m_nodes.push_back(schemaNode_(container_("a2")));
801 path.m_nodes.push_back(schemaNode_(container_("a3")));
802 expected = yang::NodeTypes::PresenceContainer;
803 }
804
805 SECTION("_list")
806 {
807 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, list_("_list")));
808 expected = yang::NodeTypes::List;
809 }
810
811 REQUIRE(ys.nodeType(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
812 }
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100813
814 SECTION("description")
815 {
816 std::optional<std::string> expected;
817 SECTION("leafInt32")
818 {
819 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
820 expected = "A 32-bit integer leaf.";
821 }
822
823 SECTION("leafString")
824 {
825 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafString")));
826 }
827
828 REQUIRE(ys.description(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
829 }
830
831 SECTION("units")
832 {
833 std::optional<std::string> expected;
834 SECTION("length")
835 {
836 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("length")));
837 expected = "m";
838 }
839
840 SECTION("wavelength")
841 {
842 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("wavelength")));
843 expected = "nm";
844 }
845
846 SECTION("leafInt32")
847 {
848 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
849 }
850
851 SECTION("duration")
852 {
853 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("duration")));
854 expected = "s";
855 }
856
857 SECTION("another-duration")
858 {
859 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("another-duration")));
860 expected = "vt";
861 }
862
863 REQUIRE(ys.units(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
864 }
865
866 SECTION("nodeType")
867 {
868 yang::NodeTypes expected;
869 SECTION("leafInt32")
870 {
871 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
872 expected = yang::NodeTypes::Leaf;
873 }
874
875 SECTION("a")
876 {
877 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
878 expected = yang::NodeTypes::Container;
879 }
880
881 SECTION("a/a2/a3")
882 {
883 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
884 path.m_nodes.push_back(schemaNode_(container_("a2")));
885 path.m_nodes.push_back(schemaNode_(container_("a3")));
886 expected = yang::NodeTypes::PresenceContainer;
887 }
888
889 SECTION("_list")
890 {
891 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, list_("_list")));
892 expected = yang::NodeTypes::List;
893 }
894
895 REQUIRE(ys.nodeType(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
896 }
Václav Kubernát0d4db442018-07-18 17:18:43 +0200897 }
898
899 SECTION("negative")
900 {
901 SECTION("nonexistent nodes")
902 {
903 SECTION("example-schema:coze")
904 {
905 node.first = "example-schema";
906 node.second = "coze";
907 }
908
909 SECTION("example-schema:a/nevim")
910 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200911 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200912 node.second = "nevim";
913 }
914
915 SECTION("modul:a/nevim")
916 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200917 path.m_nodes.push_back(schemaNode_(module_{"modul"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200918 node.second = "nevim";
919 }
920
921 REQUIRE(!ys.isPresenceContainer(path, node));
922 REQUIRE(!ys.isList(path, node));
923 REQUIRE(!ys.isLeaf(path, node));
924 REQUIRE(!ys.isContainer(path, node));
925 }
926
927 SECTION("\"is\" methods return false for existing nodes for different nodetypes")
928 {
929 SECTION("example-schema:a")
930 {
931 node.first = "example-schema";
932 node.second = "a";
933 }
934
935 SECTION("example-schema:a/a2")
936 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200937 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200938 node.second = "a2";
939 }
940
941 REQUIRE(!ys.isPresenceContainer(path, node));
942 REQUIRE(!ys.isList(path, node));
943 REQUIRE(!ys.isLeaf(path, node));
944 }
945
946 SECTION("nodetype-specific methods called with different nodetypes")
947 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200948 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200949 node.second = "a2";
950
951 REQUIRE(!ys.leafEnumHasValue(path, node, "haha"));
952 REQUIRE(!ys.listHasKey(path, node, "chacha"));
953 }
954
955 SECTION("nonexistent module")
956 {
Václav Kubernát75877de2019-11-20 17:43:02 +0100957 REQUIRE(!ys.isModule("notAModule"));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200958 }
Václav Kubernáteeb38842019-03-20 19:46:05 +0100959
960 SECTION("leafIdentityIsValid")
961 {
962 ModuleValuePair value;
963 SECTION("pizzaIdentLeaf")
964 {
965 node.first = "example-schema";
966 node.second = "pizzaIdentLeaf";
967
968 SECTION("wrong base ident")
969 {
970 SECTION("food")
971 {
972 value.second = "food";
973 }
974 SECTION("fruit")
975 {
976 value.second = "fruit";
977 }
978 }
979 SECTION("non-existent identity")
980 {
981 value.second = "nonexistent";
982 }
983 SECTION("weird module")
984 {
985 value.first = "ahahaha";
986 value.second = "pizza";
987 }
988 }
989 SECTION("different module identity, but withotu prefix")
990 {
991 node.first = "example-schema";
992 node.second = "foodIdentLeaf";
993 value.second = "pineapple";
994 }
995 REQUIRE_FALSE(ys.leafIdentityIsValid(path, node, value));
996 }
Václav Kubernát7d82da72019-04-11 15:16:38 +0200997
998 SECTION("grouping is not a node")
999 {
1000 SECTION("example-schema:arithmeticFlags")
1001 {
1002 node.first = "example-schema";
1003 node.second = "arithmeticFlags";
1004 }
1005
1006 SECTION("example-schema:flags")
1007 {
1008 node.first = "example-schema";
1009 node.second = "startAndStop";
1010 }
1011
1012 REQUIRE(!ys.isPresenceContainer(path, node));
1013 REQUIRE(!ys.isList(path, node));
1014 REQUIRE(!ys.isLeaf(path, node));
1015 REQUIRE(!ys.isContainer(path, node));
1016 }
Václav Kubernát280df4a2019-11-01 14:46:34 +01001017
1018 SECTION("choice is not a node")
1019 {
1020 SECTION("example-schema:interface")
1021 {
1022 node.first = "example-schema";
1023 node.second = "interface";
1024 }
1025
1026 REQUIRE(!ys.isPresenceContainer(path, node));
1027 REQUIRE(!ys.isList(path, node));
1028 REQUIRE(!ys.isLeaf(path, node));
1029 REQUIRE(!ys.isContainer(path, node));
1030 }
1031
1032 SECTION("case is not a node")
1033 {
1034 SECTION("example-schema:caseLoopback")
1035 {
1036 node.first = "example-schema";
1037 node.second = "caseLoopback";
1038 }
1039
1040 SECTION("example-schema:caseEthernet")
1041 {
1042 node.first = "example-schema";
1043 node.second = "caseEthernet";
1044 }
1045
1046 REQUIRE(!ys.isPresenceContainer(path, node));
1047 REQUIRE(!ys.isList(path, node));
1048 REQUIRE(!ys.isLeaf(path, node));
1049 REQUIRE(!ys.isContainer(path, node));
1050 }
Václav Kubernáta38d4172019-11-04 12:36:39 +01001051
1052 SECTION("enum is disabled by if-feature if feature is not enabled")
1053 {
1054 node.first = "example-schema";
1055 node.second = "pizzaSize";
1056
1057 std::string value = "large";
1058
1059 REQUIRE(!ys.leafEnumHasValue(path, node, value));
1060 }
Václav Kubernát0d4db442018-07-18 17:18:43 +02001061 }
1062}