2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-30 05:27:55 +00:00

[65-libyang-testutils] Filled files, ready for review

This commit is contained in:
Francis Dupont 2018-09-13 16:02:28 +02:00
parent b4e30f3708
commit 1b7963c1bc
8 changed files with 1162 additions and 3 deletions

View File

@ -1621,6 +1621,7 @@ AC_CONFIG_FILES([Makefile
src/lib/yang/Makefile
src/lib/yang/pretests/Makefile
src/lib/yang/tests/Makefile
src/lib/yang/testutils/Makefile
src/share/Makefile
src/share/database/Makefile
src/share/database/scripts/Makefile

View File

@ -1,4 +1,4 @@
SUBDIRS = . pretests tests
SUBDIRS = . testutils pretests tests
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES) $(SYSREPO_CPPFLAGS)

View File

@ -17,7 +17,8 @@ EXTRA_DIST = keatest-module.yang
TESTS =
if HAVE_GTEST
TESTS += run_unittests
run_unittests_SOURCES = adaptor_unittests.cc
run_unittests_SOURCES = yang_configs.h
run_unittests_SOURCES += adaptor_unittests.cc
run_unittests_SOURCES += adaptor_option_unittests.cc
run_unittests_SOURCES += adaptor_pool_unittests.cc
run_unittests_SOURCES += adaptor_host_unittests.cc
@ -36,11 +37,13 @@ run_unittests_SOURCES += translator_pd_pool_unittests.cc
run_unittests_SOURCES += translator_host_unittests.cc
run_unittests_SOURCES += translator_subnet_unittests.cc
run_unittests_SOURCES += translator_shared_network_unittests.cc
run_unittests_SOURCES += translator_utils_unittests.cc
run_unittests_SOURCES += run_unittests.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
run_unittests_LDADD = $(top_builddir)/src/lib/yang/libkea-yang.la
run_unittests_LDADD = $(top_builddir)/src/lib/yang/testutils/libyangtest.la
run_unittests_LDADD += $(top_builddir)/src/lib/yang/libkea-yang.la
run_unittests_LDADD += $(top_builddir)/src/lib/testutils/libkea-testutils.la
run_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la

View File

@ -0,0 +1,206 @@
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <yang/tests/yang_configs.h>
#include <boost/scoped_ptr.hpp>
#include <gtest/gtest.h>
#include <sstream>
using namespace std;
using namespace isc;
using namespace isc::yang;
using namespace isc::yang::test;
namespace {
// Test sr_type_t print.
TEST(YangReprTest, type) {
ostringstream os;
// Verify that string is "string" (vs a number).
sr_type_t t = SR_STRING_T;
os << t;
EXPECT_EQ("string", os.str());
os.str("");
// Compiler does not let to create an invalid value...
}
// Test YangReprItem basic stuff.
TEST(YangReprTest, item) {
// An item.
YRItem item1("/foo", "bar", SR_STRING_T, true);
EXPECT_EQ("/foo", item1.xpath_);
EXPECT_EQ("bar", item1.value_);
EXPECT_EQ(SR_STRING_T, item1.type_);
EXPECT_TRUE(item1.settable_);
// Another one.
YRItem item2("/foo", "bar", SR_STRING_T, false);
EXPECT_EQ("/foo", item2.xpath_);
EXPECT_EQ("bar", item2.value_);
EXPECT_EQ(SR_STRING_T, item2.type_);
EXPECT_FALSE(item2.settable_);
// Equality.
EXPECT_TRUE(item1 == item2);
EXPECT_TRUE(item2 == item1);
EXPECT_FALSE(item1 != item2);
EXPECT_FALSE(item2 != item1);
EXPECT_EQ(item1, item2);
EXPECT_EQ(item2, item1);
}
// Test get with example module.
TEST(YangReprTest, getExample) {
// Get a translator object to play with.
S_Connection conn(new Connection("utils unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
// Create a list.
string xpath = "/example-module:container/list";
S_Val s_val;
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
// Get it.
YangRepr repr(exampleModel);
YRTree tree;
EXPECT_NO_THROW(tree = repr.get(sess));
// Verify.
EXPECT_TRUE(repr.verify(exampleTree, sess, cerr));
}
// Test get with test module.
TEST(YangReprTest, getTest) {
// Get a translator object to play with.
S_Connection conn(new Connection("utils unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
// Fill the test module.
string xpath;
S_Val s_val;
xpath = "/test-module:main/string";
s_val.reset(new Val("str", SR_STRING_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
xpath = "/test-module:main/boolean";
s_val.reset(new Val(true, SR_BOOL_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
xpath = "/test-module:main/ui8";
uint8_t u8(8);
s_val.reset(new Val(u8, SR_UINT8_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
xpath = "/test-module:main/ui16";
uint16_t u16(16);
s_val.reset(new Val(u16, SR_UINT16_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
xpath = "/test-module:main/ui32";
uint32_t u32(32);
s_val.reset(new Val(u32, SR_UINT32_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
xpath = "/test-module:main/i8";
int8_t s8(8);
s_val.reset(new Val(s8, SR_INT8_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
xpath = "/test-module:main/i16";
int16_t s16(16);
s_val.reset(new Val(s16, SR_INT16_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
xpath = "/test-module:main/i32";
int32_t s32(32);
s_val.reset(new Val(s32, SR_INT32_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
xpath = "/test-module:main/id_ref";
s_val.reset(new Val("test-module:id_1", SR_IDENTITYREF_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
xpath = "/test-module:main/enum";
s_val.reset(new Val("maybe", SR_ENUM_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
// Binary.
xpath = "/test-module:main/raw";
s_val.reset(new Val("Zm9vYmFy", SR_BINARY_T));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
// Get it.
YangRepr repr(testModel);
YRTree tree;
EXPECT_NO_THROW(tree = repr.get(sess));
// Verify.
EXPECT_TRUE(repr.verify(testTree, sess, cerr));
// Some error messages will be displayed.
// Change a path.
YRTree badpath = testTree;
badpath[20].xpath_ = "/test-module:kernel-module"; // removed final 's'
EXPECT_FALSE(repr.verify(badpath, sess, cerr));
// Change a value.
YRTree badvalue = testTree;
badvalue[1].value_ = "Str"; // was "str"
EXPECT_FALSE(repr.verify(badvalue, sess, cerr));
// Change a type.
YRTree badtype = testTree;
badtype[8].type_ = SR_UINT32_T; // was SR_INT32_T
EXPECT_FALSE(repr.verify(badtype, sess, cerr));
// Add a record at the end.
YRTree badmissing = testTree;
const string& xpathpc = "/test-module:presence-container";
badmissing.push_back(YRItem(xpathpc, "", SR_CONTAINER_PRESENCE_T, false));
EXPECT_FALSE(repr.verify(badmissing, sess, cerr));
// Delete last record.
YRTree badextra = testTree;
badextra.pop_back();
EXPECT_FALSE(repr.verify(badextra, sess, cerr));
}
// Test set with example module.
TEST(YangReprTest, setExample) {
// Get a translator object to play with.
S_Connection conn(new Connection("utils unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
// Set the module content.
YangRepr repr(exampleModel);
EXPECT_NO_THROW(repr.set(exampleTree, sess));
// Verify it.
EXPECT_TRUE(repr.verify(exampleTree, sess, cerr));
}
// Test set with test module.
TEST(YangReprTest, setTest) {
// Get a translator object to play with.
S_Connection conn(new Connection("utils unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
// Set the module content.
YangRepr repr(testModel);
EXPECT_NO_THROW(repr.set(testTree, sess));
// Verify it.
EXPECT_TRUE(repr.verify(testTree, sess, cerr));
}
}; // end of anonymous namespace

View File

@ -0,0 +1,408 @@
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef ISC_YANG_CONFIGS_H
#define ISC_YANG_CONFIGS_H
#include <yang/testutils/translator_test.h>
namespace isc {
namespace yang {
namespace test {
/// @brief The example module from sysrepo tests.
const std::string exampleModel = "example-module";
const YRTree exampleTree = {
{ "/example-module:container", "", SR_CONTAINER_T, false },
{ "/example-module:container/list", "", SR_LIST_T, true }
};
/// @brief The test module from sysrepo tests.
const std::string testModel = "test-module";
const YRTree testTree = {
{ "/test-module:main", "", SR_CONTAINER_T, false },
{ "/test-module:main/string", "str", SR_STRING_T, true },
{ "/test-module:main/boolean", "true", SR_BOOL_T, true },
{ "/test-module:main/ui8", "8", SR_UINT8_T, true },
{ "/test-module:main/ui16", "16", SR_UINT16_T, true },
{ "/test-module:main/ui32", "32", SR_UINT32_T, true },
{ "/test-module:main/i8", "8", SR_INT8_T, true },
{ "/test-module:main/i16", "16", SR_INT16_T, true },
{ "/test-module:main/i32", "32", SR_INT32_T, true },
{ "/test-module:main/id_ref", "test-module:id_1", SR_IDENTITYREF_T, true },
{ "/test-module:main/enum", "maybe", SR_ENUM_T, true },
{ "/test-module:main/raw", "Zm9vYmFy", SR_BINARY_T, true },
{ "/test-module:transfer", "", SR_CONTAINER_T, false },
{ "/test-module:transfer/interval", "30", SR_UINT16_T, false },
{ "/test-module:interface", "", SR_CONTAINER_T, false },
{ "/test-module:top-level-default", "default value", SR_STRING_T, false },
{ "/test-module:university", "", SR_CONTAINER_T, false },
{ "/test-module:university/students", "", SR_CONTAINER_T, false },
{ "/test-module:university/classes", "", SR_CONTAINER_T, false },
{ "/test-module:leafref-chain", "", SR_CONTAINER_T, false },
{ "/test-module:kernel-modules", "", SR_CONTAINER_T, false },
{ "/test-module:tpdfs", "", SR_CONTAINER_T, false },
{ "/test-module:tpdfs/unival", "disabled", SR_STRING_T, false }
};
/// @brief A subnet with two pools with ietf-dhcpv6-server model.
const std::string subnetTwoPoolsModelIetf6 = "ietf-dhcpv6-server";
const YRTree subnetTwoPoolsTreeIetf6 = {
{ "/ietf-dhcpv6-server:server", "", SR_CONTAINER_PRESENCE_T, false },
{ "/ietf-dhcpv6-server:server/server-config", "", SR_CONTAINER_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges",
"", SR_CONTAINER_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']", "", SR_LIST_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/network-range-id",
"111", SR_UINT32_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/network-prefix",
"2001:db8::/48", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools",
"", SR_CONTAINER_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']", "", SR_LIST_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/pool-id", "0", SR_UINT32_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/pool-prefix",
"2001:db8::1:0/112", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/start-address",
"2001:db8::1:0", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/end-address",
"2001:db8::1:ffff", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/max-address-count",
"disabled", SR_ENUM_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']", "", SR_LIST_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/pool-id", "1", SR_UINT32_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/pool-prefix",
"2001:db8::2:0/112", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/start-address",
"2001:db8::2:0", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/end-address",
"2001:db8::2:ffff", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/max-address-count",
"disabled", SR_ENUM_T, true }
};
/// @brief A subnet with timers with ietf-dhcpv6-server model.
const std::string subnetTimersModel = "ietf-dhcpv6-server";
const YRTree subnetTimersIetf6 = {
{ "/ietf-dhcpv6-server:server", "", SR_CONTAINER_PRESENCE_T, false },
{ "/ietf-dhcpv6-server:server/server-config", "", SR_CONTAINER_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges",
"", SR_CONTAINER_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']", "", SR_LIST_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/network-range-id",
"111", SR_UINT32_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/network-prefix",
"2001:db8::/48", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools",
"", SR_CONTAINER_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']", "", SR_LIST_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/pool-id", "0", SR_UINT32_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/pool-prefix",
"2001:db8::1:0/112", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/start-address",
"2001:db8::1:0", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/end-address",
"2001:db8::1:ffff", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/renew-time", "1000", SR_UINT32_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/rebind-time", "2000", SR_UINT32_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/max-address-count",
"disabled", SR_ENUM_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']", "", SR_LIST_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/pool-id", "1", SR_UINT32_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/pool-prefix",
"2001:db8::2:0/112", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/start-address",
"2001:db8::2:0", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/end-address",
"2001:db8::2:ffff", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/renew-time", "1000", SR_UINT32_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/rebind-time", "2000", SR_UINT32_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/max-address-count",
"disabled", SR_ENUM_T, true }
};
/// @brief A subnet with two pools with ietf-dhcpv6-server model
/// which validates.
const std::string validModelIetf6 = "ietf-dhcpv6-server";
const YRTree validTreeIetf6 = {
{ "/ietf-dhcpv6-server:server", "", SR_CONTAINER_PRESENCE_T, false },
{ "/ietf-dhcpv6-server:server/server-config", "", SR_CONTAINER_T, false },
{ "/ietf-dhcpv6-server:server/server-config/serv-attributes",
"", SR_CONTAINER_T, false },
{ "/ietf-dhcpv6-server:server/server-config/serv-attributes/vendor-info",
"", SR_CONTAINER_T, false },
{ "/ietf-dhcpv6-server:server/server-config/serv-attributes"
"/vendor-info/ent-num", "2495", SR_UINT32_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges",
"", SR_CONTAINER_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']", "", SR_LIST_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/network-range-id",
"111", SR_UINT32_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/network-description",
"Subnet#111", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/network-prefix",
"2001:db8::/48", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools",
"", SR_CONTAINER_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']", "", SR_LIST_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/pool-id", "0", SR_UINT32_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/pool-prefix",
"2001:db8::1:0/112", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/start-address",
"2001:db8::1:0", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/end-address",
"2001:db8::1:ffff", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/valid-lifetime", "4000", SR_UINT32_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/preferred-lifetime",
"3000", SR_UINT32_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/renew-time", "1000", SR_UINT32_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/rebind-time", "2000", SR_UINT32_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/max-address-count",
"disabled", SR_ENUM_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='0']/option-set-id", "0", SR_UINT32_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']", "", SR_LIST_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/pool-id", "1", SR_UINT32_T, false },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/pool-prefix",
"2001:db8::2:0/112", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/start-address",
"2001:db8::2:0", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/end-address",
"2001:db8::2:ffff", SR_STRING_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/valid-lifetime", "4000", SR_UINT32_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/preferred-lifetime",
"3000", SR_UINT32_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/renew-time", "1000", SR_UINT32_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/rebind-time", "2000", SR_UINT32_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/max-address-count",
"disabled", SR_ENUM_T, true },
{ "/ietf-dhcpv6-server:server/server-config/network-ranges/"
"network-range[network-range-id='111']/address-pools/"
"address-pool[pool-id='1']/option-set-id", "0", SR_UINT32_T, true },
{ "/ietf-dhcpv6-server:server/server-config/option-sets",
"", SR_CONTAINER_T, false },
{ "/ietf-dhcpv6-server:server/server-config/option-sets"
"/option-set[option-set-id='0']", "", SR_LIST_T, true },
{ "/ietf-dhcpv6-server:server/server-config/option-sets"
"/option-set[option-set-id='0']/option-set-id",
"0", SR_UINT32_T, false }
};
/// @brief A subnet with a pool and option data lists with
/// kea-dhcp4:config model.
const std::string subnetOptionsModelKeaDhcp4 = "kea-dhcp4";
const YRTree subnetOptionsTreeKeaDhcp4 = {
{ "/kea-dhcp4:config", "", SR_CONTAINER_T, false },
{ "/kea-dhcp4:config/subnet4", "", SR_CONTAINER_T, false },
{ "/kea-dhcp4:config/subnet4/subnet4[id='111']", "", SR_LIST_T, true },
{ "/kea-dhcp4:config/subnet4/subnet4[id='111']/id",
"111", SR_UINT32_T, false },
{ "/kea-dhcp4:config/subnet4/subnet4[id='111']/option-data-list",
"", SR_CONTAINER_T, false },
{ "/kea-dhcp4:config/subnet4/subnet4[id='111']/option-data-list/"
"option-data[code='100'][space='dns']", "", SR_LIST_T, true },
{ "/kea-dhcp4:config/subnet4/subnet4[id='111']/option-data-list/"
"option-data[code='100'][space='dns']/code",
"100", SR_UINT8_T, false },
{ "/kea-dhcp4:config/subnet4/subnet4[id='111']/option-data-list/"
"option-data[code='100'][space='dns']/space",
"dns", SR_STRING_T, false },
{ "/kea-dhcp4:config/subnet4/subnet4[id='111']/option-data-list/"
"option-data[code='100'][space='dns']/data",
"12121212", SR_STRING_T, true },
{ "/kea-dhcp4:config/subnet4/subnet4[id='111']/option-data-list/"
"option-data[code='100'][space='dns']/csv-format",
"false", SR_BOOL_T, true },
{ "/kea-dhcp4:config/subnet4/subnet4[id='111']/option-data-list/"
"option-data[code='100'][space='dns']/always-send",
"false", SR_BOOL_T, true },
{ "/kea-dhcp4:config/subnet4/subnet4[id='111']/pools",
"", SR_CONTAINER_T, false },
{ "/kea-dhcp4:config/subnet4/subnet4[id='111']/pools/"
"pool[start-address='10.0.1.0'][end-address='10.0.1.255']",
"", SR_LIST_T, true },
{ "/kea-dhcp4:config/subnet4/subnet4[id='111']/pools/"
"pool[start-address='10.0.1.0'][end-address='10.0.1.255']/start-address",
"10.0.1.0", SR_STRING_T, false },
{ "/kea-dhcp4:config/subnet4/subnet4[id='111']/pools/"
"pool[start-address='10.0.1.0'][end-address='10.0.1.255']/end-address",
"10.0.1.255", SR_STRING_T, false },
{ "/kea-dhcp4:config/subnet4/subnet4[id='111']/pools/"
"pool[start-address='10.0.1.0'][end-address='10.0.1.255']/prefix",
"10.0.1.0/24", SR_STRING_T, true },
{ "/kea-dhcp4:config/subnet4/subnet4[id='111']/subnet",
"10.0.0.0/8", SR_STRING_T, true }
};
/// @brief A subnet with a pool and option data lists with
/// kea-dhcp6:config model.
const std::string subnetOptionsModelKeaDhcp6 = "kea-dhcp6";
const YRTree subnetOptionsTreeKeaDhcp6 = {
{ "/kea-dhcp6:config", "", SR_CONTAINER_T, false },
{ "/kea-dhcp6:config/subnet6", "", SR_CONTAINER_T, false },
{ "/kea-dhcp6:config/subnet6/subnet6[id='111']", "", SR_LIST_T, true },
{ "/kea-dhcp6:config/subnet6/subnet6[id='111']/id",
"111", SR_UINT32_T, false },
{ "/kea-dhcp6:config/subnet6/subnet6[id='111']/pools",
"", SR_CONTAINER_T, false },
{ "/kea-dhcp6:config/subnet6/subnet6[id='111']/pools/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']",
"", SR_LIST_T, true },
{ "/kea-dhcp6:config/subnet6/subnet6[id='111']/pools/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
"start-address", "2001:db8::1:0", SR_STRING_T, false },
{ "/kea-dhcp6:config/subnet6/subnet6[id='111']/pools/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
"end-address", "2001:db8::1:ffff", SR_STRING_T, false },
{ "/kea-dhcp6:config/subnet6/subnet6[id='111']/pools/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
"prefix", "2001:db8::1:0/112", SR_STRING_T, true },
{ "/kea-dhcp6:config/subnet6/subnet6[id='111']/pools/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
"option-data-list", "", SR_CONTAINER_T, false },
{ "/kea-dhcp6:config/subnet6/subnet6[id='111']/pools/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
"option-data-list/option-data[code='100'][space='dns']",
"", SR_LIST_T, true },
{ "/kea-dhcp6:config/subnet6/subnet6[id='111']/pools/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
"option-data-list/option-data[code='100'][space='dns']/code",
"100", SR_UINT16_T, false },
{ "/kea-dhcp6:config/subnet6/subnet6[id='111']/pools/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
"option-data-list/option-data[code='100'][space='dns']/space",
"dns", SR_STRING_T, false },
{ "/kea-dhcp6:config/subnet6/subnet6[id='111']/pools/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
"option-data-list/option-data[code='100'][space='dns']/data",
"12121212", SR_STRING_T, true },
{ "/kea-dhcp6:config/subnet6/subnet6[id='111']/pools/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
"option-data-list/option-data[code='100'][space='dns']/csv-format",
"false", SR_BOOL_T, true },
{ "/kea-dhcp6:config/subnet6/subnet6[id='111']/pools/"
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
"option-data-list/option-data[code='100'][space='dns']/always-send",
"false", SR_BOOL_T, true },
{ "/kea-dhcp6:config/subnet6/subnet6[id='111']/subnet",
"2001:db8::/48", SR_STRING_T, true }
};
}; // end of namespace isc::yang::test
}; // end of namespace isc::yang
}; // end of namespace isc
#endif // ISC_YANG_CONFIGS_H

View File

@ -0,0 +1,22 @@
SUBDIRS = .
AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES) $(SYSREPO_CPPFLAGS)
AM_CXXFLAGS = $(KEA_CXXFLAGS)
CLEANFILES = *.gcno *.gcda
if HAVE_GTEST
noinst_LTLIBRARIES = libyangtest.la
libyangtest_la_SOURCES = translator_test.cc translator_test.h
libyangtest_la_CXXFLAGS = $(AM_CXXFLAGS)
libyangtest_la_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
libyangtest_la_LDFLAGS = $(AM_LDFLAGS)
libyangtest_la_LIBADD = $(top_builddir)/src/lib/yang/libkea-yang.la
libyangtest_la_LIBADD += $(top_builddir)/src/lib/log/libkea-log.la
endif

View File

@ -0,0 +1,392 @@
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <yang/testutils/translator_test.h>
#include <boost/lexical_cast.hpp>
#include <sstream>
using namespace std;
using namespace isc::data;
namespace isc {
namespace yang {
namespace test {
YangRepr::YangReprItem
YangRepr::YangReprItem::get(const string& xpath, S_Session session) {
string val_xpath = xpath;
string value = "";
sr_type_t type = SR_UNKNOWN_T;
bool settable = true;
try {
S_Val s_val = session->get_item(xpath.c_str());
if (!s_val) {
isc_throw(BadValue, "YangReprItem failed at '" << xpath << "'");
}
val_xpath = string(s_val->xpath());
type = s_val->type();
ostringstream int_value;
switch (type) {
case SR_CONTAINER_T:
case SR_CONTAINER_PRESENCE_T:
settable = false;
break;
case SR_LIST_T:
break;
case SR_STRING_T:
value = s_val->data()->get_string();
break;
case SR_BOOL_T:
value = s_val->data()->get_bool() ? "true" : "false";
break;
case SR_UINT8_T:
int_value << static_cast<unsigned>(s_val->data()->get_uint8());
value = int_value.str();
break;
case SR_UINT16_T:
int_value << s_val->data()->get_uint16();
value = int_value.str();
break;
case SR_UINT32_T:
int_value << s_val->data()->get_uint32();
value = int_value.str();
break;
case SR_INT8_T:
int_value << static_cast<unsigned>(s_val->data()->get_int8());
value = int_value.str();
break;
case SR_INT16_T:
int_value << s_val->data()->get_int16();
value = int_value.str();
break;
case SR_INT32_T:
int_value << s_val->data()->get_int32();
value = int_value.str();
break;
case SR_IDENTITYREF_T:
value = s_val->data()->get_identityref();
break;
case SR_ENUM_T:
value = s_val->data()->get_enum();
break;
case SR_BINARY_T:
value = s_val->data()->get_binary();
break;
default:
isc_throw(NotImplemented,
"YangReprItem called with unupported type: " << type);
}
} catch (const sysrepo_exception& ex) {
isc_throw(SysrepoError,
"sysrepo error in YangReprItem: " << ex.what());
}
return (YangReprItem(val_xpath, value, type, settable));
}
YangRepr::Tree
YangRepr::get(S_Session session) const {
Tree result;
try {
const string& xpath0 = "/" + model_ + ":*//.";
TranslatorBasic tb(session);
S_Iter_Value iter = tb.getIter(xpath0);
for (;;) {
const string& xpath = tb.getNext(iter);
if (xpath.empty()) {
break;
}
result.push_back(YangReprItem::get(xpath, session));
}
} catch (const sysrepo_exception& ex) {
isc_throw(SysrepoError,
"sysrepo error in YangRepr::getTree: " << ex.what());
}
return (result);
}
bool
YangRepr::verify(const Tree& expected, S_Session session,
ostream& errs) const {
const Tree& got = get(session);
for (size_t i = 0; (i < expected.size()) && (i < got.size()); ++i) {
if (expected[i] == got[i]) {
continue;
}
errs << "expected[" << i << "]: " << expected[i] << endl;
errs << "got[" << i << "]: " << got[i] << endl;
return (false);
}
if (expected.size() == got.size()) {
return (true);
}
if (expected.size() > got.size()) {
errs << "missings " << (expected.size() - got.size());
errs << " beginning by:" << endl << expected[got.size()] << endl;
} else {
errs << "extras " << (got.size() - expected.size());
errs << " beginning by:" << endl << got[expected.size()] << endl;
}
return (false);
}
void
YangRepr::set(const Tree& tree, S_Session session) const {
for (auto item : tree) {
if (!item.settable_) {
continue;
}
try {
S_Val s_val;
switch (item.type_) {
case SR_CONTAINER_T:
case SR_CONTAINER_PRESENCE_T:
isc_throw(NotImplemented,
"YangRepr::set called for a container");
case SR_LIST_T:
break;
case SR_STRING_T:
case SR_IDENTITYREF_T:
case SR_ENUM_T:
case SR_BINARY_T:
s_val.reset(new Val(item.value_.c_str(), item.type_));
break;
case SR_BOOL_T:
if (item.value_ == "true") {
s_val.reset(new Val(true, SR_BOOL_T));
} else if (item.value_ == "false") {
s_val.reset(new Val(false, SR_BOOL_T));
} else {
isc_throw(BadValue, "'" << item.value_ << "' not a bool");
}
break;
case SR_UINT8_T:
try {
uint8_t u8 = boost::lexical_cast<unsigned>(item.value_);
s_val.reset(new Val(u8, SR_UINT8_T));
} catch (const boost::bad_lexical_cast&) {
isc_throw(BadValue,
"'" << item.value_ << "' not an uint8");
}
break;
case SR_UINT16_T:
try {
uint16_t u16 = boost::lexical_cast<uint16_t>(item.value_);
s_val.reset(new Val(u16, SR_UINT16_T));
} catch (const boost::bad_lexical_cast&) {
isc_throw(BadValue,
"'" << item.value_ << "' not an uint16");
}
break;
case SR_UINT32_T:
try {
uint32_t u32 = boost::lexical_cast<uint32_t>(item.value_);
s_val.reset(new Val(u32, SR_UINT32_T));
} catch (const boost::bad_lexical_cast&) {
isc_throw(BadValue,
"'" << item.value_ << "' not an uint32");
}
break;
case SR_INT8_T:
try {
int8_t i8 = boost::lexical_cast<int>(item.value_);
s_val.reset(new Val(i8, SR_INT8_T));
} catch (const boost::bad_lexical_cast&) {
isc_throw(BadValue,
"'" << item.value_ << "' not an int8");
}
break;
case SR_INT16_T:
try {
int16_t i16 = boost::lexical_cast<int16_t>(item.value_);
s_val.reset(new Val(i16, SR_INT16_T));
} catch (const boost::bad_lexical_cast&) {
isc_throw(BadValue,
"'" << item.value_ << "' not an int16");
}
break;
case SR_INT32_T:
try {
int32_t i32 = boost::lexical_cast<int32_t>(item.value_);
s_val.reset(new Val(i32, SR_INT32_T));
} catch (const boost::bad_lexical_cast&) {
isc_throw(BadValue,
"'" << item.value_ << "' not an int32");
}
break;
default:
isc_throw(NotImplemented,
"YangRepr::set called with unupported type: "
<< item.type_);
}
session->set_item(item.xpath_.c_str(), s_val);
} catch (const sysrepo_exception& ex) {
isc_throw(SysrepoError,
"sysrepo error in YangRepr::set for " << item
<< ", error: " << ex.what());
}
}
}
bool
YangRepr::validate(S_Session session, std::ostream& errs) const {
try {
session->validate();
return (true);
} catch (const std::exception& ex) {
errs << "validate fails with " << ex.what() << endl;
}
try {
S_Errors s_errors = session->get_last_errors();
if (!s_errors) {
errs << "no errors" << endl;
return (false);
}
size_t cnt = s_errors->error_cnt();
errs << "got " << cnt << " errors" << endl;
for (size_t i = 0; i < cnt; ++i) {
S_Error s_error = s_errors->error(i);
if (!s_error) {
continue;
}
const char* xpath = s_error->xpath();
const char* message = s_error->message();
if (!xpath || !message) {
continue;
}
// Bug in sysrepo returning message for xpath().
if (xpath == message) {
errs << message << endl;
} else {
errs << message << endl
<< "At " << xpath << endl;
}
}
} catch (const std::exception& ex) {
// Bug in sysrepo rethrowing the last error when trying to get it.
errs << "double error " << ex.what();
}
return (false);
}
ostream&
operator<<(ostream& os, sr_type_t type) {
switch (type) {
case SR_CONTAINER_T:
os << "container";
break;
case SR_CONTAINER_PRESENCE_T:
os << "container presence";
break;
case SR_LIST_T:
os << "list";
break;
case SR_STRING_T:
os << "string";
break;
case SR_BOOL_T:
os << "bool";
break;
case SR_UINT8_T:
os << "uint8";
break;
case SR_UINT16_T:
os << "uint16";
break;
case SR_UINT32_T:
os << "uint32";
break;
case SR_INT8_T:
os << "int8";
break;
case SR_INT16_T:
os << "int16";
break;
case SR_INT32_T:
os << "int32";
break;
case SR_IDENTITYREF_T:
os << "identity ref";
break;
case SR_ENUM_T:
os << "enum";
break;
case SR_BINARY_T:
os << "binary";
break;
case SR_LEAF_EMPTY_T:
os << "leaf empty";
break;
case SR_BITS_T:
os << "bits";
break;
case SR_DECIMAL64_T:
os << "decimal64";
break;
case SR_INSTANCEID_T:
os << "instance id";
break;
case SR_INT64_T:
os << "int64";
break;
case SR_UINT64_T:
os << "uint64";
break;
case SR_ANYXML_T:
os << "any xml";
break;
case SR_ANYDATA_T:
os << "any data";
break;
#ifdef SR_UNION_T
case SR_UNION_T:
os << "union";
break;
#endif
default:
os << type;
break;
}
return (os);
}
ostream& operator<<(ostream& os, const YangRepr::YangReprItem& item) {
os << item.xpath_ << " = (" << item.type_ << ") '" << item.value_ << "'";
return (os);
}
ostream& operator<<(ostream& os, const YangRepr::Tree& tree) {
for (auto item : tree) {
os << item << endl;
}
return (os);
}
}; // end of namespace isc::yang::test
}; // end of namespace isc::yang
}; // end of namespace isc

View File

@ -0,0 +1,127 @@
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef ISC_TRANSLATOR_TEST_H
#define ISC_TRANSLATOR_TEST_H 1
#include <yang/translator.h>
#include <vector>
#include <iostream>
namespace isc {
namespace yang {
namespace test {
/// @brief Yang/sysrepo datastore textual representation class.
class YangRepr {
public:
/// @brief Constructor.
///
/// @param model The model name.
YangRepr(const std::string& model) : model_(model) {
}
/// @brief The item class.
struct YangReprItem {
/// @brief Constructor with content.
///
/// @param xpath The xpath.
/// @param value The textual value.
/// @param type The type of the value.
/// @param settable The settable flag.
YangReprItem(std::string xpath, std::string value,
sr_type_t type, bool settable)
: xpath_(xpath), value_(value), type_(type), settable_(settable) {
}
/// @brief Factory from session.
///
/// @param xpath The xpath.
/// @param session Sysrepo session.
static YangReprItem get(const std::string& xpath, S_Session session);
/// @brief The xpath.
std::string xpath_;
/// @brief The textual value.
std::string value_;
/// @brief The type of the value.
sr_type_t type_;
/// @brief The settable flag.
bool settable_;
/// @brief The equal operator ignoring settable.
bool operator==(const YangReprItem& other) const {
return ((xpath_ == other.xpath_) &&
(value_ == other.value_) &&
(type_ == other.type_));
}
/// @brief The unequal operator ignoring settable.
bool operator!=(const YangReprItem& other) const {
return (!(*this == other));
}
};
/// @brief Tree type.
typedef std::vector<YangReprItem> Tree;
/// @brief Get tree from session.
///
/// @param session Sysrepo session.
Tree get(S_Session session) const;
/// @brief Verify tree.
///
/// @param expected The expected value.
/// @param session Sysrepo session.
/// @param errs Error stream.
/// @return True if verification succeeds, false with errors displayed
/// on errs if it fails.
bool verify(const Tree& expected, S_Session session,
std::ostream& errs) const;
/// @brief Set tree to session.
///
/// @param tree The tree to install.
/// @param session Sysrepo session.
void set(const Tree& tree, S_Session session) const;
/// @brief Validate.
///
/// @param session Sysrepo session.
/// @param errs Error stream.
/// @return True if validation succeeds, false with errors displayed
/// on errs if it fails.
bool validate(S_Session session, std::ostream& errs) const;
/// @brief The model name.
std::string model_;
};
/// @brief Alias for Items.
typedef YangRepr::YangReprItem YRItem;
/// @brief Alias for Trees.
typedef YangRepr::Tree YRTree;
/// @brief Overrides standard output operator for sr_type_t.
std::ostream& operator<<(std::ostream& os, sr_type_t type);
/// @brief Overrides standard output operator for @c YangReprItem object.
std::ostream& operator<<(std::ostream& os, const YRItem& item);
/// @brief Overrides standard output operator for @c Tree object.
std::ostream& operator<<(std::ostream& os, const YRTree& tree);
}; // end of namespace isc::yang::test
}; // end of namespace isc::yang
}; // end of namespace isc
#endif // ISC_TRANSLATOR_TEST_H