host_unittest.cc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. // Copyright (C) 2014-2015 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 <dhcpsrv/host.h>
  16. #include <boost/scoped_ptr.hpp>
  17. #include <gtest/gtest.h>
  18. using namespace isc;
  19. using namespace isc::dhcp;
  20. using namespace isc::asiolink;
  21. namespace {
  22. // This test verifies that it is possible to create IPv6 address
  23. // reservation.
  24. TEST(IPv6ResrvTest, constructorAddress) {
  25. IPv6Resrv resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::cafe"));
  26. EXPECT_EQ("2001:db8:1::cafe", resrv.getPrefix().toText());
  27. EXPECT_EQ(128, resrv.getPrefixLen());
  28. EXPECT_EQ(IPv6Resrv::TYPE_NA, resrv.getType());
  29. }
  30. // This test verifies that it is possible to create IPv6 prefix
  31. // reservation.
  32. TEST(IPv6ResrvTest, constructorPrefix) {
  33. IPv6Resrv resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8:1::"), 64);
  34. EXPECT_EQ("2001:db8:1::", resrv.getPrefix().toText());
  35. EXPECT_EQ(64, resrv.getPrefixLen());
  36. EXPECT_EQ(IPv6Resrv::TYPE_PD, resrv.getType());
  37. }
  38. // This test verifies that the toText() function prints correctly.
  39. TEST(IPv6ResrvTest, toText) {
  40. IPv6Resrv resrv_prefix(IPv6Resrv::TYPE_PD, IOAddress("2001:db8:1::"), 64);
  41. EXPECT_EQ("2001:db8:1::/64", resrv_prefix.toText());
  42. IPv6Resrv resrv_address(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:111::23"));
  43. EXPECT_EQ("2001:db8:111::23", resrv_address.toText());
  44. }
  45. // This test verifies that invalid prefix is rejected.
  46. TEST(IPv6ResrvTest, constructorInvalidPrefix) {
  47. // IPv4 address is invalid for IPv6 reservation.
  48. EXPECT_THROW(IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("10.0.0.1"), 128),
  49. isc::BadValue);
  50. // Multicast address is invalid for IPv6 reservation.
  51. EXPECT_THROW(IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("ff02:1::2"), 128),
  52. isc::BadValue);
  53. }
  54. // This test verifies that invalid prefix length is rejected.
  55. TEST(IPv6ResrvTest, constructiorInvalidPrefixLength) {
  56. ASSERT_NO_THROW(IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8:1::"),
  57. 128));
  58. EXPECT_THROW(IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8:1::"), 129),
  59. isc::BadValue);
  60. EXPECT_THROW(IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8:1::"), 244),
  61. isc::BadValue);
  62. EXPECT_THROW(IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::"), 64),
  63. isc::BadValue);
  64. }
  65. // This test verifies that it is possible to modify prefix and its
  66. // length in an existing reservation.
  67. TEST(IPv6ResrvTest, setPrefix) {
  68. // Create a reservation using an address and prefix length 128.
  69. IPv6Resrv resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::1"));
  70. ASSERT_EQ("2001:db8:1::1", resrv.getPrefix().toText());
  71. ASSERT_EQ(128, resrv.getPrefixLen());
  72. ASSERT_EQ(IPv6Resrv::TYPE_NA, resrv.getType());
  73. // Modify the reservation to use a prefix having a length of 48.
  74. ASSERT_NO_THROW(resrv.set(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::"), 48));
  75. EXPECT_EQ("2001:db8::", resrv.getPrefix().toText());
  76. EXPECT_EQ(48, resrv.getPrefixLen());
  77. EXPECT_EQ(IPv6Resrv::TYPE_PD, resrv.getType());
  78. // IPv4 address is invalid for IPv6 reservation.
  79. EXPECT_THROW(resrv.set(IPv6Resrv::TYPE_NA, IOAddress("10.0.0.1"), 128),
  80. isc::BadValue);
  81. // IPv6 multicast address is invalid for IPv6 reservation.
  82. EXPECT_THROW(resrv.set(IPv6Resrv::TYPE_NA, IOAddress("ff02::1:2"), 128),
  83. isc::BadValue);
  84. // Prefix length greater than 128 is invalid.
  85. EXPECT_THROW(resrv.set(IPv6Resrv::TYPE_PD, IOAddress("2001:db8:1::"), 129),
  86. isc::BadValue);
  87. }
  88. // This test checks that the equality operators work fine.
  89. TEST(IPv6ResrvTest, equal) {
  90. EXPECT_TRUE(IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::"), 64) ==
  91. IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::"), 64));
  92. EXPECT_FALSE(IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::"), 64) !=
  93. IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::"), 64));
  94. EXPECT_TRUE(IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::1")) ==
  95. IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::1")));
  96. EXPECT_FALSE(IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::1")) !=
  97. IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::1")));
  98. EXPECT_FALSE(IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::1")) ==
  99. IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::2")));
  100. EXPECT_TRUE(IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::1")) !=
  101. IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::2")));
  102. EXPECT_FALSE(IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::"), 64) ==
  103. IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::"), 48));
  104. EXPECT_TRUE(IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::"), 64) !=
  105. IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::"), 48));
  106. EXPECT_FALSE(IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::1"), 128) ==
  107. IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::1"), 128));
  108. EXPECT_TRUE(IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::1"), 128) !=
  109. IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::1"), 128));
  110. }
  111. // This test verfies that it is possible to create a Host object
  112. // using hardware address in the textual format.
  113. TEST(HostTest, createFromHWAddrString) {
  114. boost::scoped_ptr<Host> host;
  115. ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
  116. SubnetID(1), SubnetID(2),
  117. IOAddress("192.0.2.3"),
  118. "somehost.example.org")));
  119. // The HW address should be set to non-null.
  120. HWAddrPtr hwaddr = host->getHWAddress();
  121. ASSERT_TRUE(hwaddr);
  122. EXPECT_EQ("hwtype=1 01:02:03:04:05:06", hwaddr->toText());
  123. // DUID should be null if hardware address is in use.
  124. EXPECT_FALSE(host->getDuid());
  125. EXPECT_EQ(1, host->getIPv4SubnetID());
  126. EXPECT_EQ(2, host->getIPv6SubnetID());
  127. EXPECT_EQ("192.0.2.3", host->getIPv4Reservation().toText());
  128. EXPECT_EQ("somehost.example.org", host->getHostname());
  129. // Use invalid identifier name
  130. EXPECT_THROW(Host("01:02:03:04:05:06", "bogus", SubnetID(1), SubnetID(2),
  131. IOAddress("192.0.2.3"), "somehost.example.org"),
  132. isc::BadValue);
  133. // Use invalid HW address.
  134. EXPECT_THROW(Host("010203040506", "hw-address", SubnetID(1), SubnetID(2),
  135. IOAddress("192.0.2.3"), "somehost.example.org"),
  136. isc::BadValue);
  137. }
  138. // This test verifies that it is possible to create Host object using
  139. // a DUID in the textual format.
  140. TEST(HostTest, createFromDUIDString) {
  141. boost::scoped_ptr<Host> host;
  142. ASSERT_NO_THROW(host.reset(new Host("a1:b2:c3:d4:e5:06", "duid",
  143. SubnetID(10), SubnetID(20),
  144. IOAddress("192.0.2.5"),
  145. "me.example.org")));
  146. // DUID should be set to non-null value.
  147. DuidPtr duid = host->getDuid();
  148. ASSERT_TRUE(duid);
  149. EXPECT_EQ("a1:b2:c3:d4:e5:06", duid->toText());
  150. // Hardware address must be null if DUID is in use.
  151. EXPECT_FALSE(host->getHWAddress());
  152. EXPECT_EQ(10, host->getIPv4SubnetID());
  153. EXPECT_EQ(20, host->getIPv6SubnetID());
  154. EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
  155. EXPECT_EQ("me.example.org", host->getHostname());
  156. // Use invalid DUID.
  157. EXPECT_THROW(Host("bogus", "duid", SubnetID(1), SubnetID(2),
  158. IOAddress("192.0.2.3"), "somehost.example.org"),
  159. isc::BadValue);
  160. // Empty DUID is also not allowed.
  161. EXPECT_THROW(Host("", "duid", SubnetID(1), SubnetID(2),
  162. IOAddress("192.0.2.3"), "somehost.example.org"),
  163. isc::BadValue);
  164. }
  165. // This test verifies that it is possible to create Host object using
  166. // hardware address in the binary format.
  167. TEST(HostTest, createFromHWAddrBinary) {
  168. boost::scoped_ptr<Host> host;
  169. // Prepare the hardware address in binary format.
  170. const uint8_t hwaddr_data[] = {
  171. 0xaa, 0xab, 0xca, 0xda, 0xbb, 0xee
  172. };
  173. ASSERT_NO_THROW(host.reset(new Host(hwaddr_data,
  174. sizeof(hwaddr_data),
  175. Host::IDENT_HWADDR,
  176. SubnetID(1), SubnetID(2),
  177. IOAddress("192.0.2.3"),
  178. "somehost.example.org")));
  179. // Hardware address should be non-null.
  180. HWAddrPtr hwaddr = host->getHWAddress();
  181. ASSERT_TRUE(hwaddr);
  182. EXPECT_EQ("hwtype=1 aa:ab:ca:da:bb:ee", hwaddr->toText());
  183. // DUID should be null if hardware address is in use.
  184. EXPECT_FALSE(host->getDuid());
  185. EXPECT_EQ(1, host->getIPv4SubnetID());
  186. EXPECT_EQ(2, host->getIPv6SubnetID());
  187. EXPECT_EQ("192.0.2.3", host->getIPv4Reservation().toText());
  188. EXPECT_EQ("somehost.example.org", host->getHostname());
  189. }
  190. // This test verifies that it is possible to create a Host object using
  191. // DUID in the binary format.
  192. TEST(HostTest, createFromDuidBinary) {
  193. boost::scoped_ptr<Host> host;
  194. // Prepare DUID binary.
  195. const uint8_t duid_data[] = {
  196. 1, 2, 3, 4, 5, 6
  197. };
  198. ASSERT_NO_THROW(host.reset(new Host(duid_data,
  199. sizeof(duid_data),
  200. Host::IDENT_DUID,
  201. SubnetID(10), SubnetID(20),
  202. IOAddress("192.0.2.5"),
  203. "me.example.org")));
  204. // DUID should be non null.
  205. DuidPtr duid = host->getDuid();
  206. ASSERT_TRUE(duid);
  207. EXPECT_EQ("01:02:03:04:05:06", duid->toText());
  208. // Hardware address should be null if DUID is in use.
  209. EXPECT_FALSE(host->getHWAddress());
  210. EXPECT_EQ(10, host->getIPv4SubnetID());
  211. EXPECT_EQ(20, host->getIPv6SubnetID());
  212. EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
  213. EXPECT_EQ("me.example.org", host->getHostname());
  214. }
  215. // Test that it is possible to replace an identifier for a particular
  216. // Host instance (HW address -> DUID and vice versa) with a new
  217. // indentifier in the textual format.
  218. TEST(HostTest, setIdentifierString) {
  219. boost::scoped_ptr<Host> host;
  220. ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
  221. SubnetID(1), SubnetID(2),
  222. IOAddress("192.0.2.3"),
  223. "me.example.com")));
  224. // Initially, there should be a HW address, but not a DUID set.
  225. ASSERT_TRUE(host->getHWAddress());
  226. ASSERT_FALSE(host->getDuid());
  227. // Now, use a DUID as identifier.
  228. ASSERT_NO_THROW(host->setIdentifier("aabbccddee", "duid"));
  229. // Verify that the DUID is correct.
  230. DuidPtr duid = host->getDuid();
  231. ASSERT_TRUE(duid);
  232. EXPECT_EQ("aa:bb:cc:dd:ee", duid->toText());
  233. // HW address should be not set.
  234. EXPECT_FALSE(host->getHWAddress());
  235. // Now, let's do another way around.
  236. ASSERT_NO_THROW(host->setIdentifier("09:08:07:06:05:04", "hw-address"));
  237. // Verify that HW address is correct.
  238. HWAddrPtr hw_addr = host->getHWAddress();
  239. ASSERT_TRUE(hw_addr);
  240. EXPECT_EQ("hwtype=1 09:08:07:06:05:04", hw_addr->toText());
  241. // DUID should be not set.
  242. EXPECT_FALSE(host->getDuid());
  243. }
  244. // Test that it is possible to replace an identifier for a particular
  245. // Host instance (HW address -> DUID and vice versa) with the new
  246. // identifier in the binary format.
  247. TEST(HostTest, setIdentifierBinary) {
  248. boost::scoped_ptr<Host> host;
  249. ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
  250. SubnetID(1), SubnetID(2),
  251. IOAddress("192.0.2.3"),
  252. "me.example.com")));
  253. // Initially, there should be a HW address, but not a DUID set.
  254. ASSERT_TRUE(host->getHWAddress());
  255. ASSERT_FALSE(host->getDuid());
  256. // Now, use a DUID as identifier.
  257. const uint8_t duid_data[] = {
  258. 0xaa, 0xbb, 0xcc, 0xdd, 0xee
  259. };
  260. ASSERT_NO_THROW(host->setIdentifier(duid_data, sizeof(duid_data),
  261. Host::IDENT_DUID));
  262. // Verify that the DUID is correct.
  263. DuidPtr duid = host->getDuid();
  264. ASSERT_TRUE(duid);
  265. EXPECT_EQ("aa:bb:cc:dd:ee", duid->toText());
  266. // HW address should be not set.
  267. EXPECT_FALSE(host->getHWAddress());
  268. // Now, let's do another way around.
  269. const uint8_t hwaddr_data[] = {
  270. 9, 8, 7, 6, 5, 4
  271. };
  272. ASSERT_NO_THROW(host->setIdentifier(hwaddr_data, sizeof(hwaddr_data),
  273. Host::IDENT_HWADDR));
  274. // Verify that HW address is correct.
  275. HWAddrPtr hw_addr = host->getHWAddress();
  276. ASSERT_TRUE(hw_addr);
  277. EXPECT_EQ("hwtype=1 09:08:07:06:05:04", hw_addr->toText());
  278. // DUID should be not set.
  279. EXPECT_FALSE(host->getDuid());
  280. }
  281. /// @brief Checks if the reservation is in the range of reservations.
  282. ///
  283. /// @param resrv Reservation to be searched for.
  284. /// @param range Range of reservations returned by the @c Host object
  285. /// in which the reservation will be searched.
  286. bool
  287. reservationExists(const IPv6Resrv& resrv, const IPv6ResrvRange& range) {
  288. for (IPv6ResrvIterator it = range.first; it != range.second;
  289. ++it) {
  290. if (resrv == it->second) {
  291. return (true);
  292. }
  293. }
  294. return (false);
  295. }
  296. // This test verifies that the IPv6 reservations of a different type can
  297. // be added for the host.
  298. TEST(HostTest, addReservations) {
  299. boost::scoped_ptr<Host> host;
  300. ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
  301. SubnetID(1), SubnetID(2),
  302. IOAddress("192.0.2.3"))));
  303. EXPECT_FALSE(host->hasIPv6Reservation());
  304. // Add 4 reservations: 2 for NAs, 2 for PDs.
  305. ASSERT_NO_THROW(
  306. host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
  307. IOAddress("2001:db8:1::cafe")));
  308. host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
  309. IOAddress("2001:db8:1:1::"), 64));
  310. host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
  311. IOAddress("2001:db8:1:2::"), 64));
  312. host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
  313. IOAddress("2001:db8:1::1")));
  314. );
  315. EXPECT_TRUE(host->hasIPv6Reservation());
  316. // Check that reservations exist.
  317. EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
  318. IOAddress("2001:db8:1::cafe"))));
  319. EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
  320. IOAddress("2001:db8:1:1::"),
  321. 64)));
  322. EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
  323. IOAddress("2001:db8:1:2::"),
  324. 64)));
  325. EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
  326. IOAddress("2001:db8:1::1"))));
  327. // Get only NA reservations.
  328. IPv6ResrvRange addresses = host->getIPv6Reservations(IPv6Resrv::TYPE_NA);
  329. ASSERT_EQ(2, std::distance(addresses.first, addresses.second));
  330. EXPECT_TRUE(reservationExists(IPv6Resrv(IPv6Resrv::TYPE_NA,
  331. IOAddress("2001:db8:1::cafe")),
  332. addresses));
  333. EXPECT_TRUE(reservationExists(IPv6Resrv(IPv6Resrv::TYPE_NA,
  334. IOAddress("2001:db8:1::1")),
  335. addresses));
  336. // Get only PD reservations.
  337. IPv6ResrvRange prefixes = host->getIPv6Reservations(IPv6Resrv::TYPE_PD);
  338. ASSERT_EQ(2, std::distance(prefixes.first, prefixes.second));
  339. EXPECT_TRUE(reservationExists(IPv6Resrv(IPv6Resrv::TYPE_PD,
  340. IOAddress("2001:db8:1:1::"), 64),
  341. prefixes));
  342. EXPECT_TRUE(reservationExists(IPv6Resrv(IPv6Resrv::TYPE_PD,
  343. IOAddress("2001:db8:1:2::"), 64),
  344. prefixes));
  345. }
  346. // This test checks that various modifiers may be used to replace the current
  347. // values of the Host class.
  348. TEST(HostTest, setValues) {
  349. boost::scoped_ptr<Host> host;
  350. ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
  351. SubnetID(1), SubnetID(2),
  352. IOAddress("192.0.2.3"),
  353. "some-host.example.org")));
  354. ASSERT_EQ(1, host->getIPv4SubnetID());
  355. ASSERT_EQ(2, host->getIPv6SubnetID());
  356. ASSERT_EQ("192.0.2.3", host->getIPv4Reservation().toText());
  357. ASSERT_EQ("some-host.example.org", host->getHostname());
  358. host->setIPv4SubnetID(SubnetID(123));
  359. host->setIPv6SubnetID(SubnetID(234));
  360. host->setIPv4Reservation(IOAddress("10.0.0.1"));
  361. host->setHostname("other-host.example.org");
  362. EXPECT_EQ(123, host->getIPv4SubnetID());
  363. EXPECT_EQ(234, host->getIPv6SubnetID());
  364. EXPECT_EQ("10.0.0.1", host->getIPv4Reservation().toText());
  365. EXPECT_EQ("other-host.example.org", host->getHostname());
  366. // Remove IPv4 reservation.
  367. host->removeIPv4Reservation();
  368. EXPECT_EQ(IOAddress::IPV4_ZERO_ADDRESS(), host->getIPv4Reservation());
  369. // An IPv6 address can't be used for IPv4 reservations.
  370. EXPECT_THROW(host->setIPv4Reservation(IOAddress("2001:db8:1::1")),
  371. isc::BadValue);
  372. // Zero address can't be set, the removeIPv4Reservation should be
  373. // used intead.
  374. EXPECT_THROW(host->setIPv4Reservation(IOAddress::IPV4_ZERO_ADDRESS()),
  375. isc::BadValue);
  376. // Broadcast address can't be set.
  377. EXPECT_THROW(host->setIPv4Reservation(IOAddress::IPV4_BCAST_ADDRESS()),
  378. isc::BadValue);
  379. }
  380. // Test that Host constructors initialize client classes from string.
  381. TEST(HostTest, clientClassesFromConstructor) {
  382. boost::scoped_ptr<Host> host;
  383. // Prepare the hardware address in binary format.
  384. const uint8_t hwaddr_data[] = {
  385. 0xaa, 0xab, 0xca, 0xda, 0xbb, 0xee
  386. };
  387. // Try the "from binary" constructor.
  388. ASSERT_NO_THROW(host.reset(new Host(hwaddr_data,
  389. sizeof(hwaddr_data),
  390. Host::IDENT_HWADDR,
  391. SubnetID(1), SubnetID(2),
  392. IOAddress("192.0.2.3"),
  393. "somehost.example.org",
  394. "alpha, , beta",
  395. "gamma")));
  396. EXPECT_TRUE(host->getClientClasses4().contains("alpha"));
  397. EXPECT_TRUE(host->getClientClasses4().contains("beta"));
  398. EXPECT_FALSE(host->getClientClasses4().contains("gamma"));
  399. EXPECT_TRUE(host->getClientClasses6().contains("gamma"));
  400. EXPECT_FALSE(host->getClientClasses6().contains("alpha"));
  401. EXPECT_FALSE(host->getClientClasses6().contains("beta"));
  402. // Try the "from string" constructor.
  403. ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
  404. SubnetID(1), SubnetID(2),
  405. IOAddress("192.0.2.3"),
  406. "somehost.example.org",
  407. "alpha, beta, gamma",
  408. "beta, gamma")));
  409. EXPECT_TRUE(host->getClientClasses4().contains("alpha"));
  410. EXPECT_TRUE(host->getClientClasses4().contains("beta"));
  411. EXPECT_TRUE(host->getClientClasses4().contains("gamma"));
  412. EXPECT_FALSE(host->getClientClasses6().contains("alpha"));
  413. EXPECT_TRUE(host->getClientClasses6().contains("beta"));
  414. EXPECT_TRUE(host->getClientClasses6().contains("gamma"));
  415. }
  416. // Test that new client classes can be added for the Host.
  417. TEST(HostTest, addClientClasses) {
  418. boost::scoped_ptr<Host> host;
  419. ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
  420. SubnetID(1), SubnetID(2),
  421. IOAddress("192.0.2.3"))));
  422. EXPECT_FALSE(host->getClientClasses4().contains("foo"));
  423. EXPECT_FALSE(host->getClientClasses6().contains("foo"));
  424. EXPECT_FALSE(host->getClientClasses4().contains("bar"));
  425. EXPECT_FALSE(host->getClientClasses6().contains("bar"));
  426. host->addClientClass4("foo");
  427. host->addClientClass6("bar");
  428. EXPECT_TRUE(host->getClientClasses4().contains("foo"));
  429. EXPECT_FALSE(host->getClientClasses6().contains("foo"));
  430. EXPECT_FALSE(host->getClientClasses4().contains("bar"));
  431. EXPECT_TRUE(host->getClientClasses6().contains("bar"));
  432. host->addClientClass4("bar");
  433. host->addClientClass6("foo");
  434. EXPECT_TRUE(host->getClientClasses4().contains("foo"));
  435. EXPECT_TRUE(host->getClientClasses6().contains("foo"));
  436. EXPECT_TRUE(host->getClientClasses4().contains("bar"));
  437. EXPECT_TRUE(host->getClientClasses6().contains("bar"));
  438. }
  439. TEST(HostTest, getIdentifierAsText) {
  440. Host host1("01:02:03:04:05:06", "hw-address",
  441. SubnetID(1), SubnetID(2),
  442. IOAddress("192.0.2.3"));
  443. EXPECT_EQ("hwaddr=01:02:03:04:05:06", host1.getIdentifierAsText());
  444. Host host2("0a:0b:0c:0d:0e:0f:ab:cd:ef", "duid",
  445. SubnetID(1), SubnetID(2),
  446. IOAddress("192.0.2.3"));
  447. EXPECT_EQ("duid=0a:0b:0c:0d:0e:0f:ab:cd:ef",
  448. host2.getIdentifierAsText());
  449. }
  450. // This test checks that Host object is correctly described in the
  451. // textual format using the toText method.
  452. TEST(HostTest, toText) {
  453. boost::scoped_ptr<Host> host;
  454. ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
  455. SubnetID(1), SubnetID(2),
  456. IOAddress("192.0.2.3"),
  457. "myhost.example.com")));
  458. // Add 4 reservations: 2 for NAs, 2 for PDs.
  459. ASSERT_NO_THROW(
  460. host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
  461. IOAddress("2001:db8:1::cafe")));
  462. host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
  463. IOAddress("2001:db8:1:1::"), 64));
  464. host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
  465. IOAddress("2001:db8:1:2::"), 64));
  466. host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
  467. IOAddress("2001:db8:1::1")));
  468. );
  469. // Make sure that the output is correct,
  470. EXPECT_EQ("hwaddr=01:02:03:04:05:06 ipv4_subnet_id=1 ipv6_subnet_id=2"
  471. " hostname=myhost.example.com"
  472. " ipv4_reservation=192.0.2.3"
  473. " ipv6_reservation0=2001:db8:1::cafe"
  474. " ipv6_reservation1=2001:db8:1::1"
  475. " ipv6_reservation2=2001:db8:1:1::/64"
  476. " ipv6_reservation3=2001:db8:1:2::/64",
  477. host->toText());
  478. // Reset some of the data and make sure that the output is affected.
  479. host->setHostname("");
  480. host->removeIPv4Reservation();
  481. host->setIPv4SubnetID(0);
  482. EXPECT_EQ("hwaddr=01:02:03:04:05:06 ipv6_subnet_id=2"
  483. " hostname=(empty) ipv4_reservation=(no)"
  484. " ipv6_reservation0=2001:db8:1::cafe"
  485. " ipv6_reservation1=2001:db8:1::1"
  486. " ipv6_reservation2=2001:db8:1:1::/64"
  487. " ipv6_reservation3=2001:db8:1:2::/64",
  488. host->toText());
  489. // Create host identified by DUID, instead of HWADDR, with a very
  490. // basic configuration.
  491. ASSERT_NO_THROW(host.reset(new Host("11:12:13:14:15", "duid",
  492. SubnetID(0), SubnetID(0),
  493. IOAddress::IPV4_ZERO_ADDRESS(),
  494. "myhost")));
  495. EXPECT_EQ("duid=11:12:13:14:15 hostname=myhost ipv4_reservation=(no)"
  496. " ipv6_reservations=(none)", host->toText());
  497. // Add some classes.
  498. host->addClientClass4("modem");
  499. host->addClientClass4("router");
  500. EXPECT_EQ("duid=11:12:13:14:15 hostname=myhost ipv4_reservation=(no)"
  501. " ipv6_reservations=(none)"
  502. " dhcp4_class0=modem dhcp4_class1=router",
  503. host->toText());
  504. host->addClientClass6("hub");
  505. host->addClientClass6("device");
  506. EXPECT_EQ("duid=11:12:13:14:15 hostname=myhost ipv4_reservation=(no)"
  507. " ipv6_reservations=(none)"
  508. " dhcp4_class0=modem dhcp4_class1=router"
  509. " dhcp6_class0=device dhcp6_class1=hub",
  510. host->toText());
  511. }
  512. } // end of anonymous namespace