diff options
author | thomson <thomson@ubuntu16.04> | 2018-09-12 01:15:49 +0200 |
---|---|---|
committer | thomson <thomson@ubuntu16.04> | 2018-09-12 01:15:49 +0200 |
commit | 9f8f3aec5874893ec1504048e234b8d73cbe6c49 (patch) | |
tree | da46697e21cffb005ec8267f0a4d5aa2c4779cb7 | |
parent | [#65,!18] Unit-test added for sanity checking the environment. (diff) | |
download | kea-9f8f3aec5874893ec1504048e234b8d73cbe6c49.tar.xz kea-9f8f3aec5874893ec1504048e234b8d73cbe6c49.zip |
[#65,!18] Now all tests uses test-module
-rw-r--r-- | src/lib/yang/tests/Makefile.am | 2 | ||||
-rw-r--r-- | src/lib/yang/tests/test-module.yang | 605 | ||||
-rw-r--r-- | src/lib/yang/tests/translator_unittests.cc | 107 |
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()); |