blob: 598f1150d36163e3b5b434897e31be3e709c48d3 [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át3a99f002020-03-31 02:27:41 +020010#include "leaf_data_helpers.hpp"
Václav Kubernát1e09bd62020-02-17 15:13:38 +010011#include "pretty_printers.hpp"
Václav Kubernát26b56082020-02-03 18:28:56 +010012#include "trompeloeil_doctest.hpp"
Václav Kubernát0d4db442018-07-18 17:18:43 +020013#include "yang_schema.hpp"
14
Václav Kubernát4f77a252019-02-19 16:51:30 +010015const char* second_schema = R"(
16module second-schema {
17 namespace "http://example.com/nevim";
18 prefix second;
19
20 import example-schema {
21 prefix "example";
22 }
23
Václav Kubernáteeb38842019-03-20 19:46:05 +010024 identity pineapple {
25 base "example:fruit";
26 }
27
Václav Kubernát4f77a252019-02-19 16:51:30 +010028 augment /example:a {
29 container augmentedContainer {
30 }
31 }
32
33 container bla {
34 container bla2 {
35 }
36 }
37}
38)";
39
40const char* example_schema = R"(
Václav Kubernát0d4db442018-07-18 17:18:43 +020041module example-schema {
Václav Kubernát6a713d62018-10-03 18:47:34 +020042 yang-version 1.1;
Václav Kubernát0d4db442018-07-18 17:18:43 +020043 namespace "http://example.com/example-sports";
44 prefix coze;
45
Václav Kubernáteeb38842019-03-20 19:46:05 +010046 identity drink {
47 }
48
49 identity voda {
50 base "drink";
51 }
52
53 identity food {
54 }
55
56 identity fruit {
57 base "food";
58 }
59
60 identity pizza {
61 base "food";
62 }
63
64 identity hawaii {
65 base "pizza";
66 }
67
Václav Kubernát0d4db442018-07-18 17:18:43 +020068 container a {
69 container a2 {
70 container a3 {
71 presence true;
72 }
73 }
74
75 leaf leafa {
76 type string;
77 }
78 }
79
80 container b {
81 container b2 {
82 presence true;
83 container b3 {
84 }
85 }
86 }
87
88 leaf leafString {
89 type string;
90 }
91
92 leaf leafDecimal {
93 type decimal64 {
94 fraction-digits 5;
95 }
96 }
97
98 leaf leafBool {
99 type boolean;
100 }
101
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200102 leaf leafInt8 {
103 type int8;
104 }
105
106 leaf leafUint8 {
107 type uint8;
108 }
109
110 leaf leafInt16 {
111 type int16;
112 }
113
114 leaf leafUint16 {
115 type uint16;
116 }
117
118 leaf leafInt32 {
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100119 description "A 32-bit integer leaf.";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200120 type int32;
121 }
122
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200123 leaf leafUint32 {
Václav Kubernát0d4db442018-07-18 17:18:43 +0200124 type uint32;
125 }
126
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200127 leaf leafInt64 {
128 type int64;
129 }
130
131 leaf leafUint64 {
132 type uint64;
Václav Kubernátb1a75c62020-04-21 15:20:16 +0200133 default 9001;
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200134 }
135
Václav Kubernát0d4db442018-07-18 17:18:43 +0200136 leaf leafEnum {
137 type enumeration {
138 enum lol;
139 enum data;
140 enum coze;
141 }
142 }
143
Václav Kubernát6a713d62018-10-03 18:47:34 +0200144 typedef enumTypedef {
145 type enumeration {
146 enum lol;
147 enum data;
148 enum coze;
149 }
Václav Kubernátb1a75c62020-04-21 15:20:16 +0200150 default data;
Václav Kubernát6a713d62018-10-03 18:47:34 +0200151 }
152
153 typedef enumTypedefRestricted {
154 type enumTypedef {
155 enum lol;
156 enum data;
157 }
158 }
159
160 leaf leafEnumTypedef {
161 type enumTypedef;
162 }
163
164 leaf leafEnumTypedefRestricted {
165 type enumTypedef {
166 enum data;
167 enum coze;
168 }
169 }
170
171 leaf leafEnumTypedefRestricted2 {
172 type enumTypedefRestricted;
173 }
174
Václav Kubernáteeb38842019-03-20 19:46:05 +0100175 leaf foodIdentLeaf {
176 type identityref {
177 base "food";
178 }
179 }
180
181 leaf pizzaIdentLeaf {
182 type identityref {
183 base "pizza";
184 }
185 }
186
187 leaf foodDrinkIdentLeaf {
188 type identityref {
189 base "food";
190 base "drink";
191 }
192 }
193
Václav Kubernát0d4db442018-07-18 17:18:43 +0200194 list _list {
195 key number;
196
197 leaf number {
198 type int32;
199 }
200
201 container contInList {
202 presence true;
203 }
204 }
205
206 list twoKeyList {
207 key "name number";
208
209 leaf number {
210 type int32;
211 }
212
213 leaf name {
214 type string;
215 }
216 }
Václav Kubernát7d82da72019-04-11 15:16:38 +0200217
218 grouping arithmeticFlags {
219 leaf carry {
220 type boolean;
221 }
222 leaf zero {
223 type boolean;
224 }
225 }
226
227 grouping flags {
228 leaf direction {
229 type boolean;
230 }
231 leaf interrupt {
232 type boolean;
233 }
234
235 uses arithmeticFlags;
236 }
237
238 uses flags;
Václav Kubernát280df4a2019-11-01 14:46:34 +0100239
240 choice interface {
241 case caseLoopback {
242 container loopback {
243 leaf ip {
244 type string;
245 }
246 }
247 }
248
249 case caseEthernet {
250 container ethernet {
251 leaf ip {
252 type string;
253 }
254 }
255 }
256 }
257
Václav Kubernáta38d4172019-11-04 12:36:39 +0100258 feature bigPizzas;
259
260 leaf pizzaSize {
261 type enumeration {
262 enum large {
263 if-feature "bigPizzas";
264 }
265 enum medium;
266 enum small;
267 }
268 }
269
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100270 leaf length {
271 type int32;
272 units "m";
273 }
274
275 leaf wavelength {
276 type decimal64 {
277 fraction-digits 10;
278 }
279 units "nm";
280 }
281
282 typedef seconds {
283 type int32;
284 units "s";
285 }
286
287 leaf duration {
288 type seconds;
289 }
290
291 leaf another-duration {
292 type seconds;
293 units "vt";
294 }
295
Václav Kubernátbd5e3c22020-02-19 15:22:00 +0100296 leaf activeNumber {
297 type leafref {
298 path "/_list/number";
299 }
300 }
301
Václav Kubernátfa81c8c2020-02-13 17:22:46 +0100302 rpc myRpc {}
303
Václav Kubernát2984f442020-02-20 17:43:35 +0100304 leaf numberOrString {
305 type union {
306 type int32;
307 type string;
308 }
309 description "Can be an int32 or a string.";
310 }
311
312 list portSettings {
313 key "port";
314 leaf port {
315 type enumeration {
316 enum eth0;
317 enum eth1;
318 enum eth2;
319 }
320 }
321 }
322
323 feature weirdPortNames;
324
325 list portMapping {
326 key "port";
327 leaf port {
328 type enumeration {
329 enum WEIRD {
330 if-feature "weirdPortNames";
331 }
332 enum utf2;
333 enum utf3;
334 }
335 }
336 }
337
338 leaf activeMappedPort {
339 type leafref {
340 path "../portMapping/port";
341 }
342 }
343
344 leaf activePort {
345 type union {
346 type enumeration {
347 enum wlan0;
348 enum wlan1;
349 }
350 type leafref {
351 path "../portSettings/port";
352 }
353 type leafref {
354 path "../activeMappedPort";
355 }
356 }
357 }
358
Václav Kubernát0599e9f2020-04-21 09:51:33 +0200359 leaf clockSpeed {
360 type int64;
361 config false;
362 }
363
364 container systemStats {
365 config false;
366 leaf upTime {
367 type uint64;
368 }
369 }
370
Václav Kubernát0d4db442018-07-18 17:18:43 +0200371})";
372
Václav Kubernát47a3f672019-11-08 15:42:43 +0100373namespace std {
374std::ostream& operator<<(std::ostream& s, const std::set<std::string> set)
375{
376 s << std::endl << "{";
377 std::copy(set.begin(), set.end(), std::experimental::make_ostream_joiner(s, ", "));
378 s << "}" << std::endl;
379 return s;
380}
381}
382
Václav Kubernát0d4db442018-07-18 17:18:43 +0200383TEST_CASE("yangschema")
384{
Václav Kubernát4f77a252019-02-19 16:51:30 +0100385 using namespace std::string_view_literals;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200386 YangSchema ys;
Václav Kubernátb52dc252019-12-04 13:03:39 +0100387 ys.registerModuleCallback([]([[maybe_unused]] auto modName, auto, auto, auto) {
Václav Kubernát4f77a252019-02-19 16:51:30 +0100388 assert("example-schema"sv == modName);
389 return example_schema;
390 });
391 ys.addSchemaString(second_schema);
392
Václav Kubernátefcac932020-01-10 15:26:32 +0100393 schemaPath_ path{Scope::Absolute, {}};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200394 ModuleNodePair node;
395
396 SECTION("positive")
397 {
398 SECTION("isContainer")
399 {
400 SECTION("example-schema:a")
401 {
402 node.first = "example-schema";
403 node.second = "a";
404 }
405
406 SECTION("example-schema:a/a2")
407 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200408 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200409 node.second = "a2";
410 }
411
Václav Kubernát280df4a2019-11-01 14:46:34 +0100412 SECTION("example-schema:ethernet")
413 {
414 node.first = "example-schema";
415 node.second = "ethernet";
416 }
417
418 SECTION("example-schema:loopback")
419 {
420 node.first = "example-schema";
421 node.second = "loopback";
422 }
423
Václav Kubernát0d4db442018-07-18 17:18:43 +0200424 REQUIRE(ys.isContainer(path, node));
425 }
426 SECTION("isLeaf")
427 {
428 SECTION("example-schema:leafString")
429 {
430 node.first = "example-schema";
431 node.second = "leafString";
432 }
433
434 SECTION("example-schema:a/leafa")
435 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200436 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200437 node.first = "example-schema";
438 node.second = "leafa";
439 }
440
Václav Kubernát7d82da72019-04-11 15:16:38 +0200441 SECTION("example-schema:carry")
442 {
443 node.first = "example-schema";
444 node.second = "carry";
445 }
446
447 SECTION("example-schema:zero")
448 {
449 node.first = "example-schema";
450 node.second = "zero";
451 }
452
453 SECTION("example-schema:direction")
454 {
455 node.first = "example-schema";
456 node.second = "direction";
457 }
458
459 SECTION("example-schema:interrupt")
460 {
461 node.first = "example-schema";
462 node.second = "interrupt";
463 }
464
Václav Kubernát0d4db442018-07-18 17:18:43 +0200465 REQUIRE(ys.isLeaf(path, node));
466 }
467 SECTION("isModule")
468 {
Václav Kubernát75877de2019-11-20 17:43:02 +0100469 REQUIRE(ys.isModule("example-schema"));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200470 }
471 SECTION("isList")
472 {
473 SECTION("example-schema:_list")
474 {
475 node.first = "example-schema";
476 node.second = "_list";
477 }
478
479 SECTION("example-schema:twoKeyList")
480 {
481 node.first = "example-schema";
482 node.second = "twoKeyList";
483 }
484
485 REQUIRE(ys.isList(path, node));
486 }
487 SECTION("isPresenceContainer")
488 {
489 SECTION("example-schema:a/a2/a3")
490 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200491 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
492 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a2")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200493 node.second = "a3";
494 }
495
496 REQUIRE(ys.isPresenceContainer(path, node));
497 }
Václav Kubernáteeb38842019-03-20 19:46:05 +0100498
Václav Kubernát0d4db442018-07-18 17:18:43 +0200499 SECTION("listHasKey")
500 {
501 std::string key;
502
503 SECTION("_list")
504 {
505 node.first = "example-schema";
506 node.second = "_list";
507 SECTION("number")
508 key = "number";
509 }
510
511 SECTION("twoKeyList")
512 {
513 node.first = "example-schema";
514 node.second = "twoKeyList";
515 SECTION("number")
516 key = "number";
517 SECTION("name")
518 key = "name";
519 }
520
521 REQUIRE(ys.listHasKey(path, node, key));
522 }
523 SECTION("listKeys")
524 {
525 std::set<std::string> set;
526
527 SECTION("_list")
528 {
529 set = {"number"};
530 node.first = "example-schema";
531 node.second = "_list";
532 }
533
534 SECTION("twoKeyList")
535 {
536 set = {"number", "name"};
537 node.first = "example-schema";
538 node.second = "twoKeyList";
539 }
540
541 REQUIRE(ys.listKeys(path, node) == set);
542 }
543 SECTION("leafType")
544 {
Václav Kubernát3a99f002020-03-31 02:27:41 +0200545 yang::LeafDataType type;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200546
547 SECTION("leafString")
548 {
549 node.first = "example-schema";
550 node.second = "leafString";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200551 type = yang::String{};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200552 }
553
554 SECTION("leafDecimal")
555 {
556 node.first = "example-schema";
557 node.second = "leafDecimal";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200558 type = yang::Decimal{};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200559 }
560
561 SECTION("leafBool")
562 {
563 node.first = "example-schema";
564 node.second = "leafBool";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200565 type = yang::Bool{};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200566 }
567
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200568 SECTION("leafInt8")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200569 {
570 node.first = "example-schema";
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200571 node.second = "leafInt8";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200572 type = yang::Int8{};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200573 }
574
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200575 SECTION("leafUint8")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200576 {
577 node.first = "example-schema";
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200578 node.second = "leafUint8";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200579 type = yang::Uint8{};
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200580 }
581
Václav Kubernátb6d02752020-04-03 00:25:10 +0200582 SECTION("leafInt16")
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200583 {
584 node.first = "example-schema";
585 node.second = "leafInt16";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200586 type = yang::Int16{};
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200587 }
588
589 SECTION("leafUint16")
590 {
591 node.first = "example-schema";
592 node.second = "leafUint16";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200593 type = yang::Uint16{};
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200594 }
595
596 SECTION("leafInt32")
597 {
598 node.first = "example-schema";
599 node.second = "leafInt32";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200600 type = yang::Int32{};
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200601 }
602
603 SECTION("leafUint32")
604 {
605 node.first = "example-schema";
606 node.second = "leafUint32";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200607 type = yang::Uint32{};
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200608 }
609
610 SECTION("leafInt64")
611 {
612 node.first = "example-schema";
613 node.second = "leafInt64";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200614 type = yang::Int64{};
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200615 }
616
617 SECTION("leafUint64")
618 {
619 node.first = "example-schema";
620 node.second = "leafUint64";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200621 type = yang::Uint64{};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200622 }
623
624 SECTION("leafEnum")
625 {
626 node.first = "example-schema";
627 node.second = "leafEnum";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200628 type = createEnum({"lol", "data", "coze"});
629 }
630
631 SECTION("leafEnumTypedef")
632 {
633 node.first = "example-schema";
634 node.second = "leafEnumTypedef";
635 type = createEnum({"lol", "data", "coze"});
636 }
637
638 SECTION("leafEnumTypedefRestricted")
639 {
640 node.first = "example-schema";
641 node.second = "leafEnumTypedefRestricted";
642 type = createEnum({"data", "coze"});
643 }
644
645 SECTION("leafEnumTypedefRestricted2")
646 {
647 node.first = "example-schema";
648 node.second = "leafEnumTypedefRestricted2";
649 type = createEnum({"lol", "data"});
650 }
651
652 SECTION("pizzaSize")
653 {
654 node.first = "example-schema";
655 node.second = "pizzaSize";
656
657 SECTION("bigPizzas disabled")
658 {
659 type = createEnum({"small", "medium"});
660 }
661 SECTION("bigPizzas enabled")
662 {
663 ys.enableFeature("example-schema", "bigPizzas");
664 type = createEnum({"small", "medium", "large"});
665 }
666 }
667
668 SECTION("foodIdentLeaf")
669 {
670 node.first = "example-schema";
671 node.second = "foodIdentLeaf";
672 type = yang::IdentityRef{{{"second-schema", "pineapple"},
673 {"example-schema", "food"},
674 {"example-schema", "pizza"},
675 {"example-schema", "hawaii"},
676 {"example-schema", "fruit"}}};
677 }
678
679 SECTION("pizzaIdentLeaf")
680 {
681 node.first = "example-schema";
682 node.second = "pizzaIdentLeaf";
683
684 type = yang::IdentityRef{{
685 {"example-schema", "pizza"},
686 {"example-schema", "hawaii"},
687 }};
688 }
689
690 SECTION("foodDrinkIdentLeaf")
691 {
692 node.first = "example-schema";
693 node.second = "foodDrinkIdentLeaf";
694
695 type = yang::IdentityRef{{
696 {"example-schema", "food"},
697 {"example-schema", "drink"},
698 {"example-schema", "fruit"},
699 {"example-schema", "hawaii"},
700 {"example-schema", "pizza"},
701 {"example-schema", "voda"},
702 {"second-schema", "pineapple"},
703 }};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200704 }
705
Václav Kubernátb6d02752020-04-03 00:25:10 +0200706 SECTION("activeNumber")
707 {
708 node.first = "example-schema";
709 node.second = "activeNumber";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200710 type.emplace<yang::LeafRef>(
711 "/example-schema:_list/number",
Václav Kubernát13b23d72020-04-16 21:49:51 +0200712 std::make_unique<yang::TypeInfo>(ys.leafType("/example-schema:_list/number"))
Václav Kubernát3a99f002020-03-31 02:27:41 +0200713 );
Václav Kubernátb6d02752020-04-03 00:25:10 +0200714 }
715
Václav Kubernát2984f442020-02-20 17:43:35 +0100716 SECTION("activePort")
717 {
718 node.first = "example-schema";
719 node.second = "activePort";
720
721 yang::Enum enums = [&ys]() {
722 SECTION("weird ports disabled")
723 {
724 return createEnum({"utf2", "utf3"});
725 }
726 SECTION("weird ports enabled")
727 {
728 ys.enableFeature("example-schema", "weirdPortNames");
729 return createEnum({"WEIRD", "utf2", "utf3"});
730 }
731 __builtin_unreachable();
732 }();
733
734 type = yang::Union{{
Václav Kubernát13b23d72020-04-16 21:49:51 +0200735 yang::TypeInfo{createEnum({"wlan0", "wlan1"})},
736 yang::TypeInfo{yang::LeafRef{
Václav Kubernát2984f442020-02-20 17:43:35 +0100737 "/example-schema:portSettings/port",
Václav Kubernát13b23d72020-04-16 21:49:51 +0200738 std::make_unique<yang::TypeInfo>(createEnum({"eth0", "eth1", "eth2"}))
739 }},
740 yang::TypeInfo{yang::LeafRef{
Václav Kubernát2984f442020-02-20 17:43:35 +0100741 "/example-schema:activeMappedPort",
Václav Kubernát13b23d72020-04-16 21:49:51 +0200742 std::make_unique<yang::TypeInfo>(yang::LeafRef{
Václav Kubernát2984f442020-02-20 17:43:35 +0100743 "/example-schema:portMapping/port",
Václav Kubernát13b23d72020-04-16 21:49:51 +0200744 std::make_unique<yang::TypeInfo>(enums)
745 })
746 }},
Václav Kubernát2984f442020-02-20 17:43:35 +0100747 }};
748 }
749
Václav Kubernát0d4db442018-07-18 17:18:43 +0200750 REQUIRE(ys.leafType(path, node) == type);
751 }
752 SECTION("childNodes")
753 {
754 std::set<std::string> set;
755
756 SECTION("<root>")
757 {
758 set = {"example-schema:a", "example-schema:b", "example-schema:leafString",
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200759 "example-schema:leafDecimal", "example-schema:leafBool",
760 "example-schema:leafInt8", "example-schema:leafUint8",
761 "example-schema:leafInt16", "example-schema:leafUint16",
762 "example-schema:leafInt32", "example-schema:leafUint32",
763 "example-schema:leafInt64", "example-schema:leafUint64",
764 "example-schema:leafEnum", "example-schema:leafEnumTypedef",
Václav Kubernát6a713d62018-10-03 18:47:34 +0200765 "example-schema:leafEnumTypedefRestricted", "example-schema:leafEnumTypedefRestricted2",
Václav Kubernáteeb38842019-03-20 19:46:05 +0100766 "example-schema:foodIdentLeaf", "example-schema:pizzaIdentLeaf", "example-schema:foodDrinkIdentLeaf",
Václav Kubernát7d82da72019-04-11 15:16:38 +0200767 "example-schema:_list", "example-schema:twoKeyList", "second-schema:bla",
768 "example-schema:carry", "example-schema:zero", "example-schema:direction",
Václav Kubernát280df4a2019-11-01 14:46:34 +0100769 "example-schema:interrupt",
Václav Kubernáta38d4172019-11-04 12:36:39 +0100770 "example-schema:ethernet", "example-schema:loopback",
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100771 "example-schema:pizzaSize",
772 "example-schema:length", "example-schema:wavelength",
Václav Kubernátbd5e3c22020-02-19 15:22:00 +0100773 "example-schema:duration", "example-schema:another-duration",
Václav Kubernát2984f442020-02-20 17:43:35 +0100774 "example-schema:activeNumber",
775 "example-schema:numberOrString",
776 "example-schema:portSettings",
777 "example-schema:portMapping",
778 "example-schema:activeMappedPort",
Václav Kubernát0599e9f2020-04-21 09:51:33 +0200779 "example-schema:activePort",
780 "example-schema:clockSpeed",
781 "example-schema:systemStats"};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200782 }
783
Václav Kubernát4f77a252019-02-19 16:51:30 +0100784 SECTION("example-schema:a")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200785 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200786 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát4f77a252019-02-19 16:51:30 +0100787 set = {"a2", "leafa", "second-schema:augmentedContainer"};
788 }
789
790 SECTION("second-schema:bla")
791 {
792 path.m_nodes.push_back(schemaNode_(module_{"second-schema"}, container_("bla")));
793 set = {"bla2"};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200794 }
795
Václav Kubernát47a3f672019-11-08 15:42:43 +0100796 SECTION("example-schema:ethernet")
797 {
798 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("ethernet")));
799 set = {"ip"};
800 }
801
Václav Kubernáte7d4aea2018-09-11 18:15:48 +0200802 REQUIRE(ys.childNodes(path, Recursion::NonRecursive) == set);
Václav Kubernát0d4db442018-07-18 17:18:43 +0200803 }
Václav Kubernát34ee85a2020-02-18 17:12:12 +0100804 SECTION("nodeType")
805 {
806 yang::NodeTypes expected;
807 SECTION("leafInt32")
808 {
809 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
810 expected = yang::NodeTypes::Leaf;
811 }
812
813 SECTION("a")
814 {
815 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
816 expected = yang::NodeTypes::Container;
817 }
818
819 SECTION("a/a2/a3")
820 {
821 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
822 path.m_nodes.push_back(schemaNode_(container_("a2")));
823 path.m_nodes.push_back(schemaNode_(container_("a3")));
824 expected = yang::NodeTypes::PresenceContainer;
825 }
826
827 SECTION("_list")
828 {
829 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, list_("_list")));
830 expected = yang::NodeTypes::List;
831 }
832
833 REQUIRE(ys.nodeType(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
834 }
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100835
836 SECTION("description")
837 {
838 std::optional<std::string> expected;
839 SECTION("leafInt32")
840 {
841 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
842 expected = "A 32-bit integer leaf.";
843 }
844
845 SECTION("leafString")
846 {
847 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafString")));
848 }
849
Václav Kubernát2984f442020-02-20 17:43:35 +0100850 SECTION("numberOrString")
851 {
852 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("numberOrString")));
853 expected = "Can be an int32 or a string.";
854 }
855
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100856 REQUIRE(ys.description(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
857 }
858
859 SECTION("units")
860 {
Václav Kubernát13b23d72020-04-16 21:49:51 +0200861 yang::LeafDataType expectedType;
862 std::optional<std::string> expectedUnits;
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100863 SECTION("length")
864 {
865 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("length")));
Václav Kubernát13b23d72020-04-16 21:49:51 +0200866 expectedType.emplace<yang::Int32>();
867 expectedUnits = "m";
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100868 }
869
870 SECTION("wavelength")
871 {
872 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("wavelength")));
Václav Kubernát13b23d72020-04-16 21:49:51 +0200873 expectedType.emplace<yang::Decimal>();
874 expectedUnits = "nm";
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100875 }
876
877 SECTION("leafInt32")
878 {
879 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
Václav Kubernát13b23d72020-04-16 21:49:51 +0200880 expectedType.emplace<yang::Int32>();
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100881 }
882
883 SECTION("duration")
884 {
885 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("duration")));
Václav Kubernát13b23d72020-04-16 21:49:51 +0200886 expectedType.emplace<yang::Int32>();
887 expectedUnits = "s";
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100888 }
889
890 SECTION("another-duration")
891 {
892 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("another-duration")));
Václav Kubernát13b23d72020-04-16 21:49:51 +0200893 expectedType.emplace<yang::Int32>();
894 expectedUnits = "vt";
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100895 }
Václav Kubernát13b23d72020-04-16 21:49:51 +0200896 REQUIRE(ys.leafType(pathToSchemaString(path, Prefixes::WhenNeeded)) == yang::TypeInfo{expectedType, expectedUnits});
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100897 }
898
899 SECTION("nodeType")
900 {
901 yang::NodeTypes expected;
902 SECTION("leafInt32")
903 {
904 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
905 expected = yang::NodeTypes::Leaf;
906 }
907
908 SECTION("a")
909 {
910 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
911 expected = yang::NodeTypes::Container;
912 }
913
914 SECTION("a/a2/a3")
915 {
916 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
917 path.m_nodes.push_back(schemaNode_(container_("a2")));
918 path.m_nodes.push_back(schemaNode_(container_("a3")));
919 expected = yang::NodeTypes::PresenceContainer;
920 }
921
922 SECTION("_list")
923 {
924 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, list_("_list")));
925 expected = yang::NodeTypes::List;
926 }
927
928 REQUIRE(ys.nodeType(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
929 }
Václav Kubernátbd5e3c22020-02-19 15:22:00 +0100930
931 SECTION("leafrefPath")
932 {
933 REQUIRE(ys.leafrefPath("/example-schema:activeNumber") == "/example-schema:_list/number");
934 }
Václav Kubernát0599e9f2020-04-21 09:51:33 +0200935
936 SECTION("isConfig")
937 {
938 REQUIRE(ys.isConfig("/example-schema:leafInt32"));
939 REQUIRE_FALSE(ys.isConfig("/example-schema:clockSpeed"));
940 REQUIRE_FALSE(ys.isConfig("/example-schema:systemStats"));
941 REQUIRE_FALSE(ys.isConfig("/example-schema:systemStats/upTime"));
942 }
Václav Kubernátbd0d5c82020-04-21 10:22:03 +0200943
Václav Kubernátb1a75c62020-04-21 15:20:16 +0200944 SECTION("defaultValue")
945 {
946 REQUIRE(ys.defaultValue("/example-schema:leafUint64") == "9001");
947 REQUIRE(ys.defaultValue("/example-schema:leafEnumTypedefRestricted") == "data");
948 REQUIRE(ys.defaultValue("/example-schema:leafInt32") == std::nullopt);
949 }
950
Václav Kubernátbd0d5c82020-04-21 10:22:03 +0200951 SECTION("moduleNodes")
952 {
953 std::string module;
954 std::set<std::string> expectedNonRecursive;
955 std::set<std::string> expectedRecursive;
956 SECTION("example-schema")
957 {
958 module = "example-schema";
959 expectedNonRecursive = {
960 "example-schema:_list",
961 "example-schema:a",
962 "example-schema:activeMappedPort",
963 "example-schema:activeNumber",
964 "example-schema:activePort",
965 "example-schema:another-duration",
966 "example-schema:b",
967 "example-schema:carry",
968 "example-schema:clockSpeed",
969 "example-schema:direction",
970 "example-schema:duration",
971 "example-schema:ethernet",
972 "example-schema:foodDrinkIdentLeaf",
973 "example-schema:foodIdentLeaf",
974 "example-schema:interrupt",
975 "example-schema:leafBool",
976 "example-schema:leafDecimal",
977 "example-schema:leafEnum",
978 "example-schema:leafEnumTypedef",
979 "example-schema:leafEnumTypedefRestricted",
980 "example-schema:leafEnumTypedefRestricted2",
981 "example-schema:leafInt16",
982 "example-schema:leafInt32",
983 "example-schema:leafInt64",
984 "example-schema:leafInt8",
985 "example-schema:leafString",
986 "example-schema:leafUint16",
987 "example-schema:leafUint32",
988 "example-schema:leafUint64",
989 "example-schema:leafUint8",
990 "example-schema:length",
991 "example-schema:loopback",
992 "example-schema:myRpc",
993 "example-schema:numberOrString",
994 "example-schema:pizzaIdentLeaf",
995 "example-schema:pizzaSize",
996 "example-schema:portMapping",
997 "example-schema:portSettings",
998 "example-schema:systemStats",
999 "example-schema:twoKeyList",
1000 "example-schema:wavelength",
1001 "example-schema:zero"
1002 };
1003 expectedRecursive = {
1004 "/example-schema:_list",
1005 "/example-schema:_list/contInList",
1006 "/example-schema:_list/number",
1007 "/example-schema:a",
1008 "/example-schema:a/a2",
1009 "/example-schema:a/a2/a3",
1010 "/example-schema:a/leafa",
1011 "/example-schema:a/second-schema:augmentedContainer",
1012 "/example-schema:activeMappedPort",
1013 "/example-schema:activeNumber",
1014 "/example-schema:activePort",
1015 "/example-schema:another-duration",
1016 "/example-schema:b",
1017 "/example-schema:b/b2",
1018 "/example-schema:b/b2/b3",
1019 "/example-schema:carry",
1020 "/example-schema:clockSpeed",
1021 "/example-schema:direction",
1022 "/example-schema:duration",
1023 "/example-schema:foodDrinkIdentLeaf",
1024 "/example-schema:foodIdentLeaf",
1025 "/example-schema:interface/caseEthernet/ethernet",
1026 "/example-schema:interface/caseEthernet/ethernet/ip",
1027 "/example-schema:interface/caseLoopback/loopback",
1028 "/example-schema:interface/caseLoopback/loopback/ip",
1029 "/example-schema:interrupt",
1030 "/example-schema:leafBool",
1031 "/example-schema:leafDecimal",
1032 "/example-schema:leafEnum",
1033 "/example-schema:leafEnumTypedef",
1034 "/example-schema:leafEnumTypedefRestricted",
1035 "/example-schema:leafEnumTypedefRestricted2",
1036 "/example-schema:leafInt16",
1037 "/example-schema:leafInt32",
1038 "/example-schema:leafInt64",
1039 "/example-schema:leafInt8",
1040 "/example-schema:leafString",
1041 "/example-schema:leafUint16",
1042 "/example-schema:leafUint32",
1043 "/example-schema:leafUint64",
1044 "/example-schema:leafUint8",
1045 "/example-schema:length",
1046 "/example-schema:myRpc",
1047 "/example-schema:myRpc/input",
1048 "/example-schema:myRpc/output",
1049 "/example-schema:numberOrString",
1050 "/example-schema:pizzaIdentLeaf",
1051 "/example-schema:pizzaSize",
1052 "/example-schema:portMapping",
1053 "/example-schema:portMapping/port",
1054 "/example-schema:portSettings",
1055 "/example-schema:portSettings/port",
1056 "/example-schema:systemStats",
1057 "/example-schema:systemStats/upTime",
1058 "/example-schema:twoKeyList",
1059 "/example-schema:twoKeyList/name",
1060 "/example-schema:twoKeyList/number",
1061 "/example-schema:wavelength",
1062 "/example-schema:zero"
1063 };
1064 }
1065
1066 SECTION("second-schema")
1067 {
1068 module = "second-schema";
1069 expectedNonRecursive = {
1070 "second-schema:bla"
1071 };
1072 expectedRecursive = {
1073 "/second-schema:bla", "/second-schema:bla/bla2"
1074 };
1075 }
1076
1077 REQUIRE(ys.moduleNodes(module_{module}, Recursion::NonRecursive) == expectedNonRecursive);
1078 REQUIRE(ys.moduleNodes(module_{module}, Recursion::Recursive) == expectedRecursive);
1079 }
Václav Kubernát0d4db442018-07-18 17:18:43 +02001080 }
1081
1082 SECTION("negative")
1083 {
1084 SECTION("nonexistent nodes")
1085 {
1086 SECTION("example-schema:coze")
1087 {
1088 node.first = "example-schema";
1089 node.second = "coze";
1090 }
1091
1092 SECTION("example-schema:a/nevim")
1093 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +02001094 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +02001095 node.second = "nevim";
1096 }
1097
1098 SECTION("modul:a/nevim")
1099 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +02001100 path.m_nodes.push_back(schemaNode_(module_{"modul"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +02001101 node.second = "nevim";
1102 }
1103
1104 REQUIRE(!ys.isPresenceContainer(path, node));
1105 REQUIRE(!ys.isList(path, node));
1106 REQUIRE(!ys.isLeaf(path, node));
1107 REQUIRE(!ys.isContainer(path, node));
1108 }
1109
1110 SECTION("\"is\" methods return false for existing nodes for different nodetypes")
1111 {
1112 SECTION("example-schema:a")
1113 {
1114 node.first = "example-schema";
1115 node.second = "a";
1116 }
1117
1118 SECTION("example-schema:a/a2")
1119 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +02001120 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +02001121 node.second = "a2";
1122 }
1123
1124 REQUIRE(!ys.isPresenceContainer(path, node));
1125 REQUIRE(!ys.isList(path, node));
1126 REQUIRE(!ys.isLeaf(path, node));
1127 }
1128
1129 SECTION("nodetype-specific methods called with different nodetypes")
1130 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +02001131 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +02001132 node.second = "a2";
1133
Václav Kubernát0d4db442018-07-18 17:18:43 +02001134 REQUIRE(!ys.listHasKey(path, node, "chacha"));
1135 }
1136
1137 SECTION("nonexistent module")
1138 {
Václav Kubernát75877de2019-11-20 17:43:02 +01001139 REQUIRE(!ys.isModule("notAModule"));
Václav Kubernát0d4db442018-07-18 17:18:43 +02001140 }
Václav Kubernáteeb38842019-03-20 19:46:05 +01001141
Václav Kubernát7d82da72019-04-11 15:16:38 +02001142 SECTION("grouping is not a node")
1143 {
1144 SECTION("example-schema:arithmeticFlags")
1145 {
1146 node.first = "example-schema";
1147 node.second = "arithmeticFlags";
1148 }
1149
1150 SECTION("example-schema:flags")
1151 {
1152 node.first = "example-schema";
1153 node.second = "startAndStop";
1154 }
1155
1156 REQUIRE(!ys.isPresenceContainer(path, node));
1157 REQUIRE(!ys.isList(path, node));
1158 REQUIRE(!ys.isLeaf(path, node));
1159 REQUIRE(!ys.isContainer(path, node));
1160 }
Václav Kubernát280df4a2019-11-01 14:46:34 +01001161
1162 SECTION("choice is not a node")
1163 {
1164 SECTION("example-schema:interface")
1165 {
1166 node.first = "example-schema";
1167 node.second = "interface";
1168 }
1169
1170 REQUIRE(!ys.isPresenceContainer(path, node));
1171 REQUIRE(!ys.isList(path, node));
1172 REQUIRE(!ys.isLeaf(path, node));
1173 REQUIRE(!ys.isContainer(path, node));
1174 }
1175
1176 SECTION("case is not a node")
1177 {
1178 SECTION("example-schema:caseLoopback")
1179 {
1180 node.first = "example-schema";
1181 node.second = "caseLoopback";
1182 }
1183
1184 SECTION("example-schema:caseEthernet")
1185 {
1186 node.first = "example-schema";
1187 node.second = "caseEthernet";
1188 }
1189
1190 REQUIRE(!ys.isPresenceContainer(path, node));
1191 REQUIRE(!ys.isList(path, node));
1192 REQUIRE(!ys.isLeaf(path, node));
1193 REQUIRE(!ys.isContainer(path, node));
1194 }
Václav Kubernát0d4db442018-07-18 17:18:43 +02001195 }
1196}