From: Andrei Pavel Date: Mon, 7 Nov 2022 15:43:07 +0000 (+0200) Subject: [#2601] make Translator aware of all leaf base types X-Git-Tag: Kea-2.3.3~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=235f913e6472448bb8a3cd375549f19b0119014a;p=thirdparty%2Fkea.git [#2601] make Translator aware of all leaf base types Also add leafrefs and the empty leaf to the keatest-module. And add tests for those, and also unions, dec64, int64, uint64. --- diff --git a/doc/sphinx/arm/ext-netconf.rst b/doc/sphinx/arm/ext-netconf.rst index ac7256fb91..78096e0803 100644 --- a/doc/sphinx/arm/ext-netconf.rst +++ b/doc/sphinx/arm/ext-netconf.rst @@ -233,7 +233,7 @@ The installation should look similar to the following: $ ./src/share/yang/modules/utils/reinstall.sh [INF] Connection 2 created. [INF] Module "keatest-module" was installed. - [INF] File "keatest-module@2018-11-20.yang" was installed. + [INF] File "keatest-module@2022-11-30.yang" was installed. [INF] No datastore changes to apply. [INF] Connection 4 created. [ERR] Module "ietf-interfaces@2018-02-20" already installed. @@ -314,7 +314,7 @@ The list of currently installed YANG modules should be similar to this: kea-dhcp4-server | 2022-11-30 | I | user:user | 600 | | kea-dhcp6-server | 2022-11-30 | I | user:user | 600 | | kea-types | 2019-08-12 | I | user:user | 600 | | - keatest-module | 2018-11-20 | I | user:user | 600 | | + keatest-module | 2022-11-30 | I | user:user | 600 | | sysrepo-monitoring | 2022-04-08 | I | user:user | 600 | | sysrepo-plugind | 2022-03-10 | I | user:user | 644 | | yang | 2022-06-16 | I | user:user | 444 | | diff --git a/src/bin/netconf/tests/netconf_unittests.cc b/src/bin/netconf/tests/netconf_unittests.cc index cf7cd407bf..c6aa6b3ee4 100644 --- a/src/bin/netconf/tests/netconf_unittests.cc +++ b/src/bin/netconf/tests/netconf_unittests.cc @@ -493,7 +493,7 @@ TEST_F(NetconfAgentLogTest, logChanges) { addString("NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: " "created: /kea-dhcp4-server:config/subnet4[id='2']/id = 2"); addString("NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: " - "/kea-dhcp4-server:config/subnet4[id='2']/subnet = \"10.0.2.0/24\""); + "/kea-dhcp4-server:config/subnet4[id='2']/subnet = 10.0.2.0/24"); addString("NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: created: " "/kea-dhcp4-server:config/subnet4[id='2']/relay (container)"); @@ -557,7 +557,7 @@ TEST_F(NetconfAgentLogTest, logChanges2) { "deleted: /kea-dhcp4-server:config/subnet4[id='1']/id = 1"); addString( "NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: deleted: " - "/kea-dhcp4-server:config/subnet4[id='1']/subnet = \"10.0.1.0/24\""); + "/kea-dhcp4-server:config/subnet4[id='1']/subnet = 10.0.1.0/24"); addString( "NETCONF_CONFIG_CHANGED_DETAIL YANG configuration changed: deleted: " "/kea-dhcp4-server:config/subnet4[id='1']/relay (container)"); diff --git a/src/lib/yang/tests/translator_unittests.cc b/src/lib/yang/tests/translator_unittests.cc index f1de44c83f..a17b61cec2 100644 --- a/src/lib/yang/tests/translator_unittests.cc +++ b/src/lib/yang/tests/translator_unittests.cc @@ -71,6 +71,7 @@ TEST_F(TranslatorTest, getItem) { xpath = "/keatest-module:main/string"; value = "str"; EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); ASSERT_TRUE(elem); ASSERT_EQ(Element::string, elem->getType()); @@ -81,6 +82,7 @@ TEST_F(TranslatorTest, getItem) { xpath = "/keatest-module:main/boolean"; value = "true"; EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); ASSERT_TRUE(elem); ASSERT_EQ(Element::boolean, elem->getType()); @@ -92,6 +94,7 @@ TEST_F(TranslatorTest, getItem) { uint8_t u8(8); value = to_string(u8); EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); ASSERT_TRUE(elem); ASSERT_EQ(Element::integer, elem->getType()); @@ -103,6 +106,7 @@ TEST_F(TranslatorTest, getItem) { uint16_t u16(16); value = to_string(u16); EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); ASSERT_TRUE(elem); ASSERT_EQ(Element::integer, elem->getType()); @@ -114,17 +118,42 @@ TEST_F(TranslatorTest, getItem) { uint32_t u32(32); value = to_string(u32); EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); ASSERT_TRUE(elem); ASSERT_EQ(Element::integer, elem->getType()); EXPECT_EQ(32, elem->intValue()); elem.reset(); + // Unsigned 64 bit integer. + xpath = "/keatest-module:main/ui64"; + uint32_t u64(64); + value = to_string(u64); + EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); + EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); + ASSERT_TRUE(elem); + ASSERT_EQ(Element::integer, elem->getType()); + EXPECT_EQ(64, elem->intValue()); + elem.reset(); + + // Empty. + xpath = "/keatest-module:main/empty"; + value = string(); + EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); + EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); + ASSERT_TRUE(elem); + ASSERT_EQ(Element::string, elem->getType()); + EXPECT_EQ(string(), elem->stringValue()); + elem.reset(); + // Signed 8 bit integer. xpath = "/keatest-module:main/i8"; int8_t s8(8); value = to_string(s8); EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); ASSERT_TRUE(elem); ASSERT_EQ(Element::integer, elem->getType()); @@ -136,6 +165,7 @@ TEST_F(TranslatorTest, getItem) { int16_t s16(16); value = to_string(s16); EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); ASSERT_TRUE(elem); ASSERT_EQ(Element::integer, elem->getType()); @@ -147,16 +177,30 @@ TEST_F(TranslatorTest, getItem) { int32_t s32(32); value = to_string(s32); EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); ASSERT_TRUE(elem); ASSERT_EQ(Element::integer, elem->getType()); EXPECT_EQ(32, elem->intValue()); elem.reset(); + // Signed 64 bit integer. + xpath = "/keatest-module:main/i64"; + int32_t s64(64); + value = to_string(s64); + EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); + EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); + ASSERT_TRUE(elem); + ASSERT_EQ(Element::integer, elem->getType()); + EXPECT_EQ(64, elem->intValue()); + elem.reset(); + // Identity reference. xpath = "/keatest-module:main/id_ref"; value = "keatest-module:id_1"; EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); ASSERT_TRUE(elem); ASSERT_EQ(Element::string, elem->getType()); @@ -167,16 +211,29 @@ TEST_F(TranslatorTest, getItem) { xpath = "/keatest-module:main/enum"; value = "maybe"; EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); ASSERT_TRUE(elem); ASSERT_EQ(Element::string, elem->getType()); EXPECT_EQ("maybe", elem->stringValue()); elem.reset(); + // Bits. + xpath = "/keatest-module:main/options"; + value = "strict recursive logging"; + EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); + EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); + ASSERT_TRUE(elem); + ASSERT_EQ(Element::string, elem->getType()); + EXPECT_EQ("strict recursive logging", elem->stringValue()); + elem.reset(); + // Binary. xpath = "/keatest-module:main/raw"; value = "Zm9vYmFy"; EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); ASSERT_TRUE(elem); ASSERT_EQ(Element::string, elem->getType()); @@ -195,12 +252,15 @@ TEST_F(TranslatorTest, getItem) { u8 = 1; value = to_string(u8); EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); u8 = 2; value = to_string(u8); EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); u8 = 3; value = to_string(u8); EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); ASSERT_TRUE(elem); ASSERT_EQ(Element::list, elem->getType()); @@ -208,10 +268,74 @@ TEST_F(TranslatorTest, getItem) { EXPECT_EQ("[ 1, 2, 3 ]", elem->str()); elem.reset(); - // Unknown / unsupported. + // Instance identifier. + xpath = "/keatest-module:main/instance_id"; + value = "/keatest-module:main/numbers[.='1']"; + EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); + EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); + ASSERT_TRUE(elem); + ASSERT_EQ(Element::string, elem->getType()); + EXPECT_EQ(value, elem->stringValue()); + elem.reset(); + + // Union. + xpath = "/keatest-module:main/union"; + value = "8"; + EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); + EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); + ASSERT_TRUE(elem); + ASSERT_EQ(Element::string, elem->getType()); + EXPECT_EQ(value, elem->stringValue()); + elem.reset(); + value = "infinity"; + EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); + EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); + ASSERT_TRUE(elem); + ASSERT_EQ(Element::string, elem->getType()); + EXPECT_EQ(value, elem->stringValue()); + elem.reset(); + + // Leafref. + xpath = "/keatest-module:main/leafref-i8"; + value = "9"; + EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); + EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); + ASSERT_TRUE(elem); + ASSERT_EQ(Element::string, elem->getType()); + EXPECT_EQ(value, elem->stringValue()); + elem.reset(); + + // Leafref. + xpath = "/keatest-module:main/leafref-raw"; + value = "ff012345"; + EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); + EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); + ASSERT_TRUE(elem); + ASSERT_EQ(Element::string, elem->getType()); + EXPECT_EQ(value, elem->stringValue()); + elem.reset(); + + // Leafref. + xpath = "/keatest-module:main/leafref-string"; + value = "string through leafref"; + EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); + EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); + ASSERT_TRUE(elem); + ASSERT_EQ(Element::string, elem->getType()); + EXPECT_EQ(value, elem->stringValue()); + elem.reset(); + + // Decimal 64. xpath = "/keatest-module:main/dec64"; value = to_string(9.85); EXPECT_NO_THROW_LOG(sess.setItem(xpath, value)); + sess.applyChanges(); EXPECT_NO_THROW_LOG(elem = t_obj->getItemFromAbsoluteXpath(xpath)); ASSERT_TRUE(elem); ASSERT_EQ(Element::real, elem->getType()); @@ -285,6 +409,12 @@ TEST_F(TranslatorTest, valueTo) { EXPECT_EQ(elem->str(), value); elem.reset(); + // Unsigned 64 bit integer. + elem = Element::create(int64_t(1234567890123456)); + EXPECT_NO_THROW_LOG(value = Translator::translateToYang(elem, LeafBaseType::Uint64)); + EXPECT_EQ("1234567890123456", value); + elem.reset(); + // Signed 8 bit integer. elem = Element::create(-123); EXPECT_NO_THROW_LOG(value = Translator::translateToYang(elem, LeafBaseType::Int8)); @@ -303,6 +433,12 @@ TEST_F(TranslatorTest, valueTo) { EXPECT_EQ(elem->str(), value); elem.reset(); + // Signed 32 bit integer. + elem = Element::create(int64_t(-1234567890123456)); + EXPECT_NO_THROW_LOG(value = Translator::translateToYang(elem, LeafBaseType::Int64)); + EXPECT_EQ("-1234567890123456", value); + elem.reset(); + // Identity reference. elem = Element::create(str); EXPECT_NO_THROW_LOG(value = Translator::translateToYang(elem, LeafBaseType::IdentityRef)); @@ -317,11 +453,31 @@ TEST_F(TranslatorTest, valueTo) { EXPECT_NO_THROW_LOG(value = Translator::translateToYang(elem, LeafBaseType::Binary)); EXPECT_EQ("Zm9vYmFy", value); + // Bits. + elem = Element::create(string("foobar")); + EXPECT_NO_THROW_LOG(value = Translator::translateToYang(elem, LeafBaseType::Bits)); + EXPECT_EQ(elem->stringValue(), value); + // Decimal 64. double d64(.1234); elem = Element::create(d64); EXPECT_NO_THROW_LOG(value = Translator::translateToYang(elem, LeafBaseType::Dec64)); EXPECT_EQ(elem->str(), value); + + // Empty. + elem = Element::create(string()); + EXPECT_NO_THROW_LOG(value = Translator::translateToYang(elem, LeafBaseType::Empty)); + EXPECT_EQ(elem->stringValue(), value); + + // Leafref. + elem = Element::create(string("leafref")); + EXPECT_NO_THROW_LOG(value = Translator::translateToYang(elem, LeafBaseType::Leafref)); + EXPECT_EQ(elem->stringValue(), value); + + // Union. + elem = Element::create(string("union")); + EXPECT_NO_THROW_LOG(value = Translator::translateToYang(elem, LeafBaseType::Union)); + EXPECT_EQ(elem->stringValue(), value); } // Test JSON to basic YANG value conversion using sysrepo test models. @@ -391,6 +547,28 @@ TEST_F(TranslatorTest, setItem) { ASSERT_EQ(LeafBaseType::Uint32, data_node->schema().asLeaf().valueType().base()); EXPECT_EQ(elem->str(), string(data_node->asTerm().valueStr())); + // Unsigned 64 bit integer. + xpath = "/keatest-module:main/ui64"; + elem = Element::create(64); + EXPECT_NO_THROW_LOG(t_obj->setItem(xpath, elem, LeafBaseType::Uint64)); + EXPECT_NO_THROW_LOG(data_node = sess.getData(xpath)); + ASSERT_TRUE(data_node); + EXPECT_NO_THROW_LOG(data_node = data_node->findPath(xpath)); + ASSERT_TRUE(data_node); + ASSERT_EQ(LeafBaseType::Uint64, data_node->schema().asLeaf().valueType().base()); + EXPECT_EQ(elem->str(), string(data_node->asTerm().valueStr())); + + // Empty. + xpath = "/keatest-module:main/empty"; + elem = Element::create(string()); + EXPECT_NO_THROW_LOG(t_obj->setItem(xpath, elem, LeafBaseType::Empty)); + EXPECT_NO_THROW_LOG(data_node = sess.getData(xpath)); + ASSERT_TRUE(data_node); + EXPECT_NO_THROW_LOG(data_node = data_node->findPath(xpath)); + ASSERT_TRUE(data_node); + ASSERT_EQ(LeafBaseType::Empty, data_node->schema().asLeaf().valueType().base()); + EXPECT_EQ(elem->stringValue(), string(data_node->asTerm().valueStr())); + // Signed 8 bit integer. xpath = "/keatest-module:main/i8"; elem = Element::create(8); @@ -424,6 +602,17 @@ TEST_F(TranslatorTest, setItem) { ASSERT_EQ(LeafBaseType::Int32, data_node->schema().asLeaf().valueType().base()); EXPECT_EQ(elem->str(), string(data_node->asTerm().valueStr())); + // Signed 64 bit integer. + xpath = "/keatest-module:main/i64"; + elem = Element::create(64); + EXPECT_NO_THROW_LOG(t_obj->setItem(xpath, elem, LeafBaseType::Int64)); + EXPECT_NO_THROW_LOG(data_node = sess.getData(xpath)); + ASSERT_TRUE(data_node); + EXPECT_NO_THROW_LOG(data_node = data_node->findPath(xpath)); + ASSERT_TRUE(data_node); + ASSERT_EQ(LeafBaseType::Int64, data_node->schema().asLeaf().valueType().base()); + EXPECT_EQ(elem->str(), string(data_node->asTerm().valueStr())); + // Identity reference. xpath = "/keatest-module:main/id_ref"; elem = Element::create(string("keatest-module:id_1")); @@ -457,6 +646,17 @@ TEST_F(TranslatorTest, setItem) { ASSERT_EQ(LeafBaseType::Binary, data_node->schema().asLeaf().valueType().base()); EXPECT_EQ("Zm9vYmFy", string(data_node->asTerm().valueStr())); + // Bits. + xpath = "/keatest-module:main/options"; + elem = Element::create(string("strict recursive logging")); + EXPECT_NO_THROW_LOG(t_obj->setItem(xpath, elem, LeafBaseType::Bits)); + EXPECT_NO_THROW_LOG(data_node = sess.getData(xpath)); + ASSERT_TRUE(data_node); + EXPECT_NO_THROW_LOG(data_node = data_node->findPath(xpath)); + ASSERT_TRUE(data_node); + ASSERT_EQ(LeafBaseType::Bits, data_node->schema().asLeaf().valueType().base()); + EXPECT_EQ(elem->stringValue(), string(data_node->asTerm().valueStr())); + // Decimal 64. xpath = "/keatest-module:main/dec64"; double d64(9.85); @@ -478,12 +678,75 @@ TEST_F(TranslatorTest, setItem) { ASSERT_EQ(LeafBaseType::Dec64, data_node->schema().asLeaf().valueType().base()); EXPECT_EQ("[ 1, 2, 3 ]", got->str()); - // Clean it. + // Clean the leaf-list. EXPECT_NO_THROW_LOG(t_obj->deleteItem(xpath)); EXPECT_NO_THROW_LOG(data_node = sess.getData(xpath)); EXPECT_FALSE(data_node); data_node.reset(); + // Instance identifier. + xpath = "/keatest-module:main/instance_id"; + elem = Element::create(string("/keatest-module:main/numbers[.='1']")); + EXPECT_NO_THROW_LOG(t_obj->setItem(xpath, elem, LeafBaseType::InstanceIdentifier)); + EXPECT_NO_THROW_LOG(data_node = sess.getData(xpath)); + ASSERT_TRUE(data_node); + EXPECT_NO_THROW_LOG(data_node = data_node->findPath(xpath)); + ASSERT_TRUE(data_node); + ASSERT_EQ(LeafBaseType::InstanceIdentifier, data_node->schema().asLeaf().valueType().base()); + EXPECT_EQ(elem->stringValue(), string(data_node->asTerm().valueStr())); + + // Union. + xpath = "/keatest-module:main/union"; + elem = Element::create(string("8")); + EXPECT_NO_THROW_LOG(t_obj->setItem(xpath, elem, LeafBaseType::Union)); + EXPECT_NO_THROW_LOG(data_node = sess.getData(xpath)); + ASSERT_TRUE(data_node); + EXPECT_NO_THROW_LOG(data_node = data_node->findPath(xpath)); + ASSERT_TRUE(data_node); + ASSERT_EQ(LeafBaseType::Union, data_node->schema().asLeaf().valueType().base()); + EXPECT_EQ(elem->stringValue(), string(data_node->asTerm().valueStr())); + elem = Element::create(string("infinity")); + EXPECT_NO_THROW_LOG(t_obj->setItem(xpath, elem, LeafBaseType::Union)); + EXPECT_NO_THROW_LOG(data_node = sess.getData(xpath)); + ASSERT_TRUE(data_node); + EXPECT_NO_THROW_LOG(data_node = data_node->findPath(xpath)); + ASSERT_TRUE(data_node); + ASSERT_EQ(LeafBaseType::Union, data_node->schema().asLeaf().valueType().base()); + EXPECT_EQ(elem->stringValue(), string(data_node->asTerm().valueStr())); + + // Leafref. + xpath = "/keatest-module:main/leafref-i8"; + elem = Element::create(string("9")); + EXPECT_NO_THROW_LOG(t_obj->setItem(xpath, elem, LeafBaseType::Leafref)); + EXPECT_NO_THROW_LOG(data_node = sess.getData(xpath)); + ASSERT_TRUE(data_node); + EXPECT_NO_THROW_LOG(data_node = data_node->findPath(xpath)); + ASSERT_TRUE(data_node); + ASSERT_EQ(LeafBaseType::Leafref, data_node->schema().asLeaf().valueType().base()); + EXPECT_EQ(elem->stringValue(), string(data_node->asTerm().valueStr())); + + // Leafref. + xpath = "/keatest-module:main/leafref-raw"; + elem = Element::create(string("ff012345")); + EXPECT_NO_THROW_LOG(t_obj->setItem(xpath, elem, LeafBaseType::Leafref)); + EXPECT_NO_THROW_LOG(data_node = sess.getData(xpath)); + ASSERT_TRUE(data_node); + EXPECT_NO_THROW_LOG(data_node = data_node->findPath(xpath)); + ASSERT_TRUE(data_node); + ASSERT_EQ(LeafBaseType::Leafref, data_node->schema().asLeaf().valueType().base()); + EXPECT_EQ(elem->stringValue(), string(data_node->asTerm().valueStr())); + + // Leafref. + xpath = "/keatest-module:main/leafref-string"; + elem = Element::create(string("string through")); + EXPECT_NO_THROW_LOG(t_obj->setItem(xpath, elem, LeafBaseType::Leafref)); + EXPECT_NO_THROW_LOG(data_node = sess.getData(xpath)); + ASSERT_TRUE(data_node); + EXPECT_NO_THROW_LOG(data_node = data_node->findPath(xpath)); + ASSERT_TRUE(data_node); + ASSERT_EQ(LeafBaseType::Leafref, data_node->schema().asLeaf().valueType().base()); + EXPECT_EQ(elem->stringValue(), string(data_node->asTerm().valueStr())); + // Bad xpath. xpath = "/keatest-module:main/no_such_string"; elem = Element::create(string("str")); diff --git a/src/lib/yang/translator.cc b/src/lib/yang/translator.cc index 55e7990807..5b432503fd 100644 --- a/src/lib/yang/translator.cc +++ b/src/lib/yang/translator.cc @@ -262,6 +262,59 @@ Translator::getMandatoryDivergingLeaf(ElementPtr& storage, storage->set(name, x); } +Translator::Deserializer +Translator::initializeDeserializer() { + Deserializer result; + + result.emplace(LeafBaseType::Binary, [](string const& value) -> ElementPtr const { + return Element::create(decode64(value)); + }); + + for (LeafBaseType const& i : + {LeafBaseType::Bool, LeafBaseType::Dec64, LeafBaseType::Int8, LeafBaseType::Int16, + LeafBaseType::Int32, LeafBaseType::Int64, LeafBaseType::Uint8, LeafBaseType::Uint16, + LeafBaseType::Uint32, LeafBaseType::Uint64}) { + result.emplace(i, [](string const& value) -> ElementPtr const { + return Element::fromJSON(value); + }); + } + + // The rest of YANG values can be expressed as strings. + for (LeafBaseType const& i : + {LeafBaseType::Bits, LeafBaseType::Empty, LeafBaseType::Enum, LeafBaseType::IdentityRef, + LeafBaseType::InstanceIdentifier, LeafBaseType::Leafref, LeafBaseType::String, + LeafBaseType::Union, LeafBaseType::Unknown}) { + result.emplace(i, [](string const& value) -> ElementPtr const { + return Element::create(value); + }); + } + + return result; +} + +Translator::Serializer +Translator::initializeSerializer() { + Serializer result; + + result.emplace(LeafBaseType::Binary, [](string const& value) -> string const { + return encode64(value); + }); + + // The rest of YANG values can be expressed directly. + for (LeafBaseType const& i : + {LeafBaseType::Bits, LeafBaseType::Bool, LeafBaseType::Dec64, LeafBaseType::Empty, + LeafBaseType::Enum, LeafBaseType::IdentityRef, LeafBaseType::InstanceIdentifier, + LeafBaseType::Int8, LeafBaseType::Int16, LeafBaseType::Int32, LeafBaseType::Int64, + LeafBaseType::Leafref, LeafBaseType::String, LeafBaseType::Uint8, LeafBaseType::Uint16, + LeafBaseType::Uint32, LeafBaseType::Uint64, LeafBaseType::Union, LeafBaseType::Unknown}) { + result.emplace(i, [](string const& value) -> string const { + return value; + }); + } + + return result; +} + void Translator::setItem(const string& xpath, ConstElementPtr elem, LeafBaseType type) { @@ -305,26 +358,23 @@ Translator::translateFromYang(optional data_node) { NodeType const node_type(data_node->schema().nodeType()); if (node_type == NodeType::Leaf || node_type == NodeType::Leaflist) { DataNodeTerm const& leaf(data_node->asTerm()); - Value const& v(leaf.value()); - if (holds_alternative(v) || - holds_alternative(v) || - holds_alternative(v)) { - // Should be a string. Call create(). Should be slightly faster - // than wrapping value in double quotes and calling fromJSON(). - return Element::create(string(leaf.valueStr())); - } else if (holds_alternative(v)) { - return Element::create(decode64(string(leaf.valueStr()))); + LeafBaseType type; + if (node_type == NodeType::Leaf) { + type = leaf.schema().asLeaf().valueType().base(); } else { - // This can be various types so defer to fromJSON(). - return Element::fromJSON(string(leaf.valueStr())); + type = leaf.schema().asLeafList().valueType().base(); } + + static Deserializer deserializer(initializeDeserializer()); + return deserializer.at(type)(string(leaf.valueStr())); } return ElementPtr(); } optional Translator::translateToYang(ConstElementPtr const& element, - LeafBaseType const type) { + libyang::LeafBaseType const type) { + string string_representation; if (!element) { // A null ElementPtr is how we signal that this item requires no value. // Useful when setting YANG lists which is the only way to set their @@ -336,28 +386,16 @@ Translator::translateToYang(ConstElementPtr const& element, } else if (element->getType() == Element::list) { /// @todo: implement isc_throw(NotImplemented, "Translator::value(): list element"); - } - if (type == LeafBaseType::Enum || - type == LeafBaseType::String || - type == LeafBaseType::Union || - type == LeafBaseType::IdentityRef) { - // These types are usually strings in ElementPtr, but are accepted - // without the double quotes in sysrepo, so get the stringValue(). - if (element->getType() == Element::string) { - return element->stringValue(); - } else { - // Except for some nodes which are maps e.g. user-context. And also Unions and - // IdentityRefs can very well have underlying types that are different than strings. - // Use the generic str() for those. - return element->str(); - } - } else if (type == LeafBaseType::Binary) { - return encode64(element->stringValue()); + } else if (element->getType() == Element::string) { + // If it's a string, get the variant wthout quotes. + string_representation = element->stringValue(); } else { - // The rest of YANG values can be expressed using the - // general string representation of ElementPtr. - return element->str(); + // If it's not a string, also get the variant without quotes, but it's a different method. + string_representation = element->str(); } + + static Serializer serializer(initializeSerializer()); + return serializer.at(type)(string_representation); } } // namespace yang diff --git a/src/lib/yang/translator.h b/src/lib/yang/translator.h index 6576d64e12..8c49aad1c8 100644 --- a/src/lib/yang/translator.h +++ b/src/lib/yang/translator.h @@ -332,6 +332,28 @@ protected: /// @return the encoded string static std::string encode64(std::string const& input); + /// @brief Maps YANG types to functions that transform a YANG type into an ElementPtr. + using Deserializer = + std::unordered_map>; + + /// @brief Initializes the deserializer which is used to translate a YANG node to an ElementPtr. + /// + /// @return a copy of the deserializer + static Deserializer initializeDeserializer(); + + /// @brief Maps YANG types to functions that transform the string representation of an + /// Element into a string that can be passed into Session::setItem(). + using Serializer = + std::unordered_map>; + + /// @brief Initializes the serializer which is used to translate the string value of an Element + /// to a string that can be passed into Session::setItem(). + /// + /// @return a copy of the serializer + static Serializer initializeSerializer(); + /// @brief The sysrepo session. sysrepo::Session session_; diff --git a/src/lib/yang/yang_revisions.h b/src/lib/yang/yang_revisions.h index 44cce00d32..fade868897 100644 --- a/src/lib/yang/yang_revisions.h +++ b/src/lib/yang/yang_revisions.h @@ -16,7 +16,7 @@ namespace yang { // Table of module name / revision. static const std::unordered_map YANG_REVISIONS = { #ifdef KEATEST_MODULE - { "keatest-module", "2018-11-20" }, + { "keatest-module", "2022-11-30" }, #endif // KEATEST_MODULE { "ietf-dhcpv6-types", "2018-09-04" }, { "ietf-dhcpv6-options", "2018-09-04" }, diff --git a/src/share/yang/modules/Makefile.am b/src/share/yang/modules/Makefile.am index 2d97db09a0..1dfcf28269 100644 --- a/src/share/yang/modules/Makefile.am +++ b/src/share/yang/modules/Makefile.am @@ -17,7 +17,7 @@ yangmodules_list += kea-dhcp-types@2022-11-30.yang yangmodules_list += kea-dhcp4-server@2022-11-30.yang yangmodules_list += kea-dhcp6-server@2022-11-30.yang yangmodules_list += kea-types@2019-08-12.yang -yangmodules_list += keatest-module@2018-11-20.yang +yangmodules_list += keatest-module@2022-11-30.yang EXTRA_DIST = hashes ${yangmodules_list} diff --git a/src/share/yang/modules/hashes/keatest-module@2018-11-20.hash b/src/share/yang/modules/hashes/keatest-module@2018-11-20.hash deleted file mode 100644 index 480b411a77..0000000000 --- a/src/share/yang/modules/hashes/keatest-module@2018-11-20.hash +++ /dev/null @@ -1 +0,0 @@ -2369eabd01e2c10f0418d3600d9ffa286f73f642a9b35f19f83fe4c249f436a9 diff --git a/src/share/yang/modules/hashes/keatest-module@2022-11-30.hash b/src/share/yang/modules/hashes/keatest-module@2022-11-30.hash new file mode 100644 index 0000000000..fcc45c7f05 --- /dev/null +++ b/src/share/yang/modules/hashes/keatest-module@2022-11-30.hash @@ -0,0 +1 @@ +154760167c8e5986b3e3dfa52dbde018ffd23de2399da76ce30583feb10071f9 diff --git a/src/share/yang/modules/keatest-module@2018-11-20.yang b/src/share/yang/modules/keatest-module@2022-11-30.yang similarity index 90% rename from src/share/yang/modules/keatest-module@2018-11-20.yang rename to src/share/yang/modules/keatest-module@2022-11-30.yang index 8993218029..8042b26c4c 100644 --- a/src/share/yang/modules/keatest-module@2018-11-20.yang +++ b/src/share/yang/modules/keatest-module@2022-11-30.yang @@ -10,6 +10,11 @@ module keatest-module { contact "kea-dev@lists.isc.org"; + revision 2022-11-30 { + description + "Added leafrefs and empty leaf."; + } + revision 2018-11-20 { description "Initial revision"; reference ""; @@ -104,6 +109,29 @@ module keatest-module { leaf instance_id { type instance-identifier; } + leaf union { + type union { + type uint8; + type enumeration { + enum "infinity"; + } + } + } + leaf leafref-i8 { + type leafref { + path "/main/i8"; + } + } + leaf leafref-raw { + type leafref { + path "/main/raw"; + } + } + leaf leafref-string { + type leafref { + path "/main/string"; + } + } anyxml xml-data; anydata any-data; } @@ -131,13 +159,8 @@ module keatest-module { leaf instance_id { type instance-identifier; } - leaf union { - type union { - type uint8; - type enumeration { - enum "infinity"; - } - } + leaf empty { + type empty; } }