Disallow cd out of the prepare context

Issue: https://tree.taiga.io/project/jktjkt-netconf-cli/issue/202
Change-Id: I8e9772ebd1fa86469e2c497b9813686b3ff361d5
diff --git a/src/interpreter.cpp b/src/interpreter.cpp
index 43e2269..8030f3f 100644
--- a/src/interpreter.cpp
+++ b/src/interpreter.cpp
@@ -89,6 +89,9 @@
 
 void Interpreter::operator()(const cd_& cd) const
 {
+    if (auto rpcInputPath = m_datastore.inputDatastorePath(); rpcInputPath && !pathToDataString(cd.m_path, Prefixes::WhenNeeded).starts_with(m_parser.currentNode())) {
+        throw std::runtime_error("Can't cd out of `prepare` context");
+    }
     m_parser.changeNode(cd.m_path);
 }
 
diff --git a/tests/interpreter.cpp b/tests/interpreter.cpp
index 4ef0a96..ba35f89 100644
--- a/tests/interpreter.cpp
+++ b/tests/interpreter.cpp
@@ -452,6 +452,13 @@
 
         REQUIRE(parser.currentPath() == rpcPath);
 
+        SECTION("can't leave the context with cd")
+        {
+            REQUIRE_THROWS(boost::apply_visitor(Interpreter(parser, proxyDatastore), command_{cd_{{}, dataPath_{Scope::Absolute, {dataNode_{module_{{"example"}}, container_{"somewhereElse"}}}}}}));
+            REQUIRE_THROWS(boost::apply_visitor(Interpreter(parser, proxyDatastore), command_{cd_{{}, dataPath_{Scope::Relative, {dataNode_{nodeup_{}}}}}}));
+            boost::apply_visitor(Interpreter(parser, proxyDatastore), command_{cancel_{}});
+        }
+
         SECTION("exec")
         {
             REQUIRE_CALL(*input_datastore, getItems("/")).RETURN(DatastoreAccess::Tree{});