diff options
author | Francis Dupont <fdupont@isc.org> | 2024-11-14 15:52:32 +0100 |
---|---|---|
committer | Francis Dupont <fdupont@isc.org> | 2024-11-22 09:55:31 +0100 |
commit | 3193b4f7b410bd2c91e0a5266eda3399de1378f8 (patch) | |
tree | 9e8712f9aa673ab1f922b50c1e198aa00b042516 /src | |
parent | [#3609] Checkpoint: error UT to add (diff) | |
download | kea-3193b4f7b410bd2c91e0a5266eda3399de1378f8.tar.xz kea-3193b4f7b410bd2c91e0a5266eda3399de1378f8.zip |
[#3609] Checkpoint: added error UT
Diffstat (limited to 'src')
-rw-r--r-- | src/bin/agent/ca_cfg_mgr.cc | 2 | ||||
-rw-r--r-- | src/lib/http/cfg_http_header.cc | 6 | ||||
-rw-r--r-- | src/lib/http/cfg_http_header.h | 2 | ||||
-rw-r--r-- | src/lib/http/tests/cfg_http_header_unittests.cc | 111 |
4 files changed, 106 insertions, 15 deletions
diff --git a/src/bin/agent/ca_cfg_mgr.cc b/src/bin/agent/ca_cfg_mgr.cc index 4cb9da5480..95057f6231 100644 --- a/src/bin/agent/ca_cfg_mgr.cc +++ b/src/bin/agent/ca_cfg_mgr.cc @@ -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()) { diff --git a/src/lib/http/cfg_http_header.cc b/src/lib/http/cfg_http_header.cc index 7c7edf3e6b..098e95cc3f 100644 --- a/src/lib/http/cfg_http_header.cc +++ b/src/lib/http/cfg_http_header.cc @@ -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); diff --git a/src/lib/http/cfg_http_header.h b/src/lib/http/cfg_http_header.h index 8adb34f802..ae3301e453 100644 --- a/src/lib/http/cfg_http_header.h +++ b/src/lib/http/cfg_http_header.h @@ -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. /// diff --git a/src/lib/http/tests/cfg_http_header_unittests.cc b/src/lib/http/tests/cfg_http_header_unittests.cc index b88cdd092a..acd9934157 100644 --- a/src/lib/http/tests/cfg_http_header_unittests.cc +++ b/src/lib/http/tests/cfg_http_header_unittests.cc @@ -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()); +} + } |