Skip to content

Commit

Permalink
do not throw when inspecting more complex union types
Browse files Browse the repository at this point in the history
Bug: CESNET/netconf-cli#20
Reported-by: Michal Hažlinský <michal.hazlinsky@cesnet.cz>
Change-Id: I21e5939c23dd82870bba8af7ca26d0db32339470
  • Loading branch information
jktjkt committed Jan 22, 2024
1 parent 1af87af commit 5884eea
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 7 deletions.
16 changes: 10 additions & 6 deletions src/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,20 +311,24 @@ bool InstanceIdentifier::requireInstance() const
/**
* @brief Returns the types contained within this union.
*
* Due to the libyang limitations, the returned types might not contain any parsed-type representation, and therefore
* even calling types::Type::name() on it could fail (possibly with a misleading exception
* "Context not created with libyang::ContextOptions::SetPrivParsed" even when the context *was* created with this
* option).
*
* Wraps `lysc_type_union::types`
*/
std::vector<Type> Union::types() const
{
auto types = reinterpret_cast<const lysc_type_union*>(m_type)->types;
std::vector<Type> res;
if (m_typeParsed && LY_ARRAY_COUNT(types) != LY_ARRAY_COUNT(m_typeParsed->types)) {
throw std::logic_error("libyang-cpp internal error: LY_ARRAY_COUNT(lysc_type_union->types) = "
+ std::to_string(LY_ARRAY_COUNT(types)) + ", LY_ARRAY_COUNT(lysp_type->types) = "
+ std::to_string(LY_ARRAY_COUNT(m_typeParsed->types)) + ", lysp_type->name = " + m_typeParsed->name);
}

for (size_t i = 0; i < LY_ARRAY_COUNT(types); i++) {
auto typeParsed = m_typeParsed ? &m_typeParsed->types[i] : nullptr;
// Some non-trivial union types, such as inet::host, have a different number of `lysc_type_union::types`
// vs. `lysp_type::types`. When that happens, then there's absolutely nothing that we can do; the parsed type
// info just isn't available anywhere with the current libyang.
auto typeParsed = m_typeParsed && LY_ARRAY_COUNT(types) == LY_ARRAY_COUNT(m_typeParsed->types) ?
&m_typeParsed->types[i] : nullptr;
res.emplace_back(Type{types[i], typeParsed, m_ctx});
}

Expand Down
21 changes: 20 additions & 1 deletion tests/schema_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ TEST_CASE("SchemaNode")
REQUIRE(typeWithParsed.base() == libyang::LeafBaseType::String);
}

DOCTEST_SUBCASE("union")
DOCTEST_SUBCASE("simple union")
{
auto types = ctx->findPath("/type_module:leafUnion").asLeaf().valueType().asUnion().types();
REQUIRE(types.at(0).base() == libyang::LeafBaseType::String);
Expand All @@ -525,6 +525,25 @@ TEST_CASE("SchemaNode")
REQUIRE(typesWithParsed.at(1).name() == "int32");
REQUIRE(typesWithParsed.at(2).name() == "boolean");
}

DOCTEST_SUBCASE("inet::host union")
{
ctx->parseModule(with_inet_types_module, libyang::SchemaFormat::YANG);
auto types = ctx->findPath("/with-inet-types:hostname").asLeaf().valueType().asUnion().types();
REQUIRE(types.size() == 3);
REQUIRE(types.at(0).base() == libyang::LeafBaseType::String);
REQUIRE(types.at(1).base() == libyang::LeafBaseType::String);
REQUIRE(types.at(2).base() == libyang::LeafBaseType::String);

ctxWithParsed->parseModule(with_inet_types_module, libyang::SchemaFormat::YANG);
auto typesWithParsed = ctxWithParsed->findPath("/with-inet-types:hostname").asLeaf().valueType().asUnion().types();
REQUIRE(typesWithParsed.size() == 3);
REQUIRE(typesWithParsed.at(0).base() == libyang::LeafBaseType::String);
REQUIRE(typesWithParsed.at(1).base() == libyang::LeafBaseType::String);
REQUIRE(typesWithParsed.at(2).base() == libyang::LeafBaseType::String);
// in libyang::types::Union::types() there are no types in the lysp_type::types`
REQUIRE_THROWS_AS(typesWithParsed.at(0).name(), libyang::ParsedInfoUnavailable);
}
}

DOCTEST_SUBCASE("Leaf::units")
Expand Down

0 comments on commit 5884eea

Please sign in to comment.