blob: d189f50142a9df9591f8230d17c5687d2de6307a [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
695 SECTION("leafInt15")
696 {
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
744 REQUIRE(ys.leafType(path, node) == type);
745 }
746 SECTION("childNodes")
747 {
748 std::set<std::string> set;
749
750 SECTION("<root>")
751 {
752 set = {"example-schema:a", "example-schema:b", "example-schema:leafString",
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200753 "example-schema:leafDecimal", "example-schema:leafBool",
754 "example-schema:leafInt8", "example-schema:leafUint8",
755 "example-schema:leafInt16", "example-schema:leafUint16",
756 "example-schema:leafInt32", "example-schema:leafUint32",
757 "example-schema:leafInt64", "example-schema:leafUint64",
758 "example-schema:leafEnum", "example-schema:leafEnumTypedef",
Václav Kubernát6a713d62018-10-03 18:47:34 +0200759 "example-schema:leafEnumTypedefRestricted", "example-schema:leafEnumTypedefRestricted2",
Václav Kubernáteeb38842019-03-20 19:46:05 +0100760 "example-schema:foodIdentLeaf", "example-schema:pizzaIdentLeaf", "example-schema:foodDrinkIdentLeaf",
Václav Kubernát7d82da72019-04-11 15:16:38 +0200761 "example-schema:_list", "example-schema:twoKeyList", "second-schema:bla",
762 "example-schema:carry", "example-schema:zero", "example-schema:direction",
Václav Kubernát280df4a2019-11-01 14:46:34 +0100763 "example-schema:interrupt",
Václav Kubernáta38d4172019-11-04 12:36:39 +0100764 "example-schema:ethernet", "example-schema:loopback",
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100765 "example-schema:pizzaSize",
766 "example-schema:length", "example-schema:wavelength",
Václav Kubernátbd5e3c22020-02-19 15:22:00 +0100767 "example-schema:duration", "example-schema:another-duration",
768 "example-schema:activeNumber"};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200769 }
770
Václav Kubernát4f77a252019-02-19 16:51:30 +0100771 SECTION("example-schema:a")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200772 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200773 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát4f77a252019-02-19 16:51:30 +0100774 set = {"a2", "leafa", "second-schema:augmentedContainer"};
775 }
776
777 SECTION("second-schema:bla")
778 {
779 path.m_nodes.push_back(schemaNode_(module_{"second-schema"}, container_("bla")));
780 set = {"bla2"};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200781 }
782
Václav Kubernát47a3f672019-11-08 15:42:43 +0100783 SECTION("example-schema:ethernet")
784 {
785 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("ethernet")));
786 set = {"ip"};
787 }
788
Václav Kubernáte7d4aea2018-09-11 18:15:48 +0200789 REQUIRE(ys.childNodes(path, Recursion::NonRecursive) == set);
Václav Kubernát0d4db442018-07-18 17:18:43 +0200790 }
Václav Kubernát34ee85a2020-02-18 17:12:12 +0100791 SECTION("nodeType")
792 {
793 yang::NodeTypes expected;
794 SECTION("leafInt32")
795 {
796 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
797 expected = yang::NodeTypes::Leaf;
798 }
799
800 SECTION("a")
801 {
802 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
803 expected = yang::NodeTypes::Container;
804 }
805
806 SECTION("a/a2/a3")
807 {
808 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
809 path.m_nodes.push_back(schemaNode_(container_("a2")));
810 path.m_nodes.push_back(schemaNode_(container_("a3")));
811 expected = yang::NodeTypes::PresenceContainer;
812 }
813
814 SECTION("_list")
815 {
816 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, list_("_list")));
817 expected = yang::NodeTypes::List;
818 }
819
820 REQUIRE(ys.nodeType(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
821 }
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100822
823 SECTION("description")
824 {
825 std::optional<std::string> expected;
826 SECTION("leafInt32")
827 {
828 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
829 expected = "A 32-bit integer leaf.";
830 }
831
832 SECTION("leafString")
833 {
834 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafString")));
835 }
836
837 REQUIRE(ys.description(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
838 }
839
840 SECTION("units")
841 {
842 std::optional<std::string> expected;
843 SECTION("length")
844 {
845 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("length")));
846 expected = "m";
847 }
848
849 SECTION("wavelength")
850 {
851 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("wavelength")));
852 expected = "nm";
853 }
854
855 SECTION("leafInt32")
856 {
857 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
858 }
859
860 SECTION("duration")
861 {
862 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("duration")));
863 expected = "s";
864 }
865
866 SECTION("another-duration")
867 {
868 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("another-duration")));
869 expected = "vt";
870 }
871
872 REQUIRE(ys.units(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
873 }
874
875 SECTION("nodeType")
876 {
877 yang::NodeTypes expected;
878 SECTION("leafInt32")
879 {
880 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
881 expected = yang::NodeTypes::Leaf;
882 }
883
884 SECTION("a")
885 {
886 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
887 expected = yang::NodeTypes::Container;
888 }
889
890 SECTION("a/a2/a3")
891 {
892 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
893 path.m_nodes.push_back(schemaNode_(container_("a2")));
894 path.m_nodes.push_back(schemaNode_(container_("a3")));
895 expected = yang::NodeTypes::PresenceContainer;
896 }
897
898 SECTION("_list")
899 {
900 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, list_("_list")));
901 expected = yang::NodeTypes::List;
902 }
903
904 REQUIRE(ys.nodeType(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
905 }
Václav Kubernátbd5e3c22020-02-19 15:22:00 +0100906
907 SECTION("leafrefPath")
908 {
909 REQUIRE(ys.leafrefPath("/example-schema:activeNumber") == "/example-schema:_list/number");
910 }
Václav Kubernát0d4db442018-07-18 17:18:43 +0200911 }
912
913 SECTION("negative")
914 {
915 SECTION("nonexistent nodes")
916 {
917 SECTION("example-schema:coze")
918 {
919 node.first = "example-schema";
920 node.second = "coze";
921 }
922
923 SECTION("example-schema:a/nevim")
924 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200925 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200926 node.second = "nevim";
927 }
928
929 SECTION("modul:a/nevim")
930 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200931 path.m_nodes.push_back(schemaNode_(module_{"modul"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200932 node.second = "nevim";
933 }
934
935 REQUIRE(!ys.isPresenceContainer(path, node));
936 REQUIRE(!ys.isList(path, node));
937 REQUIRE(!ys.isLeaf(path, node));
938 REQUIRE(!ys.isContainer(path, node));
939 }
940
941 SECTION("\"is\" methods return false for existing nodes for different nodetypes")
942 {
943 SECTION("example-schema:a")
944 {
945 node.first = "example-schema";
946 node.second = "a";
947 }
948
949 SECTION("example-schema:a/a2")
950 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200951 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200952 node.second = "a2";
953 }
954
955 REQUIRE(!ys.isPresenceContainer(path, node));
956 REQUIRE(!ys.isList(path, node));
957 REQUIRE(!ys.isLeaf(path, node));
958 }
959
960 SECTION("nodetype-specific methods called with different nodetypes")
961 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200962 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200963 node.second = "a2";
964
965 REQUIRE(!ys.leafEnumHasValue(path, node, "haha"));
966 REQUIRE(!ys.listHasKey(path, node, "chacha"));
967 }
968
969 SECTION("nonexistent module")
970 {
Václav Kubernát75877de2019-11-20 17:43:02 +0100971 REQUIRE(!ys.isModule("notAModule"));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200972 }
Václav Kubernáteeb38842019-03-20 19:46:05 +0100973
974 SECTION("leafIdentityIsValid")
975 {
976 ModuleValuePair value;
977 SECTION("pizzaIdentLeaf")
978 {
979 node.first = "example-schema";
980 node.second = "pizzaIdentLeaf";
981
982 SECTION("wrong base ident")
983 {
984 SECTION("food")
985 {
986 value.second = "food";
987 }
988 SECTION("fruit")
989 {
990 value.second = "fruit";
991 }
992 }
993 SECTION("non-existent identity")
994 {
995 value.second = "nonexistent";
996 }
997 SECTION("weird module")
998 {
999 value.first = "ahahaha";
1000 value.second = "pizza";
1001 }
1002 }
1003 SECTION("different module identity, but withotu prefix")
1004 {
1005 node.first = "example-schema";
1006 node.second = "foodIdentLeaf";
1007 value.second = "pineapple";
1008 }
1009 REQUIRE_FALSE(ys.leafIdentityIsValid(path, node, value));
1010 }
Václav Kubernát7d82da72019-04-11 15:16:38 +02001011
1012 SECTION("grouping is not a node")
1013 {
1014 SECTION("example-schema:arithmeticFlags")
1015 {
1016 node.first = "example-schema";
1017 node.second = "arithmeticFlags";
1018 }
1019
1020 SECTION("example-schema:flags")
1021 {
1022 node.first = "example-schema";
1023 node.second = "startAndStop";
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 }
Václav Kubernát280df4a2019-11-01 14:46:34 +01001031
1032 SECTION("choice is not a node")
1033 {
1034 SECTION("example-schema:interface")
1035 {
1036 node.first = "example-schema";
1037 node.second = "interface";
1038 }
1039
1040 REQUIRE(!ys.isPresenceContainer(path, node));
1041 REQUIRE(!ys.isList(path, node));
1042 REQUIRE(!ys.isLeaf(path, node));
1043 REQUIRE(!ys.isContainer(path, node));
1044 }
1045
1046 SECTION("case is not a node")
1047 {
1048 SECTION("example-schema:caseLoopback")
1049 {
1050 node.first = "example-schema";
1051 node.second = "caseLoopback";
1052 }
1053
1054 SECTION("example-schema:caseEthernet")
1055 {
1056 node.first = "example-schema";
1057 node.second = "caseEthernet";
1058 }
1059
1060 REQUIRE(!ys.isPresenceContainer(path, node));
1061 REQUIRE(!ys.isList(path, node));
1062 REQUIRE(!ys.isLeaf(path, node));
1063 REQUIRE(!ys.isContainer(path, node));
1064 }
Václav Kubernáta38d4172019-11-04 12:36:39 +01001065
1066 SECTION("enum is disabled by if-feature if feature is not enabled")
1067 {
1068 node.first = "example-schema";
1069 node.second = "pizzaSize";
1070
1071 std::string value = "large";
1072
1073 REQUIRE(!ys.leafEnumHasValue(path, node, value));
1074 }
Václav Kubernát0d4db442018-07-18 17:18:43 +02001075 }
1076}