diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:15:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:15:43 +0000 |
commit | f5f56e1a1c4d9e9496fcb9d81131066a964ccd23 (patch) | |
tree | 49e44c6f87febed37efb953ab5485aa49f6481a7 /src/lib/dhcpsrv/tests/sanity_checks_unittest.cc | |
parent | Initial commit. (diff) | |
download | isc-kea-f5f56e1a1c4d9e9496fcb9d81131066a964ccd23.tar.xz isc-kea-f5f56e1a1c4d9e9496fcb9d81131066a964ccd23.zip |
Adding upstream version 2.4.1.upstream/2.4.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib/dhcpsrv/tests/sanity_checks_unittest.cc')
-rw-r--r-- | src/lib/dhcpsrv/tests/sanity_checks_unittest.cc | 1614 |
1 files changed, 1614 insertions, 0 deletions
diff --git a/src/lib/dhcpsrv/tests/sanity_checks_unittest.cc b/src/lib/dhcpsrv/tests/sanity_checks_unittest.cc new file mode 100644 index 0000000..7185b93 --- /dev/null +++ b/src/lib/dhcpsrv/tests/sanity_checks_unittest.cc @@ -0,0 +1,1614 @@ +// Copyright (C) 2018-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> +#include <dhcpsrv/cfg_consistency.h> +#include <dhcpsrv/cfgmgr.h> +#include <dhcpsrv/parsers/sanity_checks_parser.h> +#include <dhcpsrv/srv_config.h> +#include <dhcpsrv/lease.h> +#include <dhcpsrv/lease_mgr_factory.h> +#include <dhcpsrv/subnet.h> +#include <dhcpsrv/sanity_checker.h> +#include <dhcpsrv/testutils/test_utils.h> +#include <testutils/log_utils.h> +#include <util/range_utilities.h> +#include <cc/data.h> +#include <gtest/gtest.h> + +using namespace std; +using namespace isc::data; +using namespace isc::asiolink; +using namespace isc::dhcp; +using namespace isc::dhcp::test; + +class SanityChecksTest : public ::testing::Test { +public: + + SanityChecksTest() { + LeaseMgrFactory::destroy(); + } + + void startLeaseBackend(bool v6) { + std::ostringstream s; + s << "type=memfile " << (v6 ? "universe=6 " : "universe=4 ") + << "persist=false lfc-interval=0"; + LeaseMgrFactory::create(s.str()); + } + + void setLeaseCheck(CfgConsistency::LeaseSanity sanity) { + CfgMgr::instance().getCurrentCfg()->getConsistency()->setLeaseSanityCheck(sanity); + } + + ~SanityChecksTest() { + CfgMgr::instance().clear(); + LeaseMgrFactory::destroy(); + } + + /// @brief Generates a simple IPv4 lease. + /// + /// The HW address is randomly generated, subnet_id is specified. + /// + /// @param address Lease address. + /// @param subnet_id ID of the subnet to use. + /// + /// @return new lease with random content + Lease4Ptr newLease4(const IOAddress& address, SubnetID subnet_id) { + + // Randomize HW address. + vector<uint8_t> mac(6); + isc::util::fillRandom(mac.begin(), mac.end()); + HWAddrPtr hwaddr(new HWAddr(mac, HTYPE_ETHER)); + + vector<uint8_t> clientid(1); + + time_t timestamp = time(0) - 86400 + random() % 86400; + + // Return created lease. + return (Lease4Ptr(new Lease4(address, hwaddr, + &clientid[0], 0, // no client-id + 1200, // valid + timestamp, subnet_id, false, false, ""))); + } + + /// @brief Generates a simple IPv6 lease. + /// + /// The DUID and IAID are randomly generated, subnet_id is specified. + /// + /// @param address Lease address. + /// @param subnet_id ID of the subnet to use. + /// + /// @return new lease with random content + Lease6Ptr newLease6(const IOAddress& address, SubnetID subnet_id) { + // Let's generate DUID of random length. + std::vector<uint8_t> duid_vec(8 + random()%20); + // And then fill it with random value. + isc::util::fillRandom(duid_vec.begin(), duid_vec.end()); + DuidPtr duid(new DUID(duid_vec)); + + Lease::Type lease_type = Lease::TYPE_NA; + uint32_t iaid = 1 + random()%100; + + std::ostringstream hostname; + hostname << "hostname" << (random() % 2048); + + // Return created lease. + Lease6Ptr lease(new Lease6(lease_type, address, duid, iaid, + 1000, 1200, // pref, valid + subnet_id, + false, false, "")); // fqdn fwd, rev, hostname + return (lease); + } + + Subnet4Ptr createSubnet4(string subnet_txt, SubnetID id) { + size_t pos = subnet_txt.find("/"); + isc::asiolink::IOAddress addr(subnet_txt.substr(0, pos)); + size_t len = boost::lexical_cast<unsigned int>(subnet_txt.substr(pos + 1)); + + return (Subnet4Ptr(new Subnet4(addr, len, 1000, 2000, 3000, id))); + } + + Subnet6Ptr createSubnet6(string subnet_txt, SubnetID id) { + size_t pos = subnet_txt.find("/"); + isc::asiolink::IOAddress addr(subnet_txt.substr(0, pos)); + size_t len = boost::lexical_cast<unsigned int>(subnet_txt.substr(pos + 1)); + + return (Subnet6Ptr(new Subnet6(addr, len, 1000, 2000, 3000, 4000, id))); + } + + void + parserCheck(SrvConfig& cfg, const string& txt, bool exp_throw, + CfgConsistency::LeaseSanity exp_sanity, + CfgConsistency::ExtendedInfoSanity exp_sanity2) { + + // Reset to defaults. + cfg.getConsistency()->setLeaseSanityCheck(CfgConsistency::LEASE_CHECK_NONE); + cfg.getConsistency()->setExtendedInfoSanityCheck(CfgConsistency::EXTENDED_INFO_CHECK_FIX); + + SanityChecksParser parser; + + ElementPtr json; + EXPECT_NO_THROW(json = Element::fromJSON(txt)); + + if (exp_throw) { + // Should throw DhcpConfigError. + try { + parser.parse(cfg, json); + ADD_FAILURE() << "should throw not did not throw"; + return; + } catch (const DhcpConfigError&) { + return; + } catch (const exception& ex) { + ADD_FAILURE() << "throw another exception with " << ex.what(); + } + } else { + // Should not throw. + try { + parser.parse(cfg, json); + } catch (const exception& ex) { + ADD_FAILURE() << "throw an exception with " << ex.what(); + } + } + + EXPECT_EQ(cfg.getConsistency()->getLeaseSanityCheck(), exp_sanity); + EXPECT_EQ(cfg.getConsistency()->getExtendedInfoSanityCheck(), exp_sanity2); + } + +}; + +// Verify whether configuration parser is able to understand the values +// that are valid and reject those that are not. +TEST_F(SanityChecksTest, leaseCheck) { + + // These are valid and should be accepted. + string valid1 = "{ \"lease-checks\": \"none\" }"; + string valid2 = "{ \"lease-checks\": \"warn\" }"; + string valid3 = "{ \"lease-checks\": \"fix\" }"; + string valid4 = "{ \"lease-checks\": \"fix-del\" }"; + string valid5 = "{ \"lease-checks\": \"del\" }"; + + // These are not valid values or types. + string bogus1 = "{ \"lease-checks\": \"sanitize\" }"; + string bogus2 = "{ \"lease-checks\": \"ignore\" }"; + string bogus3 = "{ \"lease-checks\": true }"; + string bogus4 = "{ \"lease-checks\": 42 }"; + + // These are valid and should be accepted. + string valid6 = "{ \"extended-info-checks\": \"none\" }"; + string valid7 = "{ \"extended-info-checks\": \"fix\" }"; + string valid8 = "{ \"extended-info-checks\": \"strict\" }"; + string valid9 = "{ \"extended-info-checks\": \"pedantic\" }"; + string valid10 = "{ \"lease-checks\": \"fix\",\n" + " \"extended-info-checks\": \"fix\" }"; + + string bogus5 = "{ \"extended-info-checks\": \"sanitize\" }"; + string bogus6 = "{ \"extended-info-checks\": \"ignore\" }"; + string bogus7 = "{ \"extended-info-checks\": true }"; + string bogus8 = "{ \"extended-info-checks\": 42 }"; + + SrvConfig cfg; + + // The lease default should be to none. + EXPECT_EQ(cfg.getConsistency()->getLeaseSanityCheck(), + CfgConsistency::LEASE_CHECK_NONE); + + // The extended info default should be to fix. + EXPECT_EQ(cfg.getConsistency()->getExtendedInfoSanityCheck(), + CfgConsistency::EXTENDED_INFO_CHECK_FIX); + + parserCheck(cfg, valid1, false, CfgConsistency::LEASE_CHECK_NONE, + CfgConsistency::EXTENDED_INFO_CHECK_FIX); + parserCheck(cfg, valid2, false, CfgConsistency::LEASE_CHECK_WARN, + CfgConsistency::EXTENDED_INFO_CHECK_FIX); + parserCheck(cfg, valid3, false, CfgConsistency::LEASE_CHECK_FIX, + CfgConsistency::EXTENDED_INFO_CHECK_FIX); + parserCheck(cfg, valid4, false, CfgConsistency::LEASE_CHECK_FIX_DEL, + CfgConsistency::EXTENDED_INFO_CHECK_FIX); + parserCheck(cfg, valid5, false, CfgConsistency::LEASE_CHECK_DEL, + CfgConsistency::EXTENDED_INFO_CHECK_FIX); + + parserCheck(cfg, bogus1, true, CfgConsistency::LEASE_CHECK_NONE, + CfgConsistency::EXTENDED_INFO_CHECK_FIX); + parserCheck(cfg, bogus2, true, CfgConsistency::LEASE_CHECK_NONE, + CfgConsistency::EXTENDED_INFO_CHECK_FIX); + parserCheck(cfg, bogus3, true, CfgConsistency::LEASE_CHECK_NONE, + CfgConsistency::EXTENDED_INFO_CHECK_FIX); + parserCheck(cfg, bogus4, true, CfgConsistency::LEASE_CHECK_NONE, + CfgConsistency::EXTENDED_INFO_CHECK_FIX); + + parserCheck(cfg, valid6, false, CfgConsistency::LEASE_CHECK_NONE, + CfgConsistency::EXTENDED_INFO_CHECK_NONE); + parserCheck(cfg, valid7, false, CfgConsistency::LEASE_CHECK_NONE, + CfgConsistency::EXTENDED_INFO_CHECK_FIX); + parserCheck(cfg, valid8, false, CfgConsistency::LEASE_CHECK_NONE, + CfgConsistency::EXTENDED_INFO_CHECK_STRICT); + parserCheck(cfg, valid9, false, CfgConsistency::LEASE_CHECK_NONE, + CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC); + parserCheck(cfg, valid10, false, CfgConsistency::LEASE_CHECK_FIX, + CfgConsistency::EXTENDED_INFO_CHECK_FIX); + + parserCheck(cfg, bogus5, true, CfgConsistency::LEASE_CHECK_NONE, + CfgConsistency::EXTENDED_INFO_CHECK_FIX); + parserCheck(cfg, bogus6, true, CfgConsistency::LEASE_CHECK_NONE, + CfgConsistency::EXTENDED_INFO_CHECK_FIX); + parserCheck(cfg, bogus7, true, CfgConsistency::LEASE_CHECK_NONE, + CfgConsistency::EXTENDED_INFO_CHECK_FIX); + parserCheck(cfg, bogus8, true, CfgConsistency::LEASE_CHECK_NONE, + CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// Verify whether sanity checker works as expected (valid v4). +TEST_F(SanityChecksTest, valid4) { + // Create network and lease. + CfgMgr::instance().setFamily(AF_INET); + Subnet4Ptr subnet = createSubnet4("192.168.1.0/24", 1); + CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->add(subnet); + IOAddress addr("192.168.1.1"); + Lease4Ptr lease = newLease4(addr, 1); + + // Check the lease. + setLeaseCheck(CfgConsistency::LEASE_CHECK_FIX_DEL); + SanityChecker checker; + checker.checkLease(lease); + + // Verify the lease is still here in the same subnet. + ASSERT_TRUE(lease); + EXPECT_EQ(subnet->getID(), lease->subnet_id_); +} + +// Verify whether sanity checker works as expected (valid v6). +TEST_F(SanityChecksTest, valid6) { + // Create network and lease. + CfgMgr::instance().setFamily(AF_INET6); + Subnet6Ptr subnet = createSubnet6("2001:db8:1::/64", 1); + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->add(subnet); + IOAddress addr("2001:db8:1::1"); + Lease6Ptr lease = newLease6(addr, 1); + + // Check the lease. + setLeaseCheck(CfgConsistency::LEASE_CHECK_FIX_DEL); + SanityChecker checker; + checker.checkLease(lease); + + // Verify the lease is still here in the same subnet. + ASSERT_TRUE(lease); + EXPECT_EQ(subnet->getID(), lease->subnet_id_); +} + +// Verify whether sanity checker works as expected (wrong subnet v4). +TEST_F(SanityChecksTest, wrongSubnet4) { + // Create networks and lease in the second and wrong subnet. + CfgMgr::instance().setFamily(AF_INET); + Subnet4Ptr subnet1 = createSubnet4("192.168.1.0/24", 1); + Subnet4Ptr subnet2 = createSubnet4("192.168.2.0/24", 2); + CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->add(subnet1); + CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->add(subnet2); + IOAddress addr("192.168.1.1"); + Lease4Ptr lease = newLease4(addr, 2); + + // Check the lease. + setLeaseCheck(CfgConsistency::LEASE_CHECK_FIX_DEL); + SanityChecker checker; + checker.checkLease(lease); + + // Verify the lease is still here but was moved to the first and right subnet. + ASSERT_TRUE(lease); + EXPECT_EQ(subnet1->getID(), lease->subnet_id_); +} + +// Verify whether sanity checker works as expected (wrong subnet v6). +TEST_F(SanityChecksTest, wrongSubnet6) { + // Create networks and lease in the second and wrong subnet. + CfgMgr::instance().setFamily(AF_INET6); + Subnet6Ptr subnet1 = createSubnet6("2001:db8:1::/64", 1); + Subnet6Ptr subnet2 = createSubnet6("2001:db8:2::/64", 2); + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->add(subnet1); + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->add(subnet2); + IOAddress addr("2001:db8:1::1"); + Lease6Ptr lease = newLease6(addr, 2); + + // Check the lease. + setLeaseCheck(CfgConsistency::LEASE_CHECK_FIX_DEL); + SanityChecker checker; + checker.checkLease(lease); + + // Verify the lease is still here but was moved to the first and right subnet. + ASSERT_TRUE(lease); + EXPECT_EQ(subnet1->getID(), lease->subnet_id_); +} + +// Verify whether sanity checker works as expected (no subnet v4). +TEST_F(SanityChecksTest, noSubnet4) { + // Create network and lease in a wrong subnet. + CfgMgr::instance().setFamily(AF_INET); + Subnet4Ptr subnet = createSubnet4("192.168.2.0/24", 1); + CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->add(subnet); + IOAddress addr("192.168.1.1"); + Lease4Ptr lease = newLease4(addr, 1); + + // Check the lease. + setLeaseCheck(CfgConsistency::LEASE_CHECK_FIX_DEL); + SanityChecker checker; + checker.checkLease(lease); + + // Verify the lease was removed because its subnet does not exist, + EXPECT_FALSE(lease); +} + +// Verify whether sanity checker works as expected (no subnet v6). +TEST_F(SanityChecksTest, noSubnet6) { + // Create network and lease in a wrong subnet. + CfgMgr::instance().setFamily(AF_INET6); + Subnet6Ptr subnet = createSubnet6("2001:db8:2::/64", 1); + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->add(subnet); + IOAddress addr("2001:db8:1::1"); + Lease6Ptr lease = newLease6(addr, 1); + + // Check the lease. + setLeaseCheck(CfgConsistency::LEASE_CHECK_FIX_DEL); + SanityChecker checker; + checker.checkLease(lease); + + // Verify the lease was removed because its subnet does not exist, + EXPECT_FALSE(lease); +} + +// Verify whether sanity checker works as expected (guard v4). +TEST_F(SanityChecksTest, guard4) { + // Create networks and lease in the first and guarded subnet. + CfgMgr::instance().setFamily(AF_INET); + Subnet4Ptr subnet1 = createSubnet4("192.168.1.0/24", 1); + subnet1->allowClientClass("foo"); + Subnet4Ptr subnet2 = createSubnet4("192.168.1.100/24", 2); + CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->add(subnet1); + CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->add(subnet2); + IOAddress addr("192.168.1.1"); + Lease4Ptr lease = newLease4(addr, 1); + + // Check the lease. + setLeaseCheck(CfgConsistency::LEASE_CHECK_FIX_DEL); + SanityChecker checker; + checker.checkLease(lease); + + // Verify the lease is still here and in the guarded subnet. + ASSERT_TRUE(lease); + EXPECT_EQ(subnet1->getID(), lease->subnet_id_); +} + +// Verify whether sanity checker works as expected (guard v6). +TEST_F(SanityChecksTest, guard6) { + // Create networks and lease in the first and guarded subnet. + CfgMgr::instance().setFamily(AF_INET6); + Subnet6Ptr subnet1 = createSubnet6("2001:db8:1::/64", 1); + subnet1->allowClientClass("foo"); + Subnet6Ptr subnet2 = createSubnet6("2001:db8:2::100/64", 2); + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->add(subnet1); + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->add(subnet2); + IOAddress addr("2001:db8:1::1"); + Lease6Ptr lease = newLease6(addr, 1); + + // Check the lease. + setLeaseCheck(CfgConsistency::LEASE_CHECK_FIX_DEL); + SanityChecker checker; + checker.checkLease(lease); + + // Verify the lease is still here and in the guarded subnet. + ASSERT_TRUE(lease); + EXPECT_EQ(subnet1->getID(), lease->subnet_id_); +} + +// Verify whether sanity checker works as expected (guard only v4). +TEST_F(SanityChecksTest, guardOnly4) { + // Create guarded network and lease. + CfgMgr::instance().setFamily(AF_INET); + Subnet4Ptr subnet = createSubnet4("192.168.1.0/24", 1); + subnet->allowClientClass("foo"); + CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->add(subnet); + IOAddress addr("192.168.1.1"); + Lease4Ptr lease = newLease4(addr, 1); + + // Check the lease. + setLeaseCheck(CfgConsistency::LEASE_CHECK_FIX_DEL); + SanityChecker checker; + checker.checkLease(lease); + + // Verify the lease is still here in the same subnet. + ASSERT_TRUE(lease); + EXPECT_EQ(subnet->getID(), lease->subnet_id_); +} + +// Verify whether sanity checker works as expected (valid v6). +TEST_F(SanityChecksTest, guardOnly6) { + // Create guarded network and lease. + CfgMgr::instance().setFamily(AF_INET6); + Subnet6Ptr subnet = createSubnet6("2001:db8:1::/64", 1); + subnet->allowClientClass("foo"); + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->add(subnet); + IOAddress addr("2001:db8:1::1"); + Lease6Ptr lease = newLease6(addr, 1); + + // Check the lease. + setLeaseCheck(CfgConsistency::LEASE_CHECK_FIX_DEL); + SanityChecker checker; + checker.checkLease(lease); + + // Verify the lease is still here in the same subnet. + ASSERT_TRUE(lease); + EXPECT_EQ(subnet->getID(), lease->subnet_id_); +} + +class ExtendedInfoChecksTest : public LogContentTest { +public: + + /// @brief Generates a simple IPv4 lease. + /// + /// The HW address is randomly generated, user context is specified. + /// + /// @param address Lease address. + /// @param user_context User context to use. + /// + /// @return new lease with random content. + Lease4Ptr newLease4(const IOAddress& address, + ConstElementPtr user_context) { + + // Randomize HW address. + vector<uint8_t> mac(6); + isc::util::fillRandom(mac.begin(), mac.end()); + HWAddrPtr hwaddr(new HWAddr(mac, HTYPE_ETHER)); + + vector<uint8_t> clientid(1); + + time_t timestamp = time(0) - 86400 + random() % 86400; + + // Return created lease. + Lease4Ptr lease(new Lease4(address, hwaddr, + &clientid[0], 0, // no client-id + 1200, // valid + timestamp, 1, false, false, "")); + lease->setContext(user_context); + return(lease); + } + + /// @brief Generates a simple IPv6 lease. + /// + /// The DUID and IAID are randomly generated, user context is specified. + /// + /// @param address Lease address. + /// @param user_context User context to use. + /// + /// @return new lease with random content. + Lease6Ptr newLease6(const IOAddress& address, + ConstElementPtr user_context) { + // Let's generate DUID of random length. + std::vector<uint8_t> duid_vec(8 + random()%20); + // And then fill it with random value. + isc::util::fillRandom(duid_vec.begin(), duid_vec.end()); + DuidPtr duid(new DUID(duid_vec)); + + Lease::Type lease_type = Lease::TYPE_NA; + uint32_t iaid = 1 + random()%100; + + std::ostringstream hostname; + hostname << "hostname" << (random() % 2048); + + // Return created lease. + Lease6Ptr lease(new Lease6(lease_type, address, duid, iaid, + 1000, 1200, // pref, valid + 1, false, false, "")); + lease->setContext(user_context); + return(lease); + } + + /// @brief Check IPv4 scenario. + /// + /// @brief original Original user context. + /// @brief expected Expected user context. + /// @brief sanity Extended info sanity level. + /// @break logs Expected log messages. + void check4(string description, string original, string expected, + CfgConsistency::ExtendedInfoSanity sanity, + vector<string> logs = {}) { + ElementPtr orig_context; + if (!original.empty()) { + ASSERT_NO_THROW(orig_context = Element::fromJSON(original)) + << "invalid original user context, test " << description + << " is broken"; + } + ElementPtr exp_context; + if (!expected.empty()) { + ASSERT_NO_THROW(exp_context = Element::fromJSON(expected)) + << "invalid expected user context, test " << description + << " is broken"; + } + + Lease4Ptr lease = newLease4(IOAddress("192.168.1.1"), orig_context); + ConstElementPtr before; + if (orig_context) { + before = isc::data::copy(orig_context); + } + for (const string& log : logs) { + addString(log); + } + + bool ret = LeaseMgr::upgradeLease4ExtendedInfo(lease, sanity); + ConstElementPtr after = lease->getContext(); + if (!before && !after) { + EXPECT_FALSE(ret) << "null before and null after"; + } else if ((before && !after) || (!before && after)) { + EXPECT_TRUE(ret) << "only one of before and after is null"; + } else if (before->equals(*after)) { + EXPECT_FALSE(ret) << "before == after"; + } else { + EXPECT_TRUE(ret) << "before != after"; + } + if (!exp_context) { + EXPECT_FALSE(after) << "expected null, got " << *after; + } else { + ASSERT_TRUE(after) << "expected not null, got null"; + EXPECT_TRUE(exp_context->equals(*after)) + << "expected: " << *exp_context << std::endl + << "actual: " << *after << std::endl; + } + EXPECT_TRUE(checkFile()); + } + + /// @brief Check IPv6 scenario. + /// + /// @brief original Original user context. + /// @brief expected Expected user context. + /// @brief sanity Extended info sanity level. + /// @break logs Expected log messages. + void check6(string description, string original, string expected, + CfgConsistency::ExtendedInfoSanity sanity, + vector<string> logs = {}) { + ElementPtr orig_context; + if (!original.empty()) { + ASSERT_NO_THROW(orig_context = Element::fromJSON(original)) + << "invalid original user context, test " << description + << " is broken"; + } + ElementPtr exp_context; + if (!expected.empty()) { + ASSERT_NO_THROW(exp_context = Element::fromJSON(expected)) + << "invalid expected user context, test " << description + << " is broken"; + } + + Lease6Ptr lease = newLease6(IOAddress("2001::1"), orig_context); + ConstElementPtr before; + if (orig_context) { + before = isc::data::copy(orig_context); + } + for (const string& log : logs) { + addString(log); + } + + bool ret = LeaseMgr::upgradeLease6ExtendedInfo(lease, sanity); + ConstElementPtr after = lease->getContext(); + if (!before && !after) { + EXPECT_FALSE(ret) << "null before and null after"; + } else if ((before && !after) || (!before && after)) { + EXPECT_TRUE(ret) << "only one of before and after is null"; + } else if (before->equals(*after)) { + EXPECT_FALSE(ret) << "before == after"; + } else { + EXPECT_TRUE(ret) << "before != after"; + } + if (!exp_context) { + EXPECT_FALSE(after) << "expected null, got " << *after; + } else { + ASSERT_TRUE(after) << "expected not null, got null"; + EXPECT_TRUE(exp_context->equals(*after)) + << "expected: " << *exp_context << std::endl + << "actual: " << *after << std::endl; + } + EXPECT_TRUE(checkFile()); + } +}; + +// No user context is right for any sanity check level including the highest. +TEST_F(ExtendedInfoChecksTest, noUserContext4) { + string description = "no user context, pedantic"; + check4(description, "", "", CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC); +} + +// User context with a bad type is right only when no check is done. +TEST_F(ExtendedInfoChecksTest, badTypeUserContext4none) { + string description = "user context not a map, none"; + check4(description, "1", "1", CfgConsistency::EXTENDED_INFO_CHECK_NONE); +} + +// User context with a bad type is refused by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, badTypeUserContext4) { + string description = "user context not a map, fix"; + check4(description, "1", "", CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 192.168.1.1 failed checks" + " (in user context a problem was found:" + " user context is not a map)" }); +} + +// Empty user context is right only when no check is done. +TEST_F(ExtendedInfoChecksTest, emptyTypeUserContext4none) { + string description = "empty user context, none"; + check4(description, "{ }", "{ }", + CfgConsistency::EXTENDED_INFO_CHECK_NONE); +} + +// Empty user context is dropped by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, emptyTypeUserContext4) { + string description = "empty user context, fix"; + check4(description, "{ }", "", CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// No ISC entry is right in all cases. +TEST_F(ExtendedInfoChecksTest, noISC4) { + string description = "no ISC entry, pedantic"; + check4(description, "{ \"foo\": 1 }", "{ \"foo\": 1 }", + CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC); +} + +// ISC entry with a bad type is right only when no check is done. +TEST_F(ExtendedInfoChecksTest, badTypeISC4none) { + string description = "ISC entry no a map, none"; + check4(description, "{ \"ISC\": 1 }", "{ \"ISC\": 1 }", + CfgConsistency::EXTENDED_INFO_CHECK_NONE); +} + +// ISC entry with a bad type is dropped by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, badTypeISC4) { + string description = "ISC entry no a map, fix"; + check4(description, "{ \"ISC\": 1 }", "", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 192.168.1.1 failed checks" + " (in isc a problem was found:" + " ISC entry is not a map)" }); +} + +// When the ISC entry is dropped other entries are kept. +TEST_F(ExtendedInfoChecksTest, badTypeISC4other) { + string description = "ISC entry no a map with others, fix"; + check4(description, "{ \"ISC\": 1, \"foo\": 2 }", "{ \"foo\": 2 }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 192.168.1.1 failed checks" + " (in isc a problem was found:" + " ISC entry is not a map)" }); +} + +// Empty ISC entry is kept only when no check is done. +TEST_F(ExtendedInfoChecksTest, emptyISC4none) { + string description = "empty ISC entry, none"; + check4(description, "{ \"ISC\": { } }", "{ \"ISC\": { } }", + CfgConsistency::EXTENDED_INFO_CHECK_NONE); +} + +// Empty ISC entry is dropped by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, emptyISC4) { + string description = "empty ISC entry, fix"; + check4(description, "{ \"ISC\": { } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// No relay-agent-info entry is right at all sanity levels. +TEST_F(ExtendedInfoChecksTest, noRAI) { + string description = "no RAI, pedantic"; + check4(description, "{ \"ISC\": { \"foo\": 1 } }", + "{ \"ISC\": { \"foo\": 1 } }", + CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC); +} + +// relay-agent-info entry with a bad type is right only when no check is done. +TEST_F(ExtendedInfoChecksTest, badTypeRAInone) { + string description = "RAI is not a string or a map, none"; + check4(description, "{ \"ISC\": { \"relay-agent-info\": true } }", + "{ \"ISC\": { \"relay-agent-info\": true } }", + CfgConsistency::EXTENDED_INFO_CHECK_NONE); +} + +// relay-agent-info entry with a bad type is dropped by all not none sanity +// check levels. +TEST_F(ExtendedInfoChecksTest, badTypeRAI) { + string description = "RAI is not a string or a map, fix"; + check4(description, "{ \"ISC\": { \"relay-agent-info\": true } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 192.168.1.1 failed checks" + " (in relay-agent-info a problem was found:" + " relay-agent-info is not a map or a string)" }); +} + +// When relay-agent-info entry is dropped other entries are kept. +TEST_F(ExtendedInfoChecksTest, badTypeRAIother) { + string description = "RAI is not a string or a map with others, fix"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": true, \"foo\": 1 } }", + "{ \"ISC\": { \"foo\": 1 } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 192.168.1.1 failed checks" + " (in relay-agent-info a problem was found:" + " relay-agent-info is not a map or a string)" }); +} + +// String relay-agent-info entry which can't be decoded is right +// only when no check is done. +TEST_F(ExtendedInfoChecksTest, badEncodingStringRAInone) { + string description = "string RAI with a junk value, none"; + check4(description, "{ \"ISC\": { \"relay-agent-info\": \"foo\" } }", + "{ \"ISC\": { \"relay-agent-info\": \"foo\" } }", + CfgConsistency::EXTENDED_INFO_CHECK_NONE); +} + +// String relay-agent-info entry which can't be decoded is dropped +// by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, badEncodingStringRAI) { + string description = "string RAI with a junk value, fix"; + check4(description, "{ \"ISC\": { \"relay-agent-info\": \"foo\" } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 192.168.1.1 failed checks" + " (in rai a problem was found:" + " 'foo' is not a valid string of hexadecimal digits)" }); +} + +// String relay-agent-info entry for an empty option is dropped +// by all not none sanity check levels (this should not happen). +TEST_F(ExtendedInfoChecksTest, emptyStringRAI) { + string description = "string RAI with empty content, fix"; + check4(description, "{ \"ISC\": { \"relay-agent-info\": \"0x\" } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 192.168.1.1 failed checks" + " (in rai a problem was found:" + " '0x' is not a valid string of hexadecimal digits)" }); +} + +// Valid string relay-agent-info entry is upgraded by all not none +// sanity check levels. +TEST_F(ExtendedInfoChecksTest, upgradedRAI) { + string description = "valid string RAI, fix"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": \"0x0104AABBCCDD\" } }", + "{ \"ISC\": { \"relay-agent-info\": { \"sub-options\":" + " \"0x0104AABBCCDD\" } } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE4_EXTENDED_INFO_UPGRADED" + " extended info for lease 192.168.1.1 was upgraded" }); +} + +// Upgraded string relay-agent-info entry with ids. +TEST_F(ExtendedInfoChecksTest, upgradedRAIwithIds) { + string description = "valid string RAI with ids, fix"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": \"0x02030102030C03AABBCC\" } }", + "{ \"ISC\": { \"relay-agent-info\": { \"sub-options\":" + " \"0x02030102030C03AABBCC\", \"remote-id\": \"010203\"," + " \"relay-id\": \"AABBCC\" } } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE4_EXTENDED_INFO_UPGRADED" + " extended info for lease 192.168.1.1 was upgraded" }); +} + +// sub-options entry with a bad type is right up to the fix sanity level. +TEST_F(ExtendedInfoChecksTest, badTypeSubOptionsfix) { + string description = "sub-options not a string, fix"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"sub-options\": 1 } } }", + "{ \"ISC\": { \"relay-agent-info\": { \"sub-options\": 1 } } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// sub-options entry with a bad type is dropped at strict or higher +// sanity levels. +TEST_F(ExtendedInfoChecksTest, badTypeSubOptionsstrict) { + string description = "sub-options not a string, strict"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"sub-options\": 1 } } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 192.168.1.1 failed checks" + " (in sub-options a problem was found:" + " sub-options is not a string)" }); +} + +// sub-options entry which can't be decoded is right up to the fix +// sanity level. +TEST_F(ExtendedInfoChecksTest, badEncodingSubOptionsfix) { + string description = "sub-options with a junk value, fix"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"sub-options\":" + " \"foo\" } } }", + "{ \"ISC\": { \"relay-agent-info\": { \"sub-options\":" + " \"foo\" } } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// sub-options entry which can't be decoded is dropped at strict or higher +// sanity levels. +TEST_F(ExtendedInfoChecksTest, badEncodingSubOptionsstrict) { + string description = "sub-options with a junk value, strict"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"sub-options\":" + " \"foo\" } } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 192.168.1.1 failed checks" + " (in sub-options a problem was found:" + " 'foo' is not a valid string of hexadecimal digits)" }); +} + +// remote-id entry with a bad type is right up to the fix sanity level. +TEST_F(ExtendedInfoChecksTest, badTypeRemoteId4fix) { + string description = "remote-id not a string, fix"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"remote-id\": 1 } } }", + "{ \"ISC\": { \"relay-agent-info\": { \"remote-id\": 1 } } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// remote-id entry with a bad type is dropped at strict or higher +// sanity levels. +TEST_F(ExtendedInfoChecksTest, badTypeRemoteId4strict) { + string description = "remote-id not a string, strict"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"remote-id\": 1 } } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 192.168.1.1 failed checks" + " (in remote-id a problem was found:" + " remote-id is not a string)" }); +} + +// remote-id entry which can't be decoded is right up to the fix sanity level. +TEST_F(ExtendedInfoChecksTest, badEncodingRemoteId4fix) { + string description = "remote-id with a junk value, fix"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"remote-id\":" + " \"foo\" } } }", + "{ \"ISC\": { \"relay-agent-info\": { \"remote-id\":" + " \"foo\" } } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// remote-id entry which can't be decoded is dropped at strict or higher +// sanity levels. +TEST_F(ExtendedInfoChecksTest, badEncodingRemoteId4strict) { + string description = "remote-id with a junk value, strict"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"remote-id\":" + " \"foo\" } } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 192.168.1.1 failed checks" + " (in remote-id a problem was found:" + " attempt to decode a value not in base16 char set)" }); +} + +// Empty remote-id entry is right up to the fix sanity level. +TEST_F(ExtendedInfoChecksTest, emptyRemoteId4fix) { + string description = "empty remote-id, fix"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"remote-id\": \"\" } } }", + "{ \"ISC\": { \"relay-agent-info\": { \"remote-id\": \"\" } } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// Empty remote-id entry is dropped at strict or higher sanity levels. +TEST_F(ExtendedInfoChecksTest, emptyRemoteId4strict) { + string description = "empty remote-id, strict"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"remote-id\": \"\" } } }", + "", CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 192.168.1.1 failed checks" + " (in remote-id a problem was found:" + " remote-id is empty)" }); +} + +// Valid remote-id entry is right for all sanity levels. +TEST_F(ExtendedInfoChecksTest, validRemoteId4strict) { + string description = "valid remote-id, strict"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"remote-id\":" + " \"AABB\" } } }", + "{ \"ISC\": { \"relay-agent-info\": { \"remote-id\":" + " \"AABB\" } } }", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT); +} + +// relay-id entry with a bad type is right up to the fix sanity level. +TEST_F(ExtendedInfoChecksTest, badTypeRelayId4fix) { + string description = "relay-id not a string, fix"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"relay-id\": 1 } } }", + "{ \"ISC\": { \"relay-agent-info\": { \"relay-id\": 1 } } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// relay-id entry with a bad type is dropped at strict or higher +// sanity levels. +TEST_F(ExtendedInfoChecksTest, badTypeRelayId4strict) { + string description = "relay-id not a string, strict"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"relay-id\": 1 } } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 192.168.1.1 failed checks" + " (in relay-id a problem was found:" + " relay-id is not a string)" }); +} + +// relay-id entry which can't be decoded is right up to the fix sanity level. +TEST_F(ExtendedInfoChecksTest, badEncodingRelayId4fix) { + string description = "relay-id with a junk value, fix"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"relay-id\":" + " \"foo\" } } }", + "{ \"ISC\": { \"relay-agent-info\": { \"relay-id\":" + " \"foo\" } } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// relay-id entry which can't be decoded is dropped at strict or higher +// sanity levels. +TEST_F(ExtendedInfoChecksTest, badEncodingRelayId4strict) { + string description = "relay-id with a junk value, strict"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"relay-id\":" + " \"foo\" } } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 192.168.1.1 failed checks" + " (in relay-id a problem was found:" + " attempt to decode a value not in base16 char set)" }); +} + +// Empty relay-id entry is right up to the fix sanity level. +TEST_F(ExtendedInfoChecksTest, emptyRelayId4fix) { + string description = "empty relay-id, fix"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"relay-id\": \"\" } } }", + "{ \"ISC\": { \"relay-agent-info\": { \"relay-id\": \"\" } } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// Empty relay-id entry is dropped at strict or higher sanity levels. +TEST_F(ExtendedInfoChecksTest, emptyRelayId4strict) { + string description = "empty relay-id, strict"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"relay-id\": \"\" } } }", + "", CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 192.168.1.1 failed checks" + " (in relay-id a problem was found:" + " relay-id is empty)" }); +} + +// Valid relay-id entry is right for all sanity levels. +TEST_F(ExtendedInfoChecksTest, validRelayId4strict) { + string description = "valid relay-id, strict"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"relay-id\":" + " \"AABB\" } } }", + "{ \"ISC\": { \"relay-agent-info\": { \"relay-id\":" + " \"AABB\" } } }", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT); +} + +// Junk entries are right up to the strict sanity level. +TEST_F(ExtendedInfoChecksTest, junk4strict) { + string description = "junk entry, strict"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"foo\": 1 } } }", + "{ \"ISC\": { \"relay-agent-info\": { \"foo\": 1 } } }", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT); +} + +// Junk entries are dropped at the pedantic level. +TEST_F(ExtendedInfoChecksTest, junk4pedantic) { + string description = "junk entry, pedantic"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"foo\": 1 } } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC, + { "DHCPSRV_LEASE4_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 192.168.1.1 failed checks" + " (in relay-agent-info a problem was found:" + " spurious 'foo' entry in relay-agent-info)" }); +} + +// comment is not considered as a junk entry. +TEST_F(ExtendedInfoChecksTest, comment4) { + string description = "comment entry, pedantic"; + check4(description, + "{ \"ISC\": { \"relay-agent-info\": { \"comment\": \"good\" } } }", + "{ \"ISC\": { \"relay-agent-info\": { \"comment\": \"good\" } } }", + CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC); +} + +// No user context is right for any sanity check level including the highest. +TEST_F(ExtendedInfoChecksTest, noUserContext6) { + string description = "no user context, pedantic"; + check6(description, "", "", CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC); +} + +// User context with a bad type is right only when no check is done. +TEST_F(ExtendedInfoChecksTest, badTypeUserContext6none) { + string description = "user context not a map, none"; + check6(description, "1", "1", CfgConsistency::EXTENDED_INFO_CHECK_NONE); +} + +// User context with a bad type is refused by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, badTypeUserContext6) { + string description = "user context not a map, fix"; + check6(description, "1", "", CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in user context a problem was found:" + " user context is not a map)" }); +} + +// Empty user context is right only when no check is done. +TEST_F(ExtendedInfoChecksTest, emptyTypeUserContext6none) { + string description = "empty user context, none"; + check6(description, "{ }", "{ }", + CfgConsistency::EXTENDED_INFO_CHECK_NONE); +} + +// Empty user context is dropped by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, emptyTypeUserContext6) { + string description = "empty user context, fix"; + check6(description, "{ }", "", CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// No ISC entry is right in all cases. +TEST_F(ExtendedInfoChecksTest, noISC6) { + string description = "no ISC entry, pedantic"; + check6(description, "{ \"foo\": 1 }", "{ \"foo\": 1 }", + CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC); +} + +// ISC entry with a bad type is right only when no check is done. +TEST_F(ExtendedInfoChecksTest, badTypeISC6none) { + string description = "ISC entry no a map, none"; + check6(description, "{ \"ISC\": 1 }", "{ \"ISC\": 1 }", + CfgConsistency::EXTENDED_INFO_CHECK_NONE); +} + +// ISC entry with a bad type is dropped by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, badTypeISC6) { + string description = "ISC entry no a map, fix"; + check6(description, "{ \"ISC\": 1 }", "", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in isc a problem was found:" + " ISC entry is not a map)" }); +} + +// When the ISC entry is dropped other entries are kept. +TEST_F(ExtendedInfoChecksTest, badTypeISC6other) { + string description = "ISC entry no a map with others, fix"; + check6(description, "{ \"ISC\": 1, \"foo\": 2 }", "{ \"foo\": 2 }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in isc a problem was found:" + " ISC entry is not a map)" }); +} + +// Empty ISC entry is kept only when no check is done. +TEST_F(ExtendedInfoChecksTest, emptyISC6none) { + string description = "empty ISC entry, none"; + check6(description, "{ \"ISC\": { } }", "{ \"ISC\": { } }", + CfgConsistency::EXTENDED_INFO_CHECK_NONE); +} + +// Empty ISC entry is dropped by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, emptyISC6) { + string description = "empty ISC entry, fix"; + check6(description, "{ \"ISC\": { } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// relays is not upgraded when no check is done. +TEST_F(ExtendedInfoChecksTest, relaysnone) { + string description = "relays, none"; + check6(description, "{ \"ISC\": { \"relays\": true } }", + "{ \"ISC\": { \"relays\": true } }", + CfgConsistency::EXTENDED_INFO_CHECK_NONE); +} + +// relays is dropped when relay-info is present by all not none sanity +// check levels. +TEST_F(ExtendedInfoChecksTest, relaysAndRelayInfo) { + string description = "relays and relay-info, fix"; + check6(description, + "{ \"ISC\": { \"relays\": true, \"relay-info\":" + " [ { \"foo\": 1 } ] } }", + "{ \"ISC\": { \"relay-info\": [ { \"foo\": 1 } ] } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// relays with bad type is dropped by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, badTypeRelays) { + string description = "relays is not a list, fix"; + check6(description, "{ \"ISC\": { \"relays\": true } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in relays a problem was found:" + " relays is not a list)" }); +} + +// Empty relays is dropped by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, emptyRelays) { + string description = "empty relays, fix"; + check6(description, "{ \"ISC\": { \"relays\": [ ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in relays a problem was found:" + " relays is empty)" }); +} + +// Relay (element of relays) with bad type is dropped by all not none +// sanity check levels. +TEST_F(ExtendedInfoChecksTest, badTypeRelay) { + string description = "relay is not a map, fix"; + check6(description, "{ \"ISC\": { \"relays\": [ 1 ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in relay [relay#0] a problem was found:" + " relay#0 is not a map)" }); +} + +// options with bad type is dropped by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, badTypeOptions) { + string description = "options is not a string, fix"; + check6(description, "{ \"ISC\": { \"relays\": [ { \"options\": 1 } ] } }", + "", CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in options [relay#0] a problem was found:" + " options is not a string)" }); +} + +// options which can't be decoded is dropped by all not none sanity +// check levels. +TEST_F(ExtendedInfoChecksTest, badEncodingOptions) { + string description = "options with junk value, fix"; + check6(description, + "{ \"ISC\": { \"relays\": [ { \"options\": \"foo\" } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in options [relay#0] a problem was found:" + " 'foo' is not a valid string of hexadecimal digits)" }); +} + +// Valid relays is upgraded by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, upgradedRelays) { + string description = "upgraded relays, fix"; + check6(description, + "{ \"ISC\": { \"relays\": [ { \"hop\": 33," + " \"link\": \"2001:db8::1\", \"peer\": \"2001:db8::2\"," + " \"options\": \"0x00C800080102030405060708\" } ] } }", + "{ \"ISC\": { \"relay-info\": [ { \"hop\": 33," + " \"link\": \"2001:db8::1\", \"peer\": \"2001:db8::2\"," + " \"options\": \"0x00C800080102030405060708\" } ] } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED" + " extended info for lease 2001::1 was upgraded" }); +} + +// Valid relays with ids is upgraded by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, upgradedRelaysWithIds) { + string description = "upgraded relays with ids, fix"; + check6(description, + "{ \"ISC\": { \"relays\": [ { \"hop\": 100," + " \"options\": \"0x00250006010203040506003500086464646464646464\"," + " \"link\": \"2001:db8::5\", \"peer\": \"2001:db8::6\" } ] } }", + "{ \"ISC\": { \"relay-info\": [ { \"hop\": 100," + " \"options\": \"0x00250006010203040506003500086464646464646464\"," + " \"link\": \"2001:db8::5\", \"peer\": \"2001:db8::6\"," + " \"remote-id\": \"010203040506\"," + " \"relay-id\": \"6464646464646464\" } ] } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED" + " extended info for lease 2001::1 was upgraded" }); +} + +// Valid relays with 2 relays is upgraded by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, upgradedRelays2) { + string description = "upgraded relays with 2 relays, fix"; + check6(description, + "{ \"ISC\": { \"relays\": [ { \"hop\": 33," + " \"link\": \"2001:db8::1\", \"peer\": \"2001:db8::2\"," + " \"options\": \"0x00C800080102030405060708\" }, { \"hop\": 100," + " \"options\": \"0x00250006010203040506003500086464646464646464\"," + " \"link\": \"2001:db8::5\", \"peer\": \"2001:db8::6\" } ] } }", + "{ \"ISC\": { \"relay-info\": [ { \"hop\": 33," + " \"link\": \"2001:db8::1\", \"peer\": \"2001:db8::2\"," + " \"options\": \"0x00C800080102030405060708\" }, { \"hop\": 100," + " \"options\": \"0x00250006010203040506003500086464646464646464\"," + " \"link\": \"2001:db8::5\", \"peer\": \"2001:db8::6\"," + " \"remote-id\": \"010203040506\"," + " \"relay-id\": \"6464646464646464\" } ] } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED" + " extended info for lease 2001::1 was upgraded" }); +} + +// relayinfo with bad type is dropped by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, badTypeRelayInfo) { + string description = "relayinfo is not a list, fix"; + check6(description, "{ \"ISC\": { \"relay-info\": true } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in relay-info a problem was found:" + " relay-info is not a list)" }); +} + +// Empty relay-info is dropped by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, emptyRelayInfo) { + string description = "empty relay-info, fix"; + check6(description, "{ \"ISC\": { \"relay-info\": [ ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in relay-info a problem was found:" + " relay-info is empty)" }); +} + +// Relay (element of relay-info) with bad type is dropped by all not none +// sanity check levels. +TEST_F(ExtendedInfoChecksTest, badTypeRelay2) { + string description = "relay is not a map, fix"; + check6(description, "{ \"ISC\": { \"relay-info\": [ 1 ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in relay [relay#0] a problem was found:" + " relay#0 is not a map)" }); +} + +// options with bad type is dropped by all not none sanity check levels. +TEST_F(ExtendedInfoChecksTest, badTypeOptions2) { + string description = "options is not a string, fix"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"options\": 1 } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in options [relay#0] a problem was found:" + " options is not a string)" }); +} + +// options which can't be decoded is dropped by all not none sanity +// check levels. +TEST_F(ExtendedInfoChecksTest, badEncodingOptions2) { + string description = "options with junk value, fix"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"options\": \"foo\" } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_FIX, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in options [relay#0] a problem was found:" + " 'foo' is not a valid string of hexadecimal digits)" }); +} + +// Relay without a link entry is right up to fix sanity check level. +TEST_F(ExtendedInfoChecksTest, noLinkfix) { + string description = "no link, fix"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"foo\": 1 } ] } }", + "{ \"ISC\": { \"relay-info\": [ { \"foo\": 1 } ] } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// Relay without a link entry is dropped by strict sanity check level and +// higher. +TEST_F(ExtendedInfoChecksTest, noLinkstrict) { + string description = "no link, strict"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"foo\": 1 } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in link [relay#0] a problem was found:" + " no link)" }); +} + +// link entry with bad type is dropped by strict sanity check level and higher. +TEST_F(ExtendedInfoChecksTest, badTypeLink) { + string description = "link is not a string, strict"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"link\": 1 } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in link [relay#0] a problem was found:" + " link is not a string)" }); +} + +// link entry which is not an address is dropped by strict sanity check level +// and higher. +TEST_F(ExtendedInfoChecksTest, notAddressLink) { + string description = "link is not an address, strict"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"link\": \"foo\" } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in link [relay#0] a problem was found:" + " Failed to convert string to address 'foo':" + " Invalid argument)" }); +} + +// link entry which is an IPv4 (vs IPv6) address is dropped by strict sanity +// check level and higher. +TEST_F(ExtendedInfoChecksTest, notV6Link) { + string description = "link is v4, strict"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"link\":" + " \"192.128.1.1\" } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in link [relay#0] a problem was found:" + " link is not an IPv6 address)" }); +} + +// Valid link entry is right for all sanity levels. +TEST_F(ExtendedInfoChecksTest, validLink) { + string description = "valid link, strict"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"link\": \"2001::2\" } ] } }", + "{ \"ISC\": { \"relay-info\": [ { \"link\": \"2001::2\" } ] } }", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT); +} + +// remote-id entry with a bad type is right up to the fix sanity level. +TEST_F(ExtendedInfoChecksTest, badTypeRemoteId6fix) { + string description = "remote-id not a string, fix"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"remote-id\": 1 } ] } }", + "{ \"ISC\": { \"relay-info\": [ { \"remote-id\": 1 } ] } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// remote-id entry with a bad type is dropped at strict or higher +// sanity levels. +TEST_F(ExtendedInfoChecksTest, badTypeRemoteId6strict) { + string description = "remote-id not a string, strict"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"remote-id\": 1," + " \"link\": \"2001::2\" } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in remote-id [relay#0] a problem was found:" + " remote-id is not a string)" }); +} + +// remote-id entry which can't be decoded is dropped at strict or higher +// sanity levels. +TEST_F(ExtendedInfoChecksTest, badEncodingRemoteId6strict) { + string description = "remote-id with a junk value, strict"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"remote-id\": \"foo\"," + " \"link\": \"2001::2\" } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in remote-id [relay#0] a problem was found:" + " attempt to decode a value not in base16 char set)" }); +} + +// Empty remote-id entry is dropped at strict or higher sanity levels. +TEST_F(ExtendedInfoChecksTest, emptyRemoteId6strict) { + string description = "empty remote-id, strict"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"remote-id\": \"\"," + " \"link\": \"2001::2\" } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in remote-id [relay#0] a problem was found:" + " remote-id is empty)" }); +} + +// Valid remote-id entry is right at all sanity levels. +TEST_F(ExtendedInfoChecksTest, validRemoteId6strict) { + string description = "valid remote-id, strict"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"remote-id\": \"AABB\"," + " \"link\": \"2001::2\" } ] } }", + "{ \"ISC\": { \"relay-info\": [ { \"remote-id\": \"AABB\"," + " \"link\": \"2001::2\" } ] } }", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT); +} + +// relay-id entry with a bad type is right up to the fix sanity level. +TEST_F(ExtendedInfoChecksTest, badTypeRelayId6fix) { + string description = "relay-id not a string, fix"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"relay-id\": 1 } ] } }", + "{ \"ISC\": { \"relay-info\": [ { \"relay-id\": 1 } ] } }", + CfgConsistency::EXTENDED_INFO_CHECK_FIX); +} + +// relay-id entry with a bad type is dropped at strict or higher +// sanity levels. +TEST_F(ExtendedInfoChecksTest, badTypeRelayId6strict) { + string description = "relay-id not a string, strict"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"relay-id\": 1," + " \"link\": \"2001::2\" } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in relay-id [relay#0] a problem was found:" + " relay-id is not a string)" }); +} + +// relay-id entry which can't be decoded is dropped at strict or higher +// sanity levels. +TEST_F(ExtendedInfoChecksTest, badEncodingRelayId6strict) { + string description = "relay-id with a junk value, strict"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"relay-id\": \"foo\"," + " \"link\": \"2001::2\" } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in relay-id [relay#0] a problem was found:" + " attempt to decode a value not in base16 char set)" }); +} + +// Empty relay-id entry is dropped at strict or higher sanity levels. +TEST_F(ExtendedInfoChecksTest, emptyRelayId6strict) { + string description = "empty relay-id, strict"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"relay-id\": \"\"," + " \"link\": \"2001::2\" } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in relay-id [relay#0] a problem was found:" + " relay-id is empty)" }); +} + +// Valid relay-id entry is right at all sanity levels. +TEST_F(ExtendedInfoChecksTest, validRelayId6strict) { + string description = "valid relay-id, strict"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"relay-id\": \"AABB\"," + " \"link\": \"2001::2\" } ] } }", + "{ \"ISC\": { \"relay-info\": [ { \"relay-id\": \"AABB\"," + " \"link\": \"2001::2\" } ] } }", + CfgConsistency::EXTENDED_INFO_CHECK_STRICT); +} + +// Pedantic requires a peer entry. +TEST_F(ExtendedInfoChecksTest, noPeerpedantic) { + string description = "no peer, pedantic"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"link\": \"2001::2\" } ] } }", + "", CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in peer [relay#0] a problem was found:" + " no peer)" }); +} + +// peer entry with bad type is dropped by pedantic sanity check level. +TEST_F(ExtendedInfoChecksTest, badTypePeer) { + string description = "peer is not a string, pedantic"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"link\": \"2001::2\"," + " \"peer\": 1 } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in peer [relay#0] a problem was found:" + " peer is not a string)" }); +} + +// peer entry which is not an address is dropped by pedantic sanity check level. +TEST_F(ExtendedInfoChecksTest, notAddressPeer) { + string description = "peer is not an address, pedantic"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"link\": \"2001::2\"," + " \"peer\": \"foo\" } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in peer [relay#0] a problem was found:" + " Failed to convert string to address 'foo':" + " Invalid argument)" }); +} + +// peer entry which is an IPv4 (vs IPv6) address is dropped by pedantic sanity +// check level. +TEST_F(ExtendedInfoChecksTest, notV6Peer) { + string description = "peer is v4, pedantic"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"link\": \"2001::2\"," + " \"peer\": \"192.128.1.1\" } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in peer [relay#0] a problem was found:" + " peer is not an IPv6 address)" }); +} + +// Pedantic requires a hop entry. +TEST_F(ExtendedInfoChecksTest, noHop) { + string description = "no hop, pedantic"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"link\": \"2001::2\"," + " \"peer\": \"2001::3\" } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in hop [relay#0] a problem was found:" + " no hop)" }); +} + +// hop entry with bad type is dropped by pedantic sanity check level. +TEST_F(ExtendedInfoChecksTest, badTypeHop) { + string description = "hop is not an integer pedantic"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"link\": \"2001::2\"," + " \"peer\": \"2001::3\", \"hop\": false } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in hop [relay#0] a problem was found:" + " hop is not an integer)" }); +} + +// Valid relay. +TEST_F(ExtendedInfoChecksTest, valid6Pedantic) { + string description = "valid, pedantic"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"link\": \"2001::2\"," + " \"peer\": \"2001::3\", \"hop\": 10 } ] } }", + "{ \"ISC\": { \"relay-info\": [ { \"link\": \"2001::2\"," + " \"peer\": \"2001::3\", \"hop\": 10 } ] } }", + CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC); +} + +// Junk entries are dropped at the pedantic level. +TEST_F(ExtendedInfoChecksTest, junk6pedantic) { + string description = "junk entry, pedantic"; + check6(description, + "{ \"ISC\": { \"relay-info\": [ { \"link\": \"2001::2\"," + " \"peer\": \"2001::3\", \"hop\": 10, \"foo\": 1 } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in relay-info [relay#0] a problem was found:" + " spurious 'foo' entry)" }); +} + +// Same with relays post upgrade checks. +TEST_F(ExtendedInfoChecksTest, junkRelayspedantic) { + string description = "junk entry, pedantic"; + check6(description, + "{ \"ISC\": { \"relays\": [ { \"link\": \"2001::2\"," + " \"peer\": \"2001::3\", \"hop\": 10, \"foo\": 1 } ] } }", "", + CfgConsistency::EXTENDED_INFO_CHECK_PEDANTIC, + { "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL" + " extended info for lease 2001::1 failed checks" + " (in relays [relay#0] a problem was found:" + " spurious 'foo' entry)" }); +} |