summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthomson <thomson@ubuntu16.04>2018-09-12 01:15:49 +0200
committerthomson <thomson@ubuntu16.04>2018-09-12 01:15:49 +0200
commit9f8f3aec5874893ec1504048e234b8d73cbe6c49 (patch)
treeda46697e21cffb005ec8267f0a4d5aa2c4779cb7
parent[#65,!18] Unit-test added for sanity checking the environment. (diff)
downloadkea-9f8f3aec5874893ec1504048e234b8d73cbe6c49.tar.xz
kea-9f8f3aec5874893ec1504048e234b8d73cbe6c49.zip
[#65,!18] Now all tests uses test-module
-rw-r--r--src/lib/yang/tests/Makefile.am2
-rw-r--r--src/lib/yang/tests/test-module.yang605
-rw-r--r--src/lib/yang/tests/translator_unittests.cc107
3 files changed, 668 insertions, 46 deletions
diff --git a/src/lib/yang/tests/Makefile.am b/src/lib/yang/tests/Makefile.am
index 4391cddf84..066985fe3b 100644
--- a/src/lib/yang/tests/Makefile.am
+++ b/src/lib/yang/tests/Makefile.am
@@ -12,6 +12,8 @@ CLEANFILES = *.gcno *.gcda
TESTS_ENVIRONMENT = \
$(LIBTOOL) --mode=execute $(VALGRIND_COMMAND)
+EXTRA_DIST = test-module.yang
+
TESTS =
if HAVE_GTEST
TESTS += run_unittests
diff --git a/src/lib/yang/tests/test-module.yang b/src/lib/yang/tests/test-module.yang
new file mode 100644
index 0000000000..088713a12b
--- /dev/null
+++ b/src/lib/yang/tests/test-module.yang
@@ -0,0 +1,605 @@
+module test-module {
+ yang-version 1.1;
+ namespace "urn:ietf:params:xml:ns:yang:test-module";
+ prefix tm;
+
+ import ietf-inet-types {
+ prefix inet;
+ }
+
+ organization "Sysrepo and ISC";
+ description
+ "ISC imported an example module from Sysrepo tests and adapted it
+ to kea testing regime.";
+ contact
+ "kea-dev@lists.isc.org";
+
+ container container {
+ config true;
+ list list {
+ leaf leaf {
+ type string;
+ }
+ leaf key1 {
+ type string;
+ }
+ leaf key2 {
+ type string;
+ }
+ key "key1 key2";
+ }
+ }
+
+ typedef threshold-power-dBm {
+ type union {
+ type decimal64 {
+ fraction-digits 2;
+ }
+ type enumeration {
+ enum off {
+ description "No threshold configured";
+ }
+ }
+ }
+ description "Power in dBm";
+ }
+
+ container main {
+ leaf enum {
+ type enumeration {
+ enum "yes" {
+ value 1;
+ }
+ enum "no" {
+ value 2;
+ }
+ enum "maybe" {
+ value 3;
+ }
+ }
+ }
+ leaf options {
+ type bits {
+ bit strict;
+ bit recursive;
+ bit logging;
+ }
+ }
+ leaf raw {
+ type binary;
+ }
+ leaf dec64 {
+ type decimal64{
+ fraction-digits 2;
+ }
+ }
+ leaf i8 {
+ type int8;
+ }
+ leaf i16 {
+ type int16;
+ }
+ leaf i32 {
+ type int32;
+ }
+ leaf i64 {
+ type int64;
+ }
+ leaf ui8 {
+ type uint8;
+ }
+ leaf ui16 {
+ type uint16;
+ }
+ leaf ui32 {
+ type uint32;
+ }
+ leaf ui64 {
+ type uint64;
+ }
+ leaf empty {
+ type empty;
+ }
+ leaf boolean {
+ type boolean;
+ }
+ leaf string {
+ type string;
+ }
+ leaf id_ref {
+ type identityref{
+ base base_id;
+ }
+ }
+ leaf-list numbers {
+ type uint8;
+ }
+ leaf instance_id {
+ type instance-identifier;
+ }
+ anyxml xml-data;
+ anydata any-data;
+ }
+
+ identity base_id;
+
+ identity id_1 {
+ base base_id;
+ }
+
+ identity id_2 {
+ base base_id;
+ }
+
+ list list {
+ key "key";
+ leaf key {
+ type string;
+ }
+ leaf id_ref {
+ type identityref{
+ base base_id;
+ }
+ }
+ leaf instance_id {
+ type instance-identifier;
+ }
+ leaf union {
+ type union{
+ type uint8;
+ type enumeration {
+ enum "infinity";
+ }
+ }
+ }
+ container wireless{
+ presence "wireless is enabled";
+ leaf vendor_name{
+ type string;
+ }
+ }
+ }
+
+ container transfer {
+ choice how {
+ default interval;
+ case interval {
+ leaf interval {
+ type uint16;
+ default 30;
+ units minutes;
+ }
+ }
+ case daily {
+ leaf daily {
+ type empty;
+ }
+ leaf time-of-day {
+ type string;
+ units 24-hour-clock;
+ default 1am;
+ }
+ }
+ case manual {
+ leaf manual {
+ type empty;
+ }
+ }
+ }
+ }
+
+ container location {
+ presence true;
+ leaf name {
+ type string;
+ }
+
+ leaf longitude {
+ type string;
+ mandatory true;
+ }
+
+ leaf latitude {
+ type string;
+ mandatory true;
+ }
+ }
+
+ leaf hexnumber{
+ type string {
+ length "0..4";
+ pattern "[0-9a-fA-F]*";
+ }
+ }
+
+ container interface {
+ leaf ifType {
+ type enumeration {
+ enum ethernet;
+ enum atm;
+ }
+ }
+ leaf ifMTU {
+ type uint32;
+ }
+ must "ifType != 'ethernet' or " +
+ "(ifType = 'ethernet' and ifMTU = 1500)" {
+ error-message "An ethernet MTU must be 1500";
+ }
+ must "ifType != 'atm' or " +
+ "(ifType = 'atm' and ifMTU <= 17966 and ifMTU >= 64)" {
+ error-message "An atm MTU must be 64 .. 17966";
+ }
+ }
+
+ list user {
+ description "This is a list of users in the system.";
+ ordered-by user;
+ config true;
+
+ key "name";
+
+ leaf name {
+ type string;
+ }
+ leaf type {
+ type string;
+ }
+ leaf full-name {
+ type string;
+ }
+ }
+
+ leaf-list ordered-numbers {
+ ordered-by user;
+ type uint8;
+ }
+
+ list with_def {
+ config true;
+ key "name";
+ leaf name {
+ type string;
+ }
+ leaf num {
+ type int8;
+ default 0;
+ }
+ }
+
+ rpc activate-software-image {
+ input {
+ leaf image-name {
+ type string;
+ must ". != /top-level-default";
+ }
+ leaf location {
+ type string;
+ default "/";
+ must ". != 'invalid location'";
+ }
+ }
+ output {
+ leaf status {
+ type string;
+ must ". != 'invalid status'";
+ }
+ leaf version {
+ type string;
+ }
+ leaf location {
+ type string;
+ default "/";
+ }
+ container init-log {
+ list log-msg {
+ key "msg time";
+ leaf msg {
+ type string;
+ }
+ leaf time {
+ type uint32;
+ }
+ leaf msg-type {
+ type enumeration {
+ enum "error" {
+ value 1;
+ }
+ enum "warning" {
+ value 2;
+ }
+ enum "debug" {
+ value 3;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ leaf top-level-default {
+ type string;
+ default "default value";
+ }
+
+ container university {
+ container students {
+ list student {
+ ordered-by user;
+ config true;
+
+ key "name";
+
+ leaf name {
+ type string;
+ }
+
+ leaf age {
+ type uint8;
+ }
+ }
+ }
+
+ container classes {
+ list class {
+ config true;
+
+ key "title";
+
+ leaf title {
+ type string;
+ }
+
+ list student {
+ key "name";
+
+ leaf name {
+ type leafref {
+ path "../../../../students/student/name";
+ }
+ }
+ leaf age {
+ type leafref {
+ path "../../../../students/student[name = current()/../name]/age";
+ }
+ }
+ }
+ }
+ }
+ }
+
+ container leafref-chain {
+ leaf A {
+ type leafref {
+ path "../B";
+ }
+ }
+
+ leaf B {
+ type leafref {
+ path "../C";
+ }
+ }
+
+ leaf C {
+ type leafref {
+ path "../D";
+ }
+ }
+
+ leaf D {
+ type string;
+ }
+ }
+
+ grouping link {
+ container source {
+ leaf address {
+ type inet:ipv4-address;
+ }
+ leaf interface {
+ type string;
+ }
+ }
+ container destination {
+ leaf address {
+ type inet:ipv4-address;
+ }
+ leaf interface {
+ type string;
+ }
+ }
+ leaf MTU {
+ type uint16;
+ default 1500;
+ }
+ }
+
+ notification link-discovered {
+ uses link;
+ }
+
+ notification link-removed {
+ uses link;
+ }
+
+ container kernel-modules {
+ list kernel-module {
+ key "name";
+
+ leaf name {
+ type string;
+ }
+
+ leaf location {
+ type string;
+ default "/lib/modules";
+ }
+
+ leaf loaded {
+ type boolean;
+ }
+
+ action load {
+ input {
+ leaf params {
+ mandatory "true";
+ type string;
+ }
+ leaf force {
+ type boolean;
+ default "false";
+ when "../../loaded = 'false'";
+ }
+ leaf dry-run {
+ type boolean;
+ default false;
+ }
+ }
+ output {
+ leaf return-code {
+ type uint8;
+ }
+ }
+ }
+
+ action unload { }
+
+ action get-dependencies {
+ output {
+ leaf-list dependency {
+ type string;
+ }
+ leaf location {
+ type leafref {
+ path "/kernel-modules/kernel-module[name = current()/../../name]/location";
+ }
+ }
+ leaf location2 {
+ type leafref {
+ path "../../location";
+ }
+ }
+ }
+ }
+
+ }
+ }
+
+ typedef uniontpdf {
+ type union {
+ type string {
+ pattern "disabled";
+ }
+ type uint8 {
+ range "1..100";
+ }
+ }
+ default "disabled";
+ }
+
+ typedef enumtpdf {
+ type enumeration {
+ enum "a" {
+ value 1;
+ }
+ enum "b" {
+ value 2;
+ }
+ enum "c" {
+ value 3;
+ }
+ }
+ }
+
+ typedef multiplunions {
+ type union {
+ type uniontpdf;
+ type enumtpdf;
+ type union {
+ type boolean;
+ type decimal64 {
+ fraction-digits 2;
+ }
+ }
+ }
+ }
+
+ typedef leafreftpdf {
+ type leafref {
+ path "/list/key";
+ }
+ }
+
+ typedef inttpdf {
+ type uint8 {
+ range "1..100";
+ }
+ }
+
+ container tpdfs {
+ leaf unival {
+ type uniontpdf;
+ }
+
+ leaf leafrefval {
+ type leafreftpdf;
+ }
+
+ leaf intval {
+ type inttpdf;
+ }
+
+ leaf undecided {
+ type multiplunions;
+ }
+ }
+
+ leaf dec64-in-union {
+ type threshold-power-dBm;
+ }
+
+ container presence-container {
+ presence "presence-container";
+
+ leaf topleaf1 {
+ type int8;
+ }
+
+ leaf topleaf2 {
+ type int8;
+ }
+
+ container child1 {
+ leaf child1-leaf {
+ type int8;
+ }
+
+ container grandchild1 {
+ leaf grandchild1-leaf {
+ type int8;
+ default 10;
+ }
+ }
+ }
+
+ container child2 {
+ leaf child2-leaf {
+ type int8;
+ }
+
+ container grandchild2 {
+ leaf grandchild2-leaf1 {
+ type int8;
+ }
+ leaf grandchild2-leaf2 {
+ type int8;
+ }
+ leaf grandchild2-leaf3 {
+ type int8;
+ }
+ }
+ }
+ }
+}
diff --git a/src/lib/yang/tests/translator_unittests.cc b/src/lib/yang/tests/translator_unittests.cc
index 263de9be90..f3dbbf4640 100644
--- a/src/lib/yang/tests/translator_unittests.cc
+++ b/src/lib/yang/tests/translator_unittests.cc
@@ -18,13 +18,15 @@ using namespace isc::yang;
namespace {
-const std::string TEST_MODULE="example-module";
+const std::string TEST_MODULE="test-module";
-// This test verifies if there are test models installed and accessible.
-// To run those tests properly, the following models need to be installed:
-// - example-module
-// - test-module
-TEST(TranslatorBasicTest, testEnvironmentCheck) {
+
+/// @brief checks if specified schema is installed and available in sysrepo
+///
+/// @name name of the schema to be checked (without .yang)
+/// @verbose print installed schemas?
+/// @return true if installed, false otherwise.
+bool schemaInstalled(const std::string& name, bool verbose = false) {
// Get a connection.
S_Connection conn(new Connection("translator unittests"));
// Get a session.
@@ -33,24 +35,37 @@ TEST(TranslatorBasicTest, testEnvironmentCheck) {
S_Yang_Schemas schemas = sess->list_schemas();
size_t schema_cnt = schemas->schema_cnt();
- std::cout << "There are " << schema_cnt << " YANG schema(s) installed:" << endl;
+
+ if (verbose) {
+ cout << "There are " << schema_cnt << " YANG schema(s) installed:" << endl;
+ }
bool found = false;
for (int i = 0; i < schema_cnt; i++) {
- string name(schemas->schema(i)->module_name());
- if (name == TEST_MODULE) {
- found = true;
- }
- std::cout << "Schema " << i << ": " << name << endl;
+ string installed_name(schemas->schema(i)->module_name());
+ if (installed_name == name) {
+ found = true;
+ }
+
+ if (verbose) {
+ std::cout << "Schema " << i << ": " << installed_name << endl;
+ }
}
- EXPECT_TRUE(found) << "\nERROR: Module used in unit-tests " << TEST_MODULE
- << " is not installed. The environment is not suitable for\n"
- << "ERROR: running unit-tests. Please locate example-module.yang "
- << "and issue the following command:\n"
- << "ERROR: sysrepoctl --install --yang=example-module.yang\n"
- << "ERROR:\n"
- << "ERROR: Following tests will most likely fail.\n";
+ return (found);
+}
+
+// This test verifies if the test schema is installed and accessible.
+TEST(TranslatorBasicTest, environmentCheck1) {
+
+ EXPECT_TRUE(schemaInstalled(TEST_MODULE))
+ << "\nERROR: Module used in unit-tests " << TEST_MODULE
+ << " is not installed. The environment is not suitable for\n"
+ << "ERROR: running unit-tests. Please locate " << TEST_MODULE <<".yang "
+ << "and issue the following command:\n"
+ << "ERROR: sysrepoctl --install --yang=" << TEST_MODULE << ".yang\n"
+ << "ERROR:\n"
+ << "ERROR: Following tests will most likely fail.\n";
}
// Test constructor.
@@ -185,11 +200,11 @@ TEST(TranslatorBasicTest, getItem) {
ASSERT_NO_THROW(t_obj.reset(new TranslatorBasic(sess)));
// Container.
- string xpath = "/example-module:container/list";
+ string xpath = "/test-module:container/list";
S_Val s_val;
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
ConstElementPtr elem;
- EXPECT_NO_THROW(elem = t_obj->getItem("/example-module:container"));
+ EXPECT_NO_THROW(elem = t_obj->getItem("/test-module:container"));
EXPECT_FALSE(elem);
elem.reset();
@@ -358,13 +373,13 @@ TEST(TranslatorBasicTest, getItem) {
// Check error.
xpath = "null";
try {
- elem = t_obj->getItem(xpath);
- ADD_FAILURE() << "expected exception";
+ elem = t_obj->getItem(xpath);
+ ADD_FAILURE() << "expected exception";
} catch (const SysrepoError& ex) {
- EXPECT_EQ("sysrepo error getting item at 'null': Invalid argument",
- string(ex.what()));
+ EXPECT_EQ("sysrepo error getting item at 'null': Invalid argument",
+ string(ex.what()));
} catch (const std::exception& ex) {
- ADD_FAILURE() << "unexpected exception with: " << ex.what();
+ ADD_FAILURE() << "unexpected exception with: " << ex.what();
}
}
@@ -465,7 +480,7 @@ TEST(TranslatorBasicTest, valueTo) {
ASSERT_TRUE(s_val);
EXPECT_EQ(str, string(s_val->data()->get_enum()));
s_val.reset();
-
+
// Binary.
elem = Element::create(string("foobar"));
EXPECT_NO_THROW(s_val = TranslatorBasic::value(elem, SR_BINARY_T));
@@ -487,14 +502,14 @@ TEST(TranslatorBasicTest, setItem) {
ASSERT_NO_THROW(t_obj.reset(new TranslatorBasic(sess)));
// Container.
- string xpath = "/example-module:container";
+ string xpath = "/test-module:container";
ConstElementPtr elem = Element::createMap();
EXPECT_THROW(t_obj->setItem(xpath, elem, SR_CONTAINER_T), NotImplemented);
EXPECT_THROW(t_obj->setItem(xpath, elem, SR_CONTAINER_PRESENCE_T),
- NotImplemented);
+ NotImplemented);
// List.
- xpath = "/example-module:container/list";
+ xpath = "/test-module:container/list";
elem = Element::createList();
EXPECT_NO_THROW(t_obj->setItem(xpath, elem, SR_LIST_T));
S_Val s_val;
@@ -647,28 +662,28 @@ TEST(TranslatorBasicTest, setItem) {
xpath = "/test-module:main/no_such_string";
elem = Element::create(string("str"));
try {
- t_obj->setItem(xpath, elem, SR_STRING_T);
- ADD_FAILURE() << "expected exception";
+ t_obj->setItem(xpath, elem, SR_STRING_T);
+ ADD_FAILURE() << "expected exception";
} catch (const SysrepoError& ex) {
- string expected = "sysrepo error setting item '\"str\"' at '" +
- xpath + "': Request contains unknown element";
- EXPECT_EQ(expected, string(ex.what()));
+ string expected = "sysrepo error setting item '\"str\"' at '" +
+ xpath + "': Request contains unknown element";
+ EXPECT_EQ(expected, string(ex.what()));
} catch (const std::exception& ex) {
- ADD_FAILURE() << "unexpected exception with: " << ex.what();
+ ADD_FAILURE() << "unexpected exception with: " << ex.what();
}
// Bad type.
xpath = "/test-module:main/string";
elem = Element::create(true);
try {
- t_obj->setItem(xpath, elem, SR_BOOL_T);
- ADD_FAILURE() << "expected exception";
+ t_obj->setItem(xpath, elem, SR_BOOL_T);
+ ADD_FAILURE() << "expected exception";
} catch (const SysrepoError& ex) {
- string expected = "sysrepo error setting item 'true' at '" +
- xpath + "': Invalid argument";
- EXPECT_EQ(expected, string(ex.what()));
+ string expected = "sysrepo error setting item 'true' at '" +
+ xpath + "': Invalid argument";
+ EXPECT_EQ(expected, string(ex.what()));
} catch (const std::exception& ex) {
- ADD_FAILURE() << "unexpected exception with: " << ex.what();
+ ADD_FAILURE() << "unexpected exception with: " << ex.what();
}
// Delete (twice).
@@ -692,20 +707,20 @@ TEST(TranslatorBasicTest, list) {
// Empty list.
S_Iter_Value iter;
- EXPECT_NO_THROW(iter = t_obj->getIter("/example-module:container/list"));
+ EXPECT_NO_THROW(iter = t_obj->getIter("/test-module:container/list"));
ASSERT_TRUE(iter);
string xpath;
EXPECT_NO_THROW(xpath = t_obj->getNext(iter));
EXPECT_TRUE(xpath.empty());
// Retried with a filled list.
- xpath = "/example-module:container/list[key1='key1'][key2='key2']/leaf";
+ xpath = "/test-module:container/list[key1='key1'][key2='key2']/leaf";
S_Val s_val(new Val("Leaf value"));
EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
- EXPECT_NO_THROW(iter = t_obj->getIter("/example-module:container/list"));
+ EXPECT_NO_THROW(iter = t_obj->getIter("/test-module:container/list"));
ASSERT_TRUE(iter);
EXPECT_NO_THROW(xpath = t_obj->getNext(iter));
- EXPECT_EQ("/example-module:container/list[key1='key1'][key2='key2']", xpath);
+ EXPECT_EQ("/test-module:container/list[key1='key1'][key2='key2']", xpath);
EXPECT_NO_THROW(xpath = t_obj->getNext(iter));
EXPECT_TRUE(xpath.empty());