TEST(CfgSharedNetworks4Test, unparse) {
SharedNetwork4Ptr network1(new SharedNetwork4("frog"));
SharedNetwork4Ptr network2(new SharedNetwork4("dog"));
+ SharedNetwork4Ptr network3(new SharedNetwork4("cat"));
network1->setIface("eth0");
network1->addRelayAddress(IOAddress("198.16.1.1"));
network1->addRelayAddress(IOAddress("198.16.1.2"));
network2->setIface("eth1");
network2->setT1(Triplet<uint32_t>(100));
network2->setT2(Triplet<uint32_t>(200));
- network2->setValid(Triplet<uint32_t>(300));
+ network2->setValid(Triplet<uint32_t>(200, 300, 400));
+
+ network3->setIface("eth2");
+ network3->setValid(Triplet<uint32_t>(100));
CfgSharedNetworks4 cfg;
ASSERT_NO_THROW(cfg.add(network1));
ASSERT_NO_THROW(cfg.add(network2));
+ ASSERT_NO_THROW(cfg.add(network3));
std::string expected =
"[\n"
" {\n"
+ " \"interface\": \"eth2\",\n"
+ " \"name\": \"cat\",\n"
+ " \"option-data\": [ ],\n"
+ " \"relay\": { \"ip-addresses\": [ ] },\n"
+ " \"subnet4\": [ ],\n"
+ " \"valid-lifetime\": 100\n"
+ " },\n"
+ " {\n"
" \"interface\": \"eth1\",\n"
" \"name\": \"dog\",\n"
" \"rebind-timer\": 200,\n"
" \"renew-timer\": 100,\n"
" \"relay\": { \"ip-addresses\": [ ] },\n"
" \"subnet4\": [ ],\n"
- " \"valid-lifetime\": 300\n"
+ " \"valid-lifetime\": 300,\n"
+ " \"min-valid-lifetime\": 200,\n"
+ " \"max-valid-lifetime\": 400\n"
" },\n"
" {\n"
" \"calculate-tee-times\": true,\n"
TEST(CfgSharedNetworks6Test, unparse) {
SharedNetwork6Ptr network1(new SharedNetwork6("frog"));
SharedNetwork6Ptr network2(new SharedNetwork6("dog"));
+ SharedNetwork6Ptr network3(new SharedNetwork6("cat"));
network1->setIface("eth0");
network1->addRelayAddress(IOAddress("2001:db8:1::1"));
network2->setIface("eth1");
network2->setT1(Triplet<uint32_t>(100));
network2->setT2(Triplet<uint32_t>(200));
+ network2->setPreferred(Triplet<uint32_t>(200));
network2->setValid(Triplet<uint32_t>(300));
+ network3->setIface("eth2");
+ network3->setPreferred(Triplet<uint32_t>(100,200,300));
+ network3->setValid(Triplet<uint32_t>(200,300,400));
+
CfgSharedNetworks6 cfg;
ASSERT_NO_THROW(cfg.add(network1));
ASSERT_NO_THROW(cfg.add(network2));
+ ASSERT_NO_THROW(cfg.add(network3));
std::string expected =
"[\n"
" {\n"
+ " \"interface\": \"eth2\",\n"
+ " \"name\": \"cat\",\n"
+ " \"option-data\": [ ],\n"
+ " \"relay\": { \"ip-addresses\": [ ] },\n"
+ " \"subnet6\": [ ],\n"
+ " \"preferred-lifetime\": 200,\n"
+ " \"min-preferred-lifetime\": 100,\n"
+ " \"max-preferred-lifetime\": 300,\n"
+ " \"valid-lifetime\": 300,\n"
+ " \"min-valid-lifetime\": 200,\n"
+ " \"max-valid-lifetime\": 400\n"
+ " },\n"
+ " {\n"
" \"interface\": \"eth1\",\n"
" \"name\": \"dog\",\n"
" \"option-data\": [ ],\n"
" \"relay\": { \"ip-addresses\": [ ] },\n"
" \"renew-timer\": 100,\n"
" \"subnet6\": [ ],\n"
+ " \"preferred-lifetime\": 200,\n"
" \"valid-lifetime\": 300\n"
" },\n"
" {\n"
subnet2->setIface("lo");
subnet2->addRelayAddress(IOAddress("10.0.0.1"));
+ subnet2->setValid(Triplet<uint32_t>(100));
subnet3->setIface("eth1");
subnet3->requireClientClass("foo");
subnet3->setSiaddr(IOAddress("192.0.2.2"));
subnet3->setSname("frog");
subnet3->setFilename("/dev/null");
+ subnet3->setValid(Triplet<uint32_t>(100, 200, 300));
data::ElementPtr ctx1 = data::Element::fromJSON("{ \"comment\": \"foo\" }");
subnet1->setContext(ctx1);
" \"renew-timer\": 1,\n"
" \"rebind-timer\": 2,\n"
" \"relay\": { \"ip-addresses\": [ \"10.0.0.1\" ] },\n"
- " \"valid-lifetime\": 3,\n"
+ " \"valid-lifetime\": 100,\n"
" \"4o6-interface\": \"\",\n"
" \"4o6-interface-id\": \"\",\n"
" \"4o6-subnet\": \"\",\n"
" \"renew-timer\": 1,\n"
" \"rebind-timer\": 2,\n"
" \"relay\": { \"ip-addresses\": [ ] },\n"
- " \"valid-lifetime\": 3,\n"
+ " \"valid-lifetime\": 200,\n"
+ " \"min-valid-lifetime\": 100,\n"
+ " \"max-valid-lifetime\": 300,\n"
" \"4o6-interface\": \"\",\n"
" \"4o6-interface-id\": \"\",\n"
" \"4o6-subnet\": \"\",\n"
}
}
+// This test verifies the Subnet4 parser's validation logic for
+// valid-lifetime and indirectly shared lifetime parsing.
+TEST(CfgSubnets4Test, validLifetimeValidation) {
+ // First we create a set of elements that provides all
+ // required for a Subnet4.
+ std::string json =
+ " {"
+ " \"id\": 1,\n"
+ " \"subnet\": \"10.1.2.0/24\", \n"
+ " \"interface\": \"\", \n"
+ " \"renew-timer\": 100, \n"
+ " \"rebind-timer\": 200, \n"
+ " \"match-client-id\": false, \n"
+ " \"authoritative\": false, \n"
+ " \"next-server\": \"\", \n"
+ " \"server-hostname\": \"\", \n"
+ " \"boot-file-name\": \"\", \n"
+ " \"client-class\": \"\", \n"
+ " \"require-client-classes\": [] \n,"
+ " \"reservation-mode\": \"all\", \n"
+ " \"4o6-interface\": \"\", \n"
+ " \"4o6-interface-id\": \"\", \n"
+ " \"4o6-subnet\": \"\", \n"
+ " \"dhcp4o6-port\": 0, \n"
+ " \"decline-probation-period\": 86400 \n"
+ " }";
+
+
+ data::ElementPtr elems;
+ ASSERT_NO_THROW(elems = data::Element::fromJSON(json))
+ << "invalid JSON:" << json << "\n test is broken";
+
+ {
+ SCOPED_TRACE("no valid-lifetime");
+
+ data::ElementPtr copied = data::copy(elems);
+ Subnet4Ptr subnet;
+ Subnet4ConfigParser parser;
+ ASSERT_NO_THROW(subnet = parser.parse(copied));
+ ASSERT_TRUE(subnet);
+ EXPECT_TRUE(subnet->getValid().unspecified());
+ data::ConstElementPtr repr = subnet->toElement();
+ EXPECT_FALSE(repr->get("valid-lifetime"));
+ EXPECT_FALSE(repr->get("min-valid-lifetime"));
+ EXPECT_FALSE(repr->get("max-valid-lifetime"));
+ }
+
+ {
+ SCOPED_TRACE("valid-lifetime only");
+
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("valid-lifetime", data::Element::create(100));
+ Subnet4Ptr subnet;
+ Subnet4ConfigParser parser;
+ ASSERT_NO_THROW(subnet = parser.parse(copied));
+ ASSERT_TRUE(subnet);
+ EXPECT_FALSE(subnet->getValid().unspecified());
+ EXPECT_EQ(100, subnet->getValid());
+ EXPECT_EQ(100, subnet->getValid().getMin());
+ EXPECT_EQ(100, subnet->getValid().getMax());
+ data::ConstElementPtr repr = subnet->toElement();
+ data::ConstElementPtr value = repr->get("valid-lifetime");
+ ASSERT_TRUE(value);
+ EXPECT_EQ("100", value->str());
+ EXPECT_FALSE(repr->get("min-valid-lifetime"));
+ EXPECT_FALSE(repr->get("max-valid-lifetime"));
+ }
+
+ {
+ SCOPED_TRACE("min-valid-lifetime only");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("min-valid-lifetime", data::Element::create(100));
+ Subnet4Ptr subnet;
+ Subnet4ConfigParser parser;
+ ASSERT_NO_THROW(subnet = parser.parse(copied));
+ ASSERT_TRUE(subnet);
+ EXPECT_FALSE(subnet->getValid().unspecified());
+ EXPECT_EQ(100, subnet->getValid());
+ EXPECT_EQ(100, subnet->getValid().getMin());
+ EXPECT_EQ(100, subnet->getValid().getMax());
+ data::ConstElementPtr repr = subnet->toElement();
+ data::ConstElementPtr value = repr->get("valid-lifetime");
+ ASSERT_TRUE(value);
+ EXPECT_EQ("100", value->str());
+ // Bound only: forgot it was a bound.
+ EXPECT_FALSE(repr->get("min-valid-lifetime"));
+ EXPECT_FALSE(repr->get("max-valid-lifetime"));
+ }
+
+ {
+ SCOPED_TRACE("max-valid-lifetime only");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("max-valid-lifetime", data::Element::create(100));
+ Subnet4Ptr subnet;
+ Subnet4ConfigParser parser;
+ ASSERT_NO_THROW(subnet = parser.parse(copied));
+ ASSERT_TRUE(subnet);
+ EXPECT_FALSE(subnet->getValid().unspecified());
+ EXPECT_EQ(100, subnet->getValid());
+ EXPECT_EQ(100, subnet->getValid().getMin());
+ EXPECT_EQ(100, subnet->getValid().getMax());
+ data::ConstElementPtr repr = subnet->toElement();
+ data::ConstElementPtr value = repr->get("valid-lifetime");
+ ASSERT_TRUE(value);
+ EXPECT_EQ("100", value->str());
+ // Bound only: forgot it was a bound.
+ EXPECT_FALSE(repr->get("min-valid-lifetime"));
+ EXPECT_FALSE(repr->get("max-valid-lifetime"));
+ }
+
+ {
+ SCOPED_TRACE("min-valid-lifetime and valid-lifetime");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("min-valid-lifetime", data::Element::create(100));
+ // Use a different (and greater) value for the default.
+ copied->set("valid-lifetime", data::Element::create(200));
+ Subnet4Ptr subnet;
+ Subnet4ConfigParser parser;
+ ASSERT_NO_THROW(subnet = parser.parse(copied));
+ ASSERT_TRUE(subnet);
+ EXPECT_FALSE(subnet->getValid().unspecified());
+ EXPECT_EQ(200, subnet->getValid());
+ EXPECT_EQ(100, subnet->getValid().getMin());
+ EXPECT_EQ(200, subnet->getValid().getMax());
+ data::ConstElementPtr repr = subnet->toElement();
+ data::ConstElementPtr value = repr->get("valid-lifetime");
+ ASSERT_TRUE(value);
+ EXPECT_EQ("200", value->str());
+ data::ConstElementPtr min_value = repr->get("min-valid-lifetime");
+ ASSERT_TRUE(min_value);
+ EXPECT_EQ("100", min_value->str());
+ EXPECT_FALSE(repr->get("max-valid-lifetime"));
+ }
+
+ {
+ SCOPED_TRACE("max-valid-lifetime and valid-lifetime");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("max-valid-lifetime", data::Element::create(200));
+ // Use a different (and smaller) value for the default.
+ copied->set("valid-lifetime", data::Element::create(100));
+ Subnet4Ptr subnet;
+ Subnet4ConfigParser parser;
+ ASSERT_NO_THROW(subnet = parser.parse(copied));
+ ASSERT_TRUE(subnet);
+ EXPECT_FALSE(subnet->getValid().unspecified());
+ EXPECT_EQ(100, subnet->getValid());
+ EXPECT_EQ(100, subnet->getValid().getMin());
+ EXPECT_EQ(200, subnet->getValid().getMax());
+ data::ConstElementPtr repr = subnet->toElement();
+ data::ConstElementPtr value = repr->get("valid-lifetime");
+ ASSERT_TRUE(value);
+ EXPECT_EQ("100", value->str());
+ data::ConstElementPtr max_value = repr->get("max-valid-lifetime");
+ ASSERT_TRUE(max_value);
+ EXPECT_EQ("200", max_value->str());
+ EXPECT_FALSE(repr->get("min-valid-lifetime"));
+ }
+
+ {
+ SCOPED_TRACE("min-valid-lifetime and max-valid-lifetime");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("min-valid-lifetime", data::Element::create(100));
+ copied->set("max-valid-lifetime", data::Element::create(200));
+ Subnet4ConfigParser parser;
+ // No idea about the value to use for the default so failing.
+ ASSERT_THROW(parser.parse(copied), DhcpConfigError);
+ }
+
+ {
+ SCOPED_TRACE("all 3 (min, max and default) valid-lifetime");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("min-valid-lifetime", data::Element::create(100));
+ // Use a different (and greater) value for the default.
+ copied->set("valid-lifetime", data::Element::create(200));
+ // Use a different (and greater than both) value for max.
+ copied->set("max-valid-lifetime", data::Element::create(300));
+ Subnet4Ptr subnet;
+ Subnet4ConfigParser parser;
+ ASSERT_NO_THROW(subnet = parser.parse(copied));
+ ASSERT_TRUE(subnet);
+ EXPECT_FALSE(subnet->getValid().unspecified());
+ EXPECT_EQ(200, subnet->getValid());
+ EXPECT_EQ(100, subnet->getValid().getMin());
+ EXPECT_EQ(300, subnet->getValid().getMax());
+ data::ConstElementPtr repr = subnet->toElement();
+ data::ConstElementPtr value = repr->get("valid-lifetime");
+ ASSERT_TRUE(value);
+ EXPECT_EQ("200", value->str());
+ data::ConstElementPtr min_value = repr->get("min-valid-lifetime");
+ ASSERT_TRUE(min_value);
+ EXPECT_EQ("100", min_value->str());
+ data::ConstElementPtr max_value = repr->get("max-valid-lifetime");
+ ASSERT_TRUE(max_value);
+ EXPECT_EQ("300", max_value->str());
+ }
+
+ {
+ SCOPED_TRACE("default value too small");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("min-valid-lifetime", data::Element::create(200));
+ // 100 < 200 so it will fail.
+ copied->set("valid-lifetime", data::Element::create(100));
+ // Use a different (and greater than both) value for max.
+ copied->set("max-valid-lifetime", data::Element::create(300));
+ Subnet4ConfigParser parser;
+ ASSERT_THROW(parser.parse(copied), DhcpConfigError);
+ }
+
+ {
+ SCOPED_TRACE("default value too large");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("min-valid-lifetime", data::Element::create(100));
+ // Use a different (and greater) value for the default.
+ copied->set("valid-lifetime", data::Element::create(300));
+ // 300 > 200 so it will fail.
+ copied->set("max-valid-lifetime", data::Element::create(200));
+ Subnet4ConfigParser parser;
+ ASSERT_THROW(parser.parse(copied), DhcpConfigError);
+ }
+
+ {
+ SCOPED_TRACE("equal bounds are ignored");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("min-valid-lifetime", data::Element::create(100));
+ copied->set("valid-lifetime", data::Element::create(100));
+ copied->set("max-valid-lifetime", data::Element::create(100));
+ Subnet4Ptr subnet;
+ Subnet4ConfigParser parser;
+ ASSERT_NO_THROW(subnet = parser.parse(copied));
+ ASSERT_TRUE(subnet);
+ EXPECT_FALSE(subnet->getValid().unspecified());
+ EXPECT_EQ(100, subnet->getValid());
+ EXPECT_EQ(100, subnet->getValid().getMin());
+ EXPECT_EQ(100, subnet->getValid().getMax());
+ data::ConstElementPtr repr = subnet->toElement();
+ data::ConstElementPtr value = repr->get("valid-lifetime");
+ ASSERT_TRUE(value);
+ EXPECT_EQ("100", value->str());
+ EXPECT_FALSE(repr->get("min-valid-lifetime"));
+ EXPECT_FALSE(repr->get("max-valid-lifetime"));
+ }
+}
+
} // end of anonymous namespace
subnet2->setIface("lo");
subnet2->addRelayAddress(IOAddress("2001:db8:ff::2"));
+ subnet2->setValid(Triplet<uint32_t>(200));
+ subnet2->setPreferred(Triplet<uint32_t>(100));
+
subnet3->setIface("eth1");
subnet3->requireClientClass("foo");
subnet3->requireClientClass("bar");
subnet3->setCalculateTeeTimes(true);
subnet3->setT1Percent(0.50);
subnet3->setT2Percent(0.65);
+ subnet3->setValid(Triplet<uint32_t>(100, 200, 300));
+ subnet3->setPreferred(Triplet<uint32_t>(50, 100, 150));
data::ElementPtr ctx1 = data::Element::fromJSON("{ \"comment\": \"foo\" }");
subnet1->setContext(ctx1);
" \"renew-timer\": 1,\n"
" \"rebind-timer\": 2,\n"
" \"relay\": { \"ip-addresses\": [ \"2001:db8:ff::2\" ] },\n"
- " \"preferred-lifetime\": 3,\n"
- " \"valid-lifetime\": 4,\n"
+ " \"preferred-lifetime\": 100,\n"
+ " \"valid-lifetime\": 200,\n"
" \"user-context\": { },\n"
" \"pools\": [ ],\n"
" \"pd-pools\": [ ],\n"
" \"renew-timer\": 1,\n"
" \"rebind-timer\": 2,\n"
" \"relay\": { \"ip-addresses\": [ ] },\n"
- " \"preferred-lifetime\": 3,\n"
- " \"valid-lifetime\": 4,\n"
+ " \"preferred-lifetime\": 100,\n"
+ " \"min-preferred-lifetime\": 50,\n"
+ " \"max-preferred-lifetime\": 150,\n"
+ " \"valid-lifetime\": 200,\n"
+ " \"min-valid-lifetime\": 100,\n"
+ " \"max-valid-lifetime\": 300,\n"
" \"rapid-commit\": false,\n"
" \"reservation-mode\": \"all\",\n"
" \"pools\": [ ],\n"
}
}
+// This test verifies the Subnet6 parser's validation logic for
+// preferred-lifetime and indirectly shared lifetime parsing.
+// Note the valid-lifetime stuff is similar and already done for Subnet4.
+TEST(CfgSubnets6Test, preferredLifetimeValidation) {
+ // First we create a set of elements that provides all
+ // required for a Subnet6.
+ std::string json =
+ " {"
+ " \"id\": 1,\n"
+ " \"subnet\": \"2001:db8:1::/64\", \n"
+ " \"interface\": \"\", \n"
+ " \"renew-timer\": 100, \n"
+ " \"rebind-timer\": 200, \n"
+ " \"valid-lifetime\": 300, \n"
+ " \"client-class\": \"\", \n"
+ " \"require-client-classes\": [] \n,"
+ " \"reservation-mode\": \"all\", \n"
+ " \"4o6-interface\": \"\", \n"
+ " \"4o6-interface-id\": \"\", \n"
+ " \"4o6-subnet\": \"\", \n"
+ " \"dhcp4o6-port\": 0, \n"
+ " \"decline-probation-period\": 86400 \n"
+ " }";
+
+
+ data::ElementPtr elems;
+ ASSERT_NO_THROW(elems = data::Element::fromJSON(json))
+ << "invalid JSON:" << json << "\n test is broken";
+
+ {
+ SCOPED_TRACE("no preferred-lifetime");
+
+ data::ElementPtr copied = data::copy(elems);
+ Subnet6Ptr subnet;
+ Subnet6ConfigParser parser;
+ ASSERT_NO_THROW(subnet = parser.parse(copied));
+ ASSERT_TRUE(subnet);
+ EXPECT_TRUE(subnet->getPreferred().unspecified());
+ data::ConstElementPtr repr = subnet->toElement();
+ EXPECT_FALSE(repr->get("preferred-lifetime"));
+ EXPECT_FALSE(repr->get("min-preferred-lifetime"));
+ EXPECT_FALSE(repr->get("max-preferred-lifetime"));
+ }
+
+ {
+ SCOPED_TRACE("preferred-lifetime only");
+
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("preferred-lifetime", data::Element::create(100));
+ Subnet6Ptr subnet;
+ Subnet6ConfigParser parser;
+ ASSERT_NO_THROW(subnet = parser.parse(copied));
+ ASSERT_TRUE(subnet);
+ EXPECT_FALSE(subnet->getPreferred().unspecified());
+ EXPECT_EQ(100, subnet->getPreferred());
+ EXPECT_EQ(100, subnet->getPreferred().getMin());
+ EXPECT_EQ(100, subnet->getPreferred().getMax());
+ data::ConstElementPtr repr = subnet->toElement();
+ data::ConstElementPtr value = repr->get("preferred-lifetime");
+ ASSERT_TRUE(value);
+ EXPECT_EQ("100", value->str());
+ EXPECT_FALSE(repr->get("min-preferred-lifetime"));
+ EXPECT_FALSE(repr->get("max-preferred-lifetime"));
+ }
+
+ {
+ SCOPED_TRACE("min-preferred-lifetime only");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("min-preferred-lifetime", data::Element::create(100));
+ Subnet6Ptr subnet;
+ Subnet6ConfigParser parser;
+ ASSERT_NO_THROW(subnet = parser.parse(copied));
+ ASSERT_TRUE(subnet);
+ EXPECT_FALSE(subnet->getPreferred().unspecified());
+ EXPECT_EQ(100, subnet->getPreferred());
+ EXPECT_EQ(100, subnet->getPreferred().getMin());
+ EXPECT_EQ(100, subnet->getPreferred().getMax());
+ data::ConstElementPtr repr = subnet->toElement();
+ data::ConstElementPtr value = repr->get("preferred-lifetime");
+ ASSERT_TRUE(value);
+ EXPECT_EQ("100", value->str());
+ // Bound only: forgot it was a bound.
+ EXPECT_FALSE(repr->get("min-preferred-lifetime"));
+ EXPECT_FALSE(repr->get("max-preferred-lifetime"));
+ }
+
+ {
+ SCOPED_TRACE("max-preferred-lifetime only");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("max-preferred-lifetime", data::Element::create(100));
+ Subnet6Ptr subnet;
+ Subnet6ConfigParser parser;
+ ASSERT_NO_THROW(subnet = parser.parse(copied));
+ ASSERT_TRUE(subnet);
+ EXPECT_FALSE(subnet->getPreferred().unspecified());
+ EXPECT_EQ(100, subnet->getPreferred());
+ EXPECT_EQ(100, subnet->getPreferred().getMin());
+ EXPECT_EQ(100, subnet->getPreferred().getMax());
+ data::ConstElementPtr repr = subnet->toElement();
+ data::ConstElementPtr value = repr->get("preferred-lifetime");
+ ASSERT_TRUE(value);
+ EXPECT_EQ("100", value->str());
+ // Bound only: forgot it was a bound.
+ EXPECT_FALSE(repr->get("min-preferred-lifetime"));
+ EXPECT_FALSE(repr->get("max-preferred-lifetime"));
+ }
+
+ {
+ SCOPED_TRACE("min-preferred-lifetime and preferred-lifetime");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("min-preferred-lifetime", data::Element::create(100));
+ // Use a different (and greater) value for the default.
+ copied->set("preferred-lifetime", data::Element::create(200));
+ Subnet6Ptr subnet;
+ Subnet6ConfigParser parser;
+ ASSERT_NO_THROW(subnet = parser.parse(copied));
+ ASSERT_TRUE(subnet);
+ EXPECT_FALSE(subnet->getPreferred().unspecified());
+ EXPECT_EQ(200, subnet->getPreferred());
+ EXPECT_EQ(100, subnet->getPreferred().getMin());
+ EXPECT_EQ(200, subnet->getPreferred().getMax());
+ data::ConstElementPtr repr = subnet->toElement();
+ data::ConstElementPtr value = repr->get("preferred-lifetime");
+ ASSERT_TRUE(value);
+ EXPECT_EQ("200", value->str());
+ data::ConstElementPtr min_value = repr->get("min-preferred-lifetime");
+ ASSERT_TRUE(min_value);
+ EXPECT_EQ("100", min_value->str());
+ EXPECT_FALSE(repr->get("max-preferred-lifetime"));
+ }
+
+ {
+ SCOPED_TRACE("max-preferred-lifetime and preferred-lifetime");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("max-preferred-lifetime", data::Element::create(200));
+ // Use a different (and smaller) value for the default.
+ copied->set("preferred-lifetime", data::Element::create(100));
+ Subnet6Ptr subnet;
+ Subnet6ConfigParser parser;
+ ASSERT_NO_THROW(subnet = parser.parse(copied));
+ ASSERT_TRUE(subnet);
+ EXPECT_FALSE(subnet->getPreferred().unspecified());
+ EXPECT_EQ(100, subnet->getPreferred());
+ EXPECT_EQ(100, subnet->getPreferred().getMin());
+ EXPECT_EQ(200, subnet->getPreferred().getMax());
+ data::ConstElementPtr repr = subnet->toElement();
+ data::ConstElementPtr value = repr->get("preferred-lifetime");
+ ASSERT_TRUE(value);
+ EXPECT_EQ("100", value->str());
+ data::ConstElementPtr max_value = repr->get("max-preferred-lifetime");
+ ASSERT_TRUE(max_value);
+ EXPECT_EQ("200", max_value->str());
+ EXPECT_FALSE(repr->get("min-preferred-lifetime"));
+ }
+
+ {
+ SCOPED_TRACE("min-preferred-lifetime and max-preferred-lifetime");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("min-preferred-lifetime", data::Element::create(100));
+ copied->set("max-preferred-lifetime", data::Element::create(200));
+ Subnet6ConfigParser parser;
+ // No idea about the value to use for the default so failing.
+ ASSERT_THROW(parser.parse(copied), DhcpConfigError);
+ }
+
+ {
+ SCOPED_TRACE("all 3 (min, max and default) preferred-lifetime");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("min-preferred-lifetime", data::Element::create(100));
+ // Use a different (and greater) value for the default.
+ copied->set("preferred-lifetime", data::Element::create(200));
+ // Use a different (and greater than both) value for max.
+ copied->set("max-preferred-lifetime", data::Element::create(300));
+ Subnet6Ptr subnet;
+ Subnet6ConfigParser parser;
+ ASSERT_NO_THROW(subnet = parser.parse(copied));
+ ASSERT_TRUE(subnet);
+ EXPECT_FALSE(subnet->getPreferred().unspecified());
+ EXPECT_EQ(200, subnet->getPreferred());
+ EXPECT_EQ(100, subnet->getPreferred().getMin());
+ EXPECT_EQ(300, subnet->getPreferred().getMax());
+ data::ConstElementPtr repr = subnet->toElement();
+ data::ConstElementPtr value = repr->get("preferred-lifetime");
+ ASSERT_TRUE(value);
+ EXPECT_EQ("200", value->str());
+ data::ConstElementPtr min_value = repr->get("min-preferred-lifetime");
+ ASSERT_TRUE(min_value);
+ EXPECT_EQ("100", min_value->str());
+ data::ConstElementPtr max_value = repr->get("max-preferred-lifetime");
+ ASSERT_TRUE(max_value);
+ EXPECT_EQ("300", max_value->str());
+ }
+
+ {
+ SCOPED_TRACE("default value too small");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("min-preferred-lifetime", data::Element::create(200));
+ // 100 < 200 so it will fail.
+ copied->set("preferred-lifetime", data::Element::create(100));
+ // Use a different (and greater than both) value for max.
+ copied->set("max-preferred-lifetime", data::Element::create(300));
+ Subnet6ConfigParser parser;
+ ASSERT_THROW(parser.parse(copied), DhcpConfigError);
+ }
+
+ {
+ SCOPED_TRACE("default value too large");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("min-preferred-lifetime", data::Element::create(100));
+ // Use a different (and greater) value for the default.
+ copied->set("preferred-lifetime", data::Element::create(300));
+ // 300 > 200 so it will fail.
+ copied->set("max-preferred-lifetime", data::Element::create(200));
+ Subnet6ConfigParser parser;
+ ASSERT_THROW(parser.parse(copied), DhcpConfigError);
+ }
+
+ {
+ SCOPED_TRACE("equal bounds are ignored");
+ data::ElementPtr copied = data::copy(elems);
+ copied->set("min-preferred-lifetime", data::Element::create(100));
+ copied->set("preferred-lifetime", data::Element::create(100));
+ copied->set("max-preferred-lifetime", data::Element::create(100));
+ Subnet6Ptr subnet;
+ Subnet6ConfigParser parser;
+ ASSERT_NO_THROW(subnet = parser.parse(copied));
+ ASSERT_TRUE(subnet);
+ EXPECT_FALSE(subnet->getPreferred().unspecified());
+ EXPECT_EQ(100, subnet->getPreferred());
+ EXPECT_EQ(100, subnet->getPreferred().getMin());
+ EXPECT_EQ(100, subnet->getPreferred().getMax());
+ data::ConstElementPtr repr = subnet->toElement();
+ data::ConstElementPtr value = repr->get("preferred-lifetime");
+ ASSERT_TRUE(value);
+ EXPECT_EQ("100", value->str());
+ EXPECT_FALSE(repr->get("min-preferred-lifetime"));
+ EXPECT_FALSE(repr->get("max-preferred-lifetime"));
+ }
+}
+
} // end of anonymous namespace
" \"require-client-classes\": [ \"runner\" ],"
" \"user-context\": { \"comment\": \"example\" },"
" \"valid-lifetime\": 399,"
+ " \"min-valid-lifetime\": 299,"
+ " \"max-valid-lifetime\": 499,"
" \"calculate-tee-times\": true,"
" \"t1-percent\": 0.345,"
" \"t2-percent\": 0.721,"
" \"renew-timer\": 100,"
" \"rebind-timer\": 200,"
" \"valid-lifetime\": 300,"
+ " \"min-valid-lifetime\": 200,"
+ " \"max-valid-lifetime\": 400,"
" \"match-client-id\": false,"
" \"authoritative\": false,"
" \"next-server\": \"\","
EXPECT_EQ(99, network->getT1());
EXPECT_EQ(199, network->getT2());
EXPECT_EQ(399, network->getValid());
+ EXPECT_EQ(299, network->getValid().getMin());
+ EXPECT_EQ(499, network->getValid().getMax());
EXPECT_TRUE(network->getCalculateTeeTimes());
EXPECT_EQ(0.345, network->getT1Percent());
EXPECT_EQ(0.721, network->getT2Percent());
Subnet4Ptr subnet1 = network->getSubnet(SubnetID(1));
ASSERT_TRUE(subnet1);
EXPECT_EQ("10.1.2.0", subnet1->get().first.toText());
+ EXPECT_EQ(300, subnet1->getValid());
+ EXPECT_EQ(200, subnet1->getValid().getMin());
+ EXPECT_EQ(400, subnet1->getValid().getMax());
// Subnet with id 2
Subnet4Ptr subnet2 = network->getSubnet(SubnetID(2));
ASSERT_TRUE(subnet2);
EXPECT_EQ("192.0.2.0", subnet2->get().first.toText());
+ EXPECT_EQ(30, subnet2->getValid());
+ EXPECT_EQ(30, subnet2->getValid().getMin());
+ EXPECT_EQ(30, subnet2->getValid().getMax());
// DHCP options
ConstCfgOptionPtr cfg_option = network->getCfgOption();
"\"eth1\","
" \"name\": \"bird\","
" \"preferred-lifetime\": 211,"
+ " \"min-preferred-lifetime\": 111,"
+ " \"max-preferred-lifetime\": 311,"
" \"rapid-commit\": true,"
" \"rebind-timer\": 199,"
" \"relay\": { \"ip-addresses\": [ \"2001:db8:1::1\" ] },"
" \"reservation-mode\": \"out-of-pool\","
" \"user-context\": { },"
" \"valid-lifetime\": 399,"
+ " \"min-valid-lifetime\": 299,"
+ " \"max-valid-lifetime\": 499,"
" \"calculate-tee-times\": true,"
" \"t1-percent\": 0.345,"
" \"t2-percent\": 0.721,"
" \"renew-timer\": 100,"
" \"rebind-timer\": 200,"
" \"preferred-lifetime\": 300,"
+ " \"min-preferred-lifetime\": 200,"
+ " \"max-preferred-lifetime\": 400,"
" \"valid-lifetime\": 400,"
+ " \"min-valid-lifetime\": 300,"
+ " \"max-valid-lifetime\": 500,"
" \"client-class\": \"\","
" \"require-client-classes\": []\n,"
" \"reservation-mode\": \"all\","
EXPECT_EQ("bird", network->getName());
EXPECT_EQ("eth1", network->getIface().get());
EXPECT_EQ(211, network->getPreferred());
+ EXPECT_EQ(111, network->getPreferred().getMin());
+ EXPECT_EQ(311, network->getPreferred().getMax());
EXPECT_TRUE(network->getRapidCommit());
EXPECT_EQ(99, network->getT1());
EXPECT_EQ(199, network->getT2());
EXPECT_EQ(399, network->getValid());
+ EXPECT_EQ(299, network->getValid().getMin());
+ EXPECT_EQ(499, network->getValid().getMax());
EXPECT_TRUE(network->getCalculateTeeTimes());
EXPECT_EQ(0.345, network->getT1Percent());
EXPECT_EQ(0.721, network->getT2Percent());
Subnet6Ptr subnet1 = network->getSubnet(SubnetID(1));
ASSERT_TRUE(subnet1);
EXPECT_EQ("3000::", subnet1->get().first.toText());
+ EXPECT_EQ(300, subnet1->getPreferred());
+ EXPECT_EQ(200, subnet1->getPreferred().getMin());
+ EXPECT_EQ(400, subnet1->getPreferred().getMax());
+ EXPECT_EQ(400, subnet1->getValid());
+ EXPECT_EQ(300, subnet1->getValid().getMin());
+ EXPECT_EQ(500, subnet1->getValid().getMax());
// Subnet with id 2
Subnet6Ptr subnet2 = network->getSubnet(SubnetID(2));
ASSERT_TRUE(subnet2);
EXPECT_EQ("2001:db8:1::", subnet2->get().first.toText());
+ EXPECT_EQ(30, subnet2->getPreferred());
+ EXPECT_EQ(30, subnet2->getPreferred().getMin());
+ EXPECT_EQ(30, subnet2->getPreferred().getMax());
+ EXPECT_EQ(40, subnet2->getValid());
+ EXPECT_EQ(40, subnet2->getValid().getMin());
+ EXPECT_EQ(40, subnet2->getValid().getMax());
// DHCP options
ConstCfgOptionPtr cfg_option = network->getCfgOption();