Fix `prepare`
The parsing algorithm was broken and prepare couldn't recognize RPC
nodes. The mistake probably happened when I added Action support, but
with no tests. Tests are now included.
Change-Id: I1b4eb2eb76a30c4495e2aacbb6848f449eba3abb
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3ecbe0b..a1f027c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -287,6 +287,7 @@
cli_test(path_utils)
target_link_libraries(test_path_utils path)
cli_test(keyvalue_completion)
+ cli_test(prepare)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tests/init_datastore.bash.in
${CMAKE_CURRENT_BINARY_DIR}/init_datastore.bash @ONLY)
diff --git a/src/ast_commands.cpp b/src/ast_commands.cpp
index 425249e..5b99c6a 100644
--- a/src/ast_commands.cpp
+++ b/src/ast_commands.cpp
@@ -46,3 +46,8 @@
{
return this->m_format == other.m_format;
}
+
+bool prepare_::operator==(const prepare_& other) const
+{
+ return this->m_path == other.m_path;
+}
diff --git a/src/path_parser.hpp b/src/path_parser.hpp
index e1982f5..3abbce3 100644
--- a/src/path_parser.hpp
+++ b/src/path_parser.hpp
@@ -441,7 +441,7 @@
}
if (attr.m_nodes.empty()
- || (!std::holds_alternative<actionNode_>(attr.m_nodes.back().m_suffix) && !std::holds_alternative<actionNode_>(attr.m_nodes.back().m_suffix))) {
+ || (!std::holds_alternative<rpcNode_>(attr.m_nodes.back().m_suffix) && !std::holds_alternative<actionNode_>(attr.m_nodes.back().m_suffix))) {
auto& parserContext = x3::get<parser_context_tag>(ctx);
parserContext.m_errorMsg = "This is not a path to an RPC/action.";
return false;
diff --git a/src/static_schema.cpp b/src/static_schema.cpp
index e54ca68..af1004a 100644
--- a/src/static_schema.cpp
+++ b/src/static_schema.cpp
@@ -43,6 +43,15 @@
m_nodes.emplace(key, std::unordered_map<std::string, NodeInfo>());
}
+void StaticSchema::addAction(const std::string& location, const std::string& name)
+{
+ m_nodes.at(location).emplace(name, NodeInfo{yang::action{}, yang::AccessType::Writable});
+
+ //create a new set of children for the new node
+ std::string key = joinPaths(location, name);
+ m_nodes.emplace(key, std::unordered_map<std::string, NodeInfo>());
+}
+
bool StaticSchema::listHasKey(const schemaPath_& listPath, const std::string& key) const
{
return listKeys(listPath).count(key);
@@ -215,6 +224,11 @@
{
return yang::NodeTypes::Rpc;
}
+
+ yang::NodeTypes operator()(const yang::action)
+ {
+ return yang::NodeTypes::Action;
+ }
};
yang::NodeTypes StaticSchema::nodeType(const schemaPath_& location, const ModuleNodePair& node) const
diff --git a/src/static_schema.hpp b/src/static_schema.hpp
index e343087..3009d7e 100644
--- a/src/static_schema.hpp
+++ b/src/static_schema.hpp
@@ -37,6 +37,9 @@
struct rpc {
};
+struct action {
+};
+
struct module {
};
@@ -46,7 +49,7 @@
};
}
-using NodeType = std::variant<yang::container, yang::list, yang::leaf, yang::leaflist, yang::rpc>;
+using NodeType = std::variant<yang::container, yang::list, yang::leaf, yang::leaflist, yang::rpc, yang::action>;
struct NodeInfo {
NodeType m_nodeType;
@@ -87,6 +90,7 @@
void addLeafList(const std::string& location, const std::string& name, const yang::LeafDataType& type);
void addList(const std::string& location, const std::string& name, const std::set<std::string>& keys);
void addRpc(const std::string& location, const std::string& name);
+ void addAction(const std::string& location, const std::string& name);
void addModule(const std::string& name);
void addIdentity(const std::optional<identityRef_>& base, const identityRef_& name);
diff --git a/tests/prepare.cpp b/tests/prepare.cpp
new file mode 100644
index 0000000..139ef4b
--- /dev/null
+++ b/tests/prepare.cpp
@@ -0,0 +1,45 @@
+
+/*
+ * 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_doctest.hpp"
+#include "parser.hpp"
+#include "pretty_printers.hpp"
+#include "static_schema.hpp"
+
+TEST_CASE("prepare command")
+{
+ auto schema = std::make_shared<StaticSchema>();
+ schema->addModule("example");
+ schema->addRpc("/", "example:fire");
+ schema->addList("/", "example:port", {"name"});
+ schema->addLeaf("/example:port", "example:name", yang::String{});
+ schema->addAction("/example:port", "example:shutdown");
+ Parser parser(schema);
+ std::string input;
+ std::ostringstream errorStream;
+ prepare_ expected;
+ expected.m_path.m_scope = Scope::Relative;
+ SECTION("rpc")
+ {
+ input = "prepare example:fire";
+ expected.m_path.m_nodes.push_back({module_{"example"}, rpcNode_{"fire"}});
+ }
+
+ SECTION("action")
+ {
+ input = "prepare example:port[name='eth0']/shutdown";
+ expected.m_path.m_nodes.push_back({module_{"example"}, listElement_{"port", {{"name", std::string{"eth0"}}}}});
+ expected.m_path.m_nodes.push_back({actionNode_{"shutdown"}});
+ }
+
+ command_ command = parser.parseCommand(input, errorStream);
+ REQUIRE(command.type() == typeid(prepare_));
+ auto lol = boost::get<prepare_>(command);
+ REQUIRE(boost::get<prepare_>(command) == expected);
+}
diff --git a/tests/pretty_printers.hpp b/tests/pretty_printers.hpp
index ab6b917..b459a11 100644
--- a/tests/pretty_printers.hpp
+++ b/tests/pretty_printers.hpp
@@ -199,3 +199,8 @@
{
return s << "Command SET {path: " << pathToSchemaString(cmd.m_path, Prefixes::Always) << ", type " << boost::core::demangle(cmd.m_data.type().name()) << ", data: " << leafDataToString(cmd.m_data) << "}";
}
+
+std::ostream& operator<<(std::ostream& s, const prepare_ cmd)
+{
+ return s << "Command PREPARE {path: " << pathToDataString(cmd.m_path, Prefixes::Always) << "}";
+}