Migrate to libyang2

libnetconf2: getSchema and getConfig were no longer used in netconf-cli,
so I deleted them. They can get readded once the bindings get split into
a separate project.

sysrepo_access: Some sr_val stuff was removed.

YangSchema: type descriptions are not available
            availableNodes returns only input nodes for RPC nodes
            impl_getSchemaNode: no longer disables error printing

libyang: No longer supports leafrefs without the leaf it points to.

Depends-on: https://cesnet-gerrit-czechlight/c/CzechLight/dependencies/+/5171
Depends-on: https://gerrit.cesnet.cz/c/CzechLight/dependencies/+/5171
Change-Id: Ie49381a003a61a7bb028be7b2fa1d9d926ac4e58
diff --git a/tests/mock/sysrepo_subscription.cpp b/tests/mock/sysrepo_subscription.cpp
index 8faffa5..d4827bb 100644
--- a/tests/mock/sysrepo_subscription.cpp
+++ b/tests/mock/sysrepo_subscription.cpp
@@ -21,29 +21,44 @@
     {
     }
 
-    int operator()(
-        sysrepo::S_Session sess,
-        [[maybe_unused]] const char* module_name,
-        [[maybe_unused]] const char* xpath,
-        [[maybe_unused]] sr_event_t event,
-        [[maybe_unused]] uint32_t request_id)
+    sysrepo::ErrorCode operator()(
+        sysrepo::Session sess,
+        uint32_t /* sub_id */,
+        std::string_view module_name,
+        std::optional<std::string_view> /* sub_xpath */,
+        sysrepo::Event event,
+        uint32_t /* request_id */)
     {
         using namespace std::string_literals;
-        if (event == SR_EV_CHANGE) {
-            return SR_ERR_OK;
+        if (event == sysrepo::Event::Change) {
+            return sysrepo::ErrorCode::Ok;
         }
 
-        auto it = sess->get_changes_iter(("/"s + module_name + ":*//.").c_str());
+        for (const auto& it : sess.getChanges(("/"s + module_name.data() + ":*//.").c_str())) {
+            auto xpath = it.node.path();
+            std::optional<std::string> oldValue;
+            std::optional<std::string> newValue;
+            if (it.operation == sysrepo::ChangeOperation::Deleted) {
+                oldValue = it.node.schema().nodeType() == libyang::NodeType::Leaf || it.node.schema().nodeType() == libyang::NodeType::Leaflist ?
+                    std::optional<std::string>{it.node.asTerm().valueStr()} :
+                    std::nullopt;
+            } else {
+                oldValue = std::optional<std::string>{it.previousValue};
+                newValue = it.node.schema().nodeType() == libyang::NodeType::Leaf || it.node.schema().nodeType() == libyang::NodeType::Leaflist ?
+                    std::optional<std::string>{it.node.asTerm().valueStr()} :
+                    std::nullopt;
 
-        while (auto change = sess->get_change_next(it)) {
-            auto xpath = (change->new_val() ? change->new_val() : change->old_val())->xpath();
+            }
+            std::optional<std::string> previousList;
 
-            auto oldValue = change->old_val() ? std::optional{change->old_val()->val_to_string()} : std::nullopt;
-            auto newValue = change->new_val() ? std::optional{change->new_val()->val_to_string()} : std::nullopt;
-            m_recorder->write(xpath, oldValue, newValue);
+            if (it.previousList) {
+                previousList = std::string{*it.previousList};
+            }
+
+            m_recorder->write(it.operation, std::string{xpath}, oldValue, newValue, previousList);
         }
 
-        return SR_ERR_OK;
+        return sysrepo::ErrorCode::Ok;
     }
 
 private:
@@ -55,111 +70,39 @@
 
 DataSupplier::~DataSupplier() = default;
 
-SysrepoSubscription::SysrepoSubscription(const std::string& moduleName, Recorder* rec, sr_datastore_t ds)
-    : m_connection(std::make_shared<sysrepo::Connection>())
+SysrepoSubscription::SysrepoSubscription(const std::string& moduleName, Recorder* rec, sysrepo::Datastore ds)
+    : m_subscription([&moduleName, &rec, ds] { // This is an immediately invoked lambda.
+        return sysrepo::Connection{}.sessionStart(ds).onModuleChange(moduleName.c_str(),
+                rec ? sysrepo::ModuleChangeCb{MyCallback{moduleName, rec}}
+                : sysrepo::ModuleChangeCb{[](auto, auto, auto, auto, auto, auto) { return sysrepo::ErrorCode::Ok; }});
+    }())
 {
-    m_session = std::make_shared<sysrepo::Session>(m_connection, ds);
-    m_subscription = std::make_shared<sysrepo::Subscribe>(m_session);
-    sysrepo::ModuleChangeCb cb;
-    if (rec) {
-        cb = MyCallback{moduleName, rec};
-    } else {
-        cb = [](auto, auto, auto, auto, auto) { return SR_ERR_OK; };
-    }
-
-    m_subscription->module_change_subscribe(moduleName.c_str(), cb);
 }
 
-
-struct leafDataToSysrepoVal {
-    leafDataToSysrepoVal(sysrepo::S_Val v, const std::string& xpath)
-        : v(v)
-        , xpath(xpath)
-    {
-    }
-
-    void operator()(const binary_& what)
-    {
-        v->set(xpath.c_str(), what.m_value.c_str(), SR_BINARY_T);
-    }
-
-    void operator()(const enum_& what)
-    {
-        v->set(xpath.c_str(), what.m_value.c_str(), SR_ENUM_T);
-    }
-
-    void operator()(const identityRef_& what)
-    {
-        v->set(xpath.c_str(), (what.m_prefix->m_name + what.m_value).c_str(), SR_IDENTITYREF_T);
-    }
-
-    void operator()(const empty_)
-    {
-        v->set(xpath.c_str(), nullptr, SR_LEAF_EMPTY_T);
-    }
-
-    void operator()(const std::string& what)
-    {
-        v->set(xpath.c_str(), what.c_str());
-    }
-
-    void operator()(const bits_& what)
-    {
-        std::stringstream ss;
-        std::copy(what.m_bits.begin(), what.m_bits.end(), std::experimental::make_ostream_joiner(ss, " "));
-        v->set(xpath.c_str(), ss.str().c_str());
-    }
-
-    template <typename Type>
-    void operator()(const Type what)
-    {
-        v->set(xpath.c_str(), what);
-    }
-
-    void operator()([[maybe_unused]] const special_ what)
-    {
-        throw std::logic_error("Attempted to create a SR val from a special_ value");
-    }
-
-    ::sysrepo::S_Val v;
-    std::string xpath;
-};
-
 class OperationalDataCallback {
 public:
     OperationalDataCallback(const DataSupplier& dataSupplier)
         : m_dataSupplier(dataSupplier)
     {
     }
-    int operator()(
-        [[maybe_unused]] sysrepo::S_Session sess,
-        [[maybe_unused]] const char* module_name,
-        const char* path,
-        [[maybe_unused]] const char* request_xpath,
-        [[maybe_unused]] uint32_t request_id,
-        libyang::S_Data_Node& parent)
+    sysrepo::ErrorCode operator()(
+            sysrepo::Session session,
+            [[maybe_unused]] uint32_t subscriptionId,
+            [[maybe_unused]] std::string_view moduleName,
+            std::optional<std::string_view> subXPath,
+            [[maybe_unused]] std::optional<std::string_view> requestXPath,
+            [[maybe_unused]] uint32_t requestId,
+            std::optional<libyang::DataNode>& output)
     {
-        auto data = m_dataSupplier.get_data(path);
-        libyang::S_Data_Node res;
+        auto data = m_dataSupplier.get_data(subXPath->data());
         for (const auto& [p, v] : data) {
-            if (!res) {
-                res = std::make_shared<libyang::Data_Node>(
-                    sess->get_context(),
-                    p.c_str(),
-                    v.type() == typeid(empty_) ? nullptr : leafDataToString(v).c_str(),
-                    LYD_ANYDATA_CONSTSTRING,
-                    0);
+            if (!output) {
+                output = session.getContext().newPath(p.c_str(), v.type() == typeid(empty_) ? nullptr : leafDataToString(v).c_str());
             } else {
-                res->new_path(
-                    sess->get_context(),
-                    p.c_str(),
-                    v.type() == typeid(empty_) ? nullptr : leafDataToString(v).c_str(),
-                    LYD_ANYDATA_CONSTSTRING,
-                    0);
+                output->newPath(p.c_str(), v.type() == typeid(empty_) ? nullptr : leafDataToString(v).c_str());
             }
         }
-        parent = res;
-        return SR_ERR_OK;
+        return sysrepo::ErrorCode::Ok;
     }
 
 private:
@@ -167,9 +110,6 @@
 };
 
 OperationalDataSubscription::OperationalDataSubscription(const std::string& moduleName, const std::string& path, const DataSupplier& dataSupplier)
-    : m_connection(std::make_shared<sysrepo::Connection>())
-    , m_session(std::make_shared<sysrepo::Session>(m_connection))
-    , m_subscription(std::make_shared<sysrepo::Subscribe>(m_session))
+    : m_subscription(sysrepo::Connection{}.sessionStart().onOperGet(moduleName.c_str(), OperationalDataCallback{dataSupplier}, path.c_str()))
 {
-    m_subscription->oper_get_items_subscribe(moduleName.c_str(), OperationalDataCallback{dataSupplier}, path.c_str());
 }
diff --git a/tests/mock/sysrepo_subscription.hpp b/tests/mock/sysrepo_subscription.hpp
index fc2e499..85d048d 100644
--- a/tests/mock/sysrepo_subscription.hpp
+++ b/tests/mock/sysrepo_subscription.hpp
@@ -10,21 +10,15 @@
 
 #include <memory>
 #include <optional>
-#include <sysrepo-cpp/Session.hpp>
+#include <sysrepo-cpp/Connection.hpp>
 #include "datastore_access.hpp"
 
-namespace sysrepo {
-class Callback;
-class Connection;
-class Session;
-class Subscribe;
-}
 class YangSchema;
 
 class Recorder {
 public:
     virtual ~Recorder();
-    virtual void write(const std::string& xpath, const std::optional<std::string>& oldValue, const std::optional<std::string>& newValue) = 0;
+    virtual void write(const sysrepo::ChangeOperation operation, const std::string& xpath, const std::optional<std::string>& oldValue, const std::optional<std::string>& newValue, const std::optional<std::string> previousList) = 0;
 };
 
 class DataSupplier {
@@ -36,13 +30,10 @@
 
 class SysrepoSubscription {
 public:
-    SysrepoSubscription(const std::string& moduleName, Recorder* rec = nullptr, sr_datastore_t ds = SR_DS_RUNNING);
+    SysrepoSubscription(const std::string& moduleName, Recorder* rec = nullptr, sysrepo::Datastore ds = sysrepo::Datastore::Running);
 
 private:
-    std::shared_ptr<sysrepo::Connection> m_connection;
-    std::shared_ptr<sysrepo::Session> m_session;
-    std::shared_ptr<YangSchema> m_schema;
-    std::shared_ptr<sysrepo::Subscribe> m_subscription;
+    sysrepo::Subscription m_subscription;
 };
 
 class OperationalDataSubscription {
@@ -50,8 +41,6 @@
     OperationalDataSubscription(const std::string& moduleName, const std::string& path, const DataSupplier& dataSupplier);
 
 private:
-    std::shared_ptr<sysrepo::Connection> m_connection;
-    std::shared_ptr<sysrepo::Session> m_session;
     std::shared_ptr<YangSchema> m_schema;
-    std::shared_ptr<sysrepo::Subscribe> m_subscription;
+    sysrepo::Subscription m_subscription;
 };