tests: check what happens when deleting "wrong nodes"

There are two kinds of "wrong nodes", either XPaths which are wrong on
the schema level, i.e., referring to non-existing schema nodes, or
XPaths that use wrong list/leaf-list keys. Let's test both. The behavior
is different between sysrepo ("just give me your garbage, I'll silently
do a no-op on them") and Netopeer2 ("err: there's no such item"), so we
got uber-creative this Friday and reached the constexpr nirvana. I
insisted on this.

Change-Id: If771f859fd0a6463fe877cbb3f03160b8d871c67
Co-authored-by: Václav Kubernát <kubernat@cesnet.cz>
diff --git a/tests/datastore_access.cpp b/tests/datastore_access.cpp
index a9dfbfc..e9030db 100644
--- a/tests/datastore_access.cpp
+++ b/tests/datastore_access.cpp
@@ -10,8 +10,12 @@
 #include <sysrepo-cpp/Session.hpp>
 
 #ifdef sysrepo_BACKEND
+#define THROWS_ON_INVALID_SCHEMA_PATHS 0
+#define THROWS_ON_NONEXISTING_KEYS 0
 #include "sysrepo_access.hpp"
 #elif defined(netconf_BACKEND)
+#define THROWS_ON_INVALID_SCHEMA_PATHS 1
+#define THROWS_ON_NONEXISTING_KEYS 1
 #include "netconf_access.hpp"
 #include "netopeer_vars.hpp"
 #else
@@ -33,6 +37,14 @@
     IMPLEMENT_CONST_MOCK1(get_data);
 };
 
+template <int Flag, typename Callable> void tryThis(const Callable& what) {
+    if constexpr (Flag) {
+        REQUIRE_THROWS_AS(what(), std::runtime_error);
+    } else {
+        what();
+    }
+}
+
 TEST_CASE("setting/getting values")
 {
     trompeloeil::sequence seq1;
@@ -141,6 +153,22 @@
         }
     }
 
+    SECTION("deleting non-existing list keys")
+    {
+        tryThis<THROWS_ON_NONEXISTING_KEYS>([&]{
+            datastore.deleteListInstance("/example-schema:person[name='non existing']");
+            datastore.commitChanges();
+        });
+    }
+
+    SECTION("accessing non-existing schema nodes")
+    {
+        tryThis<THROWS_ON_INVALID_SCHEMA_PATHS>([&]{
+            datastore.deleteListInstance("/example-schema:non-existing-list[xxx='non existing']");
+            datastore.commitChanges();
+        });
+    }
+
     SECTION("leafref pointing to a key of a list")
     {
         {
@@ -284,6 +312,14 @@
         REQUIRE(datastore.getItems("/example-schema:pContainer") == expected);
     }
 
+    SECTION("non-existing persistent container schema node")
+    {
+        tryThis<THROWS_ON_INVALID_SCHEMA_PATHS>([&]{
+            datastore.deletePresenceContainer("/example-schema:non-existing-presence-container");
+            datastore.commitChanges();
+        });
+    }
+
     SECTION("nested presence container")
     {
         DatastoreAccess::Tree expected;
@@ -418,6 +454,22 @@
         REQUIRE(datastore.getItems("/example-schema:addresses") == expected);
     }
 
+    SECTION("non-existing leaf-list")
+    {
+        tryThis<THROWS_ON_NONEXISTING_KEYS>([&]{
+            datastore.deleteLeafListInstance("/example-schema:addresses[.='non-existing']");
+            datastore.commitChanges();
+        });
+    }
+
+    SECTION("non-existing leaf-list schema node")
+    {
+        tryThis<THROWS_ON_INVALID_SCHEMA_PATHS>([&]{
+            datastore.deleteLeafListInstance("/example-schema:non-existing[.='non-existing']");
+            datastore.commitChanges();
+        });
+    }
+
     SECTION("copying data from startup refreshes the data")
     {
         {