blob: fc57d3f55de8fc09462688ae26a97f3b27cb54e7 [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átbd5e3c22020-02-19 15:22:00 +0100293 leaf activeNumber {
294 type leafref {
295 path "/_list/number";
296 }
297 }
298
Václav Kubernátfa81c8c2020-02-13 17:22:46 +0100299 rpc myRpc {}
300
Václav Kubernát0d4db442018-07-18 17:18:43 +0200301})";
302
Václav Kubernát47a3f672019-11-08 15:42:43 +0100303namespace std {
304std::ostream& operator<<(std::ostream& s, const std::set<std::string> set)
305{
306 s << std::endl << "{";
307 std::copy(set.begin(), set.end(), std::experimental::make_ostream_joiner(s, ", "));
308 s << "}" << std::endl;
309 return s;
310}
311}
312
Václav Kubernát0d4db442018-07-18 17:18:43 +0200313TEST_CASE("yangschema")
314{
Václav Kubernát4f77a252019-02-19 16:51:30 +0100315 using namespace std::string_view_literals;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200316 YangSchema ys;
Václav Kubernátb52dc252019-12-04 13:03:39 +0100317 ys.registerModuleCallback([]([[maybe_unused]] auto modName, auto, auto, auto) {
Václav Kubernát4f77a252019-02-19 16:51:30 +0100318 assert("example-schema"sv == modName);
319 return example_schema;
320 });
321 ys.addSchemaString(second_schema);
322
Václav Kubernátefcac932020-01-10 15:26:32 +0100323 schemaPath_ path{Scope::Absolute, {}};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200324 ModuleNodePair node;
325
326 SECTION("positive")
327 {
328 SECTION("isContainer")
329 {
330 SECTION("example-schema:a")
331 {
332 node.first = "example-schema";
333 node.second = "a";
334 }
335
336 SECTION("example-schema:a/a2")
337 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200338 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200339 node.second = "a2";
340 }
341
Václav Kubernát280df4a2019-11-01 14:46:34 +0100342 SECTION("example-schema:ethernet")
343 {
344 node.first = "example-schema";
345 node.second = "ethernet";
346 }
347
348 SECTION("example-schema:loopback")
349 {
350 node.first = "example-schema";
351 node.second = "loopback";
352 }
353
Václav Kubernát0d4db442018-07-18 17:18:43 +0200354 REQUIRE(ys.isContainer(path, node));
355 }
356 SECTION("isLeaf")
357 {
358 SECTION("example-schema:leafString")
359 {
360 node.first = "example-schema";
361 node.second = "leafString";
362 }
363
364 SECTION("example-schema:a/leafa")
365 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200366 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200367 node.first = "example-schema";
368 node.second = "leafa";
369 }
370
Václav Kubernát7d82da72019-04-11 15:16:38 +0200371 SECTION("example-schema:carry")
372 {
373 node.first = "example-schema";
374 node.second = "carry";
375 }
376
377 SECTION("example-schema:zero")
378 {
379 node.first = "example-schema";
380 node.second = "zero";
381 }
382
383 SECTION("example-schema:direction")
384 {
385 node.first = "example-schema";
386 node.second = "direction";
387 }
388
389 SECTION("example-schema:interrupt")
390 {
391 node.first = "example-schema";
392 node.second = "interrupt";
393 }
394
Václav Kubernát0d4db442018-07-18 17:18:43 +0200395 REQUIRE(ys.isLeaf(path, node));
396 }
397 SECTION("isModule")
398 {
Václav Kubernát75877de2019-11-20 17:43:02 +0100399 REQUIRE(ys.isModule("example-schema"));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200400 }
401 SECTION("isList")
402 {
403 SECTION("example-schema:_list")
404 {
405 node.first = "example-schema";
406 node.second = "_list";
407 }
408
409 SECTION("example-schema:twoKeyList")
410 {
411 node.first = "example-schema";
412 node.second = "twoKeyList";
413 }
414
415 REQUIRE(ys.isList(path, node));
416 }
417 SECTION("isPresenceContainer")
418 {
419 SECTION("example-schema:a/a2/a3")
420 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200421 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
422 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a2")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200423 node.second = "a3";
424 }
425
426 REQUIRE(ys.isPresenceContainer(path, node));
427 }
428 SECTION("leafEnumHasValue")
429 {
Václav Kubernát0d4db442018-07-18 17:18:43 +0200430 std::string value;
Václav Kubernát6a713d62018-10-03 18:47:34 +0200431 SECTION("leafEnum")
432 {
433 node.first = "example-schema";
434 node.second = "leafEnum";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200435
Václav Kubernát6a713d62018-10-03 18:47:34 +0200436 SECTION("lol")
437 value = "lol";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200438
Václav Kubernát6a713d62018-10-03 18:47:34 +0200439 SECTION("data")
440 value = "data";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200441
Václav Kubernát6a713d62018-10-03 18:47:34 +0200442 SECTION("coze")
443 value = "coze";
444 }
445
446 SECTION("leafEnumTypedef")
447 {
448 node.first = "example-schema";
449 node.second = "leafEnumTypedef";
450
451 SECTION("lol")
452 value = "lol";
453
454 SECTION("data")
455 value = "data";
456
457 SECTION("coze")
458 value = "coze";
459 }
460
461 SECTION("leafEnumTypedefRestricted")
462 {
463 node.first = "example-schema";
464 node.second = "leafEnumTypedefRestricted";
465
466 SECTION("data")
467 value = "data";
468
469 SECTION("coze")
470 value = "coze";
471 }
472
473 SECTION("leafEnumTypedefRestricted2")
474 {
475 node.first = "example-schema";
476 node.second = "leafEnumTypedefRestricted2";
477
478 SECTION("lol")
479 value = "lol";
480
481 SECTION("data")
482 value = "data";
483 }
Václav Kubernát0d4db442018-07-18 17:18:43 +0200484
Václav Kubernáta38d4172019-11-04 12:36:39 +0100485 SECTION("pizzaSize")
486 {
487 node.first = "example-schema";
488 node.second = "pizzaSize";
489
490 SECTION("small")
491 {
492 value = "small";
Václav Kubernáta38d4172019-11-04 12:36:39 +0100493 }
494 SECTION("medium")
495 {
496 value = "medium";
497 }
498
499 SECTION("large")
500 {
501 ys.enableFeature("example-schema", "bigPizzas");
502 value = "large";
503 }
504 }
505
Václav Kubernát0d4db442018-07-18 17:18:43 +0200506 REQUIRE(ys.leafEnumHasValue(path, node, value));
507 }
Václav Kubernáteeb38842019-03-20 19:46:05 +0100508 SECTION("leafIdentityIsValid")
509 {
510 ModuleValuePair value;
511
512 SECTION("foodIdentLeaf")
513 {
514 node.first = "example-schema";
515 node.second = "foodIdentLeaf";
516
517 SECTION("food")
518 {
519 value.second = "food";
520 }
521 SECTION("example-schema:food")
522 {
523 value.first = "example-schema";
524 value.second = "food";
525 }
526 SECTION("pizza")
527 {
528 value.second = "pizza";
529 }
530 SECTION("example-schema:pizza")
531 {
532 value.first = "example-schema";
533 value.second = "pizza";
534 }
535 SECTION("hawaii")
536 {
537 value.second = "hawaii";
538 }
539 SECTION("example-schema:hawaii")
540 {
541 value.first = "example-schema";
542 value.second = "hawaii";
543 }
544 SECTION("fruit")
545 {
546 value.second = "fruit";
547 }
548 SECTION("example-schema:fruit")
549 {
550 value.first = "example-schema";
551 value.second = "fruit";
552 }
553 SECTION("second-schema:pineapple")
554 {
555 value.first = "second-schema";
556 value.second = "pineapple";
557 }
558 }
559
560 SECTION("pizzaIdentLeaf")
561 {
562 node.first = "example-schema";
563 node.second = "pizzaIdentLeaf";
564
565 SECTION("pizza")
566 {
567 value.second = "pizza";
568 }
569 SECTION("example-schema:pizza")
570 {
571 value.first = "example-schema";
572 value.second = "pizza";
573 }
574 SECTION("hawaii")
575 {
576 value.second = "hawaii";
577 }
578 SECTION("example-schema:hawaii")
579 {
580 value.first = "example-schema";
581 value.second = "hawaii";
582 }
583 }
584
585 SECTION("foodDrinkIdentLeaf")
586 {
587 node.first = "example-schema";
588 node.second = "foodDrinkIdentLeaf";
589
590 SECTION("food")
591 {
592 value.second = "food";
593 }
594 SECTION("example-schema:food")
595 {
596 value.first = "example-schema";
597 value.second = "food";
598 }
599 SECTION("drink")
600 {
601 value.second = "drink";
602 }
603 SECTION("example-schema:drink")
604 {
605 value.first = "example-schema";
606 value.second = "drink";
607 }
608 }
609 REQUIRE(ys.leafIdentityIsValid(path, node, value));
610 }
611
Václav Kubernát0d4db442018-07-18 17:18:43 +0200612 SECTION("listHasKey")
613 {
614 std::string key;
615
616 SECTION("_list")
617 {
618 node.first = "example-schema";
619 node.second = "_list";
620 SECTION("number")
621 key = "number";
622 }
623
624 SECTION("twoKeyList")
625 {
626 node.first = "example-schema";
627 node.second = "twoKeyList";
628 SECTION("number")
629 key = "number";
630 SECTION("name")
631 key = "name";
632 }
633
634 REQUIRE(ys.listHasKey(path, node, key));
635 }
636 SECTION("listKeys")
637 {
638 std::set<std::string> set;
639
640 SECTION("_list")
641 {
642 set = {"number"};
643 node.first = "example-schema";
644 node.second = "_list";
645 }
646
647 SECTION("twoKeyList")
648 {
649 set = {"number", "name"};
650 node.first = "example-schema";
651 node.second = "twoKeyList";
652 }
653
654 REQUIRE(ys.listKeys(path, node) == set);
655 }
656 SECTION("leafType")
657 {
658 yang::LeafDataTypes type;
659
660 SECTION("leafString")
661 {
662 node.first = "example-schema";
663 node.second = "leafString";
664 type = yang::LeafDataTypes::String;
665 }
666
667 SECTION("leafDecimal")
668 {
669 node.first = "example-schema";
670 node.second = "leafDecimal";
671 type = yang::LeafDataTypes::Decimal;
672 }
673
674 SECTION("leafBool")
675 {
676 node.first = "example-schema";
677 node.second = "leafBool";
678 type = yang::LeafDataTypes::Bool;
679 }
680
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200681 SECTION("leafInt8")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200682 {
683 node.first = "example-schema";
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200684 node.second = "leafInt8";
685 type = yang::LeafDataTypes::Int8;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200686 }
687
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200688 SECTION("leafUint8")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200689 {
690 node.first = "example-schema";
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200691 node.second = "leafUint8";
692 type = yang::LeafDataTypes::Uint8;
693 }
694
Václav Kubernátb6d02752020-04-03 00:25:10 +0200695 SECTION("leafInt16")
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200696 {
697 node.first = "example-schema";
698 node.second = "leafInt16";
699 type = yang::LeafDataTypes::Int16;
700 }
701
702 SECTION("leafUint16")
703 {
704 node.first = "example-schema";
705 node.second = "leafUint16";
706 type = yang::LeafDataTypes::Uint16;
707 }
708
709 SECTION("leafInt32")
710 {
711 node.first = "example-schema";
712 node.second = "leafInt32";
713 type = yang::LeafDataTypes::Int32;
714 }
715
716 SECTION("leafUint32")
717 {
718 node.first = "example-schema";
719 node.second = "leafUint32";
720 type = yang::LeafDataTypes::Uint32;
721 }
722
723 SECTION("leafInt64")
724 {
725 node.first = "example-schema";
726 node.second = "leafInt64";
727 type = yang::LeafDataTypes::Int64;
728 }
729
730 SECTION("leafUint64")
731 {
732 node.first = "example-schema";
733 node.second = "leafUint64";
734 type = yang::LeafDataTypes::Uint64;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200735 }
736
737 SECTION("leafEnum")
738 {
739 node.first = "example-schema";
740 node.second = "leafEnum";
741 type = yang::LeafDataTypes::Enum;
742 }
743
Václav Kubernátb6d02752020-04-03 00:25:10 +0200744 SECTION("activeNumber")
745 {
746 node.first = "example-schema";
747 node.second = "activeNumber";
748 type = yang::LeafDataTypes::LeafRef;
749 }
750
Václav Kubernát0d4db442018-07-18 17:18:43 +0200751 REQUIRE(ys.leafType(path, node) == type);
752 }
753 SECTION("childNodes")
754 {
755 std::set<std::string> set;
756
757 SECTION("<root>")
758 {
759 set = {"example-schema:a", "example-schema:b", "example-schema:leafString",
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200760 "example-schema:leafDecimal", "example-schema:leafBool",
761 "example-schema:leafInt8", "example-schema:leafUint8",
762 "example-schema:leafInt16", "example-schema:leafUint16",
763 "example-schema:leafInt32", "example-schema:leafUint32",
764 "example-schema:leafInt64", "example-schema:leafUint64",
765 "example-schema:leafEnum", "example-schema:leafEnumTypedef",
Václav Kubernát6a713d62018-10-03 18:47:34 +0200766 "example-schema:leafEnumTypedefRestricted", "example-schema:leafEnumTypedefRestricted2",
Václav Kubernáteeb38842019-03-20 19:46:05 +0100767 "example-schema:foodIdentLeaf", "example-schema:pizzaIdentLeaf", "example-schema:foodDrinkIdentLeaf",
Václav Kubernát7d82da72019-04-11 15:16:38 +0200768 "example-schema:_list", "example-schema:twoKeyList", "second-schema:bla",
769 "example-schema:carry", "example-schema:zero", "example-schema:direction",
Václav Kubernát280df4a2019-11-01 14:46:34 +0100770 "example-schema:interrupt",
Václav Kubernáta38d4172019-11-04 12:36:39 +0100771 "example-schema:ethernet", "example-schema:loopback",
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100772 "example-schema:pizzaSize",
773 "example-schema:length", "example-schema:wavelength",
Václav Kubernátbd5e3c22020-02-19 15:22:00 +0100774 "example-schema:duration", "example-schema:another-duration",
775 "example-schema:activeNumber"};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200776 }
777
Václav Kubernát4f77a252019-02-19 16:51:30 +0100778 SECTION("example-schema:a")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200779 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200780 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát4f77a252019-02-19 16:51:30 +0100781 set = {"a2", "leafa", "second-schema:augmentedContainer"};
782 }
783
784 SECTION("second-schema:bla")
785 {
786 path.m_nodes.push_back(schemaNode_(module_{"second-schema"}, container_("bla")));
787 set = {"bla2"};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200788 }
789
Václav Kubernát47a3f672019-11-08 15:42:43 +0100790 SECTION("example-schema:ethernet")
791 {
792 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("ethernet")));
793 set = {"ip"};
794 }
795
Václav Kubernáte7d4aea2018-09-11 18:15:48 +0200796 REQUIRE(ys.childNodes(path, Recursion::NonRecursive) == set);
Václav Kubernát0d4db442018-07-18 17:18:43 +0200797 }
Václav Kubernát34ee85a2020-02-18 17:12:12 +0100798 SECTION("nodeType")
799 {
800 yang::NodeTypes expected;
801 SECTION("leafInt32")
802 {
803 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
804 expected = yang::NodeTypes::Leaf;
805 }
806
807 SECTION("a")
808 {
809 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
810 expected = yang::NodeTypes::Container;
811 }
812
813 SECTION("a/a2/a3")
814 {
815 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
816 path.m_nodes.push_back(schemaNode_(container_("a2")));
817 path.m_nodes.push_back(schemaNode_(container_("a3")));
818 expected = yang::NodeTypes::PresenceContainer;
819 }
820
821 SECTION("_list")
822 {
823 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, list_("_list")));
824 expected = yang::NodeTypes::List;
825 }
826
827 REQUIRE(ys.nodeType(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
828 }
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100829
830 SECTION("description")
831 {
832 std::optional<std::string> expected;
833 SECTION("leafInt32")
834 {
835 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
836 expected = "A 32-bit integer leaf.";
837 }
838
839 SECTION("leafString")
840 {
841 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafString")));
842 }
843
844 REQUIRE(ys.description(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
845 }
846
847 SECTION("units")
848 {
849 std::optional<std::string> expected;
850 SECTION("length")
851 {
852 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("length")));
853 expected = "m";
854 }
855
856 SECTION("wavelength")
857 {
858 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("wavelength")));
859 expected = "nm";
860 }
861
862 SECTION("leafInt32")
863 {
864 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
865 }
866
867 SECTION("duration")
868 {
869 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("duration")));
870 expected = "s";
871 }
872
873 SECTION("another-duration")
874 {
875 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("another-duration")));
876 expected = "vt";
877 }
878
879 REQUIRE(ys.units(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
880 }
881
882 SECTION("nodeType")
883 {
884 yang::NodeTypes expected;
885 SECTION("leafInt32")
886 {
887 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
888 expected = yang::NodeTypes::Leaf;
889 }
890
891 SECTION("a")
892 {
893 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
894 expected = yang::NodeTypes::Container;
895 }
896
897 SECTION("a/a2/a3")
898 {
899 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
900 path.m_nodes.push_back(schemaNode_(container_("a2")));
901 path.m_nodes.push_back(schemaNode_(container_("a3")));
902 expected = yang::NodeTypes::PresenceContainer;
903 }
904
905 SECTION("_list")
906 {
907 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, list_("_list")));
908 expected = yang::NodeTypes::List;
909 }
910
911 REQUIRE(ys.nodeType(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
912 }
Václav Kubernátbd5e3c22020-02-19 15:22:00 +0100913
914 SECTION("leafrefPath")
915 {
916 REQUIRE(ys.leafrefPath("/example-schema:activeNumber") == "/example-schema:_list/number");
917 }
Václav Kubernát0d4db442018-07-18 17:18:43 +0200918 }
919
920 SECTION("negative")
921 {
922 SECTION("nonexistent nodes")
923 {
924 SECTION("example-schema:coze")
925 {
926 node.first = "example-schema";
927 node.second = "coze";
928 }
929
930 SECTION("example-schema:a/nevim")
931 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200932 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200933 node.second = "nevim";
934 }
935
936 SECTION("modul:a/nevim")
937 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200938 path.m_nodes.push_back(schemaNode_(module_{"modul"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200939 node.second = "nevim";
940 }
941
942 REQUIRE(!ys.isPresenceContainer(path, node));
943 REQUIRE(!ys.isList(path, node));
944 REQUIRE(!ys.isLeaf(path, node));
945 REQUIRE(!ys.isContainer(path, node));
946 }
947
948 SECTION("\"is\" methods return false for existing nodes for different nodetypes")
949 {
950 SECTION("example-schema:a")
951 {
952 node.first = "example-schema";
953 node.second = "a";
954 }
955
956 SECTION("example-schema:a/a2")
957 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200958 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200959 node.second = "a2";
960 }
961
962 REQUIRE(!ys.isPresenceContainer(path, node));
963 REQUIRE(!ys.isList(path, node));
964 REQUIRE(!ys.isLeaf(path, node));
965 }
966
967 SECTION("nodetype-specific methods called with different nodetypes")
968 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200969 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200970 node.second = "a2";
971
972 REQUIRE(!ys.leafEnumHasValue(path, node, "haha"));
973 REQUIRE(!ys.listHasKey(path, node, "chacha"));
974 }
975
976 SECTION("nonexistent module")
977 {
Václav Kubernát75877de2019-11-20 17:43:02 +0100978 REQUIRE(!ys.isModule("notAModule"));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200979 }
Václav Kubernáteeb38842019-03-20 19:46:05 +0100980
981 SECTION("leafIdentityIsValid")
982 {
983 ModuleValuePair value;
984 SECTION("pizzaIdentLeaf")
985 {
986 node.first = "example-schema";
987 node.second = "pizzaIdentLeaf";
988
989 SECTION("wrong base ident")
990 {
991 SECTION("food")
992 {
993 value.second = "food";
994 }
995 SECTION("fruit")
996 {
997 value.second = "fruit";
998 }
999 }
1000 SECTION("non-existent identity")
1001 {
1002 value.second = "nonexistent";
1003 }
1004 SECTION("weird module")
1005 {
1006 value.first = "ahahaha";
1007 value.second = "pizza";
1008 }
1009 }
1010 SECTION("different module identity, but withotu prefix")
1011 {
1012 node.first = "example-schema";
1013 node.second = "foodIdentLeaf";
1014 value.second = "pineapple";
1015 }
1016 REQUIRE_FALSE(ys.leafIdentityIsValid(path, node, value));
1017 }
Václav Kubernát7d82da72019-04-11 15:16:38 +02001018
1019 SECTION("grouping is not a node")
1020 {
1021 SECTION("example-schema:arithmeticFlags")
1022 {
1023 node.first = "example-schema";
1024 node.second = "arithmeticFlags";
1025 }
1026
1027 SECTION("example-schema:flags")
1028 {
1029 node.first = "example-schema";
1030 node.second = "startAndStop";
1031 }
1032
1033 REQUIRE(!ys.isPresenceContainer(path, node));
1034 REQUIRE(!ys.isList(path, node));
1035 REQUIRE(!ys.isLeaf(path, node));
1036 REQUIRE(!ys.isContainer(path, node));
1037 }
Václav Kubernát280df4a2019-11-01 14:46:34 +01001038
1039 SECTION("choice is not a node")
1040 {
1041 SECTION("example-schema:interface")
1042 {
1043 node.first = "example-schema";
1044 node.second = "interface";
1045 }
1046
1047 REQUIRE(!ys.isPresenceContainer(path, node));
1048 REQUIRE(!ys.isList(path, node));
1049 REQUIRE(!ys.isLeaf(path, node));
1050 REQUIRE(!ys.isContainer(path, node));
1051 }
1052
1053 SECTION("case is not a node")
1054 {
1055 SECTION("example-schema:caseLoopback")
1056 {
1057 node.first = "example-schema";
1058 node.second = "caseLoopback";
1059 }
1060
1061 SECTION("example-schema:caseEthernet")
1062 {
1063 node.first = "example-schema";
1064 node.second = "caseEthernet";
1065 }
1066
1067 REQUIRE(!ys.isPresenceContainer(path, node));
1068 REQUIRE(!ys.isList(path, node));
1069 REQUIRE(!ys.isLeaf(path, node));
1070 REQUIRE(!ys.isContainer(path, node));
1071 }
Václav Kubernáta38d4172019-11-04 12:36:39 +01001072
1073 SECTION("enum is disabled by if-feature if feature is not enabled")
1074 {
1075 node.first = "example-schema";
1076 node.second = "pizzaSize";
1077
1078 std::string value = "large";
1079
1080 REQUIRE(!ys.leafEnumHasValue(path, node, value));
1081 }
Václav Kubernát0d4db442018-07-18 17:18:43 +02001082 }
1083}