host_mgr_unittest.cc 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. // Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #include <config.h>
  7. #include <dhcp/duid.h>
  8. #include <dhcp/hwaddr.h>
  9. #include <dhcpsrv/cfgmgr.h>
  10. #include <dhcpsrv/host.h>
  11. #include <dhcpsrv/host_mgr.h>
  12. #include <gtest/gtest.h>
  13. #include <vector>
  14. using namespace isc;
  15. using namespace isc::dhcp;
  16. using namespace isc::asiolink;
  17. namespace {
  18. /// @brief Test fixture class for @c HostMgr class.
  19. class HostMgrTest : public ::testing::Test {
  20. protected:
  21. /// @brief Prepares the class for a test.
  22. ///
  23. /// This method crates a handful of unique HW address and DUID objects
  24. /// for use in unit tests. These objects are held in the @c hwaddrs_ and
  25. /// @c duids_ members respectively.
  26. ///
  27. /// This method also resets the @c CfgMgr configuration and re-creates
  28. /// the @c HostMgr object.
  29. virtual void SetUp();
  30. /// @brief Convenience method returning a pointer to the @c CfgHosts object
  31. /// in the @c CfgMgr.
  32. CfgHostsPtr getCfgHosts() const;
  33. /// @brief HW addresses to be used by the tests.
  34. std::vector<HWAddrPtr> hwaddrs_;
  35. /// @brief DUIDs to be used by the tests.
  36. std::vector<DuidPtr> duids_;
  37. };
  38. void
  39. // cppcheck-suppress unusedFunction
  40. HostMgrTest::SetUp() {
  41. // Remove all configuration which may be dangling from the previous test.
  42. CfgMgr::instance().clear();
  43. // Recreate HostMgr instance. It drops any previous state.
  44. HostMgr::create();
  45. // Create HW addresses from the template.
  46. const uint8_t mac_template[] = {
  47. 0x01, 0x02, 0x0A, 0xBB, 0x03, 0x00
  48. };
  49. for (uint8_t i = 0; i < 10; ++i) {
  50. std::vector<uint8_t> vec(mac_template,
  51. mac_template + sizeof(mac_template));
  52. vec[vec.size() - 1] = i;
  53. HWAddrPtr hwaddr(new HWAddr(vec, HTYPE_ETHER));
  54. hwaddrs_.push_back(hwaddr);
  55. }
  56. // Create DUIDs from the template.
  57. const uint8_t duid_template[] = {
  58. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x00
  59. };
  60. for (uint8_t i = 0; i < 10; ++i) {
  61. std::vector<uint8_t> vec(duid_template,
  62. duid_template + sizeof(mac_template));
  63. vec[vec.size() - 1] = i;
  64. DuidPtr duid(new DUID(vec));
  65. duids_.push_back(duid);
  66. }
  67. }
  68. CfgHostsPtr
  69. HostMgrTest::getCfgHosts() const {
  70. return (CfgMgr::instance().getStagingCfg()->getCfgHosts());
  71. }
  72. /// This test verifies that HostMgr returns all reservations for the
  73. /// specified HW address. The reservations are defined in the server's
  74. /// configuration.
  75. TEST_F(HostMgrTest, getAll) {
  76. // Initially, no reservations should be present.
  77. ConstHostCollection hosts = HostMgr::instance().getAll(hwaddrs_[0]);
  78. ASSERT_TRUE(hosts.empty());
  79. // Add two reservations for the same HW address. They differ by the IP
  80. // address reserved and the IPv4 subnet.
  81. getCfgHosts()->add(HostPtr(new Host(hwaddrs_[0]->toText(false),
  82. "hw-address", SubnetID(1), SubnetID(0),
  83. IOAddress("192.0.2.5"))));
  84. getCfgHosts()->add(HostPtr(new Host(hwaddrs_[0]->toText(false),
  85. "hw-address", SubnetID(10), SubnetID(0),
  86. IOAddress("192.0.3.10"))));
  87. CfgMgr::instance().commit();
  88. // If there non-matching HW address is specified, nothing should be
  89. // returned.
  90. ASSERT_TRUE(HostMgr::instance().getAll(Host::IDENT_HWADDR,
  91. &hwaddrs_[1]->hwaddr_[0],
  92. hwaddrs_[1]->hwaddr_.size()).empty());
  93. // For the correct HW address, there should be two reservations.
  94. hosts = HostMgr::instance().getAll(Host::IDENT_HWADDR,
  95. &hwaddrs_[0]->hwaddr_[0],
  96. hwaddrs_[0]->hwaddr_.size());
  97. ASSERT_EQ(2, hosts.size());
  98. // We don't know the order in which the reservations are returned so
  99. // we have to match with any of the two reservations returned.
  100. // Look for the first reservation.
  101. bool found = false;
  102. for (int i = 0; i < 2; ++i) {
  103. if (hosts[0]->getIPv4Reservation() == IOAddress("192.0.2.5")) {
  104. ASSERT_EQ(1, hosts[0]->getIPv4SubnetID());
  105. found = true;
  106. }
  107. }
  108. if (!found) {
  109. ADD_FAILURE() << "Reservation for the IPv4 address 192.0.2.5"
  110. " not found using getAll method";
  111. }
  112. // Look for the second reservation.
  113. found = false;
  114. for (int i = 0; i < 2; ++i) {
  115. if (hosts[1]->getIPv4Reservation() == IOAddress("192.0.3.10")) {
  116. ASSERT_EQ(10, hosts[1]->getIPv4SubnetID());
  117. found = true;
  118. }
  119. }
  120. if (!found) {
  121. ADD_FAILURE() << "Reservation for the IPv4 address 192.0.3.10"
  122. " not found using getAll method";
  123. }
  124. }
  125. // This test verifies that it is possible to gather all reservations for the
  126. // specified IPv4 address from the HostMgr. The reservations are specified in
  127. // the server's configuration.
  128. TEST_F(HostMgrTest, getAll4) {
  129. ConstHostCollection hosts =
  130. HostMgr::instance().getAll4(IOAddress("192.0.2.5"));
  131. ASSERT_TRUE(hosts.empty());
  132. getCfgHosts()->add(HostPtr(new Host(hwaddrs_[0]->toText(false),
  133. "hw-address", SubnetID(1), SubnetID(0),
  134. IOAddress("192.0.2.5"))));
  135. getCfgHosts()->add(HostPtr(new Host(hwaddrs_[1]->toText(false),
  136. "hw-address", SubnetID(10), SubnetID(0),
  137. IOAddress("192.0.2.5"))));
  138. CfgMgr::instance().commit();
  139. hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5"));
  140. ASSERT_EQ(2, hosts.size());
  141. // Make sure that IPv4 address is correct.
  142. EXPECT_EQ("192.0.2.5", hosts[0]->getIPv4Reservation().toText());
  143. EXPECT_EQ("192.0.2.5", hosts[1]->getIPv4Reservation().toText());
  144. // Make sure that two different hosts were returned.
  145. EXPECT_NE(hosts[0]->getIPv4SubnetID(), hosts[1]->getIPv4SubnetID());
  146. }
  147. // This test verifies that it is possible to retrieve a reservation for the
  148. // particular host using HostMgr. The reservation is specified in the server's
  149. // configuration.
  150. TEST_F(HostMgrTest, get4) {
  151. ConstHostPtr host = HostMgr::instance().get4(SubnetID(1), hwaddrs_[0]);
  152. ASSERT_FALSE(host);
  153. getCfgHosts()->add(HostPtr(new Host(hwaddrs_[0]->toText(false),
  154. "hw-address",
  155. SubnetID(1), SubnetID(2),
  156. IOAddress("192.0.2.5"))));
  157. CfgMgr::instance().commit();
  158. host = HostMgr::instance().get4(SubnetID(1), Host::IDENT_HWADDR,
  159. &hwaddrs_[0]->hwaddr_[0],
  160. hwaddrs_[0]->hwaddr_.size());
  161. ASSERT_TRUE(host);
  162. EXPECT_EQ(1, host->getIPv4SubnetID());
  163. EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
  164. }
  165. // This test verifies that it is possible to retrieve IPv6 reservations for
  166. // the particular host using HostMgr. The reservation is specified in the
  167. // server's configuration.
  168. TEST_F(HostMgrTest, get6) {
  169. ConstHostPtr host = HostMgr::instance().get6(SubnetID(2), duids_[0]);
  170. ASSERT_FALSE(host);
  171. HostPtr new_host(new Host(duids_[0]->toText(), "duid", SubnetID(1),
  172. SubnetID(2), IOAddress("0.0.0.0")));
  173. new_host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
  174. IOAddress("2001:db8:1::1")));
  175. getCfgHosts()->add(new_host);
  176. CfgMgr::instance().commit();
  177. host = HostMgr::instance().get6(SubnetID(2), Host::IDENT_DUID,
  178. &duids_[0]->getDuid()[0],
  179. duids_[0]->getDuid().size());
  180. ASSERT_TRUE(host);
  181. EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
  182. IOAddress("2001:db8:1::1"))));
  183. }
  184. // This test verifies that it is possible to retrieve the reservation of the
  185. // particular IPv6 prefix using HostMgr.
  186. TEST_F(HostMgrTest, get6ByPrefix) {
  187. ConstHostPtr host = HostMgr::instance().get6(IOAddress("2001:db8:1::"), 64);
  188. ASSERT_FALSE(host);
  189. // Add a host with a reservation for a prefix 2001:db8:1::/64.
  190. HostPtr new_host(new Host(duids_[0]->toText(), "duid", SubnetID(1),
  191. SubnetID(2), IOAddress("0.0.0.0")));
  192. new_host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
  193. IOAddress("2001:db8:1::"), 64));
  194. getCfgHosts()->add(new_host);
  195. // Add another host having a reservation for prefix 2001:db8:1:0:6::/72.
  196. new_host.reset(new Host(duids_[1]->toText(), "duid", SubnetID(2),
  197. SubnetID(3), IOAddress::IPV4_ZERO_ADDRESS()));
  198. new_host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
  199. IOAddress("2001:db8:1:0:6::"), 72));
  200. getCfgHosts()->add(new_host);
  201. CfgMgr::instance().commit();
  202. // Retrieve first reservation.
  203. host = HostMgr::instance().get6(IOAddress("2001:db8:1::"), 64);
  204. ASSERT_TRUE(host);
  205. EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
  206. IOAddress("2001:db8:1::"), 64)));
  207. // Make sure the first reservation is not retrieved when the prefix
  208. // length is incorrect.
  209. host = HostMgr::instance().get6(IOAddress("2001:db8:1::"), 72);
  210. EXPECT_FALSE(host);
  211. // Retrieve second reservation.
  212. host = HostMgr::instance().get6(IOAddress("2001:db8:1:0:6::"), 72);
  213. ASSERT_TRUE(host);
  214. EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
  215. IOAddress("2001:db8:1:0:6::"), 72)));
  216. // Make sure the second reservation is not retrieved when the prefix
  217. // length is incorrect.
  218. host = HostMgr::instance().get6(IOAddress("2001:db8:1:0:6::"), 64);
  219. EXPECT_FALSE(host);
  220. }
  221. } // end of anonymous namespace