duid_unittest.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <config.h>
  15. #include <asiolink/io_address.h>
  16. #include <dhcp/duid.h>
  17. #include <exceptions/exceptions.h>
  18. #include <boost/scoped_ptr.hpp>
  19. #include <gtest/gtest.h>
  20. #include <iostream>
  21. #include <sstream>
  22. #include <arpa/inet.h>
  23. using namespace std;
  24. using namespace isc;
  25. using namespace isc::dhcp;
  26. using namespace isc::asiolink;
  27. // don't import the entire boost namespace. It will unexpectedly hide uint8_t
  28. // for some systems.
  29. using boost::scoped_ptr;
  30. namespace {
  31. // This is a workaround for strange linking problems with gtest:
  32. // libdhcp___unittests-duid_unittest.o: In function `Compare<long unsigned int, long unsigned int>':
  33. // ~/gtest-1.6.0/include/gtest/gtest.h:1353: undefined reference to `isc::dhcp::ClientId::MAX_CLIENT_ID_LE'N
  34. // collect2: ld returned 1 exit status
  35. const size_t MAX_DUID_LEN = DUID::MAX_DUID_LEN;
  36. const size_t MAX_CLIENT_ID_LEN = DUID::MAX_DUID_LEN;
  37. // This test verifies if the constructors are working as expected
  38. // and process passed parameters.
  39. TEST(DuidTest, constructor) {
  40. uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
  41. vector<uint8_t> data2(data1, data1 + sizeof(data1));
  42. scoped_ptr<DUID> duid1(new DUID(data1, sizeof(data1)));
  43. scoped_ptr<DUID> duid2(new DUID(data2));
  44. vector<uint8_t> vecdata = duid1->getDuid();
  45. EXPECT_TRUE(data2 == vecdata);
  46. EXPECT_EQ(DUID::DUID_LLT, duid1->getType());
  47. vecdata = duid2->getDuid();
  48. EXPECT_TRUE(data2 == vecdata);
  49. EXPECT_EQ(DUID::DUID_LLT, duid2->getType());
  50. }
  51. // This test verifies if DUID size restrictions are implemented
  52. // properly.
  53. TEST(DuidTest, size) {
  54. uint8_t data[MAX_DUID_LEN + 1];
  55. vector<uint8_t> data2;
  56. for (uint8_t i = 0; i < MAX_DUID_LEN + 1; ++i) {
  57. data[i] = i;
  58. if (i < MAX_DUID_LEN)
  59. data2.push_back(i);
  60. }
  61. ASSERT_EQ(data2.size(), MAX_DUID_LEN);
  62. scoped_ptr<DUID> duidmaxsize1(new DUID(data, MAX_DUID_LEN));
  63. scoped_ptr<DUID> duidmaxsize2(new DUID(data2));
  64. EXPECT_THROW(
  65. scoped_ptr<DUID> toolarge1(new DUID(data, MAX_DUID_LEN + 1)),
  66. OutOfRange);
  67. // that's one too much
  68. data2.push_back(128);
  69. EXPECT_THROW(
  70. scoped_ptr<DUID> toolarge2(new DUID(data2)),
  71. OutOfRange);
  72. // empty duids are not allowed
  73. vector<uint8_t> empty;
  74. EXPECT_THROW(
  75. scoped_ptr<DUID> emptyDuid(new DUID(empty)),
  76. OutOfRange);
  77. EXPECT_THROW(
  78. scoped_ptr<DUID> emptyDuid2(new DUID(data, 0)),
  79. OutOfRange);
  80. }
  81. // This test verifies if the implementation supports all defined
  82. // DUID types.
  83. TEST(DuidTest, getType) {
  84. uint8_t llt[] = {0, 1, 2, 3, 4, 5, 6};
  85. uint8_t en[] = {0, 2, 2, 3, 4, 5, 6};
  86. uint8_t ll[] = {0, 3, 2, 3, 4, 5, 6};
  87. uint8_t uuid[] = {0, 4, 2, 3, 4, 5, 6};
  88. uint8_t invalid[] = {0,55, 2, 3, 4, 5, 6};
  89. scoped_ptr<DUID> duid_llt(new DUID(llt, sizeof(llt)));
  90. scoped_ptr<DUID> duid_en(new DUID(en, sizeof(en)));
  91. scoped_ptr<DUID> duid_ll(new DUID(ll, sizeof(ll)));
  92. scoped_ptr<DUID> duid_uuid(new DUID(uuid, sizeof(uuid)));
  93. scoped_ptr<DUID> duid_invalid(new DUID(invalid, sizeof(invalid)));
  94. EXPECT_EQ(DUID::DUID_LLT, duid_llt->getType());
  95. EXPECT_EQ(DUID::DUID_EN, duid_en->getType());
  96. EXPECT_EQ(DUID::DUID_LL, duid_ll->getType());
  97. EXPECT_EQ(DUID::DUID_UUID, duid_uuid->getType());
  98. EXPECT_EQ(DUID::DUID_UNKNOWN, duid_invalid->getType());
  99. }
  100. // This test checks that the DUID instance can be created from the textual
  101. // format and that error is reported if the textual format is invalid.
  102. TEST(DuidTest, fromText) {
  103. scoped_ptr<DUID> duid;
  104. // DUID with only decimal digits.
  105. ASSERT_NO_THROW(
  106. duid.reset(new DUID(DUID::fromText("00:01:02:03:04:05:06")))
  107. );
  108. EXPECT_EQ("00:01:02:03:04:05:06", duid->toText());
  109. // DUID with some hexadecimal digits (upper case and lower case).
  110. ASSERT_NO_THROW(
  111. duid.reset(new DUID(DUID::fromText("00:aa:bb:CD:ee:EF:ab")))
  112. );
  113. EXPECT_EQ("00:aa:bb:cd:ee:ef:ab", duid->toText());
  114. // DUID with one digit for a particular byte.
  115. ASSERT_NO_THROW(
  116. duid.reset(new DUID(DUID::fromText("00:a:bb:D:ee:EF:ab")))
  117. );
  118. EXPECT_EQ("00:0a:bb:0d:ee:ef:ab", duid->toText());
  119. // Repeated colon sign is not allowed.
  120. EXPECT_THROW(
  121. duid.reset(new DUID(DUID::fromText("00::bb:D:ee:EF:ab"))),
  122. isc::BadValue
  123. );
  124. // DUID with excessive number of digits for one of the bytes.
  125. EXPECT_THROW(
  126. duid.reset(new DUID(DUID::fromText("00:01:021:03:04:05:06"))),
  127. isc::BadValue
  128. );
  129. }
  130. // Test checks if the toText() returns valid texual representation
  131. TEST(DuidTest, toText) {
  132. uint8_t data1[] = {0, 1, 2, 3, 4, 0xff, 0xfe};
  133. DUID duid(data1, sizeof(data1));
  134. EXPECT_EQ("00:01:02:03:04:ff:fe", duid.toText());
  135. }
  136. // This test checks if the comparison operators are sane.
  137. TEST(DuidTest, operators) {
  138. uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
  139. uint8_t data2[] = {0, 1, 2, 3, 4};
  140. uint8_t data3[] = {0, 1, 2, 3, 4, 5, 7}; // last digit different
  141. uint8_t data4[] = {0, 1, 2, 3, 4, 5, 6}; // the same as 1
  142. scoped_ptr<DUID> duid1(new DUID(data1, sizeof(data1)));
  143. scoped_ptr<DUID> duid2(new DUID(data2, sizeof(data2)));
  144. scoped_ptr<DUID> duid3(new DUID(data3, sizeof(data3)));
  145. scoped_ptr<DUID> duid4(new DUID(data4, sizeof(data4)));
  146. EXPECT_TRUE(*duid1 == *duid4);
  147. EXPECT_FALSE(*duid1 == *duid2);
  148. EXPECT_FALSE(*duid1 == *duid3);
  149. EXPECT_FALSE(*duid1 != *duid4);
  150. EXPECT_TRUE(*duid1 != *duid2);
  151. EXPECT_TRUE(*duid1 != *duid3);
  152. }
  153. // This test verifies if the ClientId constructors are working properly
  154. // and passed parameters are used
  155. TEST(ClientIdTest, constructor) {
  156. IOAddress addr2("192.0.2.1");
  157. IOAddress addr3("2001:db8:1::1");
  158. uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
  159. vector<uint8_t> data2(data1, data1 + sizeof(data1));
  160. // checks for C-style constructor (uint8_t * + len)
  161. scoped_ptr<ClientId> id1(new ClientId(data1, sizeof(data1)));
  162. vector<uint8_t> vecdata = id1->getClientId();
  163. EXPECT_TRUE(data2 == vecdata);
  164. // checks for vector-based constructor
  165. scoped_ptr<ClientId> id2(new ClientId(data2));
  166. vecdata = id2->getClientId();
  167. EXPECT_TRUE(data2 == vecdata);
  168. }
  169. // Check that client-id sizes are reasonable
  170. TEST(ClientIdTest, size) {
  171. uint8_t data[MAX_CLIENT_ID_LEN + 1];
  172. vector<uint8_t> data2;
  173. for (uint8_t i = 0; i < MAX_CLIENT_ID_LEN + 1; ++i) {
  174. data[i] = i;
  175. if (i < MAX_CLIENT_ID_LEN)
  176. data2.push_back(i);
  177. }
  178. ASSERT_EQ(data2.size(), MAX_CLIENT_ID_LEN);
  179. scoped_ptr<ClientId> duidmaxsize1(new ClientId(data, MAX_CLIENT_ID_LEN));
  180. scoped_ptr<ClientId> duidmaxsize2(new ClientId(data2));
  181. EXPECT_THROW(
  182. scoped_ptr<ClientId> toolarge1(new ClientId(data, MAX_CLIENT_ID_LEN + 1)),
  183. OutOfRange);
  184. // that's one too much
  185. data2.push_back(128);
  186. EXPECT_THROW(
  187. scoped_ptr<ClientId> toolarge2(new ClientId(data2)),
  188. OutOfRange);
  189. // empty client-ids are not allowed
  190. vector<uint8_t> empty;
  191. EXPECT_THROW(
  192. scoped_ptr<ClientId> empty_client_id1(new ClientId(empty)),
  193. OutOfRange);
  194. EXPECT_THROW(
  195. scoped_ptr<ClientId> empty_client_id2(new ClientId(data, 0)),
  196. OutOfRange);
  197. // client-id must be at least 2 bytes long
  198. vector<uint8_t> shorty(1,17); // just a single byte with value 17
  199. EXPECT_THROW(
  200. scoped_ptr<ClientId> too_short_client_id1(new ClientId(shorty)),
  201. OutOfRange);
  202. EXPECT_THROW(
  203. scoped_ptr<ClientId> too_short_client_id1(new ClientId(data, 1)),
  204. OutOfRange);
  205. }
  206. // This test checks if the comparison operators are sane.
  207. TEST(ClientIdTest, operators) {
  208. uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
  209. uint8_t data2[] = {0, 1, 2, 3, 4};
  210. uint8_t data3[] = {0, 1, 2, 3, 4, 5, 7}; // last digit different
  211. uint8_t data4[] = {0, 1, 2, 3, 4, 5, 6}; // the same as 1
  212. scoped_ptr<ClientId> id1(new ClientId(data1, sizeof(data1)));
  213. scoped_ptr<ClientId> id2(new ClientId(data2, sizeof(data2)));
  214. scoped_ptr<ClientId> id3(new ClientId(data3, sizeof(data3)));
  215. scoped_ptr<ClientId> id4(new ClientId(data4, sizeof(data4)));
  216. EXPECT_TRUE(*id1 == *id4);
  217. EXPECT_FALSE(*id1 == *id2);
  218. EXPECT_FALSE(*id1 == *id3);
  219. EXPECT_FALSE(*id1 != *id4);
  220. EXPECT_TRUE(*id1 != *id2);
  221. EXPECT_TRUE(*id1 != *id3);
  222. }
  223. // Test checks if the toText() returns valid texual representation
  224. TEST(ClientIdTest, toText) {
  225. uint8_t data1[] = {0, 1, 2, 3, 4, 0xff, 0xfe};
  226. ClientId clientid(data1, sizeof(data1));
  227. EXPECT_EQ("00:01:02:03:04:ff:fe", clientid.toText());
  228. }
  229. // This test checks that the ClientId instance can be created from the textual
  230. // format and that error is reported if the textual format is invalid.
  231. TEST(ClientIdTest, fromText) {
  232. ClientIdPtr cid;
  233. // ClientId with only decimal digits.
  234. ASSERT_NO_THROW(
  235. cid = ClientId::fromText("00:01:02:03:04:05:06")
  236. );
  237. EXPECT_EQ("00:01:02:03:04:05:06", cid->toText());
  238. // ClientId with some hexadecimal digits (upper case and lower case).
  239. ASSERT_NO_THROW(
  240. cid = ClientId::fromText("00:aa:bb:CD:ee:EF:ab")
  241. );
  242. EXPECT_EQ("00:aa:bb:cd:ee:ef:ab", cid->toText());
  243. // ClientId with one digit for a particular byte.
  244. ASSERT_NO_THROW(
  245. cid = ClientId::fromText("00:a:bb:D:ee:EF:ab")
  246. );
  247. EXPECT_EQ("00:0a:bb:0d:ee:ef:ab", cid->toText());
  248. // Repeated colon sign in the ClientId is not allowed.
  249. EXPECT_THROW(
  250. ClientId::fromText("00::bb:D:ee:EF:ab"),
  251. isc::BadValue
  252. );
  253. // ClientId with excessive number of digits for one of the bytes.
  254. EXPECT_THROW(
  255. ClientId::fromText("00:01:021:03:04:05:06"),
  256. isc::BadValue
  257. );
  258. }
  259. } // end of anonymous namespace