Implement YangSchema subclass
While we do not necessarily want to use `-isystem` for libyang, we
definitely need to use it for Boost itself. We are only using SPirit X3
directly, but that one still brings in a great deal of other supporting
libraries, including variant and a metaprogramming library.
In our CI environment, these are installed into the same prefix. Boost
itself is OK as we're including it via cmake imported target which uses
-isystem behind the scene. However, if we then add libyang via a regular
target_include_directories, the same path gets pushed into the include
paths, this time without -isystem, but rather as a regular -I. This in
turn starts affecting Boost, and we're screwed.
Fix this by ensuring that we consider libyang to be a system library,
too. We won't get annoyed by some extra warnings and therefore we won't
be able to improve that library as much as the CI would force us
otherwise :).
Change-Id: I7ec9b28501a46f8b2219f4920cbf5c1e4df59d7e
diff --git a/tests/yang.cpp b/tests/yang.cpp
new file mode 100644
index 0000000..09bef03
--- /dev/null
+++ b/tests/yang.cpp
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
+ * Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
+ *
+ * Written by Václav Kubernát <kubervac@fit.cvut.cz>
+ *
+*/
+
+#include "trompeloeil_catch.h"
+#include "yang_schema.hpp"
+
+const char* schema = R"(
+module example-schema {
+ namespace "http://example.com/example-sports";
+ prefix coze;
+
+ container a {
+ container a2 {
+ container a3 {
+ presence true;
+ }
+ }
+
+ leaf leafa {
+ type string;
+ }
+ }
+
+ container b {
+ container b2 {
+ presence true;
+ container b3 {
+ }
+ }
+ }
+
+ leaf leafString {
+ type string;
+ }
+
+ leaf leafDecimal {
+ type decimal64 {
+ fraction-digits 5;
+ }
+ }
+
+ leaf leafBool {
+ type boolean;
+ }
+
+ leaf leafInt {
+ type int32;
+ }
+
+ leaf leafUint {
+ type uint32;
+ }
+
+ leaf leafEnum {
+ type enumeration {
+ enum lol;
+ enum data;
+ enum coze;
+ }
+ }
+
+ list _list {
+ key number;
+
+ leaf number {
+ type int32;
+ }
+
+ container contInList {
+ presence true;
+ }
+ }
+
+ list twoKeyList {
+ key "name number";
+
+ leaf number {
+ type int32;
+ }
+
+ leaf name {
+ type string;
+ }
+ }
+})";
+
+TEST_CASE("yangschema")
+{
+ YangSchema ys;
+ ys.addSchemaString(schema);
+ path_ path;
+ ModuleNodePair node;
+
+ SECTION("positive")
+ {
+ SECTION("isContainer")
+ {
+ SECTION("example-schema:a")
+ {
+ node.first = "example-schema";
+ node.second = "a";
+ }
+
+ SECTION("example-schema:a/a2")
+ {
+ path.m_nodes.push_back(node_(module_{"example-schema"}, container_("a")));
+ node.second = "a2";
+ }
+
+ REQUIRE(ys.isContainer(path, node));
+ }
+ SECTION("isLeaf")
+ {
+ SECTION("example-schema:leafString")
+ {
+ node.first = "example-schema";
+ node.second = "leafString";
+ }
+
+ SECTION("example-schema:a/leafa")
+ {
+ path.m_nodes.push_back(node_(module_{"example-schema"}, container_("a")));
+ node.first = "example-schema";
+ node.second = "leafa";
+ }
+
+ REQUIRE(ys.isLeaf(path, node));
+ }
+ SECTION("isModule")
+ {
+ REQUIRE(ys.isModule(path, "example-schema"));
+ }
+ SECTION("isList")
+ {
+ SECTION("example-schema:_list")
+ {
+ node.first = "example-schema";
+ node.second = "_list";
+ }
+
+ SECTION("example-schema:twoKeyList")
+ {
+ node.first = "example-schema";
+ node.second = "twoKeyList";
+ }
+
+ REQUIRE(ys.isList(path, node));
+ }
+ SECTION("isPresenceContainer")
+ {
+ SECTION("example-schema:a/a2/a3")
+ {
+ path.m_nodes.push_back(node_(module_{"example-schema"}, container_("a")));
+ path.m_nodes.push_back(node_(module_{"example-schema"}, container_("a2")));
+ node.second = "a3";
+ }
+
+ REQUIRE(ys.isPresenceContainer(path, node));
+ }
+ SECTION("leafEnumHasValue")
+ {
+ node.first = "example-schema";
+ node.second = "leafEnum";
+ std::string value;
+
+ SECTION("lol")
+ value = "lol";
+
+ SECTION("data")
+ value = "data";
+
+ SECTION("coze")
+ value = "coze";
+
+ REQUIRE(ys.leafEnumHasValue(path, node, value));
+ }
+ SECTION("listHasKey")
+ {
+ std::string key;
+
+ SECTION("_list")
+ {
+ node.first = "example-schema";
+ node.second = "_list";
+ SECTION("number")
+ key = "number";
+ }
+
+ SECTION("twoKeyList")
+ {
+ node.first = "example-schema";
+ node.second = "twoKeyList";
+ SECTION("number")
+ key = "number";
+ SECTION("name")
+ key = "name";
+ }
+
+ REQUIRE(ys.listHasKey(path, node, key));
+ }
+ SECTION("listKeys")
+ {
+ std::set<std::string> set;
+
+ SECTION("_list")
+ {
+ set = {"number"};
+ node.first = "example-schema";
+ node.second = "_list";
+ }
+
+ SECTION("twoKeyList")
+ {
+ set = {"number", "name"};
+ node.first = "example-schema";
+ node.second = "twoKeyList";
+ }
+
+ REQUIRE(ys.listKeys(path, node) == set);
+ }
+ SECTION("leafType")
+ {
+ yang::LeafDataTypes type;
+
+ SECTION("leafString")
+ {
+ node.first = "example-schema";
+ node.second = "leafString";
+ type = yang::LeafDataTypes::String;
+ }
+
+ SECTION("leafDecimal")
+ {
+ node.first = "example-schema";
+ node.second = "leafDecimal";
+ type = yang::LeafDataTypes::Decimal;
+ }
+
+ SECTION("leafBool")
+ {
+ node.first = "example-schema";
+ node.second = "leafBool";
+ type = yang::LeafDataTypes::Bool;
+ }
+
+ SECTION("leafInt")
+ {
+ node.first = "example-schema";
+ node.second = "leafInt";
+ type = yang::LeafDataTypes::Int;
+ }
+
+ SECTION("leafUint")
+ {
+ node.first = "example-schema";
+ node.second = "leafUint";
+ type = yang::LeafDataTypes::Uint;
+ }
+
+ SECTION("leafEnum")
+ {
+ node.first = "example-schema";
+ node.second = "leafEnum";
+ type = yang::LeafDataTypes::Enum;
+ }
+
+ REQUIRE(ys.leafType(path, node) == type);
+ }
+ SECTION("childNodes")
+ {
+ std::set<std::string> set;
+
+ SECTION("<root>")
+ {
+ set = {"example-schema:a", "example-schema:b", "example-schema:leafString",
+ "example-schema:leafDecimal", "example-schema:leafBool", "example-schema:leafInt",
+ "example-schema:leafUint", "example-schema:leafEnum", "example-schema:_list", "example-schema:twoKeyList"};
+ }
+
+ SECTION("a")
+ {
+ path.m_nodes.push_back(node_(module_{"example-schema"}, container_("a")));
+ set = {"example-schema:a2", "example-schema:leafa"};
+ }
+
+ REQUIRE(ys.childNodes(path) == set);
+ }
+ }
+
+ SECTION("negative")
+ {
+ SECTION("nonexistent nodes")
+ {
+ SECTION("example-schema:coze")
+ {
+ node.first = "example-schema";
+ node.second = "coze";
+ }
+
+ SECTION("example-schema:a/nevim")
+ {
+ path.m_nodes.push_back(node_(module_{"example-schema"}, container_("a")));
+ node.second = "nevim";
+ }
+
+ SECTION("modul:a/nevim")
+ {
+ path.m_nodes.push_back(node_(module_{"modul"}, container_("a")));
+ node.second = "nevim";
+ }
+
+ REQUIRE(!ys.isPresenceContainer(path, node));
+ REQUIRE(!ys.isList(path, node));
+ REQUIRE(!ys.isLeaf(path, node));
+ REQUIRE(!ys.isContainer(path, node));
+ }
+
+ SECTION("\"is\" methods return false for existing nodes for different nodetypes")
+ {
+ SECTION("example-schema:a")
+ {
+ node.first = "example-schema";
+ node.second = "a";
+ }
+
+ SECTION("example-schema:a/a2")
+ {
+ path.m_nodes.push_back(node_(module_{"example-schema"}, container_("a")));
+ node.second = "a2";
+ }
+
+ REQUIRE(!ys.isPresenceContainer(path, node));
+ REQUIRE(!ys.isList(path, node));
+ REQUIRE(!ys.isLeaf(path, node));
+ }
+
+ SECTION("nodetype-specific methods called with different nodetypes")
+ {
+ path.m_nodes.push_back(node_(module_{"example-schema"}, container_("a")));
+ node.second = "a2";
+
+ REQUIRE(!ys.leafEnumHasValue(path, node, "haha"));
+ REQUIRE(!ys.listHasKey(path, node, "chacha"));
+ }
+
+ SECTION("nonexistent module")
+ {
+ REQUIRE(!ys.isModule(path, "notAModule"));
+ }
+ }
+}