]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[405-update-cb_cmds] Missing space
authorFrancis Dupont <fdupont@isc.org>
Wed, 23 Jan 2019 02:32:32 +0000 (03:32 +0100)
committerFrancis Dupont <fdupont@isc.org>
Thu, 24 Jan 2019 09:39:08 +0000 (04:39 -0500)
src/lib/cc/simple_parser.cc
src/lib/cc/simple_parser.h
src/lib/cc/tests/simple_parser_unittest.cc

index 742db7940182d6fe3f7dc5dbe5f602a2111d2b1b..621383735446cf5f073139918f6c9cd82216aa12 100644 (file)
@@ -20,8 +20,43 @@ using isc::dhcp::DhcpConfigError;
 namespace isc {
 namespace data {
 
+void
+SimpleParser::checkRequired(const SimpleRequiredKeywords& required,
+                            ConstElementPtr scope) {
+    for (auto name : required) {
+        if (scope->contains(name)) {
+            continue;
+        }
+        isc_throw(DhcpConfigError, "missing '" << name << "' parameter");
+    }
+}
+
+void
+SimpleParser::checkKeywords(const SimpleKeywords& keywords,
+                            ConstElementPtr scope) {
+    string spurious;
+    for (auto entry : scope->mapValue()) {
+        if (keywords.count(entry.first) == 0) {
+            if (spurious.empty()) {
+                spurious = entry.first;
+            }
+            continue;
+        }
+        Element::types expected = keywords.at(entry.first);
+        if (entry.second->getType() == expected) {
+            continue;
+        }
+        isc_throw(DhcpConfigError, "'" << entry.first << "' parameter is not "
+                  << (expected == Element::integer ? "an " : "a ")
+                  << Element::typeToName(expected));
+    }
+    if (!spurious.empty()) {
+        isc_throw(DhcpConfigError, "spurious '" << spurious << "' parameter");
+    }
+}
+
 std::string
-SimpleParser::getString(isc::data::ConstElementPtr scope, const std::string& name) {
+SimpleParser::getString(ConstElementPtr scope, const std::string& name) {
     ConstElementPtr x = scope->get(name);
     if (!x) {
         isc_throw(DhcpConfigError,
@@ -38,7 +73,7 @@ SimpleParser::getString(isc::data::ConstElementPtr scope, const std::string& nam
 }
 
 int64_t
-SimpleParser::getInteger(isc::data::ConstElementPtr scope, const std::string& name) {
+SimpleParser::getInteger(ConstElementPtr scope, const std::string& name) {
     ConstElementPtr x = scope->get(name);
     if (!x) {
         isc_throw(DhcpConfigError,
@@ -55,7 +90,7 @@ SimpleParser::getInteger(isc::data::ConstElementPtr scope, const std::string& na
 }
 
 bool
-SimpleParser::getBoolean(isc::data::ConstElementPtr scope, const std::string& name) {
+SimpleParser::getBoolean(ConstElementPtr scope, const std::string& name) {
     ConstElementPtr x = scope->get(name);
     if (!x) {
         isc_throw(DhcpConfigError,
@@ -85,7 +120,7 @@ SimpleParser::getAddress(const ConstElementPtr& scope,
 }
 
 double
-SimpleParser::getDouble(const isc::data::ConstElementPtr& scope,
+SimpleParser::getDouble(const ConstElementPtr& scope,
                         const std::string& name) {
     ConstElementPtr x = scope->get(name);
     if (!x) {
@@ -116,7 +151,7 @@ SimpleParser::getPosition(const std::string& name, const data::ConstElementPtr p
     return (elem->getPosition());
 }
 
-size_t SimpleParser::setDefaults(isc::data::ElementPtr scope,
+size_t SimpleParser::setDefaults(ElementPtr scope,
                                  const SimpleDefaults& default_values) {
     size_t cnt = 0;
 
@@ -190,7 +225,7 @@ size_t SimpleParser::setDefaults(isc::data::ElementPtr scope,
 }
 
 size_t
-SimpleParser::setListDefaults(isc::data::ConstElementPtr list,
+SimpleParser::setListDefaults(ConstElementPtr list,
                               const SimpleDefaults& default_values) {
     size_t cnt = 0;
     BOOST_FOREACH(ElementPtr entry, list->listValue()) {
@@ -200,8 +235,8 @@ SimpleParser::setListDefaults(isc::data::ConstElementPtr list,
 }
 
 size_t
-SimpleParser::deriveParams(isc::data::ConstElementPtr parent,
-                           isc::data::ElementPtr child,
+SimpleParser::deriveParams(ConstElementPtr parent,
+                           ElementPtr child,
                            const ParamsList& params) {
     if ( (parent->getType() != Element::map) ||
          (child->getType() != Element::map)) {
index 26341018ff8749fcaa7a7662de995932642c3222..bb8e175a74b1a303476a41f238112d6ac2fac255 100644 (file)
@@ -10,6 +10,7 @@
 #include <asiolink/io_address.h>
 #include <cc/data.h>
 #include <cc/dhcp_config_error.h>
+#include <map>
 #include <vector>
 #include <string>
 #include <stdint.h>
@@ -18,7 +19,7 @@
 namespace isc {
 namespace data {
 
-/// This array defines a single entry of default values
+/// This array defines a single entry of default values.
 struct SimpleDefault {
     SimpleDefault(const char* name, isc::data::Element::types type, const char* value)
         :name_(name), type_(type), value_(value) {}
@@ -27,11 +28,17 @@ struct SimpleDefault {
     const char* value_;
 };
 
-/// This specifies all default values in a given scope (e.g. a subnet)
+/// This specifies all required keywords.
+typedef std::vector<std::string> SimpleRequiredKeywords;
+
+/// This specifies all accepted keywords with their types.
+typedef std::map<std::string, isc::data::Element::types> SimpleKeywords;
+
+/// This specifies all default values in a given scope (e.g. a subnet).
 typedef std::vector<SimpleDefault> SimpleDefaults;
 
 /// This defines a list of all parameters that are derived (or inherited) between
-/// contexts
+/// contexts.
 typedef std::vector<std::string> ParamsList;
 
 
@@ -60,6 +67,30 @@ typedef std::vector<std::string> ParamsList;
 class SimpleParser {
  public:
 
+    /// @brief Checks that all required keywords are present.
+    ///
+    /// This method throws an exception when a required
+    /// entry is not present un the given scope.
+    ///
+    /// @param required Required keywords.
+    /// @param scope Specified parameters which are checked.
+    /// @throw DhcpConfigError if a required parameter is not present.
+    static void checkRequired(const SimpleRequiredKeywords& required,
+                              isc::data::ConstElementPtr scope);
+
+    /// @brief Checks acceptable keywords with their expected type.
+    ///
+    /// This methods throws an exception when a not acceptable keyword
+    /// is found or when an acceptable entry does not have the expected type.
+    ///
+    /// @param keywords The @c SimpleKeywords keywords and types map.
+    /// @param scope Specified parameters which are checked.
+    /// @throw DhcpConfigError if a not acceptable keyword is found.
+    /// @throw DhcpConfigError if an acceptable entry does not have
+    /// the expected type.
+    static void checkKeywords(const SimpleKeywords& keywords,
+                              isc::data::ConstElementPtr scope);
+
     /// @brief Derives (inherits) parameters from parent scope to a child
     ///
     /// This method derives parameters from the parent scope to the child,
index a43dc6a4fbfb272865628b16ab401678d420af37..3c1d49cb1a868fdb70c6a6f101449481e9c4cf74 100644 (file)
@@ -14,6 +14,16 @@ using namespace isc::data;
 using namespace isc::asiolink;
 using isc::dhcp::DhcpConfigError;
 
+/// This list defines required keywords.
+const SimpleRequiredKeywords REQUIRED_KEYWORDS = { "foobar" };
+
+/// This table defines keywords and types.
+const SimpleKeywords KEYWORDS = {
+    { "id",     Element::integer },
+    { "prefix", Element::string },
+    { "map",    Element::map }
+};
+
 /// 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 = {
@@ -86,6 +96,49 @@ public:
     }
 };
 
+// This test checks if the checkRequired method works as expected.
+TEST_F(SimpleParserTest, checkRequired) {
+    ConstElementPtr empty = Element::fromJSON("{ }");
+    EXPECT_THROW(SimpleParser::checkRequired(REQUIRED_KEYWORDS, empty),
+                 DhcpConfigError);
+    ConstElementPtr other = Element::fromJSON("{ \"foo\": 1, \"bar\": 2 }");
+    EXPECT_THROW(SimpleParser::checkRequired(REQUIRED_KEYWORDS, other),
+                 DhcpConfigError);
+    ConstElementPtr good = Element::fromJSON("{ \"foobar\": 2 }");
+    EXPECT_NO_THROW(SimpleParser::checkRequired(REQUIRED_KEYWORDS, good));
+}
+
+// This test checks if the checkKeywords method works as expected.
+TEST_F(SimpleParserTest, checkKeywords) {
+    ConstElementPtr empty = Element::fromJSON("{ }");
+    EXPECT_NO_THROW(SimpleParser::checkKeywords(KEYWORDS, empty));
+    ConstElementPtr id = Element::fromJSON("{ \"id\": 1 }");
+    EXPECT_NO_THROW(SimpleParser::checkKeywords(KEYWORDS, id));
+    ConstElementPtr bad_id = Element::fromJSON("{ \"id\": true }");
+    EXPECT_THROW(SimpleParser::checkKeywords(KEYWORDS, bad_id),
+                 DhcpConfigError);
+    ConstElementPtr bad_prefix = Element::fromJSON("{ \"prefix\": 12 }");
+    EXPECT_THROW(SimpleParser::checkKeywords(KEYWORDS, bad_prefix),
+                 DhcpConfigError);
+    ConstElementPtr bad_map = Element::fromJSON("{ \"map\": [ ] }");
+    EXPECT_THROW(SimpleParser::checkKeywords(KEYWORDS, bad_map),
+                 DhcpConfigError);
+    ConstElementPtr spurious = Element::fromJSON("{ \"spurious\": 1 }");
+    EXPECT_THROW(SimpleParser::checkKeywords(KEYWORDS, spurious),
+                 DhcpConfigError);
+
+    // Bad type has precedence.
+    ConstElementPtr bad = Element::fromJSON("{ \"spurious\": 1, \"id\": true }");
+    try {
+        SimpleParser::checkKeywords(KEYWORDS, bad);
+        ADD_FAILURE() << "expect exception";
+    } catch (const DhcpConfigError& ex) {
+        EXPECT_EQ("'id' parameter is not an integer", std::string(ex.what()));
+    } catch (...) {
+        ADD_FAILURE() << "expect DhcpConfigError";
+    }
+}
+
 // This test checks if the parameters can be inherited from the global
 // scope to the subnet scope.
 TEST_F(SimpleParserTest, deriveParams) {