blob: a458909b3be58e68a5f1850768df4af24fa1ce36 [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;
133 }
134
Václav Kubernát0d4db442018-07-18 17:18:43 +0200135 leaf leafEnum {
136 type enumeration {
137 enum lol;
138 enum data;
139 enum coze;
140 }
141 }
142
Václav Kubernát6a713d62018-10-03 18:47:34 +0200143 typedef enumTypedef {
144 type enumeration {
145 enum lol;
146 enum data;
147 enum coze;
148 }
149 }
150
151 typedef enumTypedefRestricted {
152 type enumTypedef {
153 enum lol;
154 enum data;
155 }
156 }
157
158 leaf leafEnumTypedef {
159 type enumTypedef;
160 }
161
162 leaf leafEnumTypedefRestricted {
163 type enumTypedef {
164 enum data;
165 enum coze;
166 }
167 }
168
169 leaf leafEnumTypedefRestricted2 {
170 type enumTypedefRestricted;
171 }
172
Václav Kubernáteeb38842019-03-20 19:46:05 +0100173 leaf foodIdentLeaf {
174 type identityref {
175 base "food";
176 }
177 }
178
179 leaf pizzaIdentLeaf {
180 type identityref {
181 base "pizza";
182 }
183 }
184
185 leaf foodDrinkIdentLeaf {
186 type identityref {
187 base "food";
188 base "drink";
189 }
190 }
191
Václav Kubernát0d4db442018-07-18 17:18:43 +0200192 list _list {
193 key number;
194
195 leaf number {
196 type int32;
197 }
198
199 container contInList {
200 presence true;
201 }
202 }
203
204 list twoKeyList {
205 key "name number";
206
207 leaf number {
208 type int32;
209 }
210
211 leaf name {
212 type string;
213 }
214 }
Václav Kubernát7d82da72019-04-11 15:16:38 +0200215
216 grouping arithmeticFlags {
217 leaf carry {
218 type boolean;
219 }
220 leaf zero {
221 type boolean;
222 }
223 }
224
225 grouping flags {
226 leaf direction {
227 type boolean;
228 }
229 leaf interrupt {
230 type boolean;
231 }
232
233 uses arithmeticFlags;
234 }
235
236 uses flags;
Václav Kubernát280df4a2019-11-01 14:46:34 +0100237
238 choice interface {
239 case caseLoopback {
240 container loopback {
241 leaf ip {
242 type string;
243 }
244 }
245 }
246
247 case caseEthernet {
248 container ethernet {
249 leaf ip {
250 type string;
251 }
252 }
253 }
254 }
255
Václav Kubernáta38d4172019-11-04 12:36:39 +0100256 feature bigPizzas;
257
258 leaf pizzaSize {
259 type enumeration {
260 enum large {
261 if-feature "bigPizzas";
262 }
263 enum medium;
264 enum small;
265 }
266 }
267
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100268 leaf length {
269 type int32;
270 units "m";
271 }
272
273 leaf wavelength {
274 type decimal64 {
275 fraction-digits 10;
276 }
277 units "nm";
278 }
279
280 typedef seconds {
281 type int32;
282 units "s";
283 }
284
285 leaf duration {
286 type seconds;
287 }
288
289 leaf another-duration {
290 type seconds;
291 units "vt";
292 }
293
Václav Kubernátbd5e3c22020-02-19 15:22:00 +0100294 leaf activeNumber {
295 type leafref {
296 path "/_list/number";
297 }
298 }
299
Václav Kubernátfa81c8c2020-02-13 17:22:46 +0100300 rpc myRpc {}
301
Václav Kubernát2984f442020-02-20 17:43:35 +0100302 leaf numberOrString {
303 type union {
304 type int32;
305 type string;
306 }
307 description "Can be an int32 or a string.";
308 }
309
310 list portSettings {
311 key "port";
312 leaf port {
313 type enumeration {
314 enum eth0;
315 enum eth1;
316 enum eth2;
317 }
318 }
319 }
320
321 feature weirdPortNames;
322
323 list portMapping {
324 key "port";
325 leaf port {
326 type enumeration {
327 enum WEIRD {
328 if-feature "weirdPortNames";
329 }
330 enum utf2;
331 enum utf3;
332 }
333 }
334 }
335
336 leaf activeMappedPort {
337 type leafref {
338 path "../portMapping/port";
339 }
340 }
341
342 leaf activePort {
343 type union {
344 type enumeration {
345 enum wlan0;
346 enum wlan1;
347 }
348 type leafref {
349 path "../portSettings/port";
350 }
351 type leafref {
352 path "../activeMappedPort";
353 }
354 }
355 }
356
Václav Kubernát0599e9f2020-04-21 09:51:33 +0200357 leaf clockSpeed {
358 type int64;
359 config false;
360 }
361
362 container systemStats {
363 config false;
364 leaf upTime {
365 type uint64;
366 }
367 }
368
Václav Kubernát0d4db442018-07-18 17:18:43 +0200369})";
370
Václav Kubernát47a3f672019-11-08 15:42:43 +0100371namespace std {
372std::ostream& operator<<(std::ostream& s, const std::set<std::string> set)
373{
374 s << std::endl << "{";
375 std::copy(set.begin(), set.end(), std::experimental::make_ostream_joiner(s, ", "));
376 s << "}" << std::endl;
377 return s;
378}
379}
380
Václav Kubernát0d4db442018-07-18 17:18:43 +0200381TEST_CASE("yangschema")
382{
Václav Kubernát4f77a252019-02-19 16:51:30 +0100383 using namespace std::string_view_literals;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200384 YangSchema ys;
Václav Kubernátb52dc252019-12-04 13:03:39 +0100385 ys.registerModuleCallback([]([[maybe_unused]] auto modName, auto, auto, auto) {
Václav Kubernát4f77a252019-02-19 16:51:30 +0100386 assert("example-schema"sv == modName);
387 return example_schema;
388 });
389 ys.addSchemaString(second_schema);
390
Václav Kubernátefcac932020-01-10 15:26:32 +0100391 schemaPath_ path{Scope::Absolute, {}};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200392 ModuleNodePair node;
393
394 SECTION("positive")
395 {
396 SECTION("isContainer")
397 {
398 SECTION("example-schema:a")
399 {
400 node.first = "example-schema";
401 node.second = "a";
402 }
403
404 SECTION("example-schema:a/a2")
405 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200406 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200407 node.second = "a2";
408 }
409
Václav Kubernát280df4a2019-11-01 14:46:34 +0100410 SECTION("example-schema:ethernet")
411 {
412 node.first = "example-schema";
413 node.second = "ethernet";
414 }
415
416 SECTION("example-schema:loopback")
417 {
418 node.first = "example-schema";
419 node.second = "loopback";
420 }
421
Václav Kubernát0d4db442018-07-18 17:18:43 +0200422 REQUIRE(ys.isContainer(path, node));
423 }
424 SECTION("isLeaf")
425 {
426 SECTION("example-schema:leafString")
427 {
428 node.first = "example-schema";
429 node.second = "leafString";
430 }
431
432 SECTION("example-schema:a/leafa")
433 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200434 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200435 node.first = "example-schema";
436 node.second = "leafa";
437 }
438
Václav Kubernát7d82da72019-04-11 15:16:38 +0200439 SECTION("example-schema:carry")
440 {
441 node.first = "example-schema";
442 node.second = "carry";
443 }
444
445 SECTION("example-schema:zero")
446 {
447 node.first = "example-schema";
448 node.second = "zero";
449 }
450
451 SECTION("example-schema:direction")
452 {
453 node.first = "example-schema";
454 node.second = "direction";
455 }
456
457 SECTION("example-schema:interrupt")
458 {
459 node.first = "example-schema";
460 node.second = "interrupt";
461 }
462
Václav Kubernát0d4db442018-07-18 17:18:43 +0200463 REQUIRE(ys.isLeaf(path, node));
464 }
465 SECTION("isModule")
466 {
Václav Kubernát75877de2019-11-20 17:43:02 +0100467 REQUIRE(ys.isModule("example-schema"));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200468 }
469 SECTION("isList")
470 {
471 SECTION("example-schema:_list")
472 {
473 node.first = "example-schema";
474 node.second = "_list";
475 }
476
477 SECTION("example-schema:twoKeyList")
478 {
479 node.first = "example-schema";
480 node.second = "twoKeyList";
481 }
482
483 REQUIRE(ys.isList(path, node));
484 }
485 SECTION("isPresenceContainer")
486 {
487 SECTION("example-schema:a/a2/a3")
488 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200489 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
490 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a2")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200491 node.second = "a3";
492 }
493
494 REQUIRE(ys.isPresenceContainer(path, node));
495 }
Václav Kubernáteeb38842019-03-20 19:46:05 +0100496
Václav Kubernát0d4db442018-07-18 17:18:43 +0200497 SECTION("listHasKey")
498 {
499 std::string key;
500
501 SECTION("_list")
502 {
503 node.first = "example-schema";
504 node.second = "_list";
505 SECTION("number")
506 key = "number";
507 }
508
509 SECTION("twoKeyList")
510 {
511 node.first = "example-schema";
512 node.second = "twoKeyList";
513 SECTION("number")
514 key = "number";
515 SECTION("name")
516 key = "name";
517 }
518
519 REQUIRE(ys.listHasKey(path, node, key));
520 }
521 SECTION("listKeys")
522 {
523 std::set<std::string> set;
524
525 SECTION("_list")
526 {
527 set = {"number"};
528 node.first = "example-schema";
529 node.second = "_list";
530 }
531
532 SECTION("twoKeyList")
533 {
534 set = {"number", "name"};
535 node.first = "example-schema";
536 node.second = "twoKeyList";
537 }
538
539 REQUIRE(ys.listKeys(path, node) == set);
540 }
541 SECTION("leafType")
542 {
Václav Kubernát3a99f002020-03-31 02:27:41 +0200543 yang::LeafDataType type;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200544
545 SECTION("leafString")
546 {
547 node.first = "example-schema";
548 node.second = "leafString";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200549 type = yang::String{};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200550 }
551
552 SECTION("leafDecimal")
553 {
554 node.first = "example-schema";
555 node.second = "leafDecimal";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200556 type = yang::Decimal{};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200557 }
558
559 SECTION("leafBool")
560 {
561 node.first = "example-schema";
562 node.second = "leafBool";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200563 type = yang::Bool{};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200564 }
565
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200566 SECTION("leafInt8")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200567 {
568 node.first = "example-schema";
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200569 node.second = "leafInt8";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200570 type = yang::Int8{};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200571 }
572
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200573 SECTION("leafUint8")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200574 {
575 node.first = "example-schema";
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200576 node.second = "leafUint8";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200577 type = yang::Uint8{};
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200578 }
579
Václav Kubernátb6d02752020-04-03 00:25:10 +0200580 SECTION("leafInt16")
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200581 {
582 node.first = "example-schema";
583 node.second = "leafInt16";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200584 type = yang::Int16{};
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200585 }
586
587 SECTION("leafUint16")
588 {
589 node.first = "example-schema";
590 node.second = "leafUint16";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200591 type = yang::Uint16{};
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200592 }
593
594 SECTION("leafInt32")
595 {
596 node.first = "example-schema";
597 node.second = "leafInt32";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200598 type = yang::Int32{};
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200599 }
600
601 SECTION("leafUint32")
602 {
603 node.first = "example-schema";
604 node.second = "leafUint32";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200605 type = yang::Uint32{};
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200606 }
607
608 SECTION("leafInt64")
609 {
610 node.first = "example-schema";
611 node.second = "leafInt64";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200612 type = yang::Int64{};
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200613 }
614
615 SECTION("leafUint64")
616 {
617 node.first = "example-schema";
618 node.second = "leafUint64";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200619 type = yang::Uint64{};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200620 }
621
622 SECTION("leafEnum")
623 {
624 node.first = "example-schema";
625 node.second = "leafEnum";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200626 type = createEnum({"lol", "data", "coze"});
627 }
628
629 SECTION("leafEnumTypedef")
630 {
631 node.first = "example-schema";
632 node.second = "leafEnumTypedef";
633 type = createEnum({"lol", "data", "coze"});
634 }
635
636 SECTION("leafEnumTypedefRestricted")
637 {
638 node.first = "example-schema";
639 node.second = "leafEnumTypedefRestricted";
640 type = createEnum({"data", "coze"});
641 }
642
643 SECTION("leafEnumTypedefRestricted2")
644 {
645 node.first = "example-schema";
646 node.second = "leafEnumTypedefRestricted2";
647 type = createEnum({"lol", "data"});
648 }
649
650 SECTION("pizzaSize")
651 {
652 node.first = "example-schema";
653 node.second = "pizzaSize";
654
655 SECTION("bigPizzas disabled")
656 {
657 type = createEnum({"small", "medium"});
658 }
659 SECTION("bigPizzas enabled")
660 {
661 ys.enableFeature("example-schema", "bigPizzas");
662 type = createEnum({"small", "medium", "large"});
663 }
664 }
665
666 SECTION("foodIdentLeaf")
667 {
668 node.first = "example-schema";
669 node.second = "foodIdentLeaf";
670 type = yang::IdentityRef{{{"second-schema", "pineapple"},
671 {"example-schema", "food"},
672 {"example-schema", "pizza"},
673 {"example-schema", "hawaii"},
674 {"example-schema", "fruit"}}};
675 }
676
677 SECTION("pizzaIdentLeaf")
678 {
679 node.first = "example-schema";
680 node.second = "pizzaIdentLeaf";
681
682 type = yang::IdentityRef{{
683 {"example-schema", "pizza"},
684 {"example-schema", "hawaii"},
685 }};
686 }
687
688 SECTION("foodDrinkIdentLeaf")
689 {
690 node.first = "example-schema";
691 node.second = "foodDrinkIdentLeaf";
692
693 type = yang::IdentityRef{{
694 {"example-schema", "food"},
695 {"example-schema", "drink"},
696 {"example-schema", "fruit"},
697 {"example-schema", "hawaii"},
698 {"example-schema", "pizza"},
699 {"example-schema", "voda"},
700 {"second-schema", "pineapple"},
701 }};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200702 }
703
Václav Kubernátb6d02752020-04-03 00:25:10 +0200704 SECTION("activeNumber")
705 {
706 node.first = "example-schema";
707 node.second = "activeNumber";
Václav Kubernát3a99f002020-03-31 02:27:41 +0200708 type.emplace<yang::LeafRef>(
709 "/example-schema:_list/number",
Václav Kubernát13b23d72020-04-16 21:49:51 +0200710 std::make_unique<yang::TypeInfo>(ys.leafType("/example-schema:_list/number"))
Václav Kubernát3a99f002020-03-31 02:27:41 +0200711 );
Václav Kubernátb6d02752020-04-03 00:25:10 +0200712 }
713
Václav Kubernát2984f442020-02-20 17:43:35 +0100714 SECTION("activePort")
715 {
716 node.first = "example-schema";
717 node.second = "activePort";
718
719 yang::Enum enums = [&ys]() {
720 SECTION("weird ports disabled")
721 {
722 return createEnum({"utf2", "utf3"});
723 }
724 SECTION("weird ports enabled")
725 {
726 ys.enableFeature("example-schema", "weirdPortNames");
727 return createEnum({"WEIRD", "utf2", "utf3"});
728 }
729 __builtin_unreachable();
730 }();
731
732 type = yang::Union{{
Václav Kubernát13b23d72020-04-16 21:49:51 +0200733 yang::TypeInfo{createEnum({"wlan0", "wlan1"})},
734 yang::TypeInfo{yang::LeafRef{
Václav Kubernát2984f442020-02-20 17:43:35 +0100735 "/example-schema:portSettings/port",
Václav Kubernát13b23d72020-04-16 21:49:51 +0200736 std::make_unique<yang::TypeInfo>(createEnum({"eth0", "eth1", "eth2"}))
737 }},
738 yang::TypeInfo{yang::LeafRef{
Václav Kubernát2984f442020-02-20 17:43:35 +0100739 "/example-schema:activeMappedPort",
Václav Kubernát13b23d72020-04-16 21:49:51 +0200740 std::make_unique<yang::TypeInfo>(yang::LeafRef{
Václav Kubernát2984f442020-02-20 17:43:35 +0100741 "/example-schema:portMapping/port",
Václav Kubernát13b23d72020-04-16 21:49:51 +0200742 std::make_unique<yang::TypeInfo>(enums)
743 })
744 }},
Václav Kubernát2984f442020-02-20 17:43:35 +0100745 }};
746 }
747
Václav Kubernát0d4db442018-07-18 17:18:43 +0200748 REQUIRE(ys.leafType(path, node) == type);
749 }
750 SECTION("childNodes")
751 {
752 std::set<std::string> set;
753
754 SECTION("<root>")
755 {
756 set = {"example-schema:a", "example-schema:b", "example-schema:leafString",
Ivona Oboňová88c78ca2019-07-02 18:40:07 +0200757 "example-schema:leafDecimal", "example-schema:leafBool",
758 "example-schema:leafInt8", "example-schema:leafUint8",
759 "example-schema:leafInt16", "example-schema:leafUint16",
760 "example-schema:leafInt32", "example-schema:leafUint32",
761 "example-schema:leafInt64", "example-schema:leafUint64",
762 "example-schema:leafEnum", "example-schema:leafEnumTypedef",
Václav Kubernát6a713d62018-10-03 18:47:34 +0200763 "example-schema:leafEnumTypedefRestricted", "example-schema:leafEnumTypedefRestricted2",
Václav Kubernáteeb38842019-03-20 19:46:05 +0100764 "example-schema:foodIdentLeaf", "example-schema:pizzaIdentLeaf", "example-schema:foodDrinkIdentLeaf",
Václav Kubernát7d82da72019-04-11 15:16:38 +0200765 "example-schema:_list", "example-schema:twoKeyList", "second-schema:bla",
766 "example-schema:carry", "example-schema:zero", "example-schema:direction",
Václav Kubernát280df4a2019-11-01 14:46:34 +0100767 "example-schema:interrupt",
Václav Kubernáta38d4172019-11-04 12:36:39 +0100768 "example-schema:ethernet", "example-schema:loopback",
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100769 "example-schema:pizzaSize",
770 "example-schema:length", "example-schema:wavelength",
Václav Kubernátbd5e3c22020-02-19 15:22:00 +0100771 "example-schema:duration", "example-schema:another-duration",
Václav Kubernát2984f442020-02-20 17:43:35 +0100772 "example-schema:activeNumber",
773 "example-schema:numberOrString",
774 "example-schema:portSettings",
775 "example-schema:portMapping",
776 "example-schema:activeMappedPort",
Václav Kubernát0599e9f2020-04-21 09:51:33 +0200777 "example-schema:activePort",
778 "example-schema:clockSpeed",
779 "example-schema:systemStats"};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200780 }
781
Václav Kubernát4f77a252019-02-19 16:51:30 +0100782 SECTION("example-schema:a")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200783 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200784 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát4f77a252019-02-19 16:51:30 +0100785 set = {"a2", "leafa", "second-schema:augmentedContainer"};
786 }
787
788 SECTION("second-schema:bla")
789 {
790 path.m_nodes.push_back(schemaNode_(module_{"second-schema"}, container_("bla")));
791 set = {"bla2"};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200792 }
793
Václav Kubernát47a3f672019-11-08 15:42:43 +0100794 SECTION("example-schema:ethernet")
795 {
796 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("ethernet")));
797 set = {"ip"};
798 }
799
Václav Kubernáte7d4aea2018-09-11 18:15:48 +0200800 REQUIRE(ys.childNodes(path, Recursion::NonRecursive) == set);
Václav Kubernát0d4db442018-07-18 17:18:43 +0200801 }
Václav Kubernát34ee85a2020-02-18 17:12:12 +0100802 SECTION("nodeType")
803 {
804 yang::NodeTypes expected;
805 SECTION("leafInt32")
806 {
807 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
808 expected = yang::NodeTypes::Leaf;
809 }
810
811 SECTION("a")
812 {
813 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
814 expected = yang::NodeTypes::Container;
815 }
816
817 SECTION("a/a2/a3")
818 {
819 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
820 path.m_nodes.push_back(schemaNode_(container_("a2")));
821 path.m_nodes.push_back(schemaNode_(container_("a3")));
822 expected = yang::NodeTypes::PresenceContainer;
823 }
824
825 SECTION("_list")
826 {
827 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, list_("_list")));
828 expected = yang::NodeTypes::List;
829 }
830
831 REQUIRE(ys.nodeType(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
832 }
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100833
834 SECTION("description")
835 {
836 std::optional<std::string> expected;
837 SECTION("leafInt32")
838 {
839 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
840 expected = "A 32-bit integer leaf.";
841 }
842
843 SECTION("leafString")
844 {
845 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafString")));
846 }
847
Václav Kubernát2984f442020-02-20 17:43:35 +0100848 SECTION("numberOrString")
849 {
850 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("numberOrString")));
851 expected = "Can be an int32 or a string.";
852 }
853
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100854 REQUIRE(ys.description(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
855 }
856
857 SECTION("units")
858 {
Václav Kubernát13b23d72020-04-16 21:49:51 +0200859 yang::LeafDataType expectedType;
860 std::optional<std::string> expectedUnits;
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100861 SECTION("length")
862 {
863 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("length")));
Václav Kubernát13b23d72020-04-16 21:49:51 +0200864 expectedType.emplace<yang::Int32>();
865 expectedUnits = "m";
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100866 }
867
868 SECTION("wavelength")
869 {
870 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("wavelength")));
Václav Kubernát13b23d72020-04-16 21:49:51 +0200871 expectedType.emplace<yang::Decimal>();
872 expectedUnits = "nm";
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100873 }
874
875 SECTION("leafInt32")
876 {
877 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
Václav Kubernát13b23d72020-04-16 21:49:51 +0200878 expectedType.emplace<yang::Int32>();
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100879 }
880
881 SECTION("duration")
882 {
883 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("duration")));
Václav Kubernát13b23d72020-04-16 21:49:51 +0200884 expectedType.emplace<yang::Int32>();
885 expectedUnits = "s";
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100886 }
887
888 SECTION("another-duration")
889 {
890 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("another-duration")));
Václav Kubernát13b23d72020-04-16 21:49:51 +0200891 expectedType.emplace<yang::Int32>();
892 expectedUnits = "vt";
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100893 }
Václav Kubernát13b23d72020-04-16 21:49:51 +0200894 REQUIRE(ys.leafType(pathToSchemaString(path, Prefixes::WhenNeeded)) == yang::TypeInfo{expectedType, expectedUnits});
Václav Kubernát1e09bd62020-02-17 15:13:38 +0100895 }
896
897 SECTION("nodeType")
898 {
899 yang::NodeTypes expected;
900 SECTION("leafInt32")
901 {
902 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, leaf_("leafInt32")));
903 expected = yang::NodeTypes::Leaf;
904 }
905
906 SECTION("a")
907 {
908 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
909 expected = yang::NodeTypes::Container;
910 }
911
912 SECTION("a/a2/a3")
913 {
914 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
915 path.m_nodes.push_back(schemaNode_(container_("a2")));
916 path.m_nodes.push_back(schemaNode_(container_("a3")));
917 expected = yang::NodeTypes::PresenceContainer;
918 }
919
920 SECTION("_list")
921 {
922 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, list_("_list")));
923 expected = yang::NodeTypes::List;
924 }
925
926 REQUIRE(ys.nodeType(pathToSchemaString(path, Prefixes::WhenNeeded)) == expected);
927 }
Václav Kubernátbd5e3c22020-02-19 15:22:00 +0100928
929 SECTION("leafrefPath")
930 {
931 REQUIRE(ys.leafrefPath("/example-schema:activeNumber") == "/example-schema:_list/number");
932 }
Václav Kubernát0599e9f2020-04-21 09:51:33 +0200933
934 SECTION("isConfig")
935 {
936 REQUIRE(ys.isConfig("/example-schema:leafInt32"));
937 REQUIRE_FALSE(ys.isConfig("/example-schema:clockSpeed"));
938 REQUIRE_FALSE(ys.isConfig("/example-schema:systemStats"));
939 REQUIRE_FALSE(ys.isConfig("/example-schema:systemStats/upTime"));
940 }
Václav Kubernátbd0d5c82020-04-21 10:22:03 +0200941
942 SECTION("moduleNodes")
943 {
944 std::string module;
945 std::set<std::string> expectedNonRecursive;
946 std::set<std::string> expectedRecursive;
947 SECTION("example-schema")
948 {
949 module = "example-schema";
950 expectedNonRecursive = {
951 "example-schema:_list",
952 "example-schema:a",
953 "example-schema:activeMappedPort",
954 "example-schema:activeNumber",
955 "example-schema:activePort",
956 "example-schema:another-duration",
957 "example-schema:b",
958 "example-schema:carry",
959 "example-schema:clockSpeed",
960 "example-schema:direction",
961 "example-schema:duration",
962 "example-schema:ethernet",
963 "example-schema:foodDrinkIdentLeaf",
964 "example-schema:foodIdentLeaf",
965 "example-schema:interrupt",
966 "example-schema:leafBool",
967 "example-schema:leafDecimal",
968 "example-schema:leafEnum",
969 "example-schema:leafEnumTypedef",
970 "example-schema:leafEnumTypedefRestricted",
971 "example-schema:leafEnumTypedefRestricted2",
972 "example-schema:leafInt16",
973 "example-schema:leafInt32",
974 "example-schema:leafInt64",
975 "example-schema:leafInt8",
976 "example-schema:leafString",
977 "example-schema:leafUint16",
978 "example-schema:leafUint32",
979 "example-schema:leafUint64",
980 "example-schema:leafUint8",
981 "example-schema:length",
982 "example-schema:loopback",
983 "example-schema:myRpc",
984 "example-schema:numberOrString",
985 "example-schema:pizzaIdentLeaf",
986 "example-schema:pizzaSize",
987 "example-schema:portMapping",
988 "example-schema:portSettings",
989 "example-schema:systemStats",
990 "example-schema:twoKeyList",
991 "example-schema:wavelength",
992 "example-schema:zero"
993 };
994 expectedRecursive = {
995 "/example-schema:_list",
996 "/example-schema:_list/contInList",
997 "/example-schema:_list/number",
998 "/example-schema:a",
999 "/example-schema:a/a2",
1000 "/example-schema:a/a2/a3",
1001 "/example-schema:a/leafa",
1002 "/example-schema:a/second-schema:augmentedContainer",
1003 "/example-schema:activeMappedPort",
1004 "/example-schema:activeNumber",
1005 "/example-schema:activePort",
1006 "/example-schema:another-duration",
1007 "/example-schema:b",
1008 "/example-schema:b/b2",
1009 "/example-schema:b/b2/b3",
1010 "/example-schema:carry",
1011 "/example-schema:clockSpeed",
1012 "/example-schema:direction",
1013 "/example-schema:duration",
1014 "/example-schema:foodDrinkIdentLeaf",
1015 "/example-schema:foodIdentLeaf",
1016 "/example-schema:interface/caseEthernet/ethernet",
1017 "/example-schema:interface/caseEthernet/ethernet/ip",
1018 "/example-schema:interface/caseLoopback/loopback",
1019 "/example-schema:interface/caseLoopback/loopback/ip",
1020 "/example-schema:interrupt",
1021 "/example-schema:leafBool",
1022 "/example-schema:leafDecimal",
1023 "/example-schema:leafEnum",
1024 "/example-schema:leafEnumTypedef",
1025 "/example-schema:leafEnumTypedefRestricted",
1026 "/example-schema:leafEnumTypedefRestricted2",
1027 "/example-schema:leafInt16",
1028 "/example-schema:leafInt32",
1029 "/example-schema:leafInt64",
1030 "/example-schema:leafInt8",
1031 "/example-schema:leafString",
1032 "/example-schema:leafUint16",
1033 "/example-schema:leafUint32",
1034 "/example-schema:leafUint64",
1035 "/example-schema:leafUint8",
1036 "/example-schema:length",
1037 "/example-schema:myRpc",
1038 "/example-schema:myRpc/input",
1039 "/example-schema:myRpc/output",
1040 "/example-schema:numberOrString",
1041 "/example-schema:pizzaIdentLeaf",
1042 "/example-schema:pizzaSize",
1043 "/example-schema:portMapping",
1044 "/example-schema:portMapping/port",
1045 "/example-schema:portSettings",
1046 "/example-schema:portSettings/port",
1047 "/example-schema:systemStats",
1048 "/example-schema:systemStats/upTime",
1049 "/example-schema:twoKeyList",
1050 "/example-schema:twoKeyList/name",
1051 "/example-schema:twoKeyList/number",
1052 "/example-schema:wavelength",
1053 "/example-schema:zero"
1054 };
1055 }
1056
1057 SECTION("second-schema")
1058 {
1059 module = "second-schema";
1060 expectedNonRecursive = {
1061 "second-schema:bla"
1062 };
1063 expectedRecursive = {
1064 "/second-schema:bla", "/second-schema:bla/bla2"
1065 };
1066 }
1067
1068 REQUIRE(ys.moduleNodes(module_{module}, Recursion::NonRecursive) == expectedNonRecursive);
1069 REQUIRE(ys.moduleNodes(module_{module}, Recursion::Recursive) == expectedRecursive);
1070 }
Václav Kubernát0d4db442018-07-18 17:18:43 +02001071 }
1072
1073 SECTION("negative")
1074 {
1075 SECTION("nonexistent nodes")
1076 {
1077 SECTION("example-schema:coze")
1078 {
1079 node.first = "example-schema";
1080 node.second = "coze";
1081 }
1082
1083 SECTION("example-schema:a/nevim")
1084 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +02001085 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +02001086 node.second = "nevim";
1087 }
1088
1089 SECTION("modul:a/nevim")
1090 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +02001091 path.m_nodes.push_back(schemaNode_(module_{"modul"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +02001092 node.second = "nevim";
1093 }
1094
1095 REQUIRE(!ys.isPresenceContainer(path, node));
1096 REQUIRE(!ys.isList(path, node));
1097 REQUIRE(!ys.isLeaf(path, node));
1098 REQUIRE(!ys.isContainer(path, node));
1099 }
1100
1101 SECTION("\"is\" methods return false for existing nodes for different nodetypes")
1102 {
1103 SECTION("example-schema:a")
1104 {
1105 node.first = "example-schema";
1106 node.second = "a";
1107 }
1108
1109 SECTION("example-schema:a/a2")
1110 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +02001111 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +02001112 node.second = "a2";
1113 }
1114
1115 REQUIRE(!ys.isPresenceContainer(path, node));
1116 REQUIRE(!ys.isList(path, node));
1117 REQUIRE(!ys.isLeaf(path, node));
1118 }
1119
1120 SECTION("nodetype-specific methods called with different nodetypes")
1121 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +02001122 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +02001123 node.second = "a2";
1124
Václav Kubernát0d4db442018-07-18 17:18:43 +02001125 REQUIRE(!ys.listHasKey(path, node, "chacha"));
1126 }
1127
1128 SECTION("nonexistent module")
1129 {
Václav Kubernát75877de2019-11-20 17:43:02 +01001130 REQUIRE(!ys.isModule("notAModule"));
Václav Kubernát0d4db442018-07-18 17:18:43 +02001131 }
Václav Kubernáteeb38842019-03-20 19:46:05 +01001132
Václav Kubernát7d82da72019-04-11 15:16:38 +02001133 SECTION("grouping is not a node")
1134 {
1135 SECTION("example-schema:arithmeticFlags")
1136 {
1137 node.first = "example-schema";
1138 node.second = "arithmeticFlags";
1139 }
1140
1141 SECTION("example-schema:flags")
1142 {
1143 node.first = "example-schema";
1144 node.second = "startAndStop";
1145 }
1146
1147 REQUIRE(!ys.isPresenceContainer(path, node));
1148 REQUIRE(!ys.isList(path, node));
1149 REQUIRE(!ys.isLeaf(path, node));
1150 REQUIRE(!ys.isContainer(path, node));
1151 }
Václav Kubernát280df4a2019-11-01 14:46:34 +01001152
1153 SECTION("choice is not a node")
1154 {
1155 SECTION("example-schema:interface")
1156 {
1157 node.first = "example-schema";
1158 node.second = "interface";
1159 }
1160
1161 REQUIRE(!ys.isPresenceContainer(path, node));
1162 REQUIRE(!ys.isList(path, node));
1163 REQUIRE(!ys.isLeaf(path, node));
1164 REQUIRE(!ys.isContainer(path, node));
1165 }
1166
1167 SECTION("case is not a node")
1168 {
1169 SECTION("example-schema:caseLoopback")
1170 {
1171 node.first = "example-schema";
1172 node.second = "caseLoopback";
1173 }
1174
1175 SECTION("example-schema:caseEthernet")
1176 {
1177 node.first = "example-schema";
1178 node.second = "caseEthernet";
1179 }
1180
1181 REQUIRE(!ys.isPresenceContainer(path, node));
1182 REQUIRE(!ys.isList(path, node));
1183 REQUIRE(!ys.isLeaf(path, node));
1184 REQUIRE(!ys.isContainer(path, node));
1185 }
Václav Kubernát0d4db442018-07-18 17:18:43 +02001186 }
1187}