Add modules
Change-Id: Idafb0f57dd032d4f88658de15d293bdefac0567f
diff --git a/src/ast_handlers.hpp b/src/ast_handlers.hpp
index 65d8405..b58613c 100644
--- a/src/ast_handlers.hpp
+++ b/src/ast_handlers.hpp
@@ -22,7 +22,7 @@
if (parserContext.m_tmpListKeys.find(ast.first) != parserContext.m_tmpListKeys.end()) {
_pass(context) = false;
parserContext.m_errorMsg = "Key \"" + ast.first + "\" was entered more than once.";
- } else if (!schema.listHasKey(parserContext.m_curPath, parserContext.m_tmpListName, ast.first)) {
+ } else if (!schema.listHasKey(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName}, ast.first)) {
_pass(context) = false;
parserContext.m_errorMsg = parserContext.m_tmpListName + " is not indexed by \"" + ast.first + "\".";
} else {
@@ -39,7 +39,21 @@
}
};
-struct identifier_class;
+struct node_identifier_class {
+ template <typename T, typename Iterator, typename Context>
+ void on_success(Iterator const&, Iterator const&, T&, Context const& context)
+ {
+ auto& parserContext = x3::get<parser_context_tag>(context);
+
+ if (!parserContext.m_topLevelModulePresent) {
+ if (parserContext.m_errorMsg.empty())
+ parserContext.m_errorMsg = "You have to specify a top level module.";
+ _pass(context) = false;
+ }
+ }
+};
+
+struct module_identifier_class;
struct listPrefix_class {
template <typename T, typename Iterator, typename Context>
@@ -48,7 +62,7 @@
auto& parserContext = x3::get<parser_context_tag>(context);
const Schema& schema = parserContext.m_schema;
- if (schema.isList(parserContext.m_curPath, ast)) {
+ if (schema.isList(parserContext.m_curPath, {parserContext.m_curModule, ast})) {
parserContext.m_tmpListName = ast;
} else {
_pass(context) = false;
@@ -63,7 +77,7 @@
auto& parserContext = x3::get<parser_context_tag>(context);
const Schema& schema = parserContext.m_schema;
- const auto& keysNeeded = schema.listKeys(parserContext.m_curPath, parserContext.m_tmpListName);
+ const auto& keysNeeded = schema.listKeys(parserContext.m_curPath, {parserContext.m_curModule, parserContext.m_tmpListName});
std::set<std::string> keysSupplied;
for (const auto& it : ast)
keysSupplied.insert(it.first);
@@ -94,13 +108,6 @@
}
};
struct listElement_class {
- template <typename T, typename Iterator, typename Context>
- void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
- {
- auto& parserContext = x3::get<parser_context_tag>(context);
- parserContext.m_curPath.m_nodes.push_back(ast);
- }
-
template <typename Iterator, typename Exception, typename Context>
x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
{
@@ -119,11 +126,8 @@
{
auto& parserContext = x3::get<parser_context_tag>(context);
- if (!parserContext.m_curPath.m_nodes.empty()) {
- parserContext.m_curPath.m_nodes.pop_back();
- } else {
+ if (parserContext.m_curPath.m_nodes.empty())
_pass(context) = false;
- }
}
};
@@ -134,11 +138,8 @@
auto& parserContext = x3::get<parser_context_tag>(context);
const auto& schema = parserContext.m_schema;
- if (schema.isContainer(parserContext.m_curPath, ast.m_name)) {
- parserContext.m_curPath.m_nodes.push_back(ast);
- } else {
+ if (!schema.isContainer(parserContext.m_curPath, {parserContext.m_curModule, ast.m_name}))
_pass(context) = false;
- }
}
};
@@ -149,20 +150,46 @@
auto& parserContext = x3::get<parser_context_tag>(context);
const auto& schema = parserContext.m_schema;
- if (schema.isLeaf(parserContext.m_curPath, ast.m_name)) {
- parserContext.m_curPath.m_nodes.push_back(ast);
+ if (!schema.isLeaf(parserContext.m_curPath, {parserContext.m_curModule, ast.m_name}))
+ _pass(context) = false;
+ }
+};
+
+
+struct module_class {
+ template <typename T, typename Iterator, typename Context>
+ void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
+ {
+ auto& parserContext = x3::get<parser_context_tag>(context);
+ const auto& schema = parserContext.m_schema;
+
+ if (schema.isModule(parserContext.m_curPath, ast.m_name)) {
+ parserContext.m_curModule = ast.m_name;
+ parserContext.m_topLevelModulePresent = true;
} else {
+ parserContext.m_errorMsg = "Invalid module name.";
_pass(context) = false;
}
}
};
-struct path_class {
+struct node_class {
template <typename T, typename Iterator, typename Context>
- void on_success(Iterator const&, Iterator const&, T&, Context const&)
+ void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
{
+ auto& parserContext = x3::get<parser_context_tag>(context);
+ if (ast.m_suffix.type() == typeid(nodeup_)) {
+ parserContext.m_curPath.m_nodes.pop_back();
+ if (parserContext.m_curPath.m_nodes.empty())
+ parserContext.m_topLevelModulePresent = false;
+ } else {
+ parserContext.m_curPath.m_nodes.push_back(ast);
+ parserContext.m_curModule = boost::none;
+ }
}
+};
+struct path_class {
template <typename Iterator, typename Exception, typename Context>
x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
{
@@ -176,12 +203,8 @@
}
};
-struct cd_class {
- template <typename T, typename Iterator, typename Context>
- void on_success(Iterator const&, Iterator const&, T&, Context const&)
- {
- }
+struct cd_class {
template <typename Iterator, typename Exception, typename Context>
x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const& x, Context const& context)
{
@@ -199,10 +222,13 @@
auto& parserContext = x3::get<parser_context_tag>(context);
const auto& schema = parserContext.m_schema;
try {
- container_ cont = boost::get<container_>(ast.m_path.m_nodes.back());
+ boost::optional<std::string> module;
+ if (ast.m_path.m_nodes.back().m_prefix)
+ module = ast.m_path.m_nodes.back().m_prefix.value().m_name;
+ container_ cont = boost::get<container_>(ast.m_path.m_nodes.back().m_suffix);
path_ location = pathWithoutLastNode(parserContext.m_curPath);
- if (!schema.isPresenceContainer(location, cont.m_name)) {
+ if (!schema.isPresenceContainer(location, {module, cont.m_name})) {
parserContext.m_errorMsg = "This container is not a presence container.";
_pass(context) = false;
}
@@ -234,7 +260,7 @@
{
auto& parserContext = x3::get<parser_context_tag>(context);
try {
- auto leaf = boost::get<leaf_>(ast.m_nodes.back());
+ auto leaf = boost::get<leaf_>(ast.m_nodes.back().m_suffix);
} catch (boost::bad_get&) {
parserContext.m_errorMsg = "This is not a path to leaf.";
_pass(context) = false;
@@ -249,9 +275,9 @@
auto& parserContext = x3::get<parser_context_tag>(context);
auto& schema = parserContext.m_schema;
if (parserContext.m_errorMsg.empty()) {
- leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back());
+ leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
path_ location = pathWithoutLastNode(parserContext.m_curPath);
- parserContext.m_errorMsg = "Expected " + leafDataTypeToString(schema.leafType(location, leaf.m_name)) + " here:";
+ parserContext.m_errorMsg = "Expected " + leafDataTypeToString(schema.leafType(location, {parserContext.m_curModule, leaf.m_name})) + " here:";
return x3::error_handler_result::fail;
}
return x3::error_handler_result::rethrow;
@@ -271,11 +297,14 @@
{
auto& parserContext = x3::get<parser_context_tag>(context);
auto& schema = parserContext.m_schema;
+ boost::optional<std::string> module;
+ if (parserContext.m_curPath.m_nodes.back().m_prefix)
+ module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
- leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back());
+ leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
path_ location = pathWithoutLastNode(parserContext.m_curPath);
- if (schema.leafType(location, leaf.m_name) != m_type) {
+ if (schema.leafType(location, {module, leaf.m_name}) != m_type) {
_pass(context) = false;
}
}
@@ -293,11 +322,14 @@
leaf_data_base_class::on_success(start, end, ast, context);
auto& parserContext = x3::get<parser_context_tag>(context);
auto& schema = parserContext.m_schema;
+ boost::optional<std::string> module;
+ if (parserContext.m_curPath.m_nodes.back().m_prefix)
+ module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
- leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back());
+ leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
path_ location = pathWithoutLastNode(parserContext.m_curPath);
- if (!schema.leafEnumHasValue(location, leaf.m_name, ast.m_value)) {
+ if (!schema.leafEnumHasValue(location, {module, leaf.m_name}, ast.m_value)) {
_pass(context) = false;
}
}
diff --git a/src/ast_path.cpp b/src/ast_path.cpp
index 2734377..2621792 100644
--- a/src/ast_path.cpp
+++ b/src/ast_path.cpp
@@ -25,6 +25,30 @@
{
}
+bool module_::operator==(const module_& b) const
+{
+ return this->m_name == b.m_name;
+}
+
+node_::node_() = default;
+
+node_::node_(decltype(m_suffix) node)
+ : m_suffix(node)
+{
+}
+
+node_::node_(module_ module, decltype(m_suffix) node)
+ : m_prefix(module)
+ , m_suffix(node)
+{
+}
+
+
+bool node_::operator==(const node_& b) const
+{
+ return this->m_suffix == b.m_suffix && this->m_prefix == b.m_prefix;
+}
+
bool leaf_::operator==(const leaf_& b) const
{
return this->m_name == b.m_name;
@@ -49,7 +73,7 @@
}
-struct nodeToSchemaString : public boost::static_visitor<std::string> {
+struct nodeToSchemaStringVisitor : public boost::static_visitor<std::string> {
std::string operator()(const nodeup_&) const
{
return "..";
@@ -60,7 +84,7 @@
return node.m_name;
}
};
-struct nodeToDataString : public boost::static_visitor<std::string> {
+struct nodeToDataStringVisitor : public boost::static_visitor<std::string> {
std::string operator()(const listElement_& node) const
{
std::ostringstream res;
@@ -82,18 +106,48 @@
}
};
+std::string nodeToSchemaString(decltype(path_::m_nodes)::value_type node)
+{
+ return boost::apply_visitor(nodeToSchemaStringVisitor(), node.m_suffix);
+}
+
std::string pathToDataString(const path_& path)
{
std::string res;
for (const auto it : path.m_nodes)
- res = joinPaths(res, boost::apply_visitor(nodeToDataString(), it));
+ if (it.m_prefix)
+ res = joinPaths(res, it.m_prefix.value().m_name + ":" + boost::apply_visitor(nodeToDataStringVisitor(), it.m_suffix));
+ else
+ res = joinPaths(res, boost::apply_visitor(nodeToDataStringVisitor(), it.m_suffix));
+
+ return res;
+}
+
+std::string pathToAbsoluteSchemaString(const path_& path)
+{
+ std::string res;
+ if (path.m_nodes.empty()) {
+ return "";
+ }
+
+ auto topLevelModule = path.m_nodes.at(0).m_prefix.value();
+ for (const auto it : path.m_nodes) {
+ if (it.m_prefix)
+ res = joinPaths(res, it.m_prefix.value().m_name + ":" + boost::apply_visitor(nodeToSchemaStringVisitor(), it.m_suffix));
+ else
+ res = joinPaths(res, topLevelModule.m_name + ":" + boost::apply_visitor(nodeToSchemaStringVisitor(), it.m_suffix));
+ }
return res;
}
std::string pathToSchemaString(const path_& path)
{
std::string res;
- for (const auto it : path.m_nodes)
- res = joinPaths(res, boost::apply_visitor(nodeToSchemaString(), it));
+ for (const auto it : path.m_nodes) {
+ if (it.m_prefix)
+ res = joinPaths(res, it.m_prefix.value().m_name + ":" + boost::apply_visitor(nodeToSchemaStringVisitor(), it.m_suffix));
+ else
+ res = joinPaths(res, boost::apply_visitor(nodeToSchemaStringVisitor(), it.m_suffix));
+ }
return res;
}
diff --git a/src/ast_path.hpp b/src/ast_path.hpp
index 1a4b282..029d33f 100644
--- a/src/ast_path.hpp
+++ b/src/ast_path.hpp
@@ -53,15 +53,34 @@
std::map<std::string, std::string> m_keys;
};
-struct path_ {
- bool operator==(const path_& b) const;
- std::vector<boost::variant<container_, listElement_, nodeup_, leaf_>> m_nodes;
+struct module_ {
+ bool operator==(const module_& b) const;
+ std::string m_name;
};
+struct node_ {
+ boost::optional<module_> m_prefix;
+ boost::variant<container_, listElement_, nodeup_, leaf_> m_suffix;
+ node_();
+ node_(decltype(m_suffix) node);
+ node_(module_ module, decltype(m_suffix) node);
+ bool operator==(const node_& b) const;
+};
+
+struct path_ {
+ bool operator==(const path_& b) const;
+ std::vector<node_> m_nodes;
+};
+
+std::string nodeToSchemaString(decltype(path_::m_nodes)::value_type node);
+
+std::string pathToAbsoluteSchemaString(const path_& path);
std::string pathToDataString(const path_& path);
std::string pathToSchemaString(const path_& path);
BOOST_FUSION_ADAPT_STRUCT(container_, m_name)
BOOST_FUSION_ADAPT_STRUCT(listElement_, m_name, m_keys)
+BOOST_FUSION_ADAPT_STRUCT(module_, m_name)
+BOOST_FUSION_ADAPT_STRUCT(node_, m_prefix, m_suffix)
BOOST_FUSION_ADAPT_STRUCT(path_, m_nodes)
diff --git a/src/grammars.hpp b/src/grammars.hpp
index 5386417..ed21e31 100644
--- a/src/grammars.hpp
+++ b/src/grammars.hpp
@@ -13,13 +13,16 @@
x3::rule<keyValue_class, keyValue_> const keyValue = "keyValue";
-x3::rule<identifier_class, std::string> const identifier = "identifier";
+x3::rule<node_identifier_class, std::string> const node_identifier = "node_identifier";
+x3::rule<module_identifier_class, std::string> const module_identifier = "module_identifier";
x3::rule<listPrefix_class, std::string> const listPrefix = "listPrefix";
x3::rule<listSuffix_class, std::vector<keyValue_>> const listSuffix = "listSuffix";
x3::rule<listElement_class, listElement_> const listElement = "listElement";
x3::rule<nodeup_class, nodeup_> const nodeup = "nodeup";
x3::rule<container_class, container_> const container = "container";
x3::rule<leaf_class, leaf_> const leaf = "leaf";
+x3::rule<module_class, module_> const module = "module";
+x3::rule<node_class, node_> const node = "node";
x3::rule<path_class, path_> const path = "path";
x3::rule<leaf_path_class, path_> const leafPath = "leafPath";
@@ -45,13 +48,18 @@
auto const keyValue_def =
lexeme[+alnum > '=' > +alnum];
-auto const identifier_def =
+auto const module_identifier_def =
+ lexeme[
+ ((alpha | char_("_")) >> *(alnum | char_("_") | char_("-") | char_(".")))
+ ];
+
+auto const node_identifier_def =
lexeme[
((alpha | char_("_")) >> *(alnum | char_("_") | char_("-") | char_(".")))
];
auto const listPrefix_def =
- identifier >> '[';
+ node_identifier >> '[';
// even though we don't allow no keys to be supplied, the star allows me to check which keys are missing
auto const listSuffix_def =
@@ -64,14 +72,20 @@
lit("..") > x3::attr(nodeup_());
auto const container_def =
- identifier;
+ node_identifier;
+
+auto const module_def =
+ module_identifier >> x3::no_skip[':'] >> !x3::no_skip[space];
auto const leaf_def =
- identifier;
+ node_identifier;
// leaf cannot be in the middle of a path, however, I need the grammar's attribute to be a vector of variants
+auto const node_def =
+ -(module) >> x3::expect[container | listElement | nodeup | leaf];
+
auto const path_def =
- (x3::expect[container | listElement | nodeup | leaf]) % '/';
+ node % '/';
auto const leafPath_def =
path;
@@ -131,7 +145,8 @@
#endif
BOOST_SPIRIT_DEFINE(keyValue)
-BOOST_SPIRIT_DEFINE(identifier)
+BOOST_SPIRIT_DEFINE(node_identifier)
+BOOST_SPIRIT_DEFINE(module_identifier)
BOOST_SPIRIT_DEFINE(listPrefix)
BOOST_SPIRIT_DEFINE(listSuffix)
BOOST_SPIRIT_DEFINE(listElement)
@@ -139,7 +154,9 @@
BOOST_SPIRIT_DEFINE(container)
BOOST_SPIRIT_DEFINE(leaf)
BOOST_SPIRIT_DEFINE(leafPath)
+BOOST_SPIRIT_DEFINE(node)
BOOST_SPIRIT_DEFINE(path)
+BOOST_SPIRIT_DEFINE(module)
BOOST_SPIRIT_DEFINE(leaf_data)
BOOST_SPIRIT_DEFINE(leaf_data_enum)
BOOST_SPIRIT_DEFINE(leaf_data_decimal)
diff --git a/src/interpreter.cpp b/src/interpreter.cpp
index 1a4e84a..19a163b 100644
--- a/src/interpreter.cpp
+++ b/src/interpreter.cpp
@@ -35,12 +35,14 @@
void Interpreter::operator()(const create_& create) const
{
- std::cout << "Presence container " << boost::get<container_>(create.m_path.m_nodes.back()).m_name << " created." << std::endl;
+ auto cont = boost::get<container_>(create.m_path.m_nodes.back().m_suffix);
+ std::cout << "Presence container " << cont.m_name << " created." << std::endl;
}
void Interpreter::operator()(const delete_& delet) const
{
- std::cout << "Presence container " << boost::get<container_>(delet.m_path.m_nodes.back()).m_name << " deleted." << std::endl;
+ auto cont = boost::get<container_>(delet.m_path.m_nodes.back().m_suffix);
+ std::cout << "Presence container " << cont.m_name << " deleted." << std::endl;
}
Interpreter::Interpreter(Parser& parser, Schema&)
diff --git a/src/main.cpp b/src/main.cpp
index 0c02ecf..5c0d9f9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -46,24 +46,18 @@
true);
std::cout << "Welcome to netconf-cli" << std::endl;
- auto schema = std::make_shared<StaticSchema>();
- schema->addContainer("", "a", yang::ContainerTraits::Presence);
- schema->addContainer("", "b");
- schema->addLeaf("", "leafString", yang::LeafDataTypes::String);
- schema->addLeaf("", "leafDecimal", yang::LeafDataTypes::Decimal);
- schema->addLeaf("", "leafBool", yang::LeafDataTypes::Bool);
- schema->addLeaf("", "leafInt", yang::LeafDataTypes::Int);
- schema->addLeaf("", "leafUint", yang::LeafDataTypes::Uint);
- schema->addLeafEnum("", "leafEnum", {"lol", "data", "coze"});
- schema->addContainer("a", "a2");
- schema->addLeaf("a", "leafa", yang::LeafDataTypes::String);
- schema->addContainer("b", "b2", yang::ContainerTraits::Presence);
- schema->addContainer("a/a2", "a3", yang::ContainerTraits::Presence);
- schema->addContainer("b/b2", "b3");
- schema->addList("", "list", {"number"});
- schema->addContainer("list", "contInList", yang::ContainerTraits::Presence);
- schema->addList("", "twoKeyList", {"number", "name"});
- Parser parser(schema);
+ auto yangschema = std::make_shared<StaticSchema>();
+ yangschema->addModule("mod");
+ yangschema->addContainer("", "mod:a", yang::ContainerTraits::Presence);
+ yangschema->addContainer("", "mod:b");
+ yangschema->addContainer("mod:a", "mod:a2", yang::ContainerTraits::Presence);
+ yangschema->addContainer("mod:b", "mod:b2");
+ yangschema->addContainer("mod:a/mod:a2", "mod:a3");
+ yangschema->addContainer("mod:b/mod:b2", "mod:b3");
+ yangschema->addList("", "mod:list", {"number"});
+ yangschema->addContainer("mod:list", "contInList");
+ yangschema->addList("", "mod:twoKeyList", {"number", "name"});
+ Parser parser(yangschema);
while (true) {
std::cout << parser.currentNode() << "> ";
@@ -74,7 +68,7 @@
try {
command_ cmd = parser.parseCommand(input, std::cout);
- boost::apply_visitor(Interpreter(parser, *schema), cmd);
+ boost::apply_visitor(Interpreter(parser, *yangschema), cmd);
} catch (InvalidCommandException& ex) {
std::cerr << ex.what() << std::endl;
}
diff --git a/src/parser.cpp b/src/parser.cpp
index 0c62358..ac3ba84 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -42,7 +42,7 @@
void Parser::changeNode(const path_& name)
{
for (const auto& it : name.m_nodes) {
- if (it.type() == typeid(nodeup_))
+ if (it.m_suffix.type() == typeid(nodeup_))
m_curDir.m_nodes.pop_back();
else
m_curDir.m_nodes.push_back(it);
diff --git a/src/parser_context.cpp b/src/parser_context.cpp
index d3b4a90..fa64344 100644
--- a/src/parser_context.cpp
+++ b/src/parser_context.cpp
@@ -11,4 +11,7 @@
: m_schema(schema)
{
m_curPath = curDir;
+
+ if (!m_curPath.m_nodes.empty() && m_curPath.m_nodes.at(0).m_prefix)
+ m_topLevelModulePresent = true;
}
diff --git a/src/parser_context.hpp b/src/parser_context.hpp
index 99c1a63..28c5eb1 100644
--- a/src/parser_context.hpp
+++ b/src/parser_context.hpp
@@ -11,8 +11,10 @@
ParserContext(const Schema& schema, const path_ curDir);
const Schema& m_schema;
path_ m_curPath;
+ boost::optional<std::string> m_curModule;
std::string m_errorMsg;
std::string m_tmpListName;
+ bool m_topLevelModulePresent = false;
std::set<std::string> m_tmpListKeys;
bool m_errorHandled = false;
};
diff --git a/src/schema.hpp b/src/schema.hpp
index 7c05d17..2059e1b 100644
--- a/src/schema.hpp
+++ b/src/schema.hpp
@@ -40,10 +40,13 @@
yang::LeafDataTypes m_type;
std::set<std::string> m_enumValues;
};
+
+struct module {
+};
}
-using NodeType = boost::variant<yang::container, yang::list, yang::leaf>;
+using NodeType = boost::variant<yang::container, yang::list, yang::leaf, yang::module>;
class InvalidNodeException : public std::invalid_argument {
@@ -55,19 +58,24 @@
/*! \class Schema
* \brief A base schema class for schemas
* */
+
+using ModuleNodePair = std::pair<boost::optional<std::string>, std::string>;
+
class Schema {
public:
virtual ~Schema();
- virtual bool isContainer(const path_& location, const std::string& name) const = 0;
- virtual bool isLeaf(const path_& location, const std::string& name) const = 0;
- virtual bool isList(const path_& location, const std::string& name) const = 0;
- virtual bool isPresenceContainer(const path_& location, const std::string& name) const = 0;
- virtual bool leafEnumHasValue(const path_& location, const std::string& name, const std::string& value) const = 0;
- virtual bool listHasKey(const path_& location, const std::string& name, const std::string& key) const = 0;
- virtual bool nodeExists(const std::string& location, const std::string& name) const = 0;
- virtual const std::set<std::string>& listKeys(const path_& location, const std::string& name) const = 0;
- virtual yang::LeafDataTypes leafType(const path_& location, const std::string& name) const = 0;
+ virtual bool isContainer(const path_& location, const ModuleNodePair& node) const = 0;
+ virtual bool isLeaf(const path_& location, const ModuleNodePair& node) const = 0;
+ virtual bool isModule(const path_& location, const std::string& name) const = 0;
+ virtual bool isList(const path_& location, const ModuleNodePair& node) const = 0;
+ virtual bool isPresenceContainer(const path_& location, const ModuleNodePair& node) const = 0;
+ virtual bool leafEnumHasValue(const path_& location, const ModuleNodePair& node, const std::string& value) const = 0;
+ virtual bool listHasKey(const path_& location, const ModuleNodePair& node, const std::string& key) const = 0;
+ virtual bool nodeExists(const std::string& location, const std::string& node) const = 0;
+ virtual const std::set<std::string>& listKeys(const path_& location, const ModuleNodePair& node) const = 0;
+ virtual yang::LeafDataTypes leafType(const path_& location, const ModuleNodePair& node) const = 0;
+ virtual std::set<std::string> childNodes(const path_& path) const = 0;
private:
const std::unordered_map<std::string, NodeType>& children(const std::string& name) const;
diff --git a/src/static_schema.cpp b/src/static_schema.cpp
index 65debf0..86dc6fa 100644
--- a/src/static_schema.cpp
+++ b/src/static_schema.cpp
@@ -16,27 +16,34 @@
m_nodes.emplace("", std::unordered_map<std::string, NodeType>());
}
+
const std::unordered_map<std::string, NodeType>& StaticSchema::children(const std::string& name) const
{
return m_nodes.at(name);
}
-bool StaticSchema::nodeExists(const std::string& location, const std::string& name) const
+bool StaticSchema::nodeExists(const std::string& location, const std::string& node) const
{
- if (name.empty())
+ if (node.empty())
return true;
const auto& childrenRef = children(location);
- return childrenRef.find(name) != childrenRef.end();
+ return childrenRef.find(node) != childrenRef.end();
}
-bool StaticSchema::isContainer(const path_& location, const std::string& name) const
+bool StaticSchema::isModule(const path_&, const std::string& name) const
{
- std::string locationString = pathToSchemaString(location);
- if (!nodeExists(locationString, name))
+ return m_modules.find(name) != m_modules.end();
+}
+
+bool StaticSchema::isContainer(const path_& location, const ModuleNodePair& node) const
+{
+ std::string locationString = pathToAbsoluteSchemaString(location);
+ auto fullName = fullNodeName(location, node);
+ if (!nodeExists(locationString, fullName))
return false;
- return children(locationString).at(name).type() == typeid(yang::container);
+ return children(locationString).at(fullName).type() == typeid(yang::container);
}
void StaticSchema::addContainer(const std::string& location, const std::string& name, yang::ContainerTraits isPresence)
@@ -49,32 +56,33 @@
}
-bool StaticSchema::listHasKey(const path_& location, const std::string& name, const std::string& key) const
+bool StaticSchema::listHasKey(const path_& location, const ModuleNodePair& node, const std::string& key) const
{
- std::string locationString = pathToSchemaString(location);
- assert(isList(location, name));
+ std::string locationString = pathToAbsoluteSchemaString(location);
+ assert(isList(location, node));
- const auto& child = children(locationString).at(name);
+ const auto& child = children(locationString).at(fullNodeName(location, node));
const auto& list = boost::get<yang::list>(child);
return list.m_keys.find(key) != list.m_keys.end();
}
-const std::set<std::string>& StaticSchema::listKeys(const path_& location, const std::string& name) const
+const std::set<std::string>& StaticSchema::listKeys(const path_& location, const ModuleNodePair& node) const
{
- std::string locationString = pathToSchemaString(location);
- assert(isList(location, name));
+ std::string locationString = pathToAbsoluteSchemaString(location);
+ assert(isList(location, node));
- const auto& child = children(locationString).at(name);
+ const auto& child = children(locationString).at(fullNodeName(location, node));
const auto& list = boost::get<yang::list>(child);
return list.m_keys;
}
-bool StaticSchema::isList(const path_& location, const std::string& name) const
+bool StaticSchema::isList(const path_& location, const ModuleNodePair& node) const
{
- std::string locationString = pathToSchemaString(location);
- if (!nodeExists(locationString, name))
+ std::string locationString = pathToAbsoluteSchemaString(location);
+ auto fullName = fullNodeName(location, node);
+ if (!nodeExists(locationString, fullName))
return false;
- const auto& child = children(locationString).at(name);
+ const auto& child = children(locationString).at(fullName);
if (child.type() != typeid(yang::list))
return false;
@@ -88,12 +96,12 @@
m_nodes.emplace(name, std::unordered_map<std::string, NodeType>());
}
-bool StaticSchema::isPresenceContainer(const path_& location, const std::string& name) const
+bool StaticSchema::isPresenceContainer(const path_& location, const ModuleNodePair& node) const
{
- if (!isContainer(location, name))
+ if (!isContainer(location, node))
return false;
- std::string locationString = pathToSchemaString(location);
- return boost::get<yang::container>(children(locationString).at(name)).m_presence == yang::ContainerTraits::Presence;
+ std::string locationString = pathToAbsoluteSchemaString(location);
+ return boost::get<yang::container>(children(locationString).at(fullNodeName(location, node))).m_presence == yang::ContainerTraits::Presence;
}
void StaticSchema::addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type)
@@ -106,27 +114,47 @@
m_nodes.at(location).emplace(name, yang::leaf{yang::LeafDataTypes::Enum, enumValues});
}
-bool StaticSchema::leafEnumHasValue(const path_& location, const std::string& name, const std::string& value) const
+void StaticSchema::addModule(const std::string& name)
{
- std::string locationString = pathToSchemaString(location);
- assert(isLeaf(location, name));
+ m_modules.emplace(name);
+}
- const auto& child = children(locationString).at(name);
+
+bool StaticSchema::leafEnumHasValue(const path_& location, const ModuleNodePair& node, const std::string& value) const
+{
+ std::string locationString = pathToAbsoluteSchemaString(location);
+ assert(isLeaf(location, node));
+
+ const auto& child = children(locationString).at(fullNodeName(location, node));
const auto& list = boost::get<yang::leaf>(child);
return list.m_enumValues.find(value) != list.m_enumValues.end();
}
-bool StaticSchema::isLeaf(const path_& location, const std::string& name) const
+bool StaticSchema::isLeaf(const path_& location, const ModuleNodePair& node) const
{
- std::string locationString = pathToSchemaString(location);
- if (!nodeExists(locationString, name))
+ std::string locationString = pathToAbsoluteSchemaString(location);
+ auto fullName = fullNodeName(location, node);
+ if (!nodeExists(locationString, fullName))
return false;
- return children(locationString).at(name).type() == typeid(yang::leaf);
+ return children(locationString).at(fullName).type() == typeid(yang::leaf);
}
-yang::LeafDataTypes StaticSchema::leafType(const path_& location, const std::string& name) const
+yang::LeafDataTypes StaticSchema::leafType(const path_& location, const ModuleNodePair& node) const
{
- std::string locationString = pathToSchemaString(location);
- return boost::get<yang::leaf>(children(locationString).at(name)).m_type;
+ std::string locationString = pathToAbsoluteSchemaString(location);
+ return boost::get<yang::leaf>(children(locationString).at(fullNodeName(location, node))).m_type;
+}
+
+std::set<std::string> StaticSchema::childNodes(const path_& path) const
+{
+ std::string locationString = pathToAbsoluteSchemaString(path);
+ std::set<std::string> res;
+
+ auto childrenRef = children(locationString);
+
+ std::transform(childrenRef.begin(), childrenRef.end(),
+ std::inserter(res, res.end()),
+ [] (auto it) { return it.first; });
+ return res;
}
diff --git a/src/static_schema.hpp b/src/static_schema.hpp
index bab8bde..1a84e23 100644
--- a/src/static_schema.hpp
+++ b/src/static_schema.hpp
@@ -19,28 +19,33 @@
/*! \class StaticSchema
* \brief Static schema, used mainly for testing
* */
+using ModuleNodePair = std::pair<boost::optional<std::string>, std::string>;
class StaticSchema : public Schema {
public:
StaticSchema();
- bool isContainer(const path_& location, const std::string& name) const override;
- bool isLeaf(const path_& location, const std::string& name) const override;
- bool isList(const path_& location, const std::string& name) const override;
- bool isPresenceContainer(const path_& location, const std::string& name) const override;
- bool leafEnumHasValue(const path_& location, const std::string& name, const std::string& value) const override;
- bool listHasKey(const path_& location, const std::string& name, const std::string& key) const override;
- bool nodeExists(const std::string& location, const std::string& name) const override;
- const std::set<std::string>& listKeys(const path_& location, const std::string& name) const override;
- yang::LeafDataTypes leafType(const path_& location, const std::string& name) const override;
+ bool isContainer(const path_& location, const ModuleNodePair& node) const override;
+ bool isModule(const path_& location, const std::string& name) const override;
+ bool isLeaf(const path_& location, const ModuleNodePair& node) const override;
+ bool isList(const path_& location, const ModuleNodePair& node) const override;
+ bool isPresenceContainer(const path_& location, const ModuleNodePair& node) const override;
+ bool leafEnumHasValue(const path_& location, const ModuleNodePair& node, const std::string& value) const override;
+ bool listHasKey(const path_& location, const ModuleNodePair& node, const std::string& key) const override;
+ bool nodeExists(const std::string& location, const std::string& node) const override;
+ const std::set<std::string>& listKeys(const path_& location, const ModuleNodePair& node) const override;
+ yang::LeafDataTypes leafType(const path_& location, const ModuleNodePair& node) const override;
+ std::set<std::string> childNodes(const path_& path) const override;
void addContainer(const std::string& location, const std::string& name, yang::ContainerTraits isPresence = yang::ContainerTraits::None);
void addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type);
void addLeafEnum(const std::string& location, const std::string& name, std::set<std::string> enumValues);
void addList(const std::string& location, const std::string& name, const std::set<std::string>& keys);
+ void addModule(const std::string& name);
private:
const std::unordered_map<std::string, NodeType>& children(const std::string& name) const;
std::unordered_map<std::string, std::unordered_map<std::string, NodeType>> m_nodes;
+ std::set<std::string> m_modules;
};
diff --git a/src/utils.cpp b/src/utils.cpp
index b4f60ab..2900e14 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -50,3 +50,12 @@
return "";
}
}
+
+std::string fullNodeName(const path_& location, const ModuleNodePair& pair)
+{
+ if (!pair.first) {
+ return location.m_nodes.at(0).m_prefix.value().m_name + ":" + pair.second;
+ } else {
+ return pair.first.value() + ":" + pair.second;
+ }
+}
diff --git a/src/utils.hpp b/src/utils.hpp
index 9583ebe..49b5b29 100644
--- a/src/utils.hpp
+++ b/src/utils.hpp
@@ -13,3 +13,4 @@
std::string stripLastNodeFromPath(const std::string& path);
path_ pathWithoutLastNode(const path_& path);
std::string leafDataTypeToString(yang::LeafDataTypes type);
+std::string fullNodeName(const path_& location, const ModuleNodePair& pair);
diff --git a/tests/cd.cpp b/tests/cd.cpp
index 29187ff..5bf0172 100644
--- a/tests/cd.cpp
+++ b/tests/cd.cpp
@@ -14,114 +14,131 @@
TEST_CASE("cd")
{
auto schema = std::make_shared<StaticSchema>();
- schema->addContainer("", "a");
- schema->addContainer("", "b");
- schema->addContainer("a", "a2");
- schema->addContainer("b", "b2");
- schema->addContainer("a/a2", "a3");
- schema->addContainer("b/b2", "b3");
- schema->addList("", "list", {"number"});
- schema->addContainer("list", "contInList");
- schema->addList("", "twoKeyList", {"number", "name"});
+ schema->addModule("example");
+ schema->addModule("second");
+ schema->addContainer("", "example:a");
+ schema->addContainer("", "second:a");
+ schema->addContainer("", "example:b");
+ schema->addContainer("example:a", "example:a2");
+ schema->addContainer("example:b", "example:b2");
+ schema->addContainer("example:a/example:a2", "example:a3");
+ schema->addContainer("example:b/example:b2", "example:b3");
+ schema->addList("", "example:list", {"number"});
+ schema->addContainer("example:list", "example:contInList");
+ schema->addList("", "example:twoKeyList", {"number", "name"});
Parser parser(schema);
std::string input;
std::ostringstream errorStream;
+
SECTION("valid input")
{
cd_ expected;
SECTION("container")
{
- SECTION("a")
+ SECTION("example:a")
{
- input = "cd a";
- expected.m_path.m_nodes.push_back(container_("a"));
+ input = "cd example:a";
+ expected.m_path.m_nodes.push_back(node_(module_{"example"}, container_("a")));
}
- SECTION("b")
+ SECTION("second:a")
{
- input = "cd b";
- expected.m_path.m_nodes.push_back(container_("b"));
+ input = "cd second:a";
+ expected.m_path.m_nodes.push_back(node_(module_{"second"}, container_("a")));
}
- SECTION("a/a2")
+ SECTION("example:b")
{
- input = "cd a/a2";
- expected.m_path.m_nodes.push_back(container_("a"));
- expected.m_path.m_nodes.push_back(container_("a2"));
+ input = "cd example:b";
+ expected.m_path.m_nodes.push_back(node_(module_{"example"}, container_("b")));
}
- SECTION("b/b2")
+ SECTION("example:a/a2")
{
- input = "cd b/b2";
- expected.m_path.m_nodes.push_back(container_("b"));
- expected.m_path.m_nodes.push_back(container_("b2"));
+ input = "cd example:a/a2";
+ expected.m_path.m_nodes.push_back(node_(module_{"example"}, container_("a")));
+ expected.m_path.m_nodes.push_back(node_(container_("a2")));
+ }
+
+ SECTION("example:a/example:a2")
+ {
+ input = "cd example:a/example:a2";
+ expected.m_path.m_nodes.push_back(node_(module_{"example"}, container_("a")));
+ expected.m_path.m_nodes.push_back(node_(module_{"example"}, container_("a2")));
+ }
+
+ SECTION("example:b/b2")
+ {
+ input = "cd example:b/b2";
+ expected.m_path.m_nodes.push_back(node_(module_{"example"}, container_("b")));
+ expected.m_path.m_nodes.push_back(node_(container_("b2")));
}
}
SECTION("list elements")
{
- SECTION("list[number=1]")
+ SECTION("example:list[number=1]")
{
- input = "cd list[number=1]";
+ input = "cd example:list[number=1]";
auto keys = std::map<std::string, std::string>{
{"number", "1"}};
- expected.m_path.m_nodes.push_back(listElement_("list", keys));
+ expected.m_path.m_nodes.push_back(node_(module_{"example"}, listElement_("list", keys)));
}
- SECTION("list[number=1]/contInList")
+ SECTION("example:list[number=1]/contInList")
{
- input = "cd list[number=1]/contInList";
+ input = "cd example:list[number=1]/contInList";
auto keys = std::map<std::string, std::string>{
{"number", "1"}};
- expected.m_path.m_nodes.push_back(listElement_("list", keys));
- expected.m_path.m_nodes.push_back(container_("contInList"));
+ expected.m_path.m_nodes.push_back(node_(module_{"example"}, listElement_("list", keys)));
+ expected.m_path.m_nodes.push_back(node_(container_("contInList")));
}
- SECTION("twoKeyList[number=4 name=abcd]")
+ SECTION("example:twoKeyList[number=4 name=abcd]")
{
- input = "cd twoKeyList[number=4 name=abcd]";
+ input = "cd example:twoKeyList[number=4 name=abcd]";
auto keys = std::map<std::string, std::string>{
{"number", "4"},
{"name", "abcd"}};
- expected.m_path.m_nodes.push_back(listElement_("twoKeyList", keys));
+ expected.m_path.m_nodes.push_back(node_(module_{"example"}, listElement_("twoKeyList", keys)));
}
}
SECTION("whitespace handling")
{
- SECTION(" cd a ")
+ SECTION(" cd example:a ")
{
- input = " cd a ";
- expected.m_path.m_nodes.push_back(container_("a"));
+ input = " cd example:a ";
+ expected.m_path.m_nodes.push_back(node_(module_{"example"}, container_("a")));
}
}
SECTION("moving up")
{
- SECTION("a/..")
+ SECTION("example:a/..")
{
- input = "cd a/..";
- expected.m_path.m_nodes.push_back(container_("a"));
- expected.m_path.m_nodes.push_back(nodeup_());
+ input = "cd example:a/..";
+ expected.m_path.m_nodes.push_back(node_(module_{"example"}, container_("a")));
+ expected.m_path.m_nodes.push_back(node_(nodeup_()));
}
- SECTION("a/../a")
+ SECTION("example:a/../example:a")
{
- input = "cd a/../a";
- expected.m_path.m_nodes.push_back(container_("a"));
- expected.m_path.m_nodes.push_back(nodeup_());
- expected.m_path.m_nodes.push_back(container_("a"));
+ input = "cd example:a/../example:a";
+ expected.m_path.m_nodes.push_back(node_(module_{"example"}, container_("a")));
+ expected.m_path.m_nodes.push_back(node_(nodeup_()));
+ expected.m_path.m_nodes.push_back(node_(module_{"example"}, container_("a")));
}
- SECTION("a/../a/a2")
+ SECTION("example:a/../example:a/a2")
{
- input = "cd a/../a/a2";
- expected.m_path.m_nodes.push_back(container_("a"));
- expected.m_path.m_nodes.push_back(nodeup_());
- expected.m_path.m_nodes.push_back(container_("a"));
- expected.m_path.m_nodes.push_back(container_("a2"));
+ input = "cd example:a/../example:a/a2";
+ expected.m_path.m_nodes.push_back(node_(module_{"example"}, container_("a")));
+ expected.m_path.m_nodes.push_back(node_(nodeup_()));
+ expected.m_path.m_nodes.push_back(node_(module_{"example"}, container_("a")));
+ expected.m_path.m_nodes.push_back(node_(container_("a2")));
}
}
@@ -133,65 +150,124 @@
{
SECTION("missing space between a command and its arguments")
{
- SECTION("cda")
+ SECTION("cdexample:a")
{
- input = "cda";
+ input = "cdexample:a";
}
}
- SECTION("garbage arguments handling")
+
+ SECTION("whitespace between module and nodename")
{
- SECTION("cd a garbage")
+ SECTION("cd example: a")
{
- input = "cd a garbage";
- }
- SECTION("cd a/a2 garbage")
- {
- input = "cd a/a2 garbage";
- }
- }
- SECTION("invalid identifiers")
- {
- SECTION("nonexistent")
- {
- input = "cd nonexistent";
+ input = "cd example: a";
}
- SECTION("nonexistent/lol")
+ SECTION("cd example : a")
{
- input = "cd nonexistent/lol";
+ input = "cd example : a";
+ }
+
+ SECTION("cd example :a")
+ {
+ input = "cd example :a";
+ }
+ }
+
+ SECTION("entering modules")
+ {
+ SECTION("cd example")
+ {
+ input = "cd example";
+ }
+
+ SECTION("cd example:")
+ {
+ input = "cd example:";
+ }
+ }
+
+ SECTION("garbage arguments handling")
+ {
+ SECTION("cd example:a garbage")
+ {
+ input = "cd example:a garbage";
+ }
+ SECTION("cd example:a/a2 garbage")
+ {
+ input = "cd example:a/a2 garbage";
+ }
+ }
+
+ SECTION("invalid node identifiers")
+ {
+ SECTION("example:nonexistent")
+ {
+ input = "cd example:nonexistent";
+ }
+
+ SECTION("example:nonexistent/lol")
+ {
+ input = "cd example:nonexistent/lol";
+ }
+ }
+
+ SECTION("invalid module identifiers")
+ {
+ SECTION("elpmaxe:nonexistent")
+ {
+ input = "cd elpmaxe:nonexistent";
+ }
+
+ SECTION("elpmaxe:nonexistent/example:lol")
+ {
+ input = "cd elpmaxe:nonexistent/example:lol";
+ }
+ }
+
+ SECTION("no top-level module")
+ {
+ SECTION("cd a")
+ {
+ input = "cd a";
+ }
+
+ SECTION("cd example:a/../a")
+ {
+ input = "cd example:a/../a";
}
}
SECTION("invalid list key identifiers")
{
- SECTION("list")
+ SECTION("example:list")
{
- input = "cd list";
+ input = "cd example:list";
}
- SECTION("list[]")
+ SECTION("example:list[]")
{
- input = "cd list[]";
+ input = "cd example:list[]";
}
- SECTION("twoKeyList[invalidKey=4]")
+ SECTION("example:twoKeyList[invalidKey=4]")
{
- input = "cd twoKeyList[invalidKey=4]";
+ input = "cd example:twoKeyList[invalidKey=4]";
}
- SECTION("twoKeyList[number=4 number=5]")
+ SECTION("example:twoKeyList[number=4 number=5]")
{
- input = "cd twoKeyList[number=4 number=5]";
+ input = "cd example:twoKeyList[number=4 number=5]";
}
- SECTION("twoKeyList[number=4 name=lol number=7]")
+ SECTION("example:twoKeyList[number=4 name=lol number=7]")
{
- input = "cd twoKeyList[number=4 name=lol number=7]";
+ input = "cd example:twoKeyList[number=4 name=lol number=7]";
}
- SECTION("twoKeyList[number=4]")
+ SECTION("example:twoKeyList[number=4]")
{
- input = "cd twoKeyList[number=4]";
+ input = "cd example:twoKeyList[number=4]";
}
}
REQUIRE_THROWS(parser.parseCommand(input, errorStream));
diff --git a/tests/leaf_editing.cpp b/tests/leaf_editing.cpp
index b8c5591..d8f21db 100644
--- a/tests/leaf_editing.cpp
+++ b/tests/leaf_editing.cpp
@@ -14,16 +14,17 @@
TEST_CASE("leaf editing")
{
auto schema = std::make_shared<StaticSchema>();
- schema->addContainer("", "contA");
- schema->addLeaf("", "leafString", yang::LeafDataTypes::String);
- schema->addLeaf("", "leafDecimal", yang::LeafDataTypes::Decimal);
- schema->addLeaf("", "leafBool", yang::LeafDataTypes::Bool);
- schema->addLeaf("", "leafInt", yang::LeafDataTypes::Int);
- schema->addLeaf("", "leafUint", yang::LeafDataTypes::Uint);
- schema->addLeafEnum("", "leafEnum", {"lol", "data", "coze"});
- schema->addLeaf("contA", "leafInCont", yang::LeafDataTypes::String);
- schema->addList("", "list", {"number"});
- schema->addLeaf("list", "leafInList", yang::LeafDataTypes::String);
+ schema->addModule("mod");
+ schema->addContainer("", "mod:contA");
+ schema->addLeaf("", "mod:leafString", yang::LeafDataTypes::String);
+ schema->addLeaf("", "mod:leafDecimal", yang::LeafDataTypes::Decimal);
+ schema->addLeaf("", "mod:leafBool", yang::LeafDataTypes::Bool);
+ schema->addLeaf("", "mod:leafInt", yang::LeafDataTypes::Int);
+ schema->addLeaf("", "mod:leafUint", yang::LeafDataTypes::Uint);
+ schema->addLeafEnum("", "mod:leafEnum", {"lol", "data", "coze"});
+ schema->addLeaf("mod:contA", "mod:leafInCont", yang::LeafDataTypes::String);
+ schema->addList("", "mod:list", {"number"});
+ schema->addLeaf("mod:list", "mod:leafInList", yang::LeafDataTypes::String);
Parser parser(schema);
std::string input;
std::ostringstream errorStream;
@@ -34,26 +35,26 @@
SECTION("set leafString some_data")
{
- input = "set leafString some_data";
- expected.m_path.m_nodes.push_back(leaf_("leafString"));
+ input = "set mod:leafString some_data";
+ expected.m_path.m_nodes.push_back(node_{module_{"mod"}, leaf_("leafString")});
expected.m_data = std::string("some_data");
}
- SECTION("set contA/leafInCont more_data")
+ SECTION("set mod:contA/leafInCont more_data")
{
- input = "set contA/leafInCont more_data";
- expected.m_path.m_nodes.push_back(container_("contA"));
- expected.m_path.m_nodes.push_back(leaf_("leafInCont"));
+ input = "set mod:contA/leafInCont more_data";
+ expected.m_path.m_nodes.push_back(node_{module_{"mod"}, container_("contA")});
+ expected.m_path.m_nodes.push_back(node_{leaf_("leafInCont")});
expected.m_data = std::string("more_data");
}
SECTION("set list[number=1]/leafInList another_data")
{
- input = "set list[number=1]/leafInList another_data";
+ input = "set mod:list[number=1]/leafInList another_data";
auto keys = std::map<std::string, std::string>{
{"number", "1"}};
- expected.m_path.m_nodes.push_back(listElement_("list", keys));
- expected.m_path.m_nodes.push_back(leaf_("leafInList"));
+ expected.m_path.m_nodes.push_back(node_{module_{"mod"}, listElement_("list", keys)});
+ expected.m_path.m_nodes.push_back(node_{leaf_("leafInList")});
expected.m_data = std::string("another_data");
}
@@ -61,36 +62,36 @@
{
SECTION("string")
{
- input = "set leafString somedata";
- expected.m_path.m_nodes.push_back(leaf_("leafString"));
+ input = "set mod:leafString somedata";
+ expected.m_path.m_nodes.push_back(node_{module_{"mod"}, leaf_("leafString")});
expected.m_data = std::string("somedata");
}
SECTION("int")
{
- input = "set leafInt 2";
- expected.m_path.m_nodes.push_back(leaf_("leafInt"));
+ input = "set mod:leafInt 2";
+ expected.m_path.m_nodes.push_back(node_{module_{"mod"}, leaf_("leafInt")});
expected.m_data = 2;
}
SECTION("decimal")
{
- input = "set leafDecimal 3.14159";
- expected.m_path.m_nodes.push_back(leaf_("leafDecimal"));
+ input = "set mod:leafDecimal 3.14159";
+ expected.m_path.m_nodes.push_back(node_{module_{"mod"}, leaf_("leafDecimal")});
expected.m_data = 3.14159;
}
SECTION("enum")
{
- input = "set leafEnum coze";
- expected.m_path.m_nodes.push_back(leaf_("leafEnum"));
+ input = "set mod:leafEnum coze";
+ expected.m_path.m_nodes.push_back(node_{module_{"mod"}, leaf_("leafEnum")});
expected.m_data = enum_("coze");
}
SECTION("bool")
{
- input = "set leafBool true";
- expected.m_path.m_nodes.push_back(leaf_("leafBool"));
+ input = "set mod:leafBool true";
+ expected.m_path.m_nodes.push_back(node_{module_{"mod"}, leaf_("leafBool")});
expected.m_data = true;
}
}
diff --git a/tests/presence_containers.cpp b/tests/presence_containers.cpp
index 87957cb..9683daf 100644
--- a/tests/presence_containers.cpp
+++ b/tests/presence_containers.cpp
@@ -15,13 +15,14 @@
TEST_CASE("presence containers")
{
auto schema = std::make_shared<StaticSchema>();
- schema->addContainer("", "a", yang::ContainerTraits::Presence);
- schema->addContainer("", "b");
- schema->addContainer("a", "a2");
- schema->addContainer("a/a2", "a3", yang::ContainerTraits::Presence);
- schema->addContainer("b", "b2", yang::ContainerTraits::Presence);
- schema->addList("", "list", {"quote"});
- schema->addContainer("list", "contInList", yang::ContainerTraits::Presence);
+ schema->addModule("mod");
+ schema->addContainer("", "mod:a", yang::ContainerTraits::Presence);
+ schema->addContainer("", "mod:b");
+ schema->addContainer("mod:a", "mod:a2");
+ schema->addContainer("mod:a/mod:a2", "mod:a3", yang::ContainerTraits::Presence);
+ schema->addContainer("mod:b", "mod:b2", yang::ContainerTraits::Presence);
+ schema->addList("", "mod:list", {"quote"});
+ schema->addContainer("mod:list", "mod:contInList", yang::ContainerTraits::Presence);
Parser parser(schema);
std::string input;
std::ostringstream errorStream;
@@ -30,30 +31,30 @@
{
path_ expectedPath;
- SECTION("a")
+ SECTION("mod:a")
{
- input = "a";
- expectedPath.m_nodes = {container_("a")};
+ input = "mod:a";
+ expectedPath.m_nodes = {{module_{"mod"}, {container_("a")}}};
}
- SECTION("b/b2")
+ SECTION("mod:b/b2")
{
- input = "b/b2";
- expectedPath.m_nodes = {container_("b"), container_("b2")};
+ input = "mod:b/b2";
+ expectedPath.m_nodes = {{{module_{"mod"}}, container_("b")}, {container_("b2")}};
}
- SECTION("a/a2/a3")
+ SECTION("mod:a/a2/a3")
{
- input = "a/a2/a3";
- expectedPath.m_nodes = {container_("a"), container_("a2"), container_("a3")};
+ input = "mod:a/a2/a3";
+ expectedPath.m_nodes = {{{module_{"mod"}}, container_("a")}, {container_("a2")}, {container_("a3")}};
}
- SECTION("list[quote=lol]/contInList")
+ SECTION("mod:list[quote=lol]/contInList")
{
- input = "list[quote=lol]/contInList";
+ input = "mod:list[quote=lol]/contInList";
auto keys = std::map<std::string, std::string>{
{"quote", "lol"}};
- expectedPath.m_nodes = {listElement_("list", keys), container_("contInList")};
+ expectedPath.m_nodes = {{{module_{"mod"}}, listElement_("list", keys)}, {container_("contInList")}};
}
create_ expectedCreate;