]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3609] Checkpoint: added error UT
authorFrancis Dupont <fdupont@isc.org>
Thu, 14 Nov 2024 14:52:32 +0000 (15:52 +0100)
committerFrancis Dupont <fdupont@isc.org>
Fri, 22 Nov 2024 08:55:31 +0000 (09:55 +0100)
src/bin/agent/ca_cfg_mgr.cc
src/lib/http/cfg_http_header.cc
src/lib/http/cfg_http_header.h
src/lib/http/tests/cfg_http_header_unittests.cc

index 4cb9da54801dd39361a4fb849fc6e4a7b6de45c8..95057f6231f8cb6138c92e3679e6ed5575925ce0 100644 (file)
@@ -189,7 +189,7 @@ CtrlAgentCfgContext::toElement() const {
     ca->set("http-port", Element::create(static_cast<int64_t>(http_port_)));
     // Set http-headers
     if (!http_headers_.empty()) {
-        ca->set("http-headers", toElement(http_headers_));
+        ca->set("http-headers", CfgHttpHeaderstoElement(http_headers_));
     }
     // Set TLS setup when enabled
     if (!trust_anchor_.empty()) {
index 7c7edf3e6b69fd5bf9bb9462dc3918153ec6f9df..098e95cc3f77b9f9c4dc3409b296073e903ee4da 100644 (file)
@@ -25,7 +25,7 @@ CfgHttpHeader::toElement() const {
 }
 
 ElementPtr
-toElement(const CfgHttpHeaders& headers) {
+CfgHttpHeaderstoElement(const CfgHttpHeaders& headers) {
     ElementPtr list = Element::createList();
     for (auto const& header : headers) {
         list->add(header.toElement());
@@ -57,12 +57,12 @@ parseCfgHttpHeader(const ConstElementPtr& config) {
     SimpleParser::checkRequired(HTTP_HEADER_REQUIRED, config);
     string name = config->get("name")->stringValue();
     if (name.empty()) {
-        isc_throw(DhcpConfigError, "empty 'name' ("
+        isc_throw(DhcpConfigError, "empty 'name' parameter ("
                   << config->get("name")->getPosition() << ")");
     }
     string value = config->get("value")->stringValue();
     if (value.empty()) {
-        isc_throw(DhcpConfigError, "empty 'value' ("
+        isc_throw(DhcpConfigError, "empty 'value' parameter ("
                   << config->get("value")->getPosition() << ")");
     }
     CfgHttpHeader header(name, value);
index 8adb34f8024ecba5f39df606775fb9bdb6db0939..ae3301e453a3d8aa3160572732c746533350cc66 100644 (file)
@@ -56,7 +56,7 @@ void copyHttpHeaders(const CfgHttpHeaders& headers, const HTTP_MSG& message) {
 ///
 /// @param headers Config HTTP headers.
 /// @return A pointer to unparsed headers configuration.
-isc::data::ElementPtr toElement(const CfgHttpHeaders& headers);
+isc::data::ElementPtr CfgHttpHeaderstoElement(const CfgHttpHeaders& headers);
 
 /// @brief Parse config HTTP headers.
 ///
index b88cdd092a6e84ee02e75ae64ee475f4438b3d51..acd9934157de91f3d69a41179425d7486a8edf0d 100644 (file)
@@ -7,9 +7,11 @@
 #include <config.h>
 
 #include <http/cfg_http_header.h>
+#include <cc/simple_parser.h>
 #include <gtest/gtest.h>
 
 using namespace isc::data;
+using namespace isc::dhcp;
 using namespace isc::http;
 using namespace std;
 
@@ -43,21 +45,21 @@ TEST(CfgHttpHeaderTest, copy) {
     expected += "{ \"name\": \"Strict-Transport-Security\", ";
     expected += "\"value\": \"max-age=31536000\" }, ";
     expected += "{ \"name\": \"Foo\", \"value\": \"bar\" } ]";
-    EXPECT_EQ(expected, toElement(headers)->str());
+    EXPECT_EQ(expected, CfgHttpHeaderstoElement(headers)->str());
 }
 
 // This test verifies parse and toElement behavior.
 TEST(CfgHttpHeaderTest, parse) {
     // Config.
     string config = "[\n"
-       " {\n"
-       " \"name\": \"Strict-Transport-Security\",\n"
-       " \"value\": \"max-age=31536000\",\n"
-       " \"user-context\": { \"comment\": \"HSTS header\" }\n"
-       " },{\n"
-       " \"name\": \"Foo\", \"value\": \"bar\"\n"
-       " }\n"
-       " ]\n";
+        " {\n"
+        " \"name\": \"Strict-Transport-Security\",\n"
+        " \"value\": \"max-age=31536000\",\n"
+        " \"user-context\": { \"comment\": \"HSTS header\" }\n"
+        " },{\n"
+        " \"name\": \"Foo\", \"value\": \"bar\"\n"
+        " }\n"
+        " ]\n";
     ConstElementPtr json;
     ASSERT_NO_THROW(json = Element::fromJSON(config));
     CfgHttpHeaders headers;
@@ -72,8 +74,97 @@ TEST(CfgHttpHeaderTest, parse) {
     EXPECT_EQ("bar", headers[1].value_);
     EXPECT_FALSE(headers[1].getContext());
     ConstElementPtr unparsed;
-    ASSERT_NO_THROW(unparsed = toElement(headers));
+    ASSERT_NO_THROW(unparsed = CfgHttpHeaderstoElement(headers));
     EXPECT_TRUE(json->equals(*unparsed));
 }
 
+// This test verifies parse error cases.
+TEST(CfgHttpHeaderTest, parseErrors) {
+    // Scenarios.
+    struct Scenario{
+        string desc_;    // Description.
+        string config_; // Configuration.
+        string errmsg_; // Error message.
+    };
+    vector<Scenario> scenarios = {
+        {
+            "Not a list",
+            "{ \"name\": \"Foo\", \"value\": \"bar\" }",
+            "invalid type specified for parameter 'http-headers' "
+            "(<string>:1:2)"
+        },
+        {
+            "Not a map",
+            "[ \"Foo\",  \"bar\" ]",
+            "invalid type specified for 'http-headers' item (<string>:1:3)"
+        },
+        {
+            "Unknown keyword",
+            "[ { \"foo\": \"bar\" } ]",
+            "spurious 'foo' parameter"
+        },
+        {
+            "Bad name type",
+            "[ { \"name\": 1 } ]",
+            "'name' parameter is not a string"
+        },
+        {
+            "Bad value type",
+            "[ { \"value\": false } ]",
+            "'value' parameter is not a string"
+        },
+        {
+            "Bad user context type",
+            "[ { \"user-context\": \"bad\" } ]",
+            "'user-context' parameter is not a map"
+        },
+        {
+            "Missing name",
+            "[ { } ]",
+            "missing 'name' parameter"
+        },
+        {
+            "Missing value",
+            "[ { \"name\": \"Foo\" } ]",
+            "missing 'value' parameter"
+        },
+        {
+            "Empty name",
+            "[ { \"name\": \"\", \"value\": \"\" } ]",
+            "empty 'name' parameter (<string>:1:13)"
+        },
+        {
+            "Empty value",
+            "[ { \"name\": \"Foo\", \"value\": \"\" } ]",
+            "empty 'value' parameter (<string>:1:29)"
+        }
+    };
+
+    // Iterate over Scenarios.
+    ConstElementPtr json;
+    CfgHttpHeaders headers;
+    for (auto const& scenario : scenarios) {
+        SCOPED_TRACE(scenario.desc_);
+        {
+            ASSERT_NO_THROW(json = Element::fromJSON(scenario.config_));
+            try {
+                headers = parseCfgHttpHeaders(json);
+                ADD_FAILURE() << "exception is expected";
+            } catch (const DhcpConfigError& ex) {
+                EXPECT_EQ(scenario.errmsg_, ex.what());
+            } catch (...) {
+                ADD_FAILURE() << "DhcpConfigError is expected";
+            }
+        }
+    }
+
+    // No error cases.
+    ConstElementPtr null_json;
+    ASSERT_NO_THROW(headers = parseCfgHttpHeaders(null_json));
+    EXPECT_TRUE(headers.empty());
+    ConstElementPtr empty_json = Element::createList();
+    ASSERT_NO_THROW(headers = parseCfgHttpHeaders(empty_json));
+    EXPECT_TRUE(headers.empty());
+}
+
 }