Browse Source

[5039] Unit-tests for SimpleParser added.

Tomek Mrugalski 8 years ago
parent
commit
d352a45e2b

+ 1 - 0
src/lib/cc/Makefile.am

@@ -7,6 +7,7 @@ AM_CXXFLAGS = $(KEA_CXXFLAGS)
 lib_LTLIBRARIES = libkea-cc.la
 libkea_cc_la_SOURCES = data.cc data.h
 libkea_cc_la_SOURCES += command_interpreter.cc command_interpreter.h
+libkea_cc_la_SOURCES += simple_parser.cc simple_parser.h
 
 libkea_cc_la_LIBADD  = $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
 libkea_cc_la_LIBADD += $(BOOST_LIBS)

+ 14 - 115
src/lib/cc/simple_parser.cc

@@ -1,68 +1,19 @@
-#include <dhcpsrv/parsers/simple_parser.h>
+// Copyright (C) 2016 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 <cc/simple_parser.h>
 #include <boost/foreach.hpp>
 #include <boost/lexical_cast.hpp>
 #include <cc/data.h>
 #include <string>
 
 using namespace std;
-using namespace isc::data;
 
 namespace isc {
-namespace dhcp {
-
-/// This table defines default values for option definitions in DHCPv4
-const SimpleDefaults OPTION4_DEF_DEFAULTS = {
-    { "record-types", Element::string,  ""},
-    { "space",        Element::string,  "dhcp4"},
-    { "array",        Element::boolean, "false"},
-    { "encapsulate",  Element::string,  "" }
-};
-
-/// This table defines default values for option definitions in DHCPv6
-const SimpleDefaults OPTION6_DEF_DEFAULTS = {
-    { "record-types", Element::string,  ""},
-    { "space",        Element::string,  "dhcp6"},
-    { "array",        Element::boolean, "false"},
-    { "encapsulate",  Element::string,  "" }
-};
-
-/// This table defines default values for options in DHCPv4
-const SimpleDefaults OPTION4_DEFAULTS = {
-    { "space",        Element::string,  "dhcp4"},
-    { "csv-format",   Element::boolean, "true"},
-    { "encapsulate",  Element::string,  "" }
-};
-
-/// This table defines default values for options in DHCPv6
-const SimpleDefaults OPTION6_DEFAULTS = {
-    { "space",        Element::string,  "dhcp6"},
-    { "csv-format",   Element::boolean, "true"},
-    { "encapsulate",  Element::string,  "" }
-};
-
-/// This table defines default values for DHCPv4
-const SimpleDefaults GLOBAL4_DEFAULTS = {
-    { "renew-timer",        Element::integer, "900" },
-    { "rebind-timer",       Element::integer, "1800" },
-    { "valid-lifetime",     Element::integer, "7200" }
-};
-
-/// This table defines default values for both DHCPv4 and DHCPv6
-const SimpleDefaults GLOBAL6_DEFAULTS = {
-    { "renew-timer",        Element::integer, "900" },
-    { "rebind-timer",       Element::integer, "1800" },
-    { "preferred-lifetime", Element::integer, "3600" },
-    { "valid-lifetime",     Element::integer, "7200" }
-};
-
-/// This list defines parameters that can be inherited from the global
-/// scope to subnet scope.
-const ParamsList INHERIT_GLOBAL_TO_SUBNET = {
-    "renew-timer",
-    "rebind-timer",
-    "preferred-lifetime",
-    "valid-lifetime"
-};
+namespace data {
 
 std::string
 SimpleParser::getString(isc::data::ConstElementPtr scope, const std::string& name) {
@@ -104,7 +55,7 @@ SimpleParser::getBoolean(isc::data::ConstElementPtr scope, const std::string& na
 }
 
 const data::Element::Position&
-SimpleParser::getPosition(const std::string& name, const data::ConstElementPtr parent) const {
+SimpleParser::getPosition(const std::string& name, const data::ConstElementPtr parent) {
     if (!parent) {
         return (data::Element::ZERO_POSITION());
     }
@@ -178,59 +129,13 @@ size_t SimpleParser::setDefaults(isc::data::ElementPtr scope,
     return (cnt);
 }
 
-size_t SimpleParser::setGlobalDefaults(isc::data::ElementPtr global, bool v6) {
-    return (setDefaults(global, v6 ? GLOBAL6_DEFAULTS : GLOBAL4_DEFAULTS));
-}
-
-size_t SimpleParser::setOptionDefaults(isc::data::ElementPtr option, bool v6) {
-    return (setDefaults(option, v6?OPTION6_DEFAULTS : OPTION4_DEFAULTS));
-}
-
-size_t SimpleParser::setOptionListDefaults(isc::data::ElementPtr option_list, bool v6) {
-    size_t cnt = 0;
-    BOOST_FOREACH(ElementPtr single_option, option_list->listValue()) {
-        cnt += setOptionDefaults(single_option, v6);
-    }
-    return (cnt);
-}
-
-size_t SimpleParser::setOptionDefDefaults(isc::data::ElementPtr option_def, bool v6) {
-    return (setDefaults(option_def, v6? OPTION6_DEF_DEFAULTS : OPTION4_DEF_DEFAULTS));
-}
-
-size_t SimpleParser::setOptionDefListDefaults(isc::data::ElementPtr option_def_list,
-                                              bool v6) {
-    size_t cnt = 0;
-    BOOST_FOREACH(ElementPtr single_def, option_def_list->listValue()) {
-        cnt += setOptionDefDefaults(single_def, v6);
-    }
-    return (cnt);
-}
-
-
-size_t SimpleParser::setAllDefaults(isc::data::ElementPtr global, bool v6) {
+size_t
+SimpleParser::setListDefaults(isc::data::ElementPtr list,
+                              const SimpleDefaults& default_values) {
     size_t cnt = 0;
-
-    // Set global defaults first.
-    /// @todo: Uncomment as part of the ticket 5019 work.
-    //cnt = setGlobalDefaults(global, v6);
-
-    // Now set option defintion defaults for each specified option definition
-    ConstElementPtr option_defs = global->get("option-def");
-    if (option_defs) {
-        BOOST_FOREACH(ElementPtr single_def, option_defs->listValue()) {
-            cnt += setOptionDefDefaults(single_def, v6);
-        }
-    }
-
-    ConstElementPtr options = global->get("option-data");
-    if (options) {
-        BOOST_FOREACH(ElementPtr single_option, options->listValue()) {
-            cnt += setOptionDefaults(single_option, v6);
-        }
-        //setOptionListDefaults(options);
+    BOOST_FOREACH(ElementPtr entry, list->listValue()) {
+        cnt += setDefaults(entry, default_values);
     }
-
     return (cnt);
 }
 
@@ -266,11 +171,5 @@ SimpleParser::deriveParams(isc::data::ConstElementPtr parent,
     return (cnt);
 }
 
-size_t
-SimpleParser::inheritGlobalToSubnet(isc::data::ConstElementPtr global,
-                                    isc::data::ElementPtr subnet) {
-    return deriveParams(global, subnet, INHERIT_GLOBAL_TO_SUBNET);
-}
-
 }; // end of isc::dhcp namespace
 }; // end of isc namespace

+ 17 - 80
src/lib/cc/simple_parser.h

@@ -1,3 +1,9 @@
+// Copyright (C) 2016 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 SIMPLE_PARSER_H
 #define SIMPLE_PARSER_H
 
@@ -6,7 +12,7 @@
 #include <stdint.h>
 
 namespace isc {
-namespace dhcp {
+namespace data {
 
 /// This array defines a single entry of default values
 struct SimpleDefault {
@@ -62,17 +68,6 @@ class SimpleParser {
     static size_t deriveParams(isc::data::ConstElementPtr parent,
                                isc::data::ElementPtr child,
                                const ParamsList& params);
-    /// @brief Derives (inherits) parameters from global to subnet scope
-    ///
-    /// This method derives global parameters into subnet scope if they're
-    /// not defined there yet.
-    ///
-    /// @param global parameters will be inherited from here
-    /// @param subnet parameters will be inserted here
-    /// @return number of parameters copied
-    static size_t
-    inheritGlobalToSubnet(isc::data::ConstElementPtr global,
-                          isc::data::ElementPtr subnet);
 
     /// @brief Sets the default values
     ///
@@ -88,64 +83,8 @@ class SimpleParser {
     static size_t setDefaults(isc::data::ElementPtr scope,
                               const SimpleDefaults& default_values);
 
-    /// @brief Sets global defaults
-    ///
-    /// This method sets global defaults. Note it does not set the
-    /// defaults for any scopes lower than global. See @ref setAllDefaults
-    /// for that.
-    ///
-    /// @param global scope to be filled in with defaults.
-    /// @param v6 is it v6 (true) or v4 (false) option?
-    /// @return number of default values added
-    static size_t setGlobalDefaults(isc::data::ElementPtr global, bool v6);
-
-    /// @brief Sets option defaults for a single option
-    ///
-    /// This method sets default values for a single option.
-    ///
-    /// @param option an option data to be filled in with defaults.
-    /// @param v6 is it v6 (true) or v4 (false) option?
-    /// @return number of default values added
-    static size_t setOptionDefaults(isc::data::ElementPtr option, bool v6);
-
-    /// @brief Sets option defaults for the whole options list
-    ///
-    /// This method sets default values for a list of options.
-    ///
-    /// @param option_list an option data to be filled in with defaults.
-    /// @param v6 is it v6 (true) or v4 (false) option?
-    /// @return number of default values added
-    static size_t setOptionListDefaults(isc::data::ElementPtr option_list, bool v6);
-
-    /// @brief Sets option defaults for a single option definition
-    ///
-    /// This method sets default values for a single option definition.
-    ///
-    /// @param option_def an option defintion to be filled in with defaults.
-    /// @param v6 is it v6 (true) or v4 (false) option defintion?
-    /// @return number of default values added
-    static size_t setOptionDefDefaults(isc::data::ElementPtr option_def, bool v6);
-
-    /// @brief Sets option defaults for the whole option definitions list
-    ///
-    /// This method sets default values for a list of option definitions.
-    ///
-    /// @param option_def_list a list of option defintions to be filled in with defaults.
-    /// @param v6 is it v6 (true) or v4 (false) option?
-    /// @return number of default values added
-    static size_t setOptionDefListDefaults(isc::data::ElementPtr option_def_list,
-                                           bool v6);
-
-    /// @brief Sets defaults for the whole configuration
-    ///
-    /// This method sets global, options and option definition defaults. Note
-    /// it does set the defaults for scopes lower than global. If you want to
-    /// set the global defaults only, see @ref setGlobalDefaults for that.
-    ///
-    /// @param global scope to be filled in with defaults.
-    /// @param v6 true = v6, false = v4
-    /// @return number of default values added
-    static size_t setAllDefaults(isc::data::ElementPtr global, bool v6);
+    static size_t setListDefaults(isc::data::ElementPtr list,
+                                  const SimpleDefaults& default_values);
 
     /// @brief Utility method that returns position of an element
     ///
@@ -154,14 +93,9 @@ class SimpleParser {
     /// @param name position of that element will be returned
     /// @param parent parent element (optional)
     /// @return position of the element specified.
-    const data::Element::Position&
+    static const data::Element::Position&
     getPosition(const std::string& name, const data::ConstElementPtr parent =
-                data::ConstElementPtr()) const;
-
-    /// Destructor
-    ///
-    /// It's really simple, isn't it?
-    virtual ~SimpleParser() {}
+                data::ConstElementPtr());
 
  protected:
 
@@ -173,7 +107,8 @@ class SimpleParser {
     /// @param scope specified parameter will be extracted from this scope
     /// @param name name of the parameter
     /// @return a string value of the parameter
-    static std::string getString(isc::data::ConstElementPtr scope, const std::string& name);
+    static std::string getString(isc::data::ConstElementPtr scope,
+                                 const std::string& name);
 
     /// @brief Returns an integer parameter from a scope
     ///
@@ -183,7 +118,8 @@ class SimpleParser {
     /// @param scope specified parameter will be extracted from this scope
     /// @param name name of the parameter
     /// @return an integer value of the parameter
-    static int64_t getInteger(isc::data::ConstElementPtr scope, const std::string& name);
+    static int64_t getInteger(isc::data::ConstElementPtr scope,
+                              const std::string& name);
 
     /// @brief Returns a boolean parameter from a scope
     ///
@@ -193,7 +129,8 @@ class SimpleParser {
     /// @param scope specified parameter will be extracted from this scope
     /// @param name name of the parameter
     /// @return a boolean value of the parameter
-    static bool getBoolean(isc::data::ConstElementPtr scope, const std::string& name);
+    static bool getBoolean(isc::data::ConstElementPtr scope,
+                           const std::string& name);
 };
 
 };

+ 2 - 1
src/lib/cc/tests/Makefile.am

@@ -1,6 +1,6 @@
 AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES)
-AM_CXXFLAGS = $(KEA_CXXFLAGS)
+AM_CXXFLAGS = $(KEA_CXXFLAGS) -std=c++11
 
 if USE_STATIC_LINK
 AM_LDFLAGS = -static
@@ -16,6 +16,7 @@ if HAVE_GTEST
 TESTS += run_unittests
 run_unittests_SOURCES = command_interpreter_unittests.cc data_unittests.cc
 run_unittests_SOURCES += data_file_unittests.cc run_unittests.cc
+run_unittests_SOURCES += simple_parser_unittest.cc
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 

+ 132 - 0
src/lib/cc/tests/simple_parser_unittest.cc

@@ -0,0 +1,132 @@
+// Copyright (C) 2016 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 <cc/simple_parser.h>
+#include <gtest/gtest.h>
+
+using namespace isc::data;
+
+/// This table defines sample default values. Although these are DHCPv6
+/// specific, the mechanism is generic and can be used by any other component.
+const SimpleDefaults SAMPLE_DEFAULTS = {
+    { "renew-timer",        Element::integer, "900" },
+    { "rebind-timer",       Element::integer, "1800" },
+    { "preferred-lifetime", Element::integer, "3600" },
+    { "valid-lifetime",     Element::integer, "7200" }
+};
+
+/// This list defines parameters that can be inherited from one scope
+/// to another. Although these are DHCPv6 specific, the mechanism is generic and
+/// can be used by any other component.
+const ParamsList SAMPLE_INHERITS = {
+    "renew-timer",
+    "rebind-timer",
+    "preferred-lifetime",
+    "valid-lifetime"
+};
+
+/// @brief Simple Parser test fixture class
+class SimpleParserTest : public ::testing::Test {
+public:
+    /// @brief Checks if specified map has an integer parameter with expected value
+    ///
+    /// @param map map to be checked
+    /// @param param_name name of the parameter to be checked
+    /// @param exp_value expected value of the parameter.
+    void checkIntegerValue(const ConstElementPtr& map, const std::string& param_name,
+                           int64_t exp_value) {
+
+        // First check if the passed element is a map.
+        ASSERT_EQ(Element::map, map->getType());
+
+        // Now try to get the element being checked
+        ConstElementPtr elem = map->get(param_name);
+        ASSERT_TRUE(elem);
+
+        // Now check if it's indeed integer
+        ASSERT_EQ(Element::integer, elem->getType());
+
+        // Finally, check if its value meets expectation.
+        EXPECT_EQ(exp_value, elem->intValue());
+    }
+};
+
+// This test checks if the parameters can be inherited from the global
+// scope to the subnet scope.
+TEST_F(SimpleParserTest, deriveParams) {
+    ElementPtr global = Element::fromJSON("{ \"renew-timer\": 1,"
+                                          "  \"rebind-timer\": 2,"
+                                          "  \"preferred-lifetime\": 3,"
+                                          "  \"valid-lifetime\": 4"
+                                          "}");
+    ElementPtr subnet = Element::fromJSON("{ \"renew-timer\": 100 }");
+
+    // we should inherit 3 parameters. Renew-timer should remain intact,
+    // as it was already defined in the subnet scope.
+    size_t num;
+    EXPECT_NO_THROW(num = SimpleParser::deriveParams(global, subnet,
+                                                     SAMPLE_INHERITS));
+    EXPECT_EQ(3, num);
+
+    // Check the values. 3 of them are interited, while the fourth one
+    // was already defined in the subnet, so should not be inherited.
+    checkIntegerValue(subnet, "renew-timer", 100);
+    checkIntegerValue(subnet, "rebind-timer", 2);
+    checkIntegerValue(subnet, "preferred-lifetime", 3);
+    checkIntegerValue(subnet, "valid-lifetime", 4);
+}
+
+// This test checks if global defaults are properly set for DHCPv6.
+TEST_F(SimpleParserTest, setDefaults) {
+
+    ElementPtr empty = Element::fromJSON("{ }");
+    size_t num = 0;
+
+    EXPECT_NO_THROW(num = SimpleParser::setDefaults(empty, SAMPLE_DEFAULTS));
+
+    // We expect at least 4 parameters to be inserted.
+    EXPECT_GE(num, 3);
+
+    checkIntegerValue(empty, "valid-lifetime", 7200);
+    checkIntegerValue(empty, "preferred-lifetime", 3600);
+    checkIntegerValue(empty, "rebind-timer", 1800);
+    checkIntegerValue(empty, "renew-timer", 900);
+}
+
+// This test checks if global defaults are properly set for DHCPv6.
+TEST_F(SimpleParserTest, setListDefaults) {
+
+    ElementPtr empty = Element::fromJSON("[{}, {}, {}]");
+    size_t num;
+
+    EXPECT_NO_THROW(num = SimpleParser::setListDefaults(empty, SAMPLE_DEFAULTS));
+
+    // We expect at least 12 parameters to be inserted (3 entries, with
+    // 4 parameters inserted in each)
+    EXPECT_EQ(12, num);
+
+    ASSERT_EQ(Element::list, empty->getType());
+    ASSERT_EQ(3, empty->size());
+
+    ConstElementPtr first = empty->get(0);
+    ConstElementPtr second = empty->get(1);
+    ConstElementPtr third = empty->get(2);
+
+    checkIntegerValue(first, "valid-lifetime", 7200);
+    checkIntegerValue(first, "preferred-lifetime", 3600);
+    checkIntegerValue(first, "rebind-timer", 1800);
+    checkIntegerValue(first, "renew-timer", 900);
+
+    checkIntegerValue(second, "valid-lifetime", 7200);
+    checkIntegerValue(second, "preferred-lifetime", 3600);
+    checkIntegerValue(second, "rebind-timer", 1800);
+    checkIntegerValue(second, "renew-timer", 900);
+
+    checkIntegerValue(third, "valid-lifetime", 7200);
+    checkIntegerValue(third, "preferred-lifetime", 3600);
+    checkIntegerValue(third, "rebind-timer", 1800);
+    checkIntegerValue(third, "renew-timer", 900);
+}

+ 0 - 4
src/lib/dhcpsrv/Makefile.am

@@ -33,8 +33,6 @@ EXTRA_DIST =
 EXTRA_DIST += parsers/client_class_def_parser.cc
 EXTRA_DIST += parsers/client_class_def_parser.h
 EXTRA_DIST += parsers/dhcp_config_parser.h
-EXTRA_DIST += parsers/simple_parser.cc
-EXTRA_DIST += parsers/simple_parser.h
 EXTRA_DIST += parsers/dbaccess_parser.cc
 EXTRA_DIST += parsers/dbaccess_parser.h
 EXTRA_DIST += parsers/dhcp_parsers.cc
@@ -164,8 +162,6 @@ libkea_dhcpsrv_la_SOURCES += parsers/dbaccess_parser.cc
 libkea_dhcpsrv_la_SOURCES += parsers/dbaccess_parser.h
 libkea_dhcpsrv_la_SOURCES += parsers/dhcp_parsers.cc
 libkea_dhcpsrv_la_SOURCES += parsers/dhcp_parsers.h
-libkea_dhcpsrv_la_SOURCES += parsers/simple_parser.cc
-libkea_dhcpsrv_la_SOURCES += parsers/simple_parser.h
 libkea_dhcpsrv_la_SOURCES += parsers/duid_config_parser.cc
 libkea_dhcpsrv_la_SOURCES += parsers/duid_config_parser.h
 libkea_dhcpsrv_la_SOURCES += parsers/expiration_config_parser.cc