mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 13:37:55 +00:00
[65-libyang-testutils] Filled files, ready for review
This commit is contained in:
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
206
src/lib/yang/tests/translator_utils_unittests.cc
Normal file
206
src/lib/yang/tests/translator_utils_unittests.cc
Normal 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
|
408
src/lib/yang/tests/yang_configs.h
Normal file
408
src/lib/yang/tests/yang_configs.h
Normal 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
|
22
src/lib/yang/testutils/Makefile.am
Normal file
22
src/lib/yang/testutils/Makefile.am
Normal 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
|
392
src/lib/yang/testutils/translator_test.cc
Normal file
392
src/lib/yang/testutils/translator_test.cc
Normal 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
|
127
src/lib/yang/testutils/translator_test.h
Normal file
127
src/lib/yang/testutils/translator_test.h
Normal 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
|
Reference in New Issue
Block a user