duid_unittest.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  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. BadValue);
  67. // that's one too much
  68. data2.push_back(128);
  69. EXPECT_THROW(
  70. scoped_ptr<DUID> toolarge2(new DUID(data2)),
  71. BadValue);
  72. // empty duids are not allowed
  73. vector<uint8_t> empty;
  74. EXPECT_THROW(
  75. scoped_ptr<DUID> emptyDuid(new DUID(empty)),
  76. BadValue);
  77. EXPECT_THROW(
  78. scoped_ptr<DUID> emptyDuid2(new DUID(data, 0)),
  79. BadValue);
  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 verifies that empty DUID returns proper value
  137. TEST(DuidTest, empty) {
  138. DuidPtr empty;
  139. EXPECT_NO_THROW(empty = DUID::generateEmpty());
  140. // This method must return something
  141. ASSERT_TRUE(empty);
  142. // Ok, technically empty is not really empty, it's just a single
  143. // byte with value of 0.
  144. EXPECT_EQ("00", empty->toText());
  145. }
  146. // This test checks if the comparison operators are sane.
  147. TEST(DuidTest, operators) {
  148. uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
  149. uint8_t data2[] = {0, 1, 2, 3, 4};
  150. uint8_t data3[] = {0, 1, 2, 3, 4, 5, 7}; // last digit different
  151. uint8_t data4[] = {0, 1, 2, 3, 4, 5, 6}; // the same as 1
  152. scoped_ptr<DUID> duid1(new DUID(data1, sizeof(data1)));
  153. scoped_ptr<DUID> duid2(new DUID(data2, sizeof(data2)));
  154. scoped_ptr<DUID> duid3(new DUID(data3, sizeof(data3)));
  155. scoped_ptr<DUID> duid4(new DUID(data4, sizeof(data4)));
  156. EXPECT_TRUE(*duid1 == *duid4);
  157. EXPECT_FALSE(*duid1 == *duid2);
  158. EXPECT_FALSE(*duid1 == *duid3);
  159. EXPECT_FALSE(*duid1 != *duid4);
  160. EXPECT_TRUE(*duid1 != *duid2);
  161. EXPECT_TRUE(*duid1 != *duid3);
  162. }
  163. // This test verifies if the ClientId constructors are working properly
  164. // and passed parameters are used
  165. TEST(ClientIdTest, constructor) {
  166. IOAddress addr2("192.0.2.1");
  167. IOAddress addr3("2001:db8:1::1");
  168. uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
  169. vector<uint8_t> data2(data1, data1 + sizeof(data1));
  170. // checks for C-style constructor (uint8_t * + len)
  171. scoped_ptr<ClientId> id1(new ClientId(data1, sizeof(data1)));
  172. vector<uint8_t> vecdata = id1->getClientId();
  173. EXPECT_TRUE(data2 == vecdata);
  174. // checks for vector-based constructor
  175. scoped_ptr<ClientId> id2(new ClientId(data2));
  176. vecdata = id2->getClientId();
  177. EXPECT_TRUE(data2 == vecdata);
  178. }
  179. // Check that client-id sizes are reasonable
  180. TEST(ClientIdTest, size) {
  181. uint8_t data[MAX_CLIENT_ID_LEN + 1];
  182. vector<uint8_t> data2;
  183. for (uint8_t i = 0; i < MAX_CLIENT_ID_LEN + 1; ++i) {
  184. data[i] = i;
  185. if (i < MAX_CLIENT_ID_LEN)
  186. data2.push_back(i);
  187. }
  188. ASSERT_EQ(data2.size(), MAX_CLIENT_ID_LEN);
  189. scoped_ptr<ClientId> duidmaxsize1(new ClientId(data, MAX_CLIENT_ID_LEN));
  190. scoped_ptr<ClientId> duidmaxsize2(new ClientId(data2));
  191. EXPECT_THROW(
  192. scoped_ptr<ClientId> toolarge1(new ClientId(data, MAX_CLIENT_ID_LEN + 1)),
  193. BadValue);
  194. // that's one too much
  195. data2.push_back(128);
  196. EXPECT_THROW(
  197. scoped_ptr<ClientId> toolarge2(new ClientId(data2)),
  198. BadValue);
  199. // empty client-ids are not allowed
  200. vector<uint8_t> empty;
  201. EXPECT_THROW(
  202. scoped_ptr<ClientId> empty_client_id1(new ClientId(empty)),
  203. BadValue);
  204. EXPECT_THROW(
  205. scoped_ptr<ClientId> empty_client_id2(new ClientId(data, 0)),
  206. BadValue);
  207. // client-id must be at least 2 bytes long
  208. vector<uint8_t> shorty(1,17); // just a single byte with value 17
  209. EXPECT_THROW(
  210. scoped_ptr<ClientId> too_short_client_id1(new ClientId(shorty)),
  211. BadValue);
  212. EXPECT_THROW(
  213. scoped_ptr<ClientId> too_short_client_id1(new ClientId(data, 1)),
  214. BadValue);
  215. }
  216. // This test checks if the comparison operators are sane.
  217. TEST(ClientIdTest, operators) {
  218. uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
  219. uint8_t data2[] = {0, 1, 2, 3, 4};
  220. uint8_t data3[] = {0, 1, 2, 3, 4, 5, 7}; // last digit different
  221. uint8_t data4[] = {0, 1, 2, 3, 4, 5, 6}; // the same as 1
  222. scoped_ptr<ClientId> id1(new ClientId(data1, sizeof(data1)));
  223. scoped_ptr<ClientId> id2(new ClientId(data2, sizeof(data2)));
  224. scoped_ptr<ClientId> id3(new ClientId(data3, sizeof(data3)));
  225. scoped_ptr<ClientId> id4(new ClientId(data4, sizeof(data4)));
  226. EXPECT_TRUE(*id1 == *id4);
  227. EXPECT_FALSE(*id1 == *id2);
  228. EXPECT_FALSE(*id1 == *id3);
  229. EXPECT_FALSE(*id1 != *id4);
  230. EXPECT_TRUE(*id1 != *id2);
  231. EXPECT_TRUE(*id1 != *id3);
  232. }
  233. // Test checks if the toText() returns valid texual representation
  234. TEST(ClientIdTest, toText) {
  235. uint8_t data1[] = {0, 1, 2, 3, 4, 0xff, 0xfe};
  236. ClientId clientid(data1, sizeof(data1));
  237. EXPECT_EQ("00:01:02:03:04:ff:fe", clientid.toText());
  238. }
  239. // This test checks that the ClientId instance can be created from the textual
  240. // format and that error is reported if the textual format is invalid.
  241. TEST(ClientIdTest, fromText) {
  242. ClientIdPtr cid;
  243. // ClientId with only decimal digits.
  244. ASSERT_NO_THROW(
  245. cid = ClientId::fromText("00:01:02:03:04:05:06")
  246. );
  247. EXPECT_EQ("00:01:02:03:04:05:06", cid->toText());
  248. // ClientId with some hexadecimal digits (upper case and lower case).
  249. ASSERT_NO_THROW(
  250. cid = ClientId::fromText("00:aa:bb:CD:ee:EF:ab")
  251. );
  252. EXPECT_EQ("00:aa:bb:cd:ee:ef:ab", cid->toText());
  253. // ClientId with one digit for a particular byte.
  254. ASSERT_NO_THROW(
  255. cid = ClientId::fromText("00:a:bb:D:ee:EF:ab")
  256. );
  257. EXPECT_EQ("00:0a:bb:0d:ee:ef:ab", cid->toText());
  258. // ClientId without any colons is allowed.
  259. ASSERT_NO_THROW(
  260. cid = ClientId::fromText("0010abcdee");
  261. );
  262. EXPECT_EQ("00:10:ab:cd:ee", cid->toText());
  263. // Repeated colon sign in the ClientId is not allowed.
  264. EXPECT_THROW(
  265. ClientId::fromText("00::bb:D:ee:EF:ab"),
  266. isc::BadValue
  267. );
  268. // ClientId with excessive number of digits for one of the bytes.
  269. EXPECT_THROW(
  270. ClientId::fromText("00:01:021:03:04:05:06"),
  271. isc::BadValue
  272. );
  273. // ClientId with two spaces between the colons should not be allowed.
  274. EXPECT_THROW(
  275. ClientId::fromText("00:01: :03:04:05:06"),
  276. isc::BadValue
  277. );
  278. // ClientId with one space between the colons should not be allowed.
  279. EXPECT_THROW(
  280. ClientId::fromText("00:01: :03:04:05:06"),
  281. isc::BadValue
  282. );
  283. // ClientId with three spaces between the colons should not be allowed.
  284. EXPECT_THROW(
  285. ClientId::fromText("00:01: :03:04:05:06"),
  286. isc::BadValue
  287. );
  288. }
  289. } // end of anonymous namespace