Skip to content

Commit

Permalink
Wrap lyd_meta_is_internal to check if meta is internal
Browse files Browse the repository at this point in the history
There are some internal meta attributes that libyang uses for internal
stuff and they are ignored when printing the meta collections. One (and
now also the only) example of such node is yang:lyds_tree attribute.

It can be useful to check if the meta attribute is internal. For
instance, when we want to be sure that our parsed data did not contain
any meta attributes from user. However, sometimes, libyang silently
inserts these internal attributes while parsing.

We asked upstream if there could be a function that checks for us if the
attribute is internal and therefore we should ignore it. They kindly
provided us with such function (`lyd_meta_is_internal`) [1].

This commit wraps the function. Unfortunately, our Meta class does not
wrap lyd_meta, only copies data from the structure so we can't just call
this function when requested but we call it in Meta object construction
which creates a little overhead in both time and memory.

[1] CESNET/libyang@f77ca9c

Change-Id: Id772ded765569089525cf4fd5dba8a64efe87d02
  • Loading branch information
peckato1 committed Jun 3, 2024
1 parent d740b7c commit d8bf2a8
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ option(WITH_DOCS "Create and install internal documentation (needs Doxygen)" ${D
option(BUILD_SHARED_LIBS "By default, shared libs are enabled. Turn off for a static build." ON)

find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBYANG REQUIRED libyang>=3.0.1 IMPORTED_TARGET)
pkg_check_modules(LIBYANG REQUIRED libyang>=3.0.11 IMPORTED_TARGET)
set(LIBYANG_CPP_PKG_VERSION "2")

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
Expand Down
2 changes: 2 additions & 0 deletions include/libyang-cpp/DataNode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ class LIBYANG_CPP_EXPORT Meta {
std::string name() const;
std::string valueStr() const;
Module module() const;
bool isInternal() const;

private:
friend Iterator<Meta, IterationType::Meta>;
Expand All @@ -191,6 +192,7 @@ class LIBYANG_CPP_EXPORT Meta {
std::string m_name;
std::string m_value;
Module m_mod;
bool m_isInternal;
};


Expand Down
7 changes: 7 additions & 0 deletions src/DataNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,7 @@ Meta::Meta(lyd_meta* meta, std::shared_ptr<ly_ctx> ctx)
: m_name(meta->name)
, m_value(lyd_get_meta_value(meta))
, m_mod(meta->annotation->module, ctx)
, m_isInternal(lyd_meta_is_internal(meta))
{
}

Expand All @@ -999,6 +1000,12 @@ Module Meta::module() const
return m_mod;
}

/** @brief Checks if the meta attribute is considered internal for libyang, see `lyd_meta_is_internal` */
bool Meta::isInternal() const
{
return m_isInternal;
}

/**
* Creates a JSON attribute for an opaque data node.
* Wraps `lyd_new_attr`.
Expand Down
23 changes: 23 additions & 0 deletions tests/data_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1899,6 +1899,7 @@ TEST_CASE("Data Node manipulation")
}

auto meta = netconfDeletePresenceCont.meta();
REQUIRE(std::none_of(meta.begin(), meta.end(), [](const auto& meta) { return meta.isInternal(); }));
std::transform(meta.begin(), meta.end(), std::back_inserter(actual), [] (const auto& it) { return std::pair{it.name(), it.valueStr()}; });
REQUIRE(actual == expected);
}
Expand Down Expand Up @@ -1976,6 +1977,28 @@ TEST_CASE("Data Node manipulation")
REQUIRE(*out->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings) == expectedJson);
REQUIRE(*out->printStr(libyang::DataFormat::XML, libyang::PrintFlags::WithSiblings) == expectedXml);
}

DOCTEST_SUBCASE("libyang internal metadata")
{
/*
* - currently, libyang creates an internal meta node yang:lyds_tree representing a RB-tree for ordering of data in lists
* - this test depends on internal libyang implementation which can of course change anytime
* - but it seems that yang:lyds_tree can't be created manually (there is no valid value for it?) and I don't know how to test this otherwise
*/
DOCTEST_SUBCASE("leaf-list ordered by system")
{
auto node = ctx.parseData(R"({"example-schema3:valuesOrderedBySystem": [1,2,3]})"s, libyang::DataFormat::JSON, libyang::ParseOptions::Strict | libyang::ParseOptions::NoState | libyang::ParseOptions::ParseOnly);
const auto metaColl = node->meta();
REQUIRE(std::find_if(metaColl.begin(), metaColl.end(), [](const auto& meta) { return meta.isInternal(); }) != metaColl.end());
}

DOCTEST_SUBCASE("leaf-list ordered by user")
{
auto node = ctx.parseData(R"({"example-schema3:values": [1,2,3]})"s, libyang::DataFormat::JSON, libyang::ParseOptions::Strict | libyang::ParseOptions::NoState | libyang::ParseOptions::ParseOnly);
const auto metaColl = node->meta();
REQUIRE(std::find_if(metaColl.begin(), metaColl.end(), [](const auto& meta) { return meta.isInternal(); }) == metaColl.end());
}
}
}

DOCTEST_SUBCASE("Extension nodes")
Expand Down
4 changes: 4 additions & 0 deletions tests/example_schema.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,10 @@ module example-schema3 {
type int32;
}
leaf-list valuesOrderedBySystem {
type int32;
}
list person {
key 'name';
leaf name {
Expand Down

0 comments on commit d8bf2a8

Please sign in to comment.