Merge DatastoreAccess executeRpc and executeAction

Sysrepo now uses the same method for rpc and action.

Change-Id: I3a8211b670189c9724d46d6235e5a68b3107c81a
diff --git a/src/datastore_access.hpp b/src/datastore_access.hpp
index 057c96a..b29e152 100644
--- a/src/datastore_access.hpp
+++ b/src/datastore_access.hpp
@@ -50,8 +50,7 @@
     virtual void createItem(const std::string& path) = 0;
     virtual void deleteItem(const std::string& path) = 0;
     virtual void moveItem(const std::string& path, std::variant<yang::move::Absolute, yang::move::Relative> move) = 0;
-    virtual Tree executeRpc(const std::string& path, const Tree& input) = 0;
-    virtual Tree executeAction(const std::string& path, const Tree& input) = 0;
+    virtual Tree execute(const std::string& path, const Tree& input) = 0;
 
     virtual std::shared_ptr<Schema> schema() = 0;
 
diff --git a/src/interpreter.cpp b/src/interpreter.cpp
index f1682bf..acb3f0b 100644
--- a/src/interpreter.cpp
+++ b/src/interpreter.cpp
@@ -216,11 +216,7 @@
 
 void Interpreter::operator()(const prepare_& prepare) const
 {
-    if (std::holds_alternative<rpcNode_>(prepare.m_path.m_nodes.back().m_suffix)) {
-        m_datastore.initiateRpc(pathToString(toCanonicalPath(prepare.m_path)));
-    } else {
-        m_datastore.initiateAction(pathToString(toCanonicalPath(prepare.m_path)));
-    }
+    m_datastore.initiate(pathToString(toCanonicalPath(prepare.m_path)));
     m_parser.changeNode(prepare.m_path);
 }
 
diff --git a/src/netconf_access.cpp b/src/netconf_access.cpp
index 1e56659..4ed29ae 100644
--- a/src/netconf_access.cpp
+++ b/src/netconf_access.cpp
@@ -132,7 +132,7 @@
     m_session->discard();
 }
 
-DatastoreAccess::Tree NetconfAccess::impl_execute(const std::string& path, const Tree& input)
+DatastoreAccess::Tree NetconfAccess::execute(const std::string& path, const Tree& input)
 {
     auto root = m_schema->dataNodeFromPath(path);
     for (const auto& [k, v] : input) {
@@ -149,16 +149,6 @@
     return res;
 }
 
-DatastoreAccess::Tree NetconfAccess::executeRpc(const std::string& path, const Tree& input)
-{
-    return impl_execute(path, input);
-}
-
-DatastoreAccess::Tree NetconfAccess::executeAction(const std::string& path, const Tree& input)
-{
-    return impl_execute(path, input);
-}
-
 NC_DATASTORE toNcDatastore(Datastore datastore)
 {
     switch (datastore) {
diff --git a/src/netconf_access.hpp b/src/netconf_access.hpp
index 45973a6..14288bc 100644
--- a/src/netconf_access.hpp
+++ b/src/netconf_access.hpp
@@ -47,8 +47,7 @@
     void moveItem(const std::string& path, std::variant<yang::move::Absolute, yang::move::Relative> move) override;
     void commitChanges() override;
     void discardChanges() override;
-    Tree executeRpc(const std::string& path, const Tree& input) override;
-    Tree executeAction(const std::string& path, const Tree& input) override;
+    Tree execute(const std::string& path, const Tree& input) override;
     void copyConfig(const Datastore source, const Datastore destination) override;
 
     std::shared_ptr<Schema> schema() override;
diff --git a/src/proxy_datastore.cpp b/src/proxy_datastore.cpp
index 113a923..ef3c5db 100644
--- a/src/proxy_datastore.cpp
+++ b/src/proxy_datastore.cpp
@@ -59,34 +59,14 @@
     return m_datastore->dump(format);
 }
 
-namespace {
-struct getInputPath {
-    template <typename InputType>
-    auto operator()(const InputType& input)
-    {
-        return input.m_path;
-    }
-};
-}
-
-void ProxyDatastore::initiateRpc(const std::string& rpcPath)
+void ProxyDatastore::initiate(const std::string& path)
 {
     if (m_inputDatastore) {
-        throw std::runtime_error("RPC/action input already in progress (" + std::visit(getInputPath{}, m_inputPath) + ")");
+        throw std::runtime_error("RPC/action input already in progress (" + m_inputPath + ")");
     }
     m_inputDatastore = m_createTemporaryDatastore(m_datastore);
-    m_inputPath = RpcInput{rpcPath};
-    m_inputDatastore->createItem(rpcPath);
-}
-
-void ProxyDatastore::initiateAction(const std::string& actionPath)
-{
-    if (m_inputDatastore) {
-        throw std::runtime_error("RPC/action input already in progress (" + std::visit(getInputPath{}, m_inputPath) + ")");
-    }
-    m_inputDatastore = m_createTemporaryDatastore(m_datastore);
-    m_inputPath = ActionInput{actionPath};
-    m_inputDatastore->createItem(actionPath);
+    m_inputPath = path;
+    m_inputDatastore->createItem(path);
 }
 
 DatastoreAccess::Tree ProxyDatastore::execute()
@@ -96,11 +76,7 @@
     }
     auto inputData = m_inputDatastore->getItems("/");
     m_inputDatastore = nullptr;
-    if (std::holds_alternative<RpcInput>(m_inputPath)) {
-        return m_datastore->executeRpc(std::visit(getInputPath{}, m_inputPath), inputData);
-    } else {
-        return m_datastore->executeAction(std::visit(getInputPath{}, m_inputPath), inputData);
-    }
+    return m_datastore->execute(m_inputPath, inputData);
 }
 
 void ProxyDatastore::cancel()
@@ -115,7 +91,7 @@
 
 std::shared_ptr<DatastoreAccess> ProxyDatastore::pickDatastore(const std::string& path) const
 {
-    if (!m_inputDatastore || !boost::starts_with(path, std::visit(getInputPath{}, m_inputPath))) {
+    if (!m_inputDatastore || !boost::starts_with(path, m_inputPath)) {
         return m_datastore;
     } else {
         return m_inputDatastore;
diff --git a/src/proxy_datastore.hpp b/src/proxy_datastore.hpp
index e7650cd..ab7e3a2 100644
--- a/src/proxy_datastore.hpp
+++ b/src/proxy_datastore.hpp
@@ -29,8 +29,7 @@
     void copyConfig(const Datastore source, const Datastore destination);
     [[nodiscard]] std::string dump(const DataFormat format) const;
 
-    void initiateRpc(const std::string& rpcPath);
-    void initiateAction(const std::string& actionPath);
+    void initiate(const std::string& path);
     [[nodiscard]] DatastoreAccess::Tree execute();
     void cancel();
 
@@ -48,14 +47,5 @@
     std::function<std::shared_ptr<DatastoreAccess>(const std::shared_ptr<DatastoreAccess>&)> m_createTemporaryDatastore;
     std::shared_ptr<DatastoreAccess> m_inputDatastore;
 
-    struct RpcInput {
-        std::string m_path;
-    };
-
-    struct ActionInput {
-        std::string m_path;
-    };
-    // This variant is needed, so that I know whether to call executeRpc or executeAction
-    // TODO: get rid of this variant with sysrepo2 because the method for RPC/action is the same there
-    std::variant<ActionInput, RpcInput> m_inputPath;
+    std::string m_inputPath;
 };
diff --git a/src/python_netconf.cpp b/src/python_netconf.cpp
index 7a0e4d3..c6e3c44 100644
--- a/src/python_netconf.cpp
+++ b/src/python_netconf.cpp
@@ -70,7 +70,7 @@
             .def("setLeaf", &NetconfAccess::setLeaf, "xpath"_a, "value"_a)
             .def("createItem", &NetconfAccess::createItem, "xpath"_a)
             .def("deleteItem", &NetconfAccess::deleteItem, "xpath"_a)
-            .def("executeRpc", &NetconfAccess::executeRpc, "rpc"_a, "input"_a=DatastoreAccess::Tree{})
+            .def("execute", &NetconfAccess::execute, "rpc"_a, "input"_a=DatastoreAccess::Tree{})
             .def("commitChanges", &NetconfAccess::commitChanges)
             ;
 }
diff --git a/src/sysrepo_access.cpp b/src/sysrepo_access.cpp
index 7c21cad..21eca7e 100644
--- a/src/sysrepo_access.cpp
+++ b/src/sysrepo_access.cpp
@@ -329,15 +329,7 @@
 }
 }
 
-// TODO: merge this with executeAction
-DatastoreAccess::Tree SysrepoAccess::executeRpc(const std::string& path, const Tree& input)
-{
-    auto srInput = toSrVals(path, input);
-    auto output = m_session->rpc_send(path.c_str(), srInput);
-    return toTree(path, output);
-}
-
-DatastoreAccess::Tree SysrepoAccess::executeAction(const std::string& path, const Tree& input)
+DatastoreAccess::Tree SysrepoAccess::execute(const std::string& path, const Tree& input)
 {
     auto srInput = toSrVals(path, input);
     auto output = m_session->rpc_send(path.c_str(), srInput);
diff --git a/src/sysrepo_access.hpp b/src/sysrepo_access.hpp
index d0ad869..55e8ac6 100644
--- a/src/sysrepo_access.hpp
+++ b/src/sysrepo_access.hpp
@@ -33,8 +33,7 @@
     void createItem(const std::string& path) override;
     void deleteItem(const std::string& path) override;
     void moveItem(const std::string& source, std::variant<yang::move::Absolute, yang::move::Relative> move) override;
-    Tree executeRpc(const std::string& path, const Tree& input) override;
-    Tree executeAction(const std::string& path, const Tree& input) override;
+    Tree execute(const std::string& path, const Tree& input) override;
 
     std::shared_ptr<Schema> schema() override;
 
diff --git a/src/yang_access.cpp b/src/yang_access.cpp
index a460150..7a43507 100644
--- a/src/yang_access.cpp
+++ b/src/yang_access.cpp
@@ -229,7 +229,7 @@
 {
 }
 
-[[noreturn]] void YangAccess::impl_execute(const std::string& type, const std::string& path, const Tree& input)
+[[noreturn]] DatastoreAccess::Tree YangAccess::execute(const std::string& path, const Tree& input)
 {
     auto root = lyWrap(lyd_new_path(nullptr, m_ctx.get(), path.c_str(), nullptr, LYD_ANYDATA_CONSTSTRING, 0));
     if (!root) {
@@ -244,17 +244,7 @@
             getErrorsAndThrow();
         }
     }
-    throw std::logic_error("in-memory datastore doesn't support executing " + type + "s");
-}
-
-DatastoreAccess::Tree YangAccess::executeRpc(const std::string& path, const Tree& input)
-{
-    impl_execute("RPC", path, input);
-}
-
-DatastoreAccess::Tree YangAccess::executeAction(const std::string& path, const Tree& input)
-{
-    impl_execute("action", path, input);
+    throw std::logic_error("in-memory datastore doesn't support executing RPC/action");
 }
 
 void YangAccess::copyConfig(const Datastore source, const Datastore dest)
diff --git a/src/yang_access.hpp b/src/yang_access.hpp
index 62c43d6..c009420 100644
--- a/src/yang_access.hpp
+++ b/src/yang_access.hpp
@@ -30,8 +30,7 @@
     void moveItem(const std::string& source, std::variant<yang::move::Absolute, yang::move::Relative> move) override;
     void commitChanges() override;
     void discardChanges() override;
-    Tree executeRpc(const std::string& path, const Tree& input) override;
-    Tree executeAction(const std::string& path, const Tree& input) override;
+    [[noreturn]] Tree execute(const std::string& path, const Tree& input) override;
     void copyConfig(const Datastore source, const Datastore destination) override;
 
     std::shared_ptr<Schema> schema() override;
diff --git a/tests/datastore_access.cpp b/tests/datastore_access.cpp
index 43d6038..ddfe288 100644
--- a/tests/datastore_access.cpp
+++ b/tests/datastore_access.cpp
@@ -951,7 +951,7 @@
             SECTION("noop")
             {
                 rpc = "/example-schema:noop";
-                proxyDatastore.initiateRpc(rpc);
+                proxyDatastore.initiate(rpc);
             }
 
             SECTION("small nuke")
@@ -961,7 +961,7 @@
                     {"description", "dummy"s},
                     {"payload/kilotons", uint64_t{333'666}},
                 };
-                proxyDatastore.initiateRpc(rpc);
+                proxyDatastore.initiate(rpc);
                 proxyDatastore.setLeaf("/example-schema:launch-nukes/example-schema:payload/example-schema:kilotons", uint64_t{333'666});
                 // no data are returned
             }
@@ -973,7 +973,7 @@
                     {"description", "dummy"s},
                     {"payload/kilotons", uint64_t{4}},
                 };
-                proxyDatastore.initiateRpc(rpc);
+                proxyDatastore.initiate(rpc);
                 proxyDatastore.setLeaf("/example-schema:launch-nukes/example-schema:payload/example-schema:kilotons", uint64_t{4});
 
                 output = {
@@ -989,7 +989,7 @@
                     {"payload/kilotons", uint64_t{6}},
                     {"cities/targets[city='Prague']/city", "Prague"s},
                 };
-                proxyDatastore.initiateRpc(rpc);
+                proxyDatastore.initiate(rpc);
                 proxyDatastore.setLeaf("/example-schema:launch-nukes/example-schema:payload/example-schema:kilotons", uint64_t{6});
                 proxyDatastore.createItem("/example-schema:launch-nukes/example-schema:cities/example-schema:targets[city='Prague']");
                 output = {
@@ -1012,17 +1012,17 @@
                 input = {
                     {"whom", "Colton"s}
                 };
-                proxyDatastore.initiateRpc(rpc);
+                proxyDatastore.initiate(rpc);
                 proxyDatastore.setLeaf("/example-schema:fire/example-schema:whom", "Colton"s);
             }
 
-            catching<OnExec>([&] { REQUIRE(datastore->executeRpc(rpc, input) == output); });
+            catching<OnExec>([&] { REQUIRE(datastore->execute(rpc, input) == output); });
             catching<OnExec>([&] { REQUIRE(proxyDatastore.execute() == output); });
         }
 
         SECTION("non-existing RPC")
         {
-            catching<OnInvalidRpcPath>([&] { datastore->executeRpc("/example-schema:non-existing", DatastoreAccess::Tree{}); });
+            catching<OnInvalidRpcPath>([&] { datastore->execute("/example-schema:non-existing", DatastoreAccess::Tree{}); });
         }
     }
 
@@ -1045,7 +1045,7 @@
             path = "/example-schema:ports[name='A']/shutdown";
         }
 
-        catching<OnExec>([&] { REQUIRE(datastore->executeAction(path, input) == output); });
+        catching<OnExec>([&] { REQUIRE(datastore->execute(path, input) == output); });
     }
 
     waitForCompletionAndBitMore(seq1);
diff --git a/tests/datastoreaccess_mock.hpp b/tests/datastoreaccess_mock.hpp
index 751cdad..e708149 100644
--- a/tests/datastoreaccess_mock.hpp
+++ b/tests/datastoreaccess_mock.hpp
@@ -24,8 +24,7 @@
     IMPLEMENT_MOCK1(createItem);
     IMPLEMENT_MOCK1(deleteItem);
     IMPLEMENT_MOCK2(moveItem);
-    IMPLEMENT_MOCK2(executeRpc);
-    IMPLEMENT_MOCK2(executeAction);
+    IMPLEMENT_MOCK2(execute);
 
     // Can't use IMPLEMENT_MOCK for private methods - IMPLEMENT_MOCK needs full visibility of the method
     MAKE_MOCK1(listInstances, std::vector<ListInstance>(const std::string&), override);
diff --git a/tests/interpreter.cpp b/tests/interpreter.cpp
index d57ad64..c6d7c9c 100644
--- a/tests/interpreter.cpp
+++ b/tests/interpreter.cpp
@@ -454,7 +454,7 @@
         SECTION("exec")
         {
             REQUIRE_CALL(*input_datastore, getItems("/")).RETURN(DatastoreAccess::Tree{});
-            REQUIRE_CALL(*datastore, executeRpc("/example:launch-nukes", DatastoreAccess::Tree{})).RETURN(DatastoreAccess::Tree{});
+            REQUIRE_CALL(*datastore, execute("/example:launch-nukes", DatastoreAccess::Tree{})).RETURN(DatastoreAccess::Tree{});
             boost::apply_visitor(Interpreter(parser, proxyDatastore), command_{exec_{}});
         }