123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- // Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- #include <config.h>
- #include <asiolink/io_address.h>
- #include <dhcp/duid.h>
- #include <exceptions/exceptions.h>
- #include <boost/scoped_ptr.hpp>
- #include <gtest/gtest.h>
- #include <iostream>
- #include <sstream>
- #include <arpa/inet.h>
- using namespace std;
- using namespace isc;
- using namespace isc::dhcp;
- using namespace isc::asiolink;
- // don't import the entire boost namespace. It will unexpectedly hide uint8_t
- // for some systems.
- using boost::scoped_ptr;
- namespace {
- // This is a workaround for strange linking problems with gtest:
- // libdhcp___unittests-duid_unittest.o: In function `Compare<long unsigned int, long unsigned int>':
- // ~/gtest-1.6.0/include/gtest/gtest.h:1353: undefined reference to `isc::dhcp::ClientId::MAX_CLIENT_ID_LE'N
- // collect2: ld returned 1 exit status
- const size_t MAX_DUID_LEN = DUID::MAX_DUID_LEN;
- const size_t MAX_CLIENT_ID_LEN = DUID::MAX_DUID_LEN;
- // This test verifies if the constructors are working as expected
- // and process passed parameters.
- TEST(DuidTest, constructor) {
- uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
- vector<uint8_t> data2(data1, data1 + sizeof(data1));
- scoped_ptr<DUID> duid1(new DUID(data1, sizeof(data1)));
- scoped_ptr<DUID> duid2(new DUID(data2));
- vector<uint8_t> vecdata = duid1->getDuid();
- EXPECT_TRUE(data2 == vecdata);
- EXPECT_EQ(DUID::DUID_LLT, duid1->getType());
- vecdata = duid2->getDuid();
- EXPECT_TRUE(data2 == vecdata);
- EXPECT_EQ(DUID::DUID_LLT, duid2->getType());
- }
- // This test verifies if DUID size restrictions are implemented
- // properly.
- TEST(DuidTest, size) {
- uint8_t data[MAX_DUID_LEN + 1];
- vector<uint8_t> data2;
- for (uint8_t i = 0; i < MAX_DUID_LEN + 1; ++i) {
- data[i] = i;
- if (i < MAX_DUID_LEN)
- data2.push_back(i);
- }
- ASSERT_EQ(data2.size(), MAX_DUID_LEN);
- scoped_ptr<DUID> duidmaxsize1(new DUID(data, MAX_DUID_LEN));
- scoped_ptr<DUID> duidmaxsize2(new DUID(data2));
- EXPECT_THROW(
- scoped_ptr<DUID> toolarge1(new DUID(data, MAX_DUID_LEN + 1)),
- OutOfRange);
- // that's one too much
- data2.push_back(128);
- EXPECT_THROW(
- scoped_ptr<DUID> toolarge2(new DUID(data2)),
- OutOfRange);
- // empty duids are not allowed
- vector<uint8_t> empty;
- EXPECT_THROW(
- scoped_ptr<DUID> emptyDuid(new DUID(empty)),
- OutOfRange);
- EXPECT_THROW(
- scoped_ptr<DUID> emptyDuid2(new DUID(data, 0)),
- OutOfRange);
- }
- // This test verifies if the implementation supports all defined
- // DUID types.
- TEST(DuidTest, getType) {
- uint8_t llt[] = {0, 1, 2, 3, 4, 5, 6};
- uint8_t en[] = {0, 2, 2, 3, 4, 5, 6};
- uint8_t ll[] = {0, 3, 2, 3, 4, 5, 6};
- uint8_t uuid[] = {0, 4, 2, 3, 4, 5, 6};
- uint8_t invalid[] = {0,55, 2, 3, 4, 5, 6};
- scoped_ptr<DUID> duid_llt(new DUID(llt, sizeof(llt)));
- scoped_ptr<DUID> duid_en(new DUID(en, sizeof(en)));
- scoped_ptr<DUID> duid_ll(new DUID(ll, sizeof(ll)));
- scoped_ptr<DUID> duid_uuid(new DUID(uuid, sizeof(uuid)));
- scoped_ptr<DUID> duid_invalid(new DUID(invalid, sizeof(invalid)));
- EXPECT_EQ(DUID::DUID_LLT, duid_llt->getType());
- EXPECT_EQ(DUID::DUID_EN, duid_en->getType());
- EXPECT_EQ(DUID::DUID_LL, duid_ll->getType());
- EXPECT_EQ(DUID::DUID_UUID, duid_uuid->getType());
- EXPECT_EQ(DUID::DUID_UNKNOWN, duid_invalid->getType());
- }
- // This test checks that the DUID instance can be created from the textual
- // format and that error is reported if the textual format is invalid.
- TEST(DuidTest, fromText) {
- scoped_ptr<DUID> duid;
- // DUID with only decimal digits.
- ASSERT_NO_THROW(
- duid.reset(new DUID(DUID::fromText("00:01:02:03:04:05:06")))
- );
- EXPECT_EQ("00:01:02:03:04:05:06", duid->toText());
- // DUID with some hexadecimal digits (upper case and lower case).
- ASSERT_NO_THROW(
- duid.reset(new DUID(DUID::fromText("00:aa:bb:CD:ee:EF:ab")))
- );
- EXPECT_EQ("00:aa:bb:cd:ee:ef:ab", duid->toText());
- // DUID with one digit for a particular byte.
- ASSERT_NO_THROW(
- duid.reset(new DUID(DUID::fromText("00:a:bb:D:ee:EF:ab")))
- );
- EXPECT_EQ("00:0a:bb:0d:ee:ef:ab", duid->toText());
- // Repeated colon sign is not allowed.
- EXPECT_THROW(
- duid.reset(new DUID(DUID::fromText("00::bb:D:ee:EF:ab"))),
- isc::BadValue
- );
- // DUID with excessive number of digits for one of the bytes.
- EXPECT_THROW(
- duid.reset(new DUID(DUID::fromText("00:01:021:03:04:05:06"))),
- isc::BadValue
- );
- }
- // Test checks if the toText() returns valid texual representation
- TEST(DuidTest, toText) {
- uint8_t data1[] = {0, 1, 2, 3, 4, 0xff, 0xfe};
- DUID duid(data1, sizeof(data1));
- EXPECT_EQ("00:01:02:03:04:ff:fe", duid.toText());
- }
- // This test checks if the comparison operators are sane.
- TEST(DuidTest, operators) {
- uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
- uint8_t data2[] = {0, 1, 2, 3, 4};
- uint8_t data3[] = {0, 1, 2, 3, 4, 5, 7}; // last digit different
- uint8_t data4[] = {0, 1, 2, 3, 4, 5, 6}; // the same as 1
- scoped_ptr<DUID> duid1(new DUID(data1, sizeof(data1)));
- scoped_ptr<DUID> duid2(new DUID(data2, sizeof(data2)));
- scoped_ptr<DUID> duid3(new DUID(data3, sizeof(data3)));
- scoped_ptr<DUID> duid4(new DUID(data4, sizeof(data4)));
- EXPECT_TRUE(*duid1 == *duid4);
- EXPECT_FALSE(*duid1 == *duid2);
- EXPECT_FALSE(*duid1 == *duid3);
- EXPECT_FALSE(*duid1 != *duid4);
- EXPECT_TRUE(*duid1 != *duid2);
- EXPECT_TRUE(*duid1 != *duid3);
- }
- // This test verifies if the ClientId constructors are working properly
- // and passed parameters are used
- TEST(ClientIdTest, constructor) {
- IOAddress addr2("192.0.2.1");
- IOAddress addr3("2001:db8:1::1");
- uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
- vector<uint8_t> data2(data1, data1 + sizeof(data1));
- // checks for C-style constructor (uint8_t * + len)
- scoped_ptr<ClientId> id1(new ClientId(data1, sizeof(data1)));
- vector<uint8_t> vecdata = id1->getClientId();
- EXPECT_TRUE(data2 == vecdata);
- // checks for vector-based constructor
- scoped_ptr<ClientId> id2(new ClientId(data2));
- vecdata = id2->getClientId();
- EXPECT_TRUE(data2 == vecdata);
- }
- // Check that client-id sizes are reasonable
- TEST(ClientIdTest, size) {
- uint8_t data[MAX_CLIENT_ID_LEN + 1];
- vector<uint8_t> data2;
- for (uint8_t i = 0; i < MAX_CLIENT_ID_LEN + 1; ++i) {
- data[i] = i;
- if (i < MAX_CLIENT_ID_LEN)
- data2.push_back(i);
- }
- ASSERT_EQ(data2.size(), MAX_CLIENT_ID_LEN);
- scoped_ptr<ClientId> duidmaxsize1(new ClientId(data, MAX_CLIENT_ID_LEN));
- scoped_ptr<ClientId> duidmaxsize2(new ClientId(data2));
- EXPECT_THROW(
- scoped_ptr<ClientId> toolarge1(new ClientId(data, MAX_CLIENT_ID_LEN + 1)),
- OutOfRange);
- // that's one too much
- data2.push_back(128);
- EXPECT_THROW(
- scoped_ptr<ClientId> toolarge2(new ClientId(data2)),
- OutOfRange);
- // empty client-ids are not allowed
- vector<uint8_t> empty;
- EXPECT_THROW(
- scoped_ptr<ClientId> empty_client_id1(new ClientId(empty)),
- OutOfRange);
- EXPECT_THROW(
- scoped_ptr<ClientId> empty_client_id2(new ClientId(data, 0)),
- OutOfRange);
- // client-id must be at least 2 bytes long
- vector<uint8_t> shorty(1,17); // just a single byte with value 17
- EXPECT_THROW(
- scoped_ptr<ClientId> too_short_client_id1(new ClientId(shorty)),
- OutOfRange);
- EXPECT_THROW(
- scoped_ptr<ClientId> too_short_client_id1(new ClientId(data, 1)),
- OutOfRange);
- }
- // This test checks if the comparison operators are sane.
- TEST(ClientIdTest, operators) {
- uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
- uint8_t data2[] = {0, 1, 2, 3, 4};
- uint8_t data3[] = {0, 1, 2, 3, 4, 5, 7}; // last digit different
- uint8_t data4[] = {0, 1, 2, 3, 4, 5, 6}; // the same as 1
- scoped_ptr<ClientId> id1(new ClientId(data1, sizeof(data1)));
- scoped_ptr<ClientId> id2(new ClientId(data2, sizeof(data2)));
- scoped_ptr<ClientId> id3(new ClientId(data3, sizeof(data3)));
- scoped_ptr<ClientId> id4(new ClientId(data4, sizeof(data4)));
- EXPECT_TRUE(*id1 == *id4);
- EXPECT_FALSE(*id1 == *id2);
- EXPECT_FALSE(*id1 == *id3);
- EXPECT_FALSE(*id1 != *id4);
- EXPECT_TRUE(*id1 != *id2);
- EXPECT_TRUE(*id1 != *id3);
- }
- // Test checks if the toText() returns valid texual representation
- TEST(ClientIdTest, toText) {
- uint8_t data1[] = {0, 1, 2, 3, 4, 0xff, 0xfe};
- ClientId clientid(data1, sizeof(data1));
- EXPECT_EQ("00:01:02:03:04:ff:fe", clientid.toText());
- }
- // This test checks that the ClientId instance can be created from the textual
- // format and that error is reported if the textual format is invalid.
- TEST(ClientIdTest, fromText) {
- ClientIdPtr cid;
- // ClientId with only decimal digits.
- ASSERT_NO_THROW(
- cid = ClientId::fromText("00:01:02:03:04:05:06")
- );
- EXPECT_EQ("00:01:02:03:04:05:06", cid->toText());
- // ClientId with some hexadecimal digits (upper case and lower case).
- ASSERT_NO_THROW(
- cid = ClientId::fromText("00:aa:bb:CD:ee:EF:ab")
- );
- EXPECT_EQ("00:aa:bb:cd:ee:ef:ab", cid->toText());
- // ClientId with one digit for a particular byte.
- ASSERT_NO_THROW(
- cid = ClientId::fromText("00:a:bb:D:ee:EF:ab")
- );
- EXPECT_EQ("00:0a:bb:0d:ee:ef:ab", cid->toText());
- // Repeated colon sign in the ClientId is not allowed.
- EXPECT_THROW(
- ClientId::fromText("00::bb:D:ee:EF:ab"),
- isc::BadValue
- );
- // ClientId with excessive number of digits for one of the bytes.
- EXPECT_THROW(
- ClientId::fromText("00:01:021:03:04:05:06"),
- isc::BadValue
- );
- }
- } // end of anonymous namespace
|