Add support for executing RPCs

Creating a temporary YangAccess for RPC input means I need to somehow
give the right libyang schemas. For that reason I supply a callable
which is able to fetch the schema and create a YangAccess instance for
ProxyDatastore.

The ProxyDatastore class now has a simple mechanism for deciding whether
to use the normal datastore and the temporary based on a path prefix.

Change-Id: Ib455f53237598bc2620161a44fb89c48ddfeb6e3
diff --git a/tests/path_completion.cpp b/tests/path_completion.cpp
index 249dc8c..1c0c8f1 100644
--- a/tests/path_completion.cpp
+++ b/tests/path_completion.cpp
@@ -39,6 +39,8 @@
     schema->addLeaf("/", "example:leafInt", yang::Int32{});
     schema->addLeaf("/", "example:readonly", yang::Int32{}, yang::AccessType::ReadOnly);
     schema->addLeafList("/", "example:addresses", yang::String{});
+    schema->addRpc("/", "second:fire");
+    schema->addLeaf("/second:fire", "second:whom", yang::String{});
     auto mockDatastore = std::make_shared<MockDatastoreAccess>();
 
     // The parser will use DataQuery for key value completion, but I'm not testing that here, so I don't return anything.
@@ -68,7 +70,7 @@
         SECTION("ls ")
         {
             input = "ls ";
-            expectedCompletions = {"example:addresses/", "example:ano/", "example:anoda/", "example:bota/", "example:leafInt ", "example:list/", "example:ovoce/", "example:readonly ", "example:ovocezelenina/", "example:twoKeyList/", "second:amelie/"};
+            expectedCompletions = {"example:addresses/", "example:ano/", "example:anoda/", "example:bota/", "example:leafInt ", "example:list/", "example:ovoce/", "example:readonly ", "example:ovocezelenina/", "example:twoKeyList/", "second:amelie/", "second:fire/"};
             expectedContextLength = 0;
         }
 
@@ -103,7 +105,7 @@
         SECTION("ls /")
         {
             input = "ls /";
-            expectedCompletions = {"example:addresses/", "example:ano/", "example:anoda/", "example:bota/", "example:leafInt ", "example:list/", "example:ovoce/", "example:readonly ", "example:ovocezelenina/", "example:twoKeyList/", "second:amelie/"};
+            expectedCompletions = {"example:addresses/", "example:ano/", "example:anoda/", "example:bota/", "example:leafInt ", "example:list/", "example:ovoce/", "example:readonly ", "example:ovocezelenina/", "example:twoKeyList/", "second:amelie/", "second:fire/"};
             expectedContextLength = 0;
         }
 
@@ -131,7 +133,7 @@
         SECTION("ls /s")
         {
             input = "ls /s";
-            expectedCompletions = {"second:amelie/"};
+            expectedCompletions = {"second:amelie/", "second:fire/"};
             expectedContextLength = 1;
         }
 
@@ -334,5 +336,28 @@
         expectedContextLength = 0;
     }
 
+    SECTION("rpc input nodes NOT completed for rpc command")
+    {
+        input = "rpc example:fire/";
+        expectedCompletions = {};
+        expectedContextLength = 13;
+    }
+
+    SECTION("rpc input nodes completed for set command")
+    {
+        parser.changeNode({{}, {{module_{"second"}, rpcNode_{"fire"}}}});
+        input = "set ";
+        expectedCompletions = {"whom "};
+        expectedContextLength = 0;
+    }
+
+    SECTION("completion for other stuff while inside an rpc")
+    {
+        parser.changeNode({{}, {{module_{"second"}, rpcNode_{"fire"}}}});
+        input = "set ../";
+        expectedCompletions = {"example:addresses", "example:ano/", "example:anoda/", "example:bota/", "example:leafInt ", "example:list", "example:ovoce", "example:ovocezelenina", "example:twoKeyList", "second:amelie/", "second:fire/"};
+        expectedContextLength = 0;
+    }
+
     REQUIRE(parser.completeCommand(input, errorStream) == (Completions{expectedCompletions, expectedContextLength}));
 }