blob: 679325012df9b68517b6a85b4f7315c1b9d2e178 [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
Jan Kundráta33cf082019-03-28 11:55:57 +01009#include "trompeloeil_doctest.h"
Václav Kubernát0d4db442018-07-18 17:18:43 +020010#include "yang_schema.hpp"
11
Václav Kubernát4f77a252019-02-19 16:51:30 +010012const char* second_schema = R"(
13module second-schema {
14 namespace "http://example.com/nevim";
15 prefix second;
16
17 import example-schema {
18 prefix "example";
19 }
20
Václav Kubernáteeb38842019-03-20 19:46:05 +010021 identity pineapple {
22 base "example:fruit";
23 }
24
Václav Kubernát4f77a252019-02-19 16:51:30 +010025 augment /example:a {
26 container augmentedContainer {
27 }
28 }
29
30 container bla {
31 container bla2 {
32 }
33 }
34}
35)";
36
37const char* example_schema = R"(
Václav Kubernát0d4db442018-07-18 17:18:43 +020038module example-schema {
Václav Kubernát6a713d62018-10-03 18:47:34 +020039 yang-version 1.1;
Václav Kubernát0d4db442018-07-18 17:18:43 +020040 namespace "http://example.com/example-sports";
41 prefix coze;
42
Václav Kubernáteeb38842019-03-20 19:46:05 +010043 identity drink {
44 }
45
46 identity voda {
47 base "drink";
48 }
49
50 identity food {
51 }
52
53 identity fruit {
54 base "food";
55 }
56
57 identity pizza {
58 base "food";
59 }
60
61 identity hawaii {
62 base "pizza";
63 }
64
Václav Kubernát0d4db442018-07-18 17:18:43 +020065 container a {
66 container a2 {
67 container a3 {
68 presence true;
69 }
70 }
71
72 leaf leafa {
73 type string;
74 }
75 }
76
77 container b {
78 container b2 {
79 presence true;
80 container b3 {
81 }
82 }
83 }
84
85 leaf leafString {
86 type string;
87 }
88
89 leaf leafDecimal {
90 type decimal64 {
91 fraction-digits 5;
92 }
93 }
94
95 leaf leafBool {
96 type boolean;
97 }
98
99 leaf leafInt {
100 type int32;
101 }
102
103 leaf leafUint {
104 type uint32;
105 }
106
107 leaf leafEnum {
108 type enumeration {
109 enum lol;
110 enum data;
111 enum coze;
112 }
113 }
114
Václav Kubernát6a713d62018-10-03 18:47:34 +0200115 typedef enumTypedef {
116 type enumeration {
117 enum lol;
118 enum data;
119 enum coze;
120 }
121 }
122
123 typedef enumTypedefRestricted {
124 type enumTypedef {
125 enum lol;
126 enum data;
127 }
128 }
129
130 leaf leafEnumTypedef {
131 type enumTypedef;
132 }
133
134 leaf leafEnumTypedefRestricted {
135 type enumTypedef {
136 enum data;
137 enum coze;
138 }
139 }
140
141 leaf leafEnumTypedefRestricted2 {
142 type enumTypedefRestricted;
143 }
144
Václav Kubernáteeb38842019-03-20 19:46:05 +0100145 leaf foodIdentLeaf {
146 type identityref {
147 base "food";
148 }
149 }
150
151 leaf pizzaIdentLeaf {
152 type identityref {
153 base "pizza";
154 }
155 }
156
157 leaf foodDrinkIdentLeaf {
158 type identityref {
159 base "food";
160 base "drink";
161 }
162 }
163
Václav Kubernát0d4db442018-07-18 17:18:43 +0200164 list _list {
165 key number;
166
167 leaf number {
168 type int32;
169 }
170
171 container contInList {
172 presence true;
173 }
174 }
175
176 list twoKeyList {
177 key "name number";
178
179 leaf number {
180 type int32;
181 }
182
183 leaf name {
184 type string;
185 }
186 }
Václav Kubernát7d82da72019-04-11 15:16:38 +0200187
188 grouping arithmeticFlags {
189 leaf carry {
190 type boolean;
191 }
192 leaf zero {
193 type boolean;
194 }
195 }
196
197 grouping flags {
198 leaf direction {
199 type boolean;
200 }
201 leaf interrupt {
202 type boolean;
203 }
204
205 uses arithmeticFlags;
206 }
207
208 uses flags;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200209})";
210
211TEST_CASE("yangschema")
212{
Václav Kubernát4f77a252019-02-19 16:51:30 +0100213 using namespace std::string_view_literals;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200214 YangSchema ys;
Václav Kubernát4f77a252019-02-19 16:51:30 +0100215 ys.registerModuleCallback([]([[maybe_unused]] auto modName, auto, auto) {
216 assert("example-schema"sv == modName);
217 return example_schema;
218 });
219 ys.addSchemaString(second_schema);
220
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200221 schemaPath_ path;
Václav Kubernát0d4db442018-07-18 17:18:43 +0200222 ModuleNodePair node;
223
224 SECTION("positive")
225 {
226 SECTION("isContainer")
227 {
228 SECTION("example-schema:a")
229 {
230 node.first = "example-schema";
231 node.second = "a";
232 }
233
234 SECTION("example-schema:a/a2")
235 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200236 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200237 node.second = "a2";
238 }
239
240 REQUIRE(ys.isContainer(path, node));
241 }
242 SECTION("isLeaf")
243 {
244 SECTION("example-schema:leafString")
245 {
246 node.first = "example-schema";
247 node.second = "leafString";
248 }
249
250 SECTION("example-schema:a/leafa")
251 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200252 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200253 node.first = "example-schema";
254 node.second = "leafa";
255 }
256
Václav Kubernát7d82da72019-04-11 15:16:38 +0200257 SECTION("example-schema:carry")
258 {
259 node.first = "example-schema";
260 node.second = "carry";
261 }
262
263 SECTION("example-schema:zero")
264 {
265 node.first = "example-schema";
266 node.second = "zero";
267 }
268
269 SECTION("example-schema:direction")
270 {
271 node.first = "example-schema";
272 node.second = "direction";
273 }
274
275 SECTION("example-schema:interrupt")
276 {
277 node.first = "example-schema";
278 node.second = "interrupt";
279 }
280
Václav Kubernát0d4db442018-07-18 17:18:43 +0200281 REQUIRE(ys.isLeaf(path, node));
282 }
283 SECTION("isModule")
284 {
285 REQUIRE(ys.isModule(path, "example-schema"));
286 }
287 SECTION("isList")
288 {
289 SECTION("example-schema:_list")
290 {
291 node.first = "example-schema";
292 node.second = "_list";
293 }
294
295 SECTION("example-schema:twoKeyList")
296 {
297 node.first = "example-schema";
298 node.second = "twoKeyList";
299 }
300
301 REQUIRE(ys.isList(path, node));
302 }
303 SECTION("isPresenceContainer")
304 {
305 SECTION("example-schema:a/a2/a3")
306 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200307 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
308 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a2")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200309 node.second = "a3";
310 }
311
312 REQUIRE(ys.isPresenceContainer(path, node));
313 }
314 SECTION("leafEnumHasValue")
315 {
Václav Kubernát0d4db442018-07-18 17:18:43 +0200316 std::string value;
Václav Kubernát6a713d62018-10-03 18:47:34 +0200317 SECTION("leafEnum")
318 {
319 node.first = "example-schema";
320 node.second = "leafEnum";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200321
Václav Kubernát6a713d62018-10-03 18:47:34 +0200322 SECTION("lol")
323 value = "lol";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200324
Václav Kubernát6a713d62018-10-03 18:47:34 +0200325 SECTION("data")
326 value = "data";
Václav Kubernát0d4db442018-07-18 17:18:43 +0200327
Václav Kubernát6a713d62018-10-03 18:47:34 +0200328 SECTION("coze")
329 value = "coze";
330 }
331
332 SECTION("leafEnumTypedef")
333 {
334 node.first = "example-schema";
335 node.second = "leafEnumTypedef";
336
337 SECTION("lol")
338 value = "lol";
339
340 SECTION("data")
341 value = "data";
342
343 SECTION("coze")
344 value = "coze";
345 }
346
347 SECTION("leafEnumTypedefRestricted")
348 {
349 node.first = "example-schema";
350 node.second = "leafEnumTypedefRestricted";
351
352 SECTION("data")
353 value = "data";
354
355 SECTION("coze")
356 value = "coze";
357 }
358
359 SECTION("leafEnumTypedefRestricted2")
360 {
361 node.first = "example-schema";
362 node.second = "leafEnumTypedefRestricted2";
363
364 SECTION("lol")
365 value = "lol";
366
367 SECTION("data")
368 value = "data";
369 }
Václav Kubernát0d4db442018-07-18 17:18:43 +0200370
371 REQUIRE(ys.leafEnumHasValue(path, node, value));
372 }
Václav Kubernáteeb38842019-03-20 19:46:05 +0100373 SECTION("leafIdentityIsValid")
374 {
375 ModuleValuePair value;
376
377 SECTION("foodIdentLeaf")
378 {
379 node.first = "example-schema";
380 node.second = "foodIdentLeaf";
381
382 SECTION("food")
383 {
384 value.second = "food";
385 }
386 SECTION("example-schema:food")
387 {
388 value.first = "example-schema";
389 value.second = "food";
390 }
391 SECTION("pizza")
392 {
393 value.second = "pizza";
394 }
395 SECTION("example-schema:pizza")
396 {
397 value.first = "example-schema";
398 value.second = "pizza";
399 }
400 SECTION("hawaii")
401 {
402 value.second = "hawaii";
403 }
404 SECTION("example-schema:hawaii")
405 {
406 value.first = "example-schema";
407 value.second = "hawaii";
408 }
409 SECTION("fruit")
410 {
411 value.second = "fruit";
412 }
413 SECTION("example-schema:fruit")
414 {
415 value.first = "example-schema";
416 value.second = "fruit";
417 }
418 SECTION("second-schema:pineapple")
419 {
420 value.first = "second-schema";
421 value.second = "pineapple";
422 }
423 }
424
425 SECTION("pizzaIdentLeaf")
426 {
427 node.first = "example-schema";
428 node.second = "pizzaIdentLeaf";
429
430 SECTION("pizza")
431 {
432 value.second = "pizza";
433 }
434 SECTION("example-schema:pizza")
435 {
436 value.first = "example-schema";
437 value.second = "pizza";
438 }
439 SECTION("hawaii")
440 {
441 value.second = "hawaii";
442 }
443 SECTION("example-schema:hawaii")
444 {
445 value.first = "example-schema";
446 value.second = "hawaii";
447 }
448 }
449
450 SECTION("foodDrinkIdentLeaf")
451 {
452 node.first = "example-schema";
453 node.second = "foodDrinkIdentLeaf";
454
455 SECTION("food")
456 {
457 value.second = "food";
458 }
459 SECTION("example-schema:food")
460 {
461 value.first = "example-schema";
462 value.second = "food";
463 }
464 SECTION("drink")
465 {
466 value.second = "drink";
467 }
468 SECTION("example-schema:drink")
469 {
470 value.first = "example-schema";
471 value.second = "drink";
472 }
473 }
474 REQUIRE(ys.leafIdentityIsValid(path, node, value));
475 }
476
Václav Kubernát0d4db442018-07-18 17:18:43 +0200477 SECTION("listHasKey")
478 {
479 std::string key;
480
481 SECTION("_list")
482 {
483 node.first = "example-schema";
484 node.second = "_list";
485 SECTION("number")
486 key = "number";
487 }
488
489 SECTION("twoKeyList")
490 {
491 node.first = "example-schema";
492 node.second = "twoKeyList";
493 SECTION("number")
494 key = "number";
495 SECTION("name")
496 key = "name";
497 }
498
499 REQUIRE(ys.listHasKey(path, node, key));
500 }
501 SECTION("listKeys")
502 {
503 std::set<std::string> set;
504
505 SECTION("_list")
506 {
507 set = {"number"};
508 node.first = "example-schema";
509 node.second = "_list";
510 }
511
512 SECTION("twoKeyList")
513 {
514 set = {"number", "name"};
515 node.first = "example-schema";
516 node.second = "twoKeyList";
517 }
518
519 REQUIRE(ys.listKeys(path, node) == set);
520 }
521 SECTION("leafType")
522 {
523 yang::LeafDataTypes type;
524
525 SECTION("leafString")
526 {
527 node.first = "example-schema";
528 node.second = "leafString";
529 type = yang::LeafDataTypes::String;
530 }
531
532 SECTION("leafDecimal")
533 {
534 node.first = "example-schema";
535 node.second = "leafDecimal";
536 type = yang::LeafDataTypes::Decimal;
537 }
538
539 SECTION("leafBool")
540 {
541 node.first = "example-schema";
542 node.second = "leafBool";
543 type = yang::LeafDataTypes::Bool;
544 }
545
546 SECTION("leafInt")
547 {
548 node.first = "example-schema";
549 node.second = "leafInt";
550 type = yang::LeafDataTypes::Int;
551 }
552
553 SECTION("leafUint")
554 {
555 node.first = "example-schema";
556 node.second = "leafUint";
557 type = yang::LeafDataTypes::Uint;
558 }
559
560 SECTION("leafEnum")
561 {
562 node.first = "example-schema";
563 node.second = "leafEnum";
564 type = yang::LeafDataTypes::Enum;
565 }
566
567 REQUIRE(ys.leafType(path, node) == type);
568 }
569 SECTION("childNodes")
570 {
571 std::set<std::string> set;
572
573 SECTION("<root>")
574 {
575 set = {"example-schema:a", "example-schema:b", "example-schema:leafString",
576 "example-schema:leafDecimal", "example-schema:leafBool", "example-schema:leafInt",
Václav Kubernát6a713d62018-10-03 18:47:34 +0200577 "example-schema:leafUint", "example-schema:leafEnum", "example-schema:leafEnumTypedef",
578 "example-schema:leafEnumTypedefRestricted", "example-schema:leafEnumTypedefRestricted2",
Václav Kubernáteeb38842019-03-20 19:46:05 +0100579 "example-schema:foodIdentLeaf", "example-schema:pizzaIdentLeaf", "example-schema:foodDrinkIdentLeaf",
Václav Kubernát7d82da72019-04-11 15:16:38 +0200580 "example-schema:_list", "example-schema:twoKeyList", "second-schema:bla",
581 "example-schema:carry", "example-schema:zero", "example-schema:direction",
582 "example-schema:interrupt"};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200583 }
584
Václav Kubernát4f77a252019-02-19 16:51:30 +0100585 SECTION("example-schema:a")
Václav Kubernát0d4db442018-07-18 17:18:43 +0200586 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200587 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát4f77a252019-02-19 16:51:30 +0100588 set = {"a2", "leafa", "second-schema:augmentedContainer"};
589 }
590
591 SECTION("second-schema:bla")
592 {
593 path.m_nodes.push_back(schemaNode_(module_{"second-schema"}, container_("bla")));
594 set = {"bla2"};
Václav Kubernát0d4db442018-07-18 17:18:43 +0200595 }
596
Václav Kubernáte7d4aea2018-09-11 18:15:48 +0200597 REQUIRE(ys.childNodes(path, Recursion::NonRecursive) == set);
Václav Kubernát0d4db442018-07-18 17:18:43 +0200598 }
599 }
600
601 SECTION("negative")
602 {
603 SECTION("nonexistent nodes")
604 {
605 SECTION("example-schema:coze")
606 {
607 node.first = "example-schema";
608 node.second = "coze";
609 }
610
611 SECTION("example-schema:a/nevim")
612 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200613 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200614 node.second = "nevim";
615 }
616
617 SECTION("modul:a/nevim")
618 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200619 path.m_nodes.push_back(schemaNode_(module_{"modul"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200620 node.second = "nevim";
621 }
622
623 REQUIRE(!ys.isPresenceContainer(path, node));
624 REQUIRE(!ys.isList(path, node));
625 REQUIRE(!ys.isLeaf(path, node));
626 REQUIRE(!ys.isContainer(path, node));
627 }
628
629 SECTION("\"is\" methods return false for existing nodes for different nodetypes")
630 {
631 SECTION("example-schema:a")
632 {
633 node.first = "example-schema";
634 node.second = "a";
635 }
636
637 SECTION("example-schema:a/a2")
638 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200639 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200640 node.second = "a2";
641 }
642
643 REQUIRE(!ys.isPresenceContainer(path, node));
644 REQUIRE(!ys.isList(path, node));
645 REQUIRE(!ys.isLeaf(path, node));
646 }
647
648 SECTION("nodetype-specific methods called with different nodetypes")
649 {
Václav Kubernát2eaceb82018-10-08 19:56:30 +0200650 path.m_nodes.push_back(schemaNode_(module_{"example-schema"}, container_("a")));
Václav Kubernát0d4db442018-07-18 17:18:43 +0200651 node.second = "a2";
652
653 REQUIRE(!ys.leafEnumHasValue(path, node, "haha"));
654 REQUIRE(!ys.listHasKey(path, node, "chacha"));
655 }
656
657 SECTION("nonexistent module")
658 {
659 REQUIRE(!ys.isModule(path, "notAModule"));
660 }
Václav Kubernáteeb38842019-03-20 19:46:05 +0100661
662 SECTION("leafIdentityIsValid")
663 {
664 ModuleValuePair value;
665 SECTION("pizzaIdentLeaf")
666 {
667 node.first = "example-schema";
668 node.second = "pizzaIdentLeaf";
669
670 SECTION("wrong base ident")
671 {
672 SECTION("food")
673 {
674 value.second = "food";
675 }
676 SECTION("fruit")
677 {
678 value.second = "fruit";
679 }
680 }
681 SECTION("non-existent identity")
682 {
683 value.second = "nonexistent";
684 }
685 SECTION("weird module")
686 {
687 value.first = "ahahaha";
688 value.second = "pizza";
689 }
690 }
691 SECTION("different module identity, but withotu prefix")
692 {
693 node.first = "example-schema";
694 node.second = "foodIdentLeaf";
695 value.second = "pineapple";
696 }
697 REQUIRE_FALSE(ys.leafIdentityIsValid(path, node, value));
698 }
Václav Kubernát7d82da72019-04-11 15:16:38 +0200699
700 SECTION("grouping is not a node")
701 {
702 SECTION("example-schema:arithmeticFlags")
703 {
704 node.first = "example-schema";
705 node.second = "arithmeticFlags";
706 }
707
708 SECTION("example-schema:flags")
709 {
710 node.first = "example-schema";
711 node.second = "startAndStop";
712 }
713
714 REQUIRE(!ys.isPresenceContainer(path, node));
715 REQUIRE(!ys.isList(path, node));
716 REQUIRE(!ys.isLeaf(path, node));
717 REQUIRE(!ys.isContainer(path, node));
718 }
Václav Kubernát0d4db442018-07-18 17:18:43 +0200719 }
720}