mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 13:37:55 +00:00
[4300] Added "circuit-id" as supported identifier into Host class.
This commit is contained in:
parent
f1289b6cc0
commit
2b12535e20
@ -162,6 +162,9 @@ Host::getIdentifierAsText(const IdentifierType& type, const uint8_t* value,
|
|||||||
case IDENT_DUID:
|
case IDENT_DUID:
|
||||||
s << "duid";
|
s << "duid";
|
||||||
break;
|
break;
|
||||||
|
case IDENT_CIRCUIT_ID:
|
||||||
|
s << "circuit-id";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
isc_throw(BadValue, "requested conversion of the unsupported"
|
isc_throw(BadValue, "requested conversion of the unsupported"
|
||||||
" identifier into textual form");
|
" identifier into textual form");
|
||||||
@ -185,6 +188,10 @@ Host::setIdentifier(const uint8_t* identifier, const size_t len,
|
|||||||
|
|
||||||
void
|
void
|
||||||
Host::setIdentifier(const std::string& identifier, const std::string& name) {
|
Host::setIdentifier(const std::string& identifier, const std::string& name) {
|
||||||
|
// HW address and DUID are special cases because they are typically
|
||||||
|
// specified as values with colons between consecutive octets. Thus,
|
||||||
|
// we use the HWAddr and DUID classes to validate them and to
|
||||||
|
// convert them into binary format.
|
||||||
if (name == "hw-address") {
|
if (name == "hw-address") {
|
||||||
HWAddr hwaddr(HWAddr::fromText(identifier));
|
HWAddr hwaddr(HWAddr::fromText(identifier));
|
||||||
identifier_type_= IDENT_HWADDR;
|
identifier_type_= IDENT_HWADDR;
|
||||||
@ -196,8 +203,38 @@ Host::setIdentifier(const std::string& identifier, const std::string& name) {
|
|||||||
identifier_value_ = duid.getDuid();
|
identifier_value_ = duid.getDuid();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
isc_throw(isc::BadValue, "invalid client identifier type '"
|
if (name == "circuit-id") {
|
||||||
<< name << "' when creating host instance");
|
identifier_type_ = IDENT_CIRCUIT_ID;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
isc_throw(isc::BadValue, "invalid client identifier type '"
|
||||||
|
<< name << "' when creating host instance");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here we're converting values other than DUID and HW address. These
|
||||||
|
// values can either be specified as strings of hexadecimal digits or
|
||||||
|
// strings in quotes. The latter are copied to a vector excluding quote
|
||||||
|
// characters.
|
||||||
|
|
||||||
|
// Try to convert the values in quotes into a vector of ASCII codes.
|
||||||
|
// If the identifier lacks opening and closing quote, this will return
|
||||||
|
// an empty value, in which case we'll try to decode it as a string of
|
||||||
|
// hexadecimal digits.
|
||||||
|
std::vector<uint8_t> binary = util::str::quotedStringToBinary(identifier);
|
||||||
|
if (binary.empty()) {
|
||||||
|
try {
|
||||||
|
util::encode::decodeHex(identifier, binary);
|
||||||
|
|
||||||
|
} catch (...) {
|
||||||
|
// The string doesn't match any known pattern, so we have to
|
||||||
|
// report an error at this point.
|
||||||
|
isc_throw(isc::BadValue, "invalid host identifier value '"
|
||||||
|
<< identifier << "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Successfully decoded the identifier, so let's use it.
|
||||||
|
identifier_value_.swap(binary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +223,15 @@ public:
|
|||||||
/// is useful in cases when the reservation is specified in the server
|
/// is useful in cases when the reservation is specified in the server
|
||||||
/// configuration file, where:
|
/// configuration file, where:
|
||||||
/// - MAC address is specified as: "01:02:03:04:05:06"
|
/// - MAC address is specified as: "01:02:03:04:05:06"
|
||||||
/// - Other identifiers are specified as: "010203040506abcd"
|
/// - DUID can be specified as: "01:02:03:04:05:06:ab:cd" or "010203040506abcd".
|
||||||
|
/// - Other identifiers are specified as: "010203040506abcd" or as
|
||||||
|
/// "'some identfier'".
|
||||||
|
///
|
||||||
|
/// In case of identifiers other than HW address and DUID it is possible to use
|
||||||
|
/// textual representation, e.g. 'some identifier', which is converted to a
|
||||||
|
/// vector of ASCII codes represnting characters in a given string, excluding
|
||||||
|
/// quotes. This is useful in cases when specific identifiers, e.g. circuit-id
|
||||||
|
/// are manually assigned user friendly values.
|
||||||
///
|
///
|
||||||
/// @param identifier Identifier in the textual format. The expected formats
|
/// @param identifier Identifier in the textual format. The expected formats
|
||||||
/// for the hardware address and other identifiers are provided above.
|
/// for the hardware address and other identifiers are provided above.
|
||||||
|
@ -7,8 +7,12 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include <dhcpsrv/host.h>
|
#include <dhcpsrv/host.h>
|
||||||
|
#include <util/encode/hex.h>
|
||||||
|
#include <util/range_utilities.h>
|
||||||
#include <boost/scoped_ptr.hpp>
|
#include <boost/scoped_ptr.hpp>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
using namespace isc;
|
using namespace isc;
|
||||||
using namespace isc::dhcp;
|
using namespace isc::dhcp;
|
||||||
@ -16,6 +20,11 @@ using namespace isc::asiolink;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
/// @brief Holds a type of the last identifier in @c IdentifierType enum.
|
||||||
|
///
|
||||||
|
/// This value must be updated when new identifiers are added to the enum.
|
||||||
|
const Host::IdentifierType LAST_IDENTIFIER_TYPE = Host::IDENT_CIRCUIT_ID;
|
||||||
|
|
||||||
// This test verifies that it is possible to create IPv6 address
|
// This test verifies that it is possible to create IPv6 address
|
||||||
// reservation.
|
// reservation.
|
||||||
TEST(IPv6ResrvTest, constructorAddress) {
|
TEST(IPv6ResrvTest, constructorAddress) {
|
||||||
@ -121,9 +130,70 @@ TEST(IPv6ResrvTest, equal) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Test fixture class for @c Host.
|
||||||
|
class HostTest : public ::testing::Test {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// @brief Constructor.
|
||||||
|
///
|
||||||
|
/// Re-initializes random number generator.
|
||||||
|
HostTest() {
|
||||||
|
srand(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Checks if the reservation is in the range of reservations.
|
||||||
|
///
|
||||||
|
/// @param resrv Reservation to be searched for.
|
||||||
|
/// @param range Range of reservations returned by the @c Host object
|
||||||
|
/// in which the reservation will be searched.
|
||||||
|
///
|
||||||
|
/// @return true if reservation exists, false otherwise.
|
||||||
|
bool
|
||||||
|
reservationExists(const IPv6Resrv& resrv, const IPv6ResrvRange& range) {
|
||||||
|
for (IPv6ResrvIterator it = range.first; it != range.second;
|
||||||
|
++it) {
|
||||||
|
if (resrv == it->second) {
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Converts identifier type to its name.
|
||||||
|
///
|
||||||
|
/// @param type identifier type.
|
||||||
|
/// @return Identifier name as specified in a configuration file.
|
||||||
|
std::string identifierName(const Host::IdentifierType& type) const {
|
||||||
|
switch (type) {
|
||||||
|
case Host::IDENT_HWADDR:
|
||||||
|
return ("hw-address");
|
||||||
|
case Host::IDENT_DUID:
|
||||||
|
return ("duid");
|
||||||
|
case Host::IDENT_CIRCUIT_ID:
|
||||||
|
return ("circuit-id");
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
return ("unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Returns upper bound of the supported identifier types.
|
||||||
|
///
|
||||||
|
/// Some unit tests verify the @c Host class behavior for all
|
||||||
|
/// supported identifier types. The unit test needs to iterate
|
||||||
|
/// over all supported identifier types and thus it must be
|
||||||
|
/// aware of the upper bound of the @c Host::IdentifierType
|
||||||
|
/// enum. The upper bound is the numeric representation of the
|
||||||
|
/// last identifier type plus 1.
|
||||||
|
unsigned int
|
||||||
|
identifierTypeUpperBound() const {
|
||||||
|
return (static_cast<unsigned int>(LAST_IDENTIFIER_TYPE) + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// This test verfies that it is possible to create a Host object
|
// This test verfies that it is possible to create a Host object
|
||||||
// using hardware address in the textual format.
|
// using hardware address in the textual format.
|
||||||
TEST(HostTest, createFromHWAddrString) {
|
TEST_F(HostTest, createFromHWAddrString) {
|
||||||
boost::scoped_ptr<Host> host;
|
boost::scoped_ptr<Host> host;
|
||||||
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
|
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
|
||||||
SubnetID(1), SubnetID(2),
|
SubnetID(1), SubnetID(2),
|
||||||
@ -155,7 +225,7 @@ TEST(HostTest, createFromHWAddrString) {
|
|||||||
|
|
||||||
// This test verifies that it is possible to create Host object using
|
// This test verifies that it is possible to create Host object using
|
||||||
// a DUID in the textual format.
|
// a DUID in the textual format.
|
||||||
TEST(HostTest, createFromDUIDString) {
|
TEST_F(HostTest, createFromDUIDString) {
|
||||||
boost::scoped_ptr<Host> host;
|
boost::scoped_ptr<Host> host;
|
||||||
ASSERT_NO_THROW(host.reset(new Host("a1:b2:c3:d4:e5:06", "duid",
|
ASSERT_NO_THROW(host.reset(new Host("a1:b2:c3:d4:e5:06", "duid",
|
||||||
SubnetID(10), SubnetID(20),
|
SubnetID(10), SubnetID(20),
|
||||||
@ -189,7 +259,7 @@ TEST(HostTest, createFromDUIDString) {
|
|||||||
|
|
||||||
// This test verifies that it is possible to create Host object using
|
// This test verifies that it is possible to create Host object using
|
||||||
// hardware address in the binary format.
|
// hardware address in the binary format.
|
||||||
TEST(HostTest, createFromHWAddrBinary) {
|
TEST_F(HostTest, createFromHWAddrBinary) {
|
||||||
boost::scoped_ptr<Host> host;
|
boost::scoped_ptr<Host> host;
|
||||||
// Prepare the hardware address in binary format.
|
// Prepare the hardware address in binary format.
|
||||||
const uint8_t hwaddr_data[] = {
|
const uint8_t hwaddr_data[] = {
|
||||||
@ -217,7 +287,7 @@ TEST(HostTest, createFromHWAddrBinary) {
|
|||||||
|
|
||||||
// This test verifies that it is possible to create a Host object using
|
// This test verifies that it is possible to create a Host object using
|
||||||
// DUID in the binary format.
|
// DUID in the binary format.
|
||||||
TEST(HostTest, createFromDuidBinary) {
|
TEST_F(HostTest, createFromDuidBinary) {
|
||||||
boost::scoped_ptr<Host> host;
|
boost::scoped_ptr<Host> host;
|
||||||
// Prepare DUID binary.
|
// Prepare DUID binary.
|
||||||
const uint8_t duid_data[] = {
|
const uint8_t duid_data[] = {
|
||||||
@ -243,103 +313,270 @@ TEST(HostTest, createFromDuidBinary) {
|
|||||||
EXPECT_EQ("me.example.org", host->getHostname());
|
EXPECT_EQ("me.example.org", host->getHostname());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that it is possible to replace an identifier for a particular
|
// This test verifies that it is possible create Host instance using all
|
||||||
// Host instance (HW address -> DUID and vice versa) with a new
|
// supported identifiers in a binary format.
|
||||||
// indentifier in the textual format.
|
TEST_F(HostTest, createFromIdentifierBinary) {
|
||||||
TEST(HostTest, setIdentifierString) {
|
|
||||||
boost::scoped_ptr<Host> host;
|
boost::scoped_ptr<Host> host;
|
||||||
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
|
// Iterate over all supported identifier types.
|
||||||
SubnetID(1), SubnetID(2),
|
for (unsigned int i = 0; i < identifierTypeUpperBound(); ++i) {
|
||||||
IOAddress("192.0.2.3"),
|
const Host::IdentifierType type = static_cast<Host::IdentifierType>(i);
|
||||||
"me.example.com")));
|
// Create identifier of variable length and fill with random values.
|
||||||
// Initially, there should be a HW address, but not a DUID set.
|
std::vector<uint8_t> identifier(random() % 14 + 6);
|
||||||
ASSERT_TRUE(host->getHWAddress());
|
util::fillRandom(identifier.begin(), identifier.end());
|
||||||
ASSERT_FALSE(host->getDuid());
|
|
||||||
|
|
||||||
// Now, use a DUID as identifier.
|
// Try to create a Host instance using this identifier.
|
||||||
ASSERT_NO_THROW(host->setIdentifier("aabbccddee", "duid"));
|
ASSERT_NO_THROW(host.reset(new Host(&identifier[0], identifier.size(),
|
||||||
|
type, SubnetID(10), SubnetID(20),
|
||||||
|
IOAddress("192.0.2.5"),
|
||||||
|
"me.example.org")));
|
||||||
|
|
||||||
// Verify that the DUID is correct.
|
// Retrieve identifier from Host instance and check if it is correct.
|
||||||
DuidPtr duid = host->getDuid();
|
const std::vector<uint8_t>& identifier_returned = host->getIdentifier();
|
||||||
ASSERT_TRUE(duid);
|
EXPECT_TRUE(identifier_returned == identifier);
|
||||||
EXPECT_EQ("aa:bb:cc:dd:ee", duid->toText());
|
EXPECT_EQ(type, host->getIdentifierType());
|
||||||
// HW address should be not set.
|
|
||||||
EXPECT_FALSE(host->getHWAddress());
|
|
||||||
|
|
||||||
// Now, let's do another way around.
|
EXPECT_EQ(10, host->getIPv4SubnetID());
|
||||||
|
EXPECT_EQ(20, host->getIPv6SubnetID());
|
||||||
ASSERT_NO_THROW(host->setIdentifier("09:08:07:06:05:04", "hw-address"));
|
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
|
||||||
|
EXPECT_EQ("me.example.org", host->getHostname());
|
||||||
// Verify that HW address is correct.
|
}
|
||||||
HWAddrPtr hw_addr = host->getHWAddress();
|
}
|
||||||
ASSERT_TRUE(hw_addr);
|
|
||||||
EXPECT_EQ("hwtype=1 09:08:07:06:05:04", hw_addr->toText());
|
// This test verifies that it is possible to create Host instance using
|
||||||
// DUID should be not set.
|
// all supported identifiers in hexadecimal format.
|
||||||
EXPECT_FALSE(host->getDuid());
|
TEST_F(HostTest, createFromIdentifierHex) {
|
||||||
}
|
boost::scoped_ptr<Host> host;
|
||||||
|
// Iterate over all supported identifiers.
|
||||||
// Test that it is possible to replace an identifier for a particular
|
for (unsigned int i = 0; i < identifierTypeUpperBound(); ++i) {
|
||||||
// Host instance (HW address -> DUID and vice versa) with the new
|
const Host::IdentifierType type = static_cast<Host::IdentifierType>(i);
|
||||||
// identifier in the binary format.
|
// Create identifier of a variable length.
|
||||||
TEST(HostTest, setIdentifierBinary) {
|
std::vector<uint8_t> identifier(random() % 14 + 6);
|
||||||
boost::scoped_ptr<Host> host;
|
util::fillRandom(identifier.begin(), identifier.end());
|
||||||
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
|
|
||||||
SubnetID(1), SubnetID(2),
|
// HW address is a special case, because it must contain colons
|
||||||
IOAddress("192.0.2.3"),
|
// between consecutive octets.
|
||||||
"me.example.com")));
|
HWAddrPtr hwaddr;
|
||||||
// Initially, there should be a HW address, but not a DUID set.
|
if (type == Host::IDENT_HWADDR) {
|
||||||
ASSERT_TRUE(host->getHWAddress());
|
hwaddr.reset(new HWAddr(identifier, HTYPE_ETHER));
|
||||||
ASSERT_FALSE(host->getDuid());
|
}
|
||||||
|
|
||||||
// Now, use a DUID as identifier.
|
// Convert identifier to hexadecimal representation.
|
||||||
const uint8_t duid_data[] = {
|
const std::string identifier_hex = (hwaddr ?
|
||||||
0xaa, 0xbb, 0xcc, 0xdd, 0xee
|
hwaddr->toText(false) :
|
||||||
};
|
util::encode::encodeHex(identifier));
|
||||||
ASSERT_NO_THROW(host->setIdentifier(duid_data, sizeof(duid_data),
|
const std::string identifier_name = identifierName(type);
|
||||||
Host::IDENT_DUID));
|
|
||||||
|
// Try to create Host instance.
|
||||||
// Verify that the DUID is correct.
|
ASSERT_NO_THROW(host.reset(new Host(identifier_hex, identifier_name,
|
||||||
DuidPtr duid = host->getDuid();
|
SubnetID(10), SubnetID(20),
|
||||||
ASSERT_TRUE(duid);
|
IOAddress("192.0.2.5"),
|
||||||
EXPECT_EQ("aa:bb:cc:dd:ee", duid->toText());
|
"me.example.org")))
|
||||||
// HW address should be not set.
|
<< "test failed for " << identifier_name << "="
|
||||||
EXPECT_FALSE(host->getHWAddress());
|
<< identifier_hex;
|
||||||
|
|
||||||
// Now, let's do another way around.
|
// Retrieve the identifier from the Host instance and verify if it
|
||||||
|
// is correct.
|
||||||
const uint8_t hwaddr_data[] = {
|
const std::vector<uint8_t>& identifier_returned = host->getIdentifier();
|
||||||
9, 8, 7, 6, 5, 4
|
EXPECT_TRUE(identifier_returned == identifier);
|
||||||
};
|
EXPECT_EQ(type, host->getIdentifierType());
|
||||||
ASSERT_NO_THROW(host->setIdentifier(hwaddr_data, sizeof(hwaddr_data),
|
|
||||||
Host::IDENT_HWADDR));
|
EXPECT_EQ(10, host->getIPv4SubnetID());
|
||||||
|
EXPECT_EQ(20, host->getIPv6SubnetID());
|
||||||
// Verify that HW address is correct.
|
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
|
||||||
HWAddrPtr hw_addr = host->getHWAddress();
|
EXPECT_EQ("me.example.org", host->getHostname());
|
||||||
ASSERT_TRUE(hw_addr);
|
}
|
||||||
EXPECT_EQ("hwtype=1 09:08:07:06:05:04", hw_addr->toText());
|
}
|
||||||
// DUID should be not set.
|
|
||||||
EXPECT_FALSE(host->getDuid());
|
// This test verifies that it is possible to create Host instance using
|
||||||
}
|
// identifiers specified as text in quotes.
|
||||||
|
TEST_F(HostTest, createFromIdentifierString) {
|
||||||
/// @brief Checks if the reservation is in the range of reservations.
|
boost::scoped_ptr<Host> host;
|
||||||
///
|
// It is not allowed to specify HW address or DUID as a string in quotes.
|
||||||
/// @param resrv Reservation to be searched for.
|
for (unsigned int i = 2; i < identifierTypeUpperBound(); ++i) {
|
||||||
/// @param range Range of reservations returned by the @c Host object
|
const Host::IdentifierType type = static_cast<Host::IdentifierType>(i);
|
||||||
/// in which the reservation will be searched.
|
const std::string identifier_name = identifierName(type);
|
||||||
bool
|
|
||||||
reservationExists(const IPv6Resrv& resrv, const IPv6ResrvRange& range) {
|
// Construct unique identifier for a host. This is a string
|
||||||
for (IPv6ResrvIterator it = range.first; it != range.second;
|
// consisting of a word "idenetifier", hyphen and the name of
|
||||||
++it) {
|
// the identifier, e.g. "identifier-hw-address".
|
||||||
if (resrv == it->second) {
|
std::ostringstream identifier_without_quotes;
|
||||||
return (true);
|
identifier_without_quotes << "identifier-" << identifier_name;
|
||||||
}
|
|
||||||
|
// Insert quotes to the identifier to indicate to the Host
|
||||||
|
// constructor that it is encoded as a text.
|
||||||
|
std::ostringstream identifier;
|
||||||
|
identifier << "'" << identifier_without_quotes.str() << "'";
|
||||||
|
|
||||||
|
ASSERT_NO_THROW(host.reset(new Host(identifier.str(), identifier_name,
|
||||||
|
SubnetID(10), SubnetID(20),
|
||||||
|
IOAddress("192.0.2.5"),
|
||||||
|
"me.example.org")))
|
||||||
|
<< "test failed for " << identifier_name << "="
|
||||||
|
<< identifier.str();
|
||||||
|
|
||||||
|
// Get the identifier from the Host and convert it back to the string
|
||||||
|
// format, so as it can be compared with the identifier used during
|
||||||
|
// Host object construction.
|
||||||
|
const std::vector<uint8_t>& identifier_returned = host->getIdentifier();
|
||||||
|
const std::string identifier_returned_str(identifier_returned.begin(),
|
||||||
|
identifier_returned.end());
|
||||||
|
// Exclude quotes in comparison. Quotes should have been removed.
|
||||||
|
EXPECT_EQ(identifier_without_quotes.str(), identifier_returned_str);
|
||||||
|
EXPECT_EQ(type, host->getIdentifierType());
|
||||||
|
|
||||||
|
EXPECT_EQ(10, host->getIPv4SubnetID());
|
||||||
|
EXPECT_EQ(20, host->getIPv6SubnetID());
|
||||||
|
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
|
||||||
|
EXPECT_EQ("me.example.org", host->getHostname());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test verifies that it is possible to override a host identifier
|
||||||
|
// using setIdentifier method with an identifier specified in
|
||||||
|
// hexadecimal format.
|
||||||
|
TEST_F(HostTest, setIdentifierHex) {
|
||||||
|
boost::scoped_ptr<Host> host;
|
||||||
|
// Iterate over all supported identifiers.
|
||||||
|
for (unsigned int i = 0; i < identifierTypeUpperBound(); ++i) {
|
||||||
|
|
||||||
|
// In order to test that setIdentifier replaces an existing
|
||||||
|
// identifier we have to initialize Host with a different
|
||||||
|
// identifier first. We pick the next identifier after the
|
||||||
|
// one we want to set. If 'i' points to the last one, we
|
||||||
|
// use the first one.
|
||||||
|
unsigned int j = (i + 1) % identifierTypeUpperBound();
|
||||||
|
|
||||||
|
Host::IdentifierType type = static_cast<Host::IdentifierType>(j);
|
||||||
|
// Create identifier of a variable length.
|
||||||
|
std::vector<uint8_t> identifier(random() % 14 + 6);
|
||||||
|
util::fillRandom(identifier.begin(), identifier.end());
|
||||||
|
|
||||||
|
// HW address is a special case, because it must contain colons
|
||||||
|
// between consecutive octets.
|
||||||
|
HWAddrPtr hwaddr;
|
||||||
|
if (type == Host::IDENT_HWADDR) {
|
||||||
|
hwaddr.reset(new HWAddr(identifier, HTYPE_ETHER));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert identifier to hexadecimal representation.
|
||||||
|
std::string identifier_hex = (hwaddr ?
|
||||||
|
hwaddr->toText(false) :
|
||||||
|
util::encode::encodeHex(identifier));
|
||||||
|
std::string identifier_name = identifierName(type);
|
||||||
|
|
||||||
|
// Try to create Host instance.
|
||||||
|
ASSERT_NO_THROW(host.reset(new Host(identifier_hex, identifier_name,
|
||||||
|
SubnetID(10), SubnetID(20),
|
||||||
|
IOAddress("192.0.2.5"),
|
||||||
|
"me.example.org")))
|
||||||
|
<< "test failed for " << identifier_name << "="
|
||||||
|
<< identifier_hex;
|
||||||
|
|
||||||
|
// Retrieve the identifier from the Host instance and verify if it
|
||||||
|
// is correct.
|
||||||
|
std::vector<uint8_t> identifier_returned = host->getIdentifier();
|
||||||
|
EXPECT_TRUE(identifier_returned == identifier);
|
||||||
|
EXPECT_EQ(type, host->getIdentifierType());
|
||||||
|
|
||||||
|
EXPECT_EQ(10, host->getIPv4SubnetID());
|
||||||
|
EXPECT_EQ(20, host->getIPv6SubnetID());
|
||||||
|
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
|
||||||
|
EXPECT_EQ("me.example.org", host->getHostname());
|
||||||
|
|
||||||
|
// Now use another identifier.
|
||||||
|
type = static_cast<Host::IdentifierType>(i);
|
||||||
|
// Create identifier of a variable length.
|
||||||
|
identifier.resize(random() % 14 + 6);
|
||||||
|
util::fillRandom(identifier.begin(), identifier.end());
|
||||||
|
|
||||||
|
hwaddr.reset();
|
||||||
|
if (type == Host::IDENT_HWADDR) {
|
||||||
|
hwaddr.reset(new HWAddr(identifier, HTYPE_ETHER));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert identifier to hexadecimal representation.
|
||||||
|
identifier_hex = (hwaddr ? hwaddr->toText(false) :
|
||||||
|
util::encode::encodeHex(identifier));
|
||||||
|
identifier_name = identifierName(type);
|
||||||
|
|
||||||
|
// Try to replace identifier for a host.
|
||||||
|
ASSERT_NO_THROW(host->setIdentifier(identifier_hex, identifier_name))
|
||||||
|
<< "test failed for " << identifier_name << "="
|
||||||
|
<< identifier_hex;
|
||||||
|
|
||||||
|
// Retrieve the identifier from the Host instance and verify if it
|
||||||
|
// is correct.
|
||||||
|
identifier_returned = host->getIdentifier();
|
||||||
|
EXPECT_TRUE(identifier_returned == identifier);
|
||||||
|
EXPECT_EQ(type, host->getIdentifierType());
|
||||||
|
|
||||||
|
EXPECT_EQ(10, host->getIPv4SubnetID());
|
||||||
|
EXPECT_EQ(20, host->getIPv6SubnetID());
|
||||||
|
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
|
||||||
|
EXPECT_EQ("me.example.org", host->getHostname());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test verifies that it is possible to override a host identifier
|
||||||
|
// using setIdentifier method with an identifier specified in binary
|
||||||
|
// format.
|
||||||
|
TEST_F(HostTest, setIdentifierBinary) {
|
||||||
|
boost::scoped_ptr<Host> host;
|
||||||
|
// Iterate over all supported identifier types.
|
||||||
|
for (unsigned int i = 0; i < identifierTypeUpperBound(); ++i) {
|
||||||
|
|
||||||
|
// In order to test that setIdentifier replaces an existing
|
||||||
|
// identifier we have to initialize Host with a different
|
||||||
|
// identifier first. We pick the next identifier after the
|
||||||
|
// one we want to set. If 'i' points to the last one, we
|
||||||
|
// use the first one.
|
||||||
|
unsigned int j = (i + 1) % identifierTypeUpperBound();
|
||||||
|
|
||||||
|
Host::IdentifierType type = static_cast<Host::IdentifierType>(j);
|
||||||
|
// Create identifier of variable length and fill with random values.
|
||||||
|
std::vector<uint8_t> identifier(random() % 14 + 6);
|
||||||
|
util::fillRandom(identifier.begin(), identifier.end());
|
||||||
|
|
||||||
|
// Try to create a Host instance using this identifier.
|
||||||
|
ASSERT_NO_THROW(host.reset(new Host(&identifier[0], identifier.size(),
|
||||||
|
type, SubnetID(10), SubnetID(20),
|
||||||
|
IOAddress("192.0.2.5"),
|
||||||
|
"me.example.org")));
|
||||||
|
|
||||||
|
// Retrieve identifier from Host instance and check if it is correct.
|
||||||
|
std::vector<uint8_t> identifier_returned = host->getIdentifier();
|
||||||
|
EXPECT_TRUE(identifier_returned == identifier);
|
||||||
|
EXPECT_EQ(type, host->getIdentifierType());
|
||||||
|
|
||||||
|
EXPECT_EQ(10, host->getIPv4SubnetID());
|
||||||
|
EXPECT_EQ(20, host->getIPv6SubnetID());
|
||||||
|
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
|
||||||
|
EXPECT_EQ("me.example.org", host->getHostname());
|
||||||
|
|
||||||
|
type = static_cast<Host::IdentifierType>(i);
|
||||||
|
// Create identifier of variable length and fill with random values.
|
||||||
|
identifier.resize(random() % 14 + 6);
|
||||||
|
util::fillRandom(identifier.begin(), identifier.end());
|
||||||
|
|
||||||
|
// Try to set new identifier.
|
||||||
|
ASSERT_NO_THROW(host->setIdentifier(&identifier[0], identifier.size(),
|
||||||
|
type));
|
||||||
|
|
||||||
|
// Retrieve identifier from Host instance and check if it is correct.
|
||||||
|
identifier_returned = host->getIdentifier();
|
||||||
|
EXPECT_TRUE(identifier_returned == identifier);
|
||||||
|
EXPECT_EQ(type, host->getIdentifierType());
|
||||||
|
|
||||||
|
EXPECT_EQ(10, host->getIPv4SubnetID());
|
||||||
|
EXPECT_EQ(20, host->getIPv6SubnetID());
|
||||||
|
EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
|
||||||
|
EXPECT_EQ("me.example.org", host->getHostname());
|
||||||
}
|
}
|
||||||
return (false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test verifies that the IPv6 reservations of a different type can
|
// This test verifies that the IPv6 reservations of a different type can
|
||||||
// be added for the host.
|
// be added for the host.
|
||||||
TEST(HostTest, addReservations) {
|
TEST_F(HostTest, addReservations) {
|
||||||
boost::scoped_ptr<Host> host;
|
boost::scoped_ptr<Host> host;
|
||||||
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
|
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
|
||||||
SubnetID(1), SubnetID(2),
|
SubnetID(1), SubnetID(2),
|
||||||
@ -397,7 +634,7 @@ TEST(HostTest, addReservations) {
|
|||||||
|
|
||||||
// This test checks that various modifiers may be used to replace the current
|
// This test checks that various modifiers may be used to replace the current
|
||||||
// values of the Host class.
|
// values of the Host class.
|
||||||
TEST(HostTest, setValues) {
|
TEST_F(HostTest, setValues) {
|
||||||
boost::scoped_ptr<Host> host;
|
boost::scoped_ptr<Host> host;
|
||||||
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
|
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
|
||||||
SubnetID(1), SubnetID(2),
|
SubnetID(1), SubnetID(2),
|
||||||
@ -436,7 +673,7 @@ TEST(HostTest, setValues) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test that Host constructors initialize client classes from string.
|
// Test that Host constructors initialize client classes from string.
|
||||||
TEST(HostTest, clientClassesFromConstructor) {
|
TEST_F(HostTest, clientClassesFromConstructor) {
|
||||||
boost::scoped_ptr<Host> host;
|
boost::scoped_ptr<Host> host;
|
||||||
// Prepare the hardware address in binary format.
|
// Prepare the hardware address in binary format.
|
||||||
const uint8_t hwaddr_data[] = {
|
const uint8_t hwaddr_data[] = {
|
||||||
@ -477,7 +714,7 @@ TEST(HostTest, clientClassesFromConstructor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test that new client classes can be added for the Host.
|
// Test that new client classes can be added for the Host.
|
||||||
TEST(HostTest, addClientClasses) {
|
TEST_F(HostTest, addClientClasses) {
|
||||||
boost::scoped_ptr<Host> host;
|
boost::scoped_ptr<Host> host;
|
||||||
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
|
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
|
||||||
SubnetID(1), SubnetID(2),
|
SubnetID(1), SubnetID(2),
|
||||||
@ -504,7 +741,7 @@ TEST(HostTest, addClientClasses) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This test checks that it is possible to add DHCPv4 options for a host.
|
// This test checks that it is possible to add DHCPv4 options for a host.
|
||||||
TEST(HostTest, addOptions4) {
|
TEST_F(HostTest, addOptions4) {
|
||||||
Host host("01:02:03:04:05:06", "hw-address", SubnetID(1), SubnetID(2),
|
Host host("01:02:03:04:05:06", "hw-address", SubnetID(1), SubnetID(2),
|
||||||
IOAddress("192.0.2.3"));
|
IOAddress("192.0.2.3"));
|
||||||
|
|
||||||
@ -568,7 +805,7 @@ TEST(HostTest, addOptions4) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This test checks that it is possible to add DHCPv6 options for a host.
|
// This test checks that it is possible to add DHCPv6 options for a host.
|
||||||
TEST(HostTest, addOptions6) {
|
TEST_F(HostTest, addOptions6) {
|
||||||
Host host("01:02:03:04:05:06", "hw-address", SubnetID(1), SubnetID(2),
|
Host host("01:02:03:04:05:06", "hw-address", SubnetID(1), SubnetID(2),
|
||||||
IOAddress("192.0.2.3"));
|
IOAddress("192.0.2.3"));
|
||||||
|
|
||||||
@ -633,22 +870,31 @@ TEST(HostTest, addOptions6) {
|
|||||||
|
|
||||||
// This test verifies that it is possible to retrieve a textual
|
// This test verifies that it is possible to retrieve a textual
|
||||||
// representation of the host identifier.
|
// representation of the host identifier.
|
||||||
TEST(HostTest, getIdentifierAsText) {
|
TEST_F(HostTest, getIdentifierAsText) {
|
||||||
|
// HW address
|
||||||
Host host1("01:02:03:04:05:06", "hw-address",
|
Host host1("01:02:03:04:05:06", "hw-address",
|
||||||
SubnetID(1), SubnetID(2),
|
SubnetID(1), SubnetID(2),
|
||||||
IOAddress("192.0.2.3"));
|
IOAddress("192.0.2.3"));
|
||||||
EXPECT_EQ("hwaddr=010203040506", host1.getIdentifierAsText());
|
EXPECT_EQ("hwaddr=010203040506", host1.getIdentifierAsText());
|
||||||
|
|
||||||
|
// DUID
|
||||||
Host host2("0a:0b:0c:0d:0e:0f:ab:cd:ef", "duid",
|
Host host2("0a:0b:0c:0d:0e:0f:ab:cd:ef", "duid",
|
||||||
SubnetID(1), SubnetID(2),
|
SubnetID(1), SubnetID(2),
|
||||||
IOAddress("192.0.2.3"));
|
IOAddress("192.0.2.3"));
|
||||||
EXPECT_EQ("duid=0A0B0C0D0E0FABCDEF",
|
EXPECT_EQ("duid=0A0B0C0D0E0FABCDEF",
|
||||||
host2.getIdentifierAsText());
|
host2.getIdentifierAsText());
|
||||||
|
|
||||||
|
// Circuit id.
|
||||||
|
Host host3("'marcin's-home'", "circuit-id",
|
||||||
|
SubnetID(1), SubnetID(2),
|
||||||
|
IOAddress("192.0.2.3"));
|
||||||
|
EXPECT_EQ("circuit-id=6D617263696E27732D686F6D65",
|
||||||
|
host3.getIdentifierAsText());
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test checks that Host object is correctly described in the
|
// This test checks that Host object is correctly described in the
|
||||||
// textual format using the toText method.
|
// textual format using the toText method.
|
||||||
TEST(HostTest, toText) {
|
TEST_F(HostTest, toText) {
|
||||||
boost::scoped_ptr<Host> host;
|
boost::scoped_ptr<Host> host;
|
||||||
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
|
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
|
||||||
SubnetID(1), SubnetID(2),
|
SubnetID(1), SubnetID(2),
|
||||||
@ -720,7 +966,7 @@ TEST(HostTest, toText) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test verifies if the host can store HostId properly.
|
// Test verifies if the host can store HostId properly.
|
||||||
TEST(HostTest, hostId) {
|
TEST_F(HostTest, hostId) {
|
||||||
boost::scoped_ptr<Host> host;
|
boost::scoped_ptr<Host> host;
|
||||||
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
|
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
|
||||||
SubnetID(1), SubnetID(2),
|
SubnetID(1), SubnetID(2),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user