" \"data\": \"ABCDEF0105\",\n"
" \"csv-format\": false\n"
" } ],\n"
- "\"client-classes\": [ {\n"
- " \"name\": \"all\",\n"
- " \"comment\": \"match all\",\n"
- " \"test\": \"'' == ''\"\n"
- " } ],\n"
+ "\"client-classes\": [\n"
+ " {\n"
+ " \"name\": \"all\",\n"
+ " \"comment\": \"match all\",\n"
+ " \"test\": \"'' == ''\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"none\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"two\",\n"
+ " \"comment\": \"first comment\",\n"
+ " \"comment\": \"second comment\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"both\",\n"
+ " \"comment\": \"a comment\",\n"
+ " \"user-context\": {\n"
+ " \"version\": 1\n"
+ " }\n"
+ " }\n"
+ " ],\n"
"\"shared-networks\": [ {\n"
" \"name\": \"foo\"\n,"
" \"comment\": \"A shared network\"\n,"
ASSERT_TRUE(ctx_opt_desc->get("comment"));
EXPECT_EQ("\"Set option value\"", ctx_opt_desc->get("comment")->str());
- // And there is a client class.
+ // And there are some client classes.
ClientClassDictionaryPtr dict =
CfgMgr::instance().getStagingCfg()->getClientClassDictionary();
ASSERT_TRUE(dict);
- EXPECT_EQ(1, dict->getClasses()->size());
+ EXPECT_EQ(4, dict->getClasses()->size());
ClientClassDefPtr cclass = dict->findClass("all");
ASSERT_TRUE(cclass);
EXPECT_EQ("all", cclass->getName());
ASSERT_TRUE(ctx_class->get("comment"));
EXPECT_EQ("\"match all\"", ctx_class->get("comment")->str());
+ // The 'none' class has no user-context/comment.
+ cclass = dict->findClass("none");
+ ASSERT_TRUE(cclass);
+ EXPECT_EQ("none", cclass->getName());
+ EXPECT_EQ("", cclass->getTest());
+ EXPECT_FALSE(cclass->getContext());
+
+ // The 'two' class has two comments.
+ cclass = dict->findClass("two");
+ EXPECT_EQ("two", cclass->getName());
+ EXPECT_EQ("", cclass->getTest());
+ ctx_class = cclass->getContext();
+ ASSERT_TRUE(ctx_class);
+ ASSERT_EQ(1, ctx_class->size());
+ ASSERT_TRUE(ctx_class->get("comment"));
+ ASSERT_EQ(Element::list, cclass->getContext()->get("comment")->getType());
+ ASSERT_EQ(2, cclass->getContext()->get("comment")->size());
+
+ // The 'both' class has a user context and a comment.
+ cclass = dict->findClass("both");
+ EXPECT_EQ("both", cclass->getName());
+ EXPECT_EQ("", cclass->getTest());
+ ctx_class = cclass->getContext();
+ ASSERT_TRUE(ctx_class);
+ ASSERT_EQ(2, ctx_class->size());
+ ASSERT_TRUE(ctx_class->get("comment"));
+ EXPECT_EQ("\"a comment\"", ctx_class->get("comment")->str());
+ ASSERT_TRUE(ctx_class->get("version"));
+ EXPECT_EQ("1", ctx_class->get("version")->str());
+
// Now verify that the shared network was indeed configured.
CfgSharedNetworks4Ptr cfg_net = CfgMgr::instance().getStagingCfg()
->getCfgSharedNetworks4();
#include <cc/data.h>
#include <cc/simple_parser.h>
#include <cc/cfg_to_element.h>
+#include <testutils/user_context_utils.h>
#include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcp4/tests/dhcp4_test_utils.h>
using namespace isc::data;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
+using namespace isc::test;
namespace {
// CONFIGURATION 0
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 1
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"subnet4\": [\n"
// CONFIGURATION 2
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"renew-timer\": 1000,\n"
" \"subnet4\": [\n"
// CONFIGURATION 3
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 4
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 5
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
"{\n"
" \"boot-file-name\": \"bar\",\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"next-server\": \"1.2.3.4\",\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 7
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
"{\n"
" \"boot-file-name\": \"nofile\",\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"next-server\": \"192.0.0.1\",\n"
" \"rebind-timer\": 2000,\n"
"{\n"
" \"echo-client-id\": false,\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
"{\n"
" \"echo-client-id\": true,\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 11
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 12
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"match-client-id\": true,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 13
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 14
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 15
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 23
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-data\": [\n"
" {\n"
// CONFIGURATION 24
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 25
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-data\": [\n"
" {\n"
// CONFIGURATION 26
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-data\": [\n"
" {\n"
// CONFIGURATION 27
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-data\": [\n"
" {\n"
// CONFIGURATION 28
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-data\": [\n"
" {\n"
// CONFIGURATION 29
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 30
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 31
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 32
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-data\": [\n"
" {\n"
// CONFIGURATION 33
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-data\": [\n"
" {\n"
// CONFIGURATION 34
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-data\": [\n"
" {\n"
// CONFIGURATION 35
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-data\": [\n"
" {\n"
// CONFIGURATION 36
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-data\": [\n"
" {\n"
// CONFIGURATION 37
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"eth0\", \"eth1\" ]\n"
+" \"interfaces\": [ \"eth0\", \"eth1\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 38
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"eth0\", \"*\", \"eth1\" ]\n"
+" \"interfaces\": [ \"eth0\", \"*\", \"eth1\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
" \"server-port\": 777\n"
" },\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 40
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 41
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 42
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-def\": [\n"
" {\n"
// CONFIGURATION 44
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"subnet4\": [ ]\n"
" }\n",
// CONFIGURATION 45
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"subnet4\": [ ]\n"
" }\n",
"{\n"
" \"decline-probation-period\": 12345,\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"subnet4\": [ ]\n"
" }\n",
" \"unwarned-reclaim-cycles\": 10\n"
" },\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"subnet4\": [ ]\n"
" }\n",
// CONFIGURATION 48
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 49
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 50
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 51
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 52
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
" }\n"
" ],\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 54
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 55
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 56
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
// CONFIGURATION 57
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"rebind-timer\": 2000,\n"
" \"renew-timer\": 1000,\n"
" \"comment\": \"match all\",\n"
" \"name\": \"all\",\n"
" \"test\": \"'' == ''\"\n"
+" },\n"
+" {\n"
+" \"name\": \"none\"\n"
+" },\n"
+" {\n"
+" \"comment\": [ \"first comment\", \"second comment\" ],\n"
+" \"name\": \"two\"\n"
+" },\n"
+" {\n"
+" \"comment\": \"a comment\",\n"
+" \"name\": \"both\",\n"
+" \"user-context\": {\n"
+" \"version\": 1\n"
+" }\n"
" }\n"
" ],\n"
" \"option-data\": [\n"
" \"option-def\": [ ],\n"
" \"server-hostname\": \"\",\n"
" \"test\": \"'' == ''\"\n"
+" },\n"
+" {\n"
+" \"comment\": \"a comment\",\n"
+" \"boot-file-name\": \"\",\n"
+" \"name\": \"both\",\n"
+" \"next-server\": \"0.0.0.0\",\n"
+" \"option-data\": [ ],\n"
+" \"option-def\": [ ],\n"
+" \"server-hostname\": \"\",\n"
+" \"user-context\": {\n"
+" \"version\": 1\n"
+" }\n"
+" },\n"
+" {\n"
+" \"boot-file-name\": \"\",\n"
+" \"name\": \"none\",\n"
+" \"next-server\": \"0.0.0.0\",\n"
+" \"option-data\": [ ],\n"
+" \"option-def\": [ ],\n"
+" \"server-hostname\": \"\"\n"
+" },\n"
+" {\n"
+" \"comment\": [ \"first comment\", \"second comment\" ],\n"
+" \"boot-file-name\": \"\",\n"
+" \"name\": \"two\",\n"
+" \"next-server\": \"0.0.0.0\",\n"
+" \"option-data\": [ ],\n"
+" \"option-def\": [ ],\n"
+" \"server-hostname\": \"\"\n"
" }\n"
" ],\n"
" \"decline-probation-period\": 86400,\n"
void
outputFormatted(const std::string& config) {
// pretty print it
- ConstElementPtr json = parseJSON(config);
+ ConstElementPtr json = extractComments(parseDHCP4(config));
std::string prettier = prettyPrint(json, 4, 4);
// get it as a line array
std::list<std::string> lines;
ASSERT_NO_THROW(outputFormatted(dhcp->str()));
} else {
expected = UNPARSED_CONFIGS[config_counter];
- ConstElementPtr json;
- ASSERT_NO_THROW(json = parseDHCP4(expected, true));
- ASSERT_NO_THROW(json = parseJSON(expected));
- EXPECT_TRUE(isEquivalent(dhcp, json));
+ ElementPtr jsond;
+ ASSERT_NO_THROW(jsond = parseDHCP4(expected, true));
+ ElementPtr jsonj;
+ ASSERT_NO_THROW(jsonj = parseJSON(expected));
+ EXPECT_TRUE(isEquivalent(dhcp, jsonj));
+ EXPECT_TRUE(isEquivalent(jsond, moveComments(jsonj)));
std::string current = prettyPrint(dhcp, 4, 4) + "\n";
EXPECT_EQ(expected, current);
if (expected != current) {
#include <cc/data.h>
#include <cc/simple_parser.h>
#include <cc/cfg_to_element.h>
+#include <testutils/user_context_utils.h>
#include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcp4/tests/dhcp4_test_utils.h>
using namespace isc::data;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
+using namespace isc::test;
namespace {
void
outputFormatted(const std::string& config) {
// pretty print it
- ConstElementPtr json = parseJSON(config);
+ ConstElementPtr json = extractComments(parseDHCP4(config));
std::string prettier = prettyPrint(json, 4, 4);
// get it as a line array
std::list<std::string> lines;
ASSERT_NO_THROW(outputFormatted(dhcp->str()));
} else {
expected = UNPARSED_CONFIGS[config_counter];
- ConstElementPtr json;
- ASSERT_NO_THROW(json = parseDHCP4(expected, true));
- ASSERT_NO_THROW(json = parseJSON(expected));
- EXPECT_TRUE(isEquivalent(dhcp, json));
+ ElementPtr jsond;
+ ASSERT_NO_THROW(jsond = parseDHCP4(expected, true));
+ ElementPtr jsonj;
+ ASSERT_NO_THROW(jsonj = parseJSON(expected));
+ EXPECT_TRUE(isEquivalent(dhcp, jsonj));
+ EXPECT_TRUE(isEquivalent(jsond, moveComments(jsonj)));
std::string current = prettyPrint(dhcp, 4, 4) + "\n";
EXPECT_EQ(expected, current);
if (expected != current) {
" \"data\": \"ABCDEF0105\",\n"
" \"csv-format\": false\n"
" } ],\n"
- "\"client-classes\": [ {\n"
- " \"name\": \"all\",\n"
- " \"comment\": \"match all\",\n"
- " \"test\": \"'' == ''\"\n"
- " } ],\n"
+ "\"client-classes\": [\n"
+ " {\n"
+ " \"name\": \"all\",\n"
+ " \"comment\": \"match all\",\n"
+ " \"test\": \"'' == ''\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"none\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"two\",\n"
+ " \"comment\": \"first comment\",\n"
+ " \"comment\": \"second comment\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"both\",\n"
+ " \"comment\": \"a comment\",\n"
+ " \"user-context\": {\n"
+ " \"version\": 1\n"
+ " }\n"
+ " }\n"
+ " ],\n"
"\"shared-networks\": [ {\n"
" \"name\": \"foo\"\n,"
" \"comment\": \"A shared network\"\n,"
ASSERT_TRUE(ctx_opt_desc->get("comment"));
EXPECT_EQ("\"Set option value\"", ctx_opt_desc->get("comment")->str());
- // And there is a client class.
+ // And there there are some client classes.
ClientClassDictionaryPtr dict =
CfgMgr::instance().getStagingCfg()->getClientClassDictionary();
ASSERT_TRUE(dict);
- EXPECT_EQ(1, dict->getClasses()->size());
+ EXPECT_EQ(4, dict->getClasses()->size());
ClientClassDefPtr cclass = dict->findClass("all");
ASSERT_TRUE(cclass);
EXPECT_EQ("all", cclass->getName());
ASSERT_TRUE(ctx_class->get("comment"));
EXPECT_EQ("\"match all\"", ctx_class->get("comment")->str());
+ // The 'none' class has no user-context/comment.
+ cclass = dict->findClass("none");
+ ASSERT_TRUE(cclass);
+ EXPECT_EQ("none", cclass->getName());
+ EXPECT_EQ("", cclass->getTest());
+ EXPECT_FALSE(cclass->getContext());
+
+ // The 'two' class has two comments.
+ cclass = dict->findClass("two");
+ EXPECT_EQ("two", cclass->getName());
+ EXPECT_EQ("", cclass->getTest());
+ ctx_class = cclass->getContext();
+ ASSERT_TRUE(ctx_class);
+ ASSERT_EQ(1, ctx_class->size());
+ ASSERT_TRUE(ctx_class->get("comment"));
+ ASSERT_EQ(Element::list, cclass->getContext()->get("comment")->getType());
+ ASSERT_EQ(2, cclass->getContext()->get("comment")->size());
+
+ // The 'both' class has a user context and a comment.
+ cclass = dict->findClass("both");
+ EXPECT_EQ("both", cclass->getName());
+ EXPECT_EQ("", cclass->getTest());
+ ctx_class = cclass->getContext();
+ ASSERT_TRUE(ctx_class);
+ ASSERT_EQ(2, ctx_class->size());
+ ASSERT_TRUE(ctx_class->get("comment"));
+ EXPECT_EQ("\"a comment\"", ctx_class->get("comment")->str());
+ ASSERT_TRUE(ctx_class->get("version"));
+ EXPECT_EQ("1", ctx_class->get("version")->str());
+
// Now verify that the shared network was indeed configured.
CfgSharedNetworks6Ptr cfg_net = CfgMgr::instance().getStagingCfg()
->getCfgSharedNetworks6();
#include <cc/data.h>
#include <cc/simple_parser.h>
#include <cc/cfg_to_element.h>
+#include <testutils/user_context_utils.h>
+#include <testutils/user_context_utils.h>
#include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcp6/tests/dhcp6_test_utils.h>
using namespace isc::data;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
+using namespace isc::test;
namespace {
// CONFIGURATION 0
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 1
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 2
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 3
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 4
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 5
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 6
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 8
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 9
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 10
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 11
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 12
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 13
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 19
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-data\": [\n"
" {\n"
// CONFIGURATION 20
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 21
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-data\": [\n"
" {\n"
// CONFIGURATION 22
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-data\": [\n"
" {\n"
// CONFIGURATION 23
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-data\": [\n"
" {\n"
// CONFIGURATION 24
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 25
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 26
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-data\": [\n"
" {\n"
// CONFIGURATION 27
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-data\": [\n"
" {\n"
// CONFIGURATION 28
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"eth0\" ]\n"
+" \"interfaces\": [ \"eth0\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 29
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"eth0\", \"eth1\", \"*\" ]\n"
+" \"interfaces\": [ \"eth0\", \"eth1\", \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 30
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 31
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
" \"server-port\": 777\n"
" },\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 33
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 34
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"option-def\": [\n"
" {\n"
// CONFIGURATION 35
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"mac-sources\": [ \"rfc6939\", \"rfc4649\", \"rfc4580\" ],\n"
" \"preferred-lifetime\": 3000,\n"
// CONFIGURATION 36
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"mac-sources\": [ \"client-link-addr-option\", \"remote-id\", \"subscriber-id\" ],\n"
" \"preferred-lifetime\": 3000,\n"
// CONFIGURATION 38
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 39
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"subnet6\": [ ]\n"
" }\n",
// CONFIGURATION 40
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"subnet6\": [ ]\n"
" }\n",
"{\n"
" \"decline-probation-period\": 12345,\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"subnet6\": [ ]\n"
" }\n",
" \"unwarned-reclaim-cycles\": 10\n"
" },\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"subnet6\": [ ]\n"
" }\n",
" }\n"
" ],\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 44
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 45
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 46
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 47
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 48
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 49
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
// CONFIGURATION 50
"{\n"
" \"interfaces-config\": {\n"
-" \"interfaces\": [ \"*\" ]\n"
+" \"interfaces\": [ \"*\" ],\n"
+" \"re-detect\": false\n"
" },\n"
" \"preferred-lifetime\": 3000,\n"
" \"rebind-timer\": 2000,\n"
" \"comment\": \"match all\",\n"
" \"name\": \"all\",\n"
" \"test\": \"'' == ''\"\n"
+" },\n"
+" {\n"
+" \"name\": \"none\"\n"
+" },\n"
+" {\n"
+" \"comment\": [ \"first comment\", \"second comment\" ],\n"
+" \"name\": \"two\"\n"
+" },\n"
+" {\n"
+" \"comment\": \"a comment\",\n"
+" \"name\": \"both\",\n"
+" \"user-context\": {\n"
+" \"version\": 1\n"
+" }\n"
" }\n"
" ],\n"
" \"option-data\": [\n"
" \"name\": \"all\",\n"
" \"option-data\": [ ],\n"
" \"test\": \"'' == ''\"\n"
+" },\n"
+" {\n"
+" \"comment\": \"a comment\",\n"
+" \"name\": \"both\",\n"
+" \"option-data\": [ ],\n"
+" \"user-context\": {\n"
+" \"version\": 1\n"
+" }\n"
+" },\n"
+" {\n"
+" \"name\": \"none\",\n"
+" \"option-data\": [ ]\n"
+" },\n"
+" {\n"
+" \"comment\": [ \"first comment\", \"second comment\" ],\n"
+" \"name\": \"two\",\n"
+" \"option-data\": [ ]\n"
" }\n"
" ],\n"
" \"decline-probation-period\": 86400,\n"
void
outputFormatted(const std::string& config) {
// pretty print it
- ConstElementPtr json = parseJSON(config);
+ ConstElementPtr json = extractComments(parseDHCP6(config));
std::string prettier = prettyPrint(json, 4, 4);
// get it as a line array
std::list<std::string> lines;
ASSERT_NO_THROW(outputFormatted(dhcp->str()));
} else {
expected = UNPARSED_CONFIGS[config_counter];
- ConstElementPtr json;
- ASSERT_NO_THROW(json = parseDHCP6(expected, true));
- ASSERT_NO_THROW(json = parseJSON(expected));
- EXPECT_TRUE(isEquivalent(dhcp, json));
+ ElementPtr jsond;
+ ASSERT_NO_THROW(jsond = parseDHCP6(expected, true));
+ ElementPtr jsonj;
+ ASSERT_NO_THROW(jsonj = parseJSON(expected));
+ EXPECT_TRUE(isEquivalent(dhcp, jsonj));
+ EXPECT_TRUE(isEquivalent(jsond, moveComments(jsonj)));
std::string current = prettyPrint(dhcp, 4, 4) + "\n";
EXPECT_EQ(expected, current);
if (expected != current) {
#include <cc/data.h>
#include <cc/simple_parser.h>
#include <cc/cfg_to_element.h>
+#include <testutils/user_context_utils.h>
+#include <testutils/user_context_utils.h>
#include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcp6/tests/dhcp6_test_utils.h>
using namespace isc::data;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
+using namespace isc::test;
namespace {
void
outputFormatted(const std::string& config) {
// pretty print it
- ConstElementPtr json = parseJSON(config);
+ ConstElementPtr json = extractComments(parseDHCP6(config));
std::string prettier = prettyPrint(json, 4, 4);
// get it as a line array
std::list<std::string> lines;
ASSERT_NO_THROW(outputFormatted(dhcp->str()));
} else {
expected = UNPARSED_CONFIGS[config_counter];
- ConstElementPtr json;
- ASSERT_NO_THROW(json = parseDHCP6(expected, true));
- ASSERT_NO_THROW(json = parseJSON(expected));
- EXPECT_TRUE(isEquivalent(dhcp, json));
+ ElementPtr jsond;
+ ASSERT_NO_THROW(jsond = parseDHCP6(expected, true));
+ ElementPtr jsonj;
+ ASSERT_NO_THROW(jsonj = parseJSON(expected));
+ EXPECT_TRUE(isEquivalent(dhcp, jsonj));
+ EXPECT_TRUE(isEquivalent(jsond, moveComments(jsonj)));
std::string current = prettyPrint(dhcp, 4, 4) + "\n";
EXPECT_EQ(expected, current);
if (expected != current) {
}; // end of isc::test namespace
}; // end of isc namespace
+
+namespace {
+
+/// @brief Recursive helper
+///
+/// Instead of returning a unmodified copy a @ref UnModified exception
+/// is raised with the unmodified value
+///
+/// @tparam EP ElementPtr or ConstElementPtr (compiler will infer which one)
+/// @param element the element to traverse
+/// @return a modified copy where comment entries were moved to user-context
+/// @throw UnModified with the unmodified value
+template<typename EP>
+EP extractComments1(EP element) {
+ bool modified = false;
+
+ // On lists recurse on items
+ if (element->getType() == Element::list) {
+ ElementPtr result = ElementPtr(new ListElement());
+ typedef std::vector<ElementPtr> ListType;
+ const ListType& list = element->listValue();
+ for (ListType::const_iterator it = list.cbegin();
+ it != list.cend(); ++it) {
+ try {
+ result->add(extractComments1(*it));
+ modified = true;
+ }
+ catch (const UnModified<ElementPtr>& ex) {
+ result->add(ex.get());
+ }
+ }
+ if (!modified) {
+ throw UnModified<EP>(element);
+ }
+ return (result);
+ } else if (element->getType() != Element::map) {
+ throw UnModified<EP>(element);
+ }
+
+ // Process maps: recurse on items
+ ElementPtr result = ElementPtr(new MapElement());
+ bool has_comment = false;
+ typedef std::map<std::string, ConstElementPtr> map_type;
+ const map_type& map = element->mapValue();
+ for (map_type::const_iterator it = map.cbegin(); it != map.cend(); ++it) {
+ if (it->first == "comment") {
+ // Do not traverse comment entries
+ result->set("comment", it->second);
+ } else if (it->first == "user-context") {
+ if (it->second->contains("comment")) {
+ // Note there is a entry to move
+ has_comment = true;
+ } else {
+ // Do not traverse user-context entries
+ result->set("user-context", it->second);
+ }
+ } else {
+ // Not comment or user-context
+ try {
+ result->set(it->first, extractComments1(it->second));
+ modified = true;
+ }
+ catch (const UnModified<ConstElementPtr>& ex) {
+ result->set(it->first, ex.get());
+ }
+ }
+ }
+ // Check if the value should be not modified
+ if (!has_comment && !modified) {
+ throw UnModified<EP>(element);
+ }
+
+ if (has_comment) {
+ // Move the comment entry
+ const map_type& uc_map = element->get("user-context")->mapValue();
+ ElementPtr user_context = Element::createMap();
+ ConstElementPtr comment;
+ for (map_type::const_iterator it = uc_map.cbegin();
+ it != uc_map.cend(); ++it) {
+ if (it->first == "comment") {
+ comment = it->second;
+ } else {
+ user_context->set(it->first, it->second);
+ }
+ }
+ if (user_context->size() > 0) {
+ result->set("user-context", user_context);
+ }
+ result->combine_set("comment", comment);
+ }
+
+ return (result);
+}
+
+} // anonymous namespace
+
+namespace isc {
+namespace test {
+
+ElementPtr extractComments(ElementPtr element) {
+ ElementPtr result;
+ try {
+ result = extractComments1(element);
+ }
+ catch (const UnModified<ElementPtr>& ex) {
+ result = ex.get();
+ }
+ return result;
+}
+
+}; // end of isc::test namespace
+}; // end of isc namespace
/// @return a processed copy of element or unmodified element
isc::data::ElementPtr moveComments(isc::data::ElementPtr element);
+/// @brief Extract comment entries from user-context
+///
+/// @param element
+/// @return a processed copy of element or unmodified element
+ isc::data::ElementPtr extractComments(isc::data::ElementPtr element);
+
}; // end of isc::test namespace
}; // end of isc namespace