]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#2601] make Translator aware of all leaf base types
authorAndrei Pavel <andrei@isc.org>
Mon, 7 Nov 2022 15:43:07 +0000 (17:43 +0200)
committerRazvan Becheriu <razvan@isc.org>
Fri, 25 Nov 2022 16:15:33 +0000 (18:15 +0200)
Also add leafrefs and the empty leaf to the keatest-module.
And add tests for those, and also unions, dec64, int64, uint64.

doc/sphinx/arm/ext-netconf.rst
src/bin/netconf/tests/netconf_unittests.cc
src/lib/yang/tests/translator_unittests.cc
src/lib/yang/translator.cc
src/lib/yang/translator.h
src/lib/yang/yang_revisions.h
src/share/yang/modules/Makefile.am
src/share/yang/modules/hashes/keatest-module@2018-11-20.hash [deleted file]
src/share/yang/modules/hashes/keatest-module@2022-11-30.hash [new file with mode: 0644]
src/share/yang/modules/keatest-module@2022-11-30.yang [moved from src/share/yang/modules/keatest-module@2018-11-20.yang with 90% similarity]

index ac7256fb912277087b609fe8f0f115bbc19afdd8..78096e080377cb8a6e4c410b418d2d5bf0f25a79 100644 (file)
@@ -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           |            |
index cf7cd407bfcbd6289737db0818db07884994ecc5..c6aa6b3ee4f23405eec89da09dd84f91bf11c25a 100644 (file)
@@ -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)");
index f1de44c83f24bfaf10abc8ad5d134d60ea143d11..a17b61cec25ba7671011805691d11e4832c1109d 100644 (file)
@@ -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"));
index 55e7990807ea096c3e55ac3575364047b213c2be..5b432503fd49a789258519abc12109bd1add6467 100644 (file)
@@ -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<DataNode> 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<string>(v) ||
-            holds_alternative<Enum>(v) ||
-            holds_alternative<IdentityRef>(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<Binary>(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<string>
 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
index 6576d64e126aaee9a30897df8dc174b78b391b8a..8c49aad1c859ae77f9fa73643f1069576424a1b5 100644 (file)
@@ -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<libyang::LeafBaseType,
+                           std::function<isc::data::ElementPtr const(std::string const&)>>;
+
+    /// @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<libyang::LeafBaseType,
+                           std::function<std::string const(std::string const&)>>;
+
+    /// @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_;
 
index 44cce00d3251950bf8266fbe123479eff6e93506..fade8688974ecede7935297d58d4eb92ff0a7c5b 100644 (file)
@@ -16,7 +16,7 @@ namespace yang {
 // Table of module name / revision.
 static const std::unordered_map<std::string, std::string> 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" },
index 2d97db09a0739bbda6847d3421eaa7fccf75c42e..1dfcf282693fc28e17fd8093de416b5b144e42a2 100644 (file)
@@ -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 (file)
index 480b411..0000000
+++ /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 (file)
index 0000000..fcc45c7
--- /dev/null
@@ -0,0 +1 @@
+154760167c8e5986b3e3dfa52dbde018ffd23de2399da76ce30583feb10071f9
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 8993218029edb6c7995ab1979af732b1b4550be6..8042b26c4c03a7076357d288ae547e0912c257c1 100644 (file)
@@ -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;
     }
   }