subnet_unittest.cc 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958
  1. // Copyright (C) 2012-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 <asiolink/io_address.h>
  16. #include <dhcp/option.h>
  17. #include <dhcp/dhcp6.h>
  18. #include <dhcpsrv/subnet.h>
  19. #include <exceptions/exceptions.h>
  20. #include <boost/scoped_ptr.hpp>
  21. #include <gtest/gtest.h>
  22. // don't import the entire boost namespace. It will unexpectedly hide uint8_t
  23. // for some systems.
  24. using boost::scoped_ptr;
  25. using namespace isc;
  26. using namespace isc::dhcp;
  27. using namespace isc::asiolink;
  28. namespace {
  29. TEST(Subnet4Test, constructor) {
  30. EXPECT_NO_THROW(Subnet4 subnet1(IOAddress("192.0.2.2"), 16,
  31. 1, 2, 3, 10));
  32. EXPECT_THROW(Subnet4 subnet2(IOAddress("192.0.2.0"), 33, 1, 2, 3),
  33. BadValue); // invalid prefix length
  34. EXPECT_THROW(Subnet4 subnet3(IOAddress("2001:db8::1"), 24, 1, 2, 3),
  35. BadValue); // IPv6 addresses are not allowed in Subnet4
  36. }
  37. // Checks that the subnet id can be either autogenerated or set to an
  38. // arbitrary value through the constructor.
  39. TEST(Subnet4Test, subnetID) {
  40. // Create subnet and don't specify id, so as it is autogenerated.
  41. Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 24, 1000, 2000,
  42. 3000));
  43. SubnetID id0 = subnet->getID();
  44. // Create another subnet and let id be autogenerated.
  45. subnet.reset(new Subnet4(IOAddress("192.0.3.0"), 24, 1000, 2000,
  46. 3000));
  47. SubnetID id1 = subnet->getID();
  48. // The autogenerated ids must not be equal.
  49. EXPECT_NE(id0, id1);
  50. // Create third subnet but this time select an arbitrary id. The id
  51. // we use the one of the second subnet. That way we ensure that the
  52. // subnet id we provide via constructor is used and it is not
  53. // autogenerated - if it was autogenerated we would get id other
  54. // than id1 because id1 has already been used.
  55. subnet.reset(new Subnet4(IOAddress("192.0.4.0"), 24, 1000, 2000,
  56. 3000, id1));
  57. EXPECT_EQ(id1, subnet->getID());
  58. }
  59. TEST(Subnet4Test, inRange) {
  60. Subnet4 subnet(IOAddress("192.0.2.1"), 24, 1000, 2000, 3000);
  61. EXPECT_EQ(1000, subnet.getT1());
  62. EXPECT_EQ(2000, subnet.getT2());
  63. EXPECT_EQ(3000, subnet.getValid());
  64. EXPECT_EQ("0.0.0.0", subnet.getRelayInfo().addr_.toText());
  65. EXPECT_FALSE(subnet.inRange(IOAddress("192.0.0.0")));
  66. EXPECT_TRUE(subnet.inRange(IOAddress("192.0.2.0")));
  67. EXPECT_TRUE(subnet.inRange(IOAddress("192.0.2.1")));
  68. EXPECT_TRUE(subnet.inRange(IOAddress("192.0.2.255")));
  69. EXPECT_FALSE(subnet.inRange(IOAddress("192.0.3.0")));
  70. EXPECT_FALSE(subnet.inRange(IOAddress("0.0.0.0")));
  71. EXPECT_FALSE(subnet.inRange(IOAddress("255.255.255.255")));
  72. }
  73. // Checks whether the relay field has sane default and if it can
  74. // be changed, stored and retrieved
  75. TEST(Subnet4Test, relay) {
  76. Subnet4 subnet(IOAddress("192.0.2.1"), 24, 1000, 2000, 3000);
  77. EXPECT_EQ("0.0.0.0", subnet.getRelayInfo().addr_.toText());
  78. subnet.setRelayInfo(IOAddress("192.0.123.45"));
  79. EXPECT_EQ("192.0.123.45", subnet.getRelayInfo().addr_.toText());
  80. }
  81. // Checks whether siaddr field can be set and retrieved correctly.
  82. TEST(Subnet4Test, siaddr) {
  83. Subnet4 subnet(IOAddress("192.0.2.1"), 24, 1000, 2000, 3000);
  84. // Check if the default is 0.0.0.0
  85. EXPECT_EQ("0.0.0.0", subnet.getSiaddr().toText());
  86. // Check that we can set it up
  87. EXPECT_NO_THROW(subnet.setSiaddr(IOAddress("1.2.3.4")));
  88. // Check that we can get it back
  89. EXPECT_EQ("1.2.3.4", subnet.getSiaddr().toText());
  90. // Check that only v4 addresses are supported
  91. EXPECT_THROW(subnet.setSiaddr(IOAddress("2001:db8::1")),
  92. BadValue);
  93. }
  94. TEST(Subnet4Test, Pool4InSubnet4) {
  95. Subnet4Ptr subnet(new Subnet4(IOAddress("192.1.2.0"), 24, 1, 2, 3));
  96. PoolPtr pool1(new Pool4(IOAddress("192.1.2.0"), 25));
  97. PoolPtr pool2(new Pool4(IOAddress("192.1.2.128"), 26));
  98. PoolPtr pool3(new Pool4(IOAddress("192.1.2.192"), 30));
  99. EXPECT_NO_THROW(subnet->addPool(pool1));
  100. // If there's only one pool, get that pool
  101. PoolPtr mypool = subnet->getAnyPool(Lease::TYPE_V4);
  102. EXPECT_EQ(mypool, pool1);
  103. EXPECT_NO_THROW(subnet->addPool(pool2));
  104. EXPECT_NO_THROW(subnet->addPool(pool3));
  105. // If there are more than one pool and we didn't provide hint, we
  106. // should get the first pool
  107. EXPECT_NO_THROW(mypool = subnet->getAnyPool(Lease::TYPE_V4));
  108. EXPECT_EQ(mypool, pool1);
  109. // If we provide a hint, we should get a pool that this hint belongs to
  110. EXPECT_NO_THROW(mypool = subnet->getPool(Lease::TYPE_V4,
  111. IOAddress("192.1.2.195")));
  112. EXPECT_EQ(mypool, pool3);
  113. }
  114. TEST(Subnet4Test, Subnet4_Pool4_checks) {
  115. Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
  116. // this one is in subnet
  117. Pool4Ptr pool1(new Pool4(IOAddress("192.255.0.0"), 16));
  118. subnet->addPool(pool1);
  119. // this one is larger than the subnet!
  120. Pool4Ptr pool2(new Pool4(IOAddress("193.0.0.0"), 24));
  121. EXPECT_THROW(subnet->addPool(pool2), BadValue);
  122. // this one is totally out of blue
  123. Pool4Ptr pool3(new Pool4(IOAddress("1.2.3.4"), 16));
  124. EXPECT_THROW(subnet->addPool(pool3), BadValue);
  125. }
  126. // Tests whether Subnet4 object is able to store and process properly
  127. // information about allowed client class (a single class).
  128. TEST(Subnet4Test, clientClasses) {
  129. // Create the V4 subnet.
  130. Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
  131. // This client does not belong to any class.
  132. isc::dhcp::ClientClasses no_class;
  133. // This client belongs to foo only.
  134. isc::dhcp::ClientClasses foo_class;
  135. foo_class.insert("foo");
  136. // This client belongs to bar only. I like that client.
  137. isc::dhcp::ClientClasses bar_class;
  138. bar_class.insert("bar");
  139. // This client belongs to foo, bar and baz classes.
  140. isc::dhcp::ClientClasses three_classes;
  141. three_classes.insert("foo");
  142. three_classes.insert("bar");
  143. three_classes.insert("baz");
  144. // No class restrictions defined, any client should be supported
  145. EXPECT_TRUE(subnet->clientSupported(no_class));
  146. EXPECT_TRUE(subnet->clientSupported(foo_class));
  147. EXPECT_TRUE(subnet->clientSupported(bar_class));
  148. EXPECT_TRUE(subnet->clientSupported(three_classes));
  149. // Let's allow only clients belongning to "bar" class.
  150. subnet->allowClientClass("bar");
  151. EXPECT_FALSE(subnet->clientSupported(no_class));
  152. EXPECT_FALSE(subnet->clientSupported(foo_class));
  153. EXPECT_TRUE(subnet->clientSupported(bar_class));
  154. EXPECT_TRUE(subnet->clientSupported(three_classes));
  155. }
  156. // Tests whether Subnet4 object is able to store and process properly
  157. // information about allowed client classes (multiple classes allowed).
  158. TEST(Subnet4Test, clientClassesMultiple) {
  159. // Create the V4 subnet.
  160. Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
  161. // This client does not belong to any class.
  162. isc::dhcp::ClientClasses no_class;
  163. // This client belongs to foo only.
  164. isc::dhcp::ClientClasses foo_class;
  165. foo_class.insert("foo");
  166. // This client belongs to bar only. I like that client.
  167. isc::dhcp::ClientClasses bar_class;
  168. bar_class.insert("bar");
  169. // No class restrictions defined, any client should be supported
  170. EXPECT_TRUE(subnet->clientSupported(no_class));
  171. EXPECT_TRUE(subnet->clientSupported(foo_class));
  172. EXPECT_TRUE(subnet->clientSupported(bar_class));
  173. // Let's allow clients belongning to "bar" or "foo" class.
  174. subnet->allowClientClass("bar");
  175. subnet->allowClientClass("foo");
  176. // Class-less clients are to be rejected.
  177. EXPECT_FALSE(subnet->clientSupported(no_class));
  178. // Clients in foo class should be accepted.
  179. EXPECT_TRUE(subnet->clientSupported(foo_class));
  180. // Clients in bar class should be accepted as well.
  181. EXPECT_TRUE(subnet->clientSupported(bar_class));
  182. }
  183. TEST(Subnet4Test, addInvalidOption) {
  184. // Create the V4 subnet.
  185. Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
  186. // Create NULL pointer option. Attempt to add NULL option
  187. // should result in exception.
  188. OptionPtr option2;
  189. ASSERT_FALSE(option2);
  190. EXPECT_THROW(subnet->getCfgOption()->add(option2, false, "dhcp4"),
  191. isc::BadValue);
  192. }
  193. // This test verifies that inRange() and inPool() methods work properly.
  194. TEST(Subnet4Test, inRangeinPool) {
  195. Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.0.0"), 8, 1, 2, 3));
  196. // this one is in subnet
  197. Pool4Ptr pool1(new Pool4(IOAddress("192.2.0.0"), 16));
  198. subnet->addPool(pool1);
  199. // 192.1.1.1 belongs to the subnet...
  200. EXPECT_TRUE(subnet->inRange(IOAddress("192.1.1.1")));
  201. // ... but it does not belong to any pool within
  202. EXPECT_FALSE(subnet->inPool(Lease::TYPE_V4, IOAddress("192.1.1.1")));
  203. // the last address that is in range, but out of pool
  204. EXPECT_TRUE(subnet->inRange(IOAddress("192.1.255.255")));
  205. EXPECT_FALSE(subnet->inPool(Lease::TYPE_V4, IOAddress("192.1.255.255")));
  206. // the first address that is in range, in pool
  207. EXPECT_TRUE(subnet->inRange(IOAddress("192.2.0.0")));
  208. EXPECT_TRUE (subnet->inPool(Lease::TYPE_V4, IOAddress("192.2.0.0")));
  209. // let's try something in the middle as well
  210. EXPECT_TRUE(subnet->inRange(IOAddress("192.2.3.4")));
  211. EXPECT_TRUE (subnet->inPool(Lease::TYPE_V4, IOAddress("192.2.3.4")));
  212. // the last address that is in range, in pool
  213. EXPECT_TRUE(subnet->inRange(IOAddress("192.2.255.255")));
  214. EXPECT_TRUE (subnet->inPool(Lease::TYPE_V4, IOAddress("192.2.255.255")));
  215. // the first address that is in range, but out of pool
  216. EXPECT_TRUE(subnet->inRange(IOAddress("192.3.0.0")));
  217. EXPECT_FALSE(subnet->inPool(Lease::TYPE_V4, IOAddress("192.3.0.0")));
  218. }
  219. // This test checks if the toText() method returns text representation
  220. TEST(Subnet4Test, toText) {
  221. Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
  222. EXPECT_EQ("192.0.2.0/24", subnet->toText());
  223. }
  224. // This test checks if the get() method returns proper parameters
  225. TEST(Subnet4Test, get) {
  226. Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 28, 1, 2, 3));
  227. EXPECT_EQ("192.0.2.0", subnet->get().first.toText());
  228. EXPECT_EQ(28, subnet->get().second);
  229. }
  230. // Checks if last allocated address/prefix is stored/retrieved properly
  231. TEST(Subnet4Test, lastAllocated) {
  232. IOAddress addr("192.0.2.17");
  233. IOAddress last("192.0.2.255");
  234. Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
  235. // Check initial conditions (all should be set to the last address in range)
  236. EXPECT_EQ(last.toText(), subnet->getLastAllocated(Lease::TYPE_V4).toText());
  237. // Now set last allocated for IA
  238. EXPECT_NO_THROW(subnet->setLastAllocated(Lease::TYPE_V4, addr));
  239. EXPECT_EQ(addr.toText(), subnet->getLastAllocated(Lease::TYPE_V4).toText());
  240. // No, you can't set the last allocated IPv6 address in IPv4 subnet
  241. EXPECT_THROW(subnet->setLastAllocated(Lease::TYPE_TA, addr), BadValue);
  242. EXPECT_THROW(subnet->setLastAllocated(Lease::TYPE_TA, addr), BadValue);
  243. EXPECT_THROW(subnet->setLastAllocated(Lease::TYPE_PD, addr), BadValue);
  244. }
  245. // Checks if the V4 is the only allowed type for Pool4 and if getPool()
  246. // is working properly.
  247. TEST(Subnet4Test, PoolType) {
  248. Subnet4Ptr subnet(new Subnet4(IOAddress("192.2.0.0"), 16, 1, 2, 3));
  249. PoolPtr pool1(new Pool4(IOAddress("192.2.1.0"), 24));
  250. PoolPtr pool2(new Pool4(IOAddress("192.2.2.0"), 24));
  251. PoolPtr pool3(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:3::"), 64));
  252. PoolPtr pool4(new Pool6(Lease::TYPE_TA, IOAddress("2001:db8:1:4::"), 64));
  253. PoolPtr pool5(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1:1::"), 64));
  254. // There should be no pools of any type by default
  255. EXPECT_EQ(PoolPtr(), subnet->getAnyPool(Lease::TYPE_V4));
  256. // It should not be possible to ask for V6 pools in Subnet4
  257. EXPECT_THROW(subnet->getAnyPool(Lease::TYPE_NA), BadValue);
  258. EXPECT_THROW(subnet->getAnyPool(Lease::TYPE_TA), BadValue);
  259. EXPECT_THROW(subnet->getAnyPool(Lease::TYPE_PD), BadValue);
  260. // Let's add a single V4 pool and check that it can be retrieved
  261. EXPECT_NO_THROW(subnet->addPool(pool1));
  262. // If there's only one IA pool, get that pool (without and with hint)
  263. EXPECT_EQ(pool1, subnet->getAnyPool(Lease::TYPE_V4));
  264. EXPECT_EQ(pool1, subnet->getPool(Lease::TYPE_V4, IOAddress("192.0.1.167")));
  265. // Let's add additional V4 pool
  266. EXPECT_NO_THROW(subnet->addPool(pool2));
  267. // Try without hints
  268. EXPECT_EQ(pool1, subnet->getAnyPool(Lease::TYPE_V4));
  269. // Try with valid hints
  270. EXPECT_EQ(pool1, subnet->getPool(Lease::TYPE_V4, IOAddress("192.2.1.5")));
  271. EXPECT_EQ(pool2, subnet->getPool(Lease::TYPE_V4, IOAddress("192.2.2.254")));
  272. // Try with bogus hints (hints should be ingored)
  273. EXPECT_EQ(pool1, subnet->getPool(Lease::TYPE_V4, IOAddress("10.1.1.1")));
  274. // Trying to add Pool6 to Subnet4 is a big no,no!
  275. EXPECT_THROW(subnet->addPool(pool3), BadValue);
  276. EXPECT_THROW(subnet->addPool(pool4), BadValue);
  277. EXPECT_THROW(subnet->addPool(pool5), BadValue);
  278. }
  279. // Tests for Subnet6
  280. TEST(Subnet6Test, constructor) {
  281. EXPECT_NO_THROW(Subnet6 subnet1(IOAddress("2001:db8:1::"), 64,
  282. 1, 2, 3, 4));
  283. EXPECT_THROW(Subnet6 subnet2(IOAddress("2001:db8:1::"), 129, 1, 2, 3, 4),
  284. BadValue); // invalid prefix length
  285. EXPECT_THROW(Subnet6 subnet3(IOAddress("192.168.0.0"), 32, 1, 2, 3, 4),
  286. BadValue); // IPv4 addresses are not allowed in Subnet6
  287. }
  288. // Checks that the subnet id can be either autogenerated or set to an
  289. // arbitrary value through the constructor.
  290. TEST(Subnet6Test, subnetID) {
  291. // Create subnet and don't specify id, so as it is autogenerated.
  292. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 64, 1000, 2000,
  293. 3000, 4000));
  294. SubnetID id0 = subnet->getID();
  295. // Create another subnet and let id be autogenerated.
  296. subnet.reset(new Subnet6(IOAddress("2001:db8:2::"), 64, 1000, 2000,
  297. 3000, 4000));
  298. SubnetID id1 = subnet->getID();
  299. // The autogenerated ids must not be equal.
  300. EXPECT_NE(id0, id1);
  301. // Create third subnet but this time select an arbitrary id. The id
  302. // we use us the one of second subnet. That way we ensure that the
  303. // subnet id we provide via constructor is used and it is not
  304. // autogenerated - if it was autogenerated we would get id other
  305. // than id1 because id1 has already been used.
  306. subnet.reset(new Subnet6(IOAddress("2001:db8:3::"), 64, 1000, 2000,
  307. 3000, 4000, id1));
  308. EXPECT_EQ(id1, subnet->getID());
  309. }
  310. TEST(Subnet6Test, inRange) {
  311. Subnet6 subnet(IOAddress("2001:db8:1::"), 64, 1000, 2000, 3000, 4000);
  312. EXPECT_EQ(1000, subnet.getT1());
  313. EXPECT_EQ(2000, subnet.getT2());
  314. EXPECT_EQ(3000, subnet.getPreferred());
  315. EXPECT_EQ(4000, subnet.getValid());
  316. EXPECT_FALSE(subnet.inRange(IOAddress("2001:db8:0:ffff:ffff:ffff:ffff:ffff")));
  317. EXPECT_TRUE(subnet.inRange(IOAddress("2001:db8:1::0")));
  318. EXPECT_TRUE(subnet.inRange(IOAddress("2001:db8:1::1")));
  319. EXPECT_TRUE(subnet.inRange(IOAddress("2001:db8:1::ffff:ffff:ffff:ffff")));
  320. EXPECT_FALSE(subnet.inRange(IOAddress("2001:db8:1:1::")));
  321. EXPECT_FALSE(subnet.inRange(IOAddress("::")));
  322. }
  323. // Checks whether the relay field has sane default and if it can
  324. // be changed, stored and retrieved
  325. TEST(Subnet6Test, relay) {
  326. Subnet6 subnet(IOAddress("2001:db8:1::"), 64, 1000, 2000, 3000, 4000);
  327. EXPECT_EQ("::", subnet.getRelayInfo().addr_.toText());
  328. subnet.setRelayInfo(IOAddress("2001:ffff::1"));
  329. EXPECT_EQ("2001:ffff::1", subnet.getRelayInfo().addr_.toText());
  330. }
  331. TEST(Subnet6Test, Pool6InSubnet6) {
  332. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  333. PoolPtr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 64));
  334. PoolPtr pool2(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:2::"), 64));
  335. PoolPtr pool3(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:3::"), 64));
  336. subnet->addPool(pool1);
  337. // If there's only one pool, get that pool
  338. PoolPtr mypool = subnet->getAnyPool(Lease::TYPE_NA);
  339. EXPECT_EQ(mypool, pool1);
  340. subnet->addPool(pool2);
  341. subnet->addPool(pool3);
  342. // If there are more than one pool and we didn't provide hint, we
  343. // should get the first pool
  344. mypool = subnet->getAnyPool(Lease::TYPE_NA);
  345. EXPECT_EQ(mypool, pool1);
  346. // If we provide a hint, we should get a pool that this hint belongs to
  347. mypool = subnet->getPool(Lease::TYPE_NA, IOAddress("2001:db8:1:3::dead:beef"));
  348. EXPECT_EQ(mypool, pool3);
  349. }
  350. // Check if Subnet6 supports different types of pools properly.
  351. TEST(Subnet6Test, poolTypes) {
  352. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  353. PoolPtr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 64));
  354. PoolPtr pool2(new Pool6(Lease::TYPE_TA, IOAddress("2001:db8:1:2::"), 64));
  355. PoolPtr pool3(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1:3::"), 64));
  356. PoolPtr pool4(new Pool6(Lease::TYPE_PD, IOAddress("3000:1::"), 64));
  357. PoolPtr pool5(new Pool4(IOAddress("192.0.2.0"), 24));
  358. // There should be no pools of any type by default
  359. EXPECT_EQ(PoolPtr(), subnet->getAnyPool(Lease::TYPE_NA));
  360. EXPECT_EQ(PoolPtr(), subnet->getAnyPool(Lease::TYPE_TA));
  361. EXPECT_EQ(PoolPtr(), subnet->getAnyPool(Lease::TYPE_PD));
  362. // Trying to get IPv4 pool from Subnet6 is not allowed
  363. EXPECT_THROW(subnet->getAnyPool(Lease::TYPE_V4), BadValue);
  364. // Let's add a single IA pool and check that it can be retrieved
  365. EXPECT_NO_THROW(subnet->addPool(pool1));
  366. // If there's only one IA pool, get that pool
  367. EXPECT_EQ(pool1, subnet->getAnyPool(Lease::TYPE_NA));
  368. EXPECT_EQ(pool1, subnet->getPool(Lease::TYPE_NA, IOAddress("2001:db8:1:1::1")));
  369. // Check if pools of different type are not returned
  370. EXPECT_EQ(PoolPtr(), subnet->getAnyPool(Lease::TYPE_TA));
  371. EXPECT_EQ(PoolPtr(), subnet->getAnyPool(Lease::TYPE_PD));
  372. // We ask with good hints, but wrong types, should return nothing
  373. EXPECT_EQ(PoolPtr(), subnet->getPool(Lease::TYPE_PD, IOAddress("2001:db8:1:2::1")));
  374. EXPECT_EQ(PoolPtr(), subnet->getPool(Lease::TYPE_TA, IOAddress("2001:db8:1:3::1")));
  375. // Let's add TA and PD pools
  376. EXPECT_NO_THROW(subnet->addPool(pool2));
  377. EXPECT_NO_THROW(subnet->addPool(pool3));
  378. // Try without hints
  379. EXPECT_EQ(pool1, subnet->getAnyPool(Lease::TYPE_NA));
  380. EXPECT_EQ(pool2, subnet->getAnyPool(Lease::TYPE_TA));
  381. EXPECT_EQ(pool3, subnet->getAnyPool(Lease::TYPE_PD));
  382. // Try with valid hints
  383. EXPECT_EQ(pool1, subnet->getPool(Lease::TYPE_NA, IOAddress("2001:db8:1:1::1")));
  384. EXPECT_EQ(pool2, subnet->getPool(Lease::TYPE_TA, IOAddress("2001:db8:1:2::1")));
  385. EXPECT_EQ(pool3, subnet->getPool(Lease::TYPE_PD, IOAddress("2001:db8:1:3::1")));
  386. // Try with bogus hints (hints should be ingored)
  387. EXPECT_EQ(pool1, subnet->getPool(Lease::TYPE_NA, IOAddress("2001:db8:1:7::1")));
  388. EXPECT_EQ(pool2, subnet->getPool(Lease::TYPE_TA, IOAddress("2001:db8:1:7::1")));
  389. EXPECT_EQ(pool3, subnet->getPool(Lease::TYPE_PD, IOAddress("2001:db8:1:7::1")));
  390. // Let's add a second PD pool
  391. EXPECT_NO_THROW(subnet->addPool(pool4));
  392. // Without hints, it should return the first pool
  393. EXPECT_EQ(pool3, subnet->getAnyPool(Lease::TYPE_PD));
  394. // With valid hint, it should return that hint
  395. EXPECT_EQ(pool3, subnet->getPool(Lease::TYPE_PD, IOAddress("2001:db8:1:3::1")));
  396. EXPECT_EQ(pool4, subnet->getPool(Lease::TYPE_PD, IOAddress("3000:1::")));
  397. // With invalid hint, it should return the first pool
  398. EXPECT_EQ(pool3, subnet->getPool(Lease::TYPE_PD, IOAddress("2001:db8::123")));
  399. // Adding Pool4 to Subnet6 is a big no, no!
  400. EXPECT_THROW(subnet->addPool(pool5), BadValue);
  401. }
  402. // Tests whether Subnet6 object is able to store and process properly
  403. // information about allowed client class (a single class).
  404. TEST(Subnet6Test, clientClasses) {
  405. // Create the V6 subnet.
  406. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  407. // This client does not belong to any class.
  408. isc::dhcp::ClientClasses no_class;
  409. // This client belongs to foo only.
  410. isc::dhcp::ClientClasses foo_class;
  411. foo_class.insert("foo");
  412. // This client belongs to bar only. I like that client.
  413. isc::dhcp::ClientClasses bar_class;
  414. bar_class.insert("bar");
  415. // This client belongs to foo, bar and baz classes.
  416. isc::dhcp::ClientClasses three_classes;
  417. three_classes.insert("foo");
  418. three_classes.insert("bar");
  419. three_classes.insert("baz");
  420. // No class restrictions defined, any client should be supported
  421. EXPECT_TRUE(subnet->clientSupported(no_class));
  422. EXPECT_TRUE(subnet->clientSupported(foo_class));
  423. EXPECT_TRUE(subnet->clientSupported(bar_class));
  424. EXPECT_TRUE(subnet->clientSupported(three_classes));
  425. // Let's allow only clients belongning to "bar" class.
  426. subnet->allowClientClass("bar");
  427. EXPECT_FALSE(subnet->clientSupported(no_class));
  428. EXPECT_FALSE(subnet->clientSupported(foo_class));
  429. EXPECT_TRUE(subnet->clientSupported(bar_class));
  430. EXPECT_TRUE(subnet->clientSupported(three_classes));
  431. }
  432. // Tests whether Subnet6 object is able to store and process properly
  433. // information about allowed client class (multiple classes allowed).
  434. TEST(Subnet6Test, clientClassesMultiple) {
  435. // Create the V6 subnet.
  436. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  437. // This client does not belong to any class.
  438. isc::dhcp::ClientClasses no_class;
  439. // This client belongs to foo only.
  440. isc::dhcp::ClientClasses foo_class;
  441. foo_class.insert("foo");
  442. // This client belongs to bar only. I like that client.
  443. isc::dhcp::ClientClasses bar_class;
  444. bar_class.insert("bar");
  445. // No class restrictions defined, any client should be supported
  446. EXPECT_TRUE(subnet->clientSupported(no_class));
  447. EXPECT_TRUE(subnet->clientSupported(foo_class));
  448. EXPECT_TRUE(subnet->clientSupported(bar_class));
  449. // Let's allow only clients belongning to "foo" or "bar" class.
  450. subnet->allowClientClass("foo");
  451. subnet->allowClientClass("bar");
  452. // Class-less clients are to be rejected.
  453. EXPECT_FALSE(subnet->clientSupported(no_class));
  454. // Clients in foo class should be accepted.
  455. EXPECT_TRUE(subnet->clientSupported(foo_class));
  456. // Clients in bar class should be accepted as well.
  457. EXPECT_TRUE(subnet->clientSupported(bar_class));
  458. }
  459. TEST(Subnet6Test, Subnet6_Pool6_checks) {
  460. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  461. // this one is in subnet
  462. Pool6Ptr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 64));
  463. subnet->addPool(pool1);
  464. // this one is larger than the subnet!
  465. Pool6Ptr pool2(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8::"), 48));
  466. EXPECT_THROW(subnet->addPool(pool2), BadValue);
  467. // this one is totally out of blue
  468. Pool6Ptr pool3(new Pool6(Lease::TYPE_NA, IOAddress("3000::"), 16));
  469. EXPECT_THROW(subnet->addPool(pool3), BadValue);
  470. Pool6Ptr pool4(new Pool6(Lease::TYPE_NA, IOAddress("4001:db8:1::"), 80));
  471. EXPECT_THROW(subnet->addPool(pool4), BadValue);
  472. }
  473. TEST(Subnet6Test, addOptions) {
  474. // Create as subnet to add options to it.
  475. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  476. // Differentiate options by their codes (100-109)
  477. for (uint16_t code = 100; code < 110; ++code) {
  478. OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
  479. ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, "dhcp6"));
  480. }
  481. // Add 7 options to another option space. The option codes partially overlap
  482. // with option codes that we have added to dhcp6 option space.
  483. for (uint16_t code = 105; code < 112; ++code) {
  484. OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
  485. ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, "isc"));
  486. }
  487. // Get options from the Subnet and check if all 10 are there.
  488. OptionContainerPtr options = subnet->getCfgOption()->getAll("dhcp6");
  489. ASSERT_TRUE(options);
  490. ASSERT_EQ(10, options->size());
  491. // Validate codes of options added to dhcp6 option space.
  492. uint16_t expected_code = 100;
  493. for (OptionContainer::const_iterator option_desc = options->begin();
  494. option_desc != options->end(); ++option_desc) {
  495. ASSERT_TRUE(option_desc->option_);
  496. EXPECT_EQ(expected_code, option_desc->option_->getType());
  497. ++expected_code;
  498. }
  499. options = subnet->getCfgOption()->getAll("isc");
  500. ASSERT_TRUE(options);
  501. ASSERT_EQ(7, options->size());
  502. // Validate codes of options added to isc option space.
  503. expected_code = 105;
  504. for (OptionContainer::const_iterator option_desc = options->begin();
  505. option_desc != options->end(); ++option_desc) {
  506. ASSERT_TRUE(option_desc->option_);
  507. EXPECT_EQ(expected_code, option_desc->option_->getType());
  508. ++expected_code;
  509. }
  510. // Try to get options from a non-existing option space.
  511. options = subnet->getCfgOption()->getAll("abcd");
  512. ASSERT_TRUE(options);
  513. EXPECT_TRUE(options->empty());
  514. }
  515. TEST(Subnet6Test, addNonUniqueOptions) {
  516. // Create as subnet to add options to it.
  517. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  518. // Create a set of options with non-unique codes.
  519. for (int i = 0; i < 2; ++i) {
  520. // In the inner loop we create options with unique codes (100-109).
  521. for (uint16_t code = 100; code < 110; ++code) {
  522. OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
  523. ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, "dhcp6"));
  524. }
  525. }
  526. // Sanity check that all options are there.
  527. OptionContainerPtr options = subnet->getCfgOption()->getAll("dhcp6");
  528. ASSERT_EQ(20, options->size());
  529. // Use container index #1 to get the options by their codes.
  530. OptionContainerTypeIndex& idx = options->get<1>();
  531. // Look for the codes 100-109.
  532. for (uint16_t code = 100; code < 110; ++ code) {
  533. // For each code we should get two instances of options->
  534. std::pair<OptionContainerTypeIndex::const_iterator,
  535. OptionContainerTypeIndex::const_iterator> range =
  536. idx.equal_range(code);
  537. // Distance between iterators indicates how many options
  538. // have been retured for the particular code.
  539. ASSERT_EQ(2, distance(range.first, range.second));
  540. // Check that returned options actually have the expected option code.
  541. for (OptionContainerTypeIndex::const_iterator option_desc = range.first;
  542. option_desc != range.second; ++option_desc) {
  543. ASSERT_TRUE(option_desc->option_);
  544. EXPECT_EQ(code, option_desc->option_->getType());
  545. }
  546. }
  547. // Let's try to find some non-exiting option.
  548. const uint16_t non_existing_code = 150;
  549. std::pair<OptionContainerTypeIndex::const_iterator,
  550. OptionContainerTypeIndex::const_iterator> range =
  551. idx.equal_range(non_existing_code);
  552. // Empty set is expected.
  553. EXPECT_EQ(0, distance(range.first, range.second));
  554. }
  555. TEST(Subnet6Test, addPersistentOption) {
  556. // Create as subnet to add options to it.
  557. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  558. // Add 10 options to the subnet with option codes 100 - 109.
  559. for (uint16_t code = 100; code < 110; ++code) {
  560. OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
  561. // We create 10 options and want some of them to be flagged
  562. // persistent and some non-persistent. Persistent options are
  563. // those that server sends to clients regardless if they ask
  564. // for them or not. We pick 3 out of 10 options and mark them
  565. // non-persistent and 7 other options persistent.
  566. // Code values: 102, 105 and 108 are divisible by 3
  567. // and options with these codes will be flagged non-persistent.
  568. // Options with other codes will be flagged persistent.
  569. bool persistent = (code % 3) ? true : false;
  570. ASSERT_NO_THROW(subnet->getCfgOption()->add(option, persistent, "dhcp6"));
  571. }
  572. // Get added options from the subnet.
  573. OptionContainerPtr options = subnet->getCfgOption()->getAll("dhcp6");
  574. // options->get<2> returns reference to container index #2. This
  575. // index is used to access options by the 'persistent' flag.
  576. OptionContainerPersistIndex& idx = options->get<2>();
  577. // Get all persistent options->
  578. std::pair<OptionContainerPersistIndex::const_iterator,
  579. OptionContainerPersistIndex::const_iterator> range_persistent =
  580. idx.equal_range(true);
  581. // 3 out of 10 options have been flagged persistent.
  582. ASSERT_EQ(7, distance(range_persistent.first, range_persistent.second));
  583. // Get all non-persistent options->
  584. std::pair<OptionContainerPersistIndex::const_iterator,
  585. OptionContainerPersistIndex::const_iterator> range_non_persistent =
  586. idx.equal_range(false);
  587. // 7 out of 10 options have been flagged persistent.
  588. ASSERT_EQ(3, distance(range_non_persistent.first, range_non_persistent.second));
  589. }
  590. TEST(Subnet6Test, getOptions) {
  591. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8::"), 56, 1, 2, 3, 4));
  592. // Add 10 options to a "dhcp6" option space in the subnet.
  593. for (uint16_t code = 100; code < 110; ++code) {
  594. OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
  595. ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, "dhcp6"));
  596. }
  597. // Check that we can get each added option descriptor using
  598. // individually.
  599. for (uint16_t code = 100; code < 110; ++code) {
  600. std::ostringstream stream;
  601. // First, try the invalid option space name.
  602. OptionDescriptor desc = subnet->getCfgOption()->get("isc", code);
  603. // Returned descriptor should contain NULL option ptr.
  604. EXPECT_FALSE(desc.option_);
  605. // Now, try the valid option space.
  606. desc = subnet->getCfgOption()->get("dhcp6", code);
  607. // Test that the option code matches the expected code.
  608. ASSERT_TRUE(desc.option_);
  609. EXPECT_EQ(code, desc.option_->getType());
  610. }
  611. }
  612. TEST(Subnet6Test, addVendorOption) {
  613. // Create as subnet to add options to it.
  614. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  615. // Differentiate options by their codes (100-109)
  616. for (uint16_t code = 100; code < 110; ++code) {
  617. OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
  618. ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, "vendor-12345678"));
  619. }
  620. // Add 7 options to another option space. The option codes partially overlap
  621. // with option codes that we have added to dhcp6 option space.
  622. for (uint16_t code = 105; code < 112; ++code) {
  623. OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
  624. ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, "vendor-87654321"));
  625. }
  626. // Get options from the Subnet and check if all 10 are there.
  627. OptionContainerPtr options = subnet->getCfgOption()->getAll(12345678);
  628. ASSERT_TRUE(options);
  629. ASSERT_EQ(10, options->size());
  630. // Validate codes of options added to dhcp6 option space.
  631. uint16_t expected_code = 100;
  632. for (OptionContainer::const_iterator option_desc = options->begin();
  633. option_desc != options->end(); ++option_desc) {
  634. ASSERT_TRUE(option_desc->option_);
  635. EXPECT_EQ(expected_code, option_desc->option_->getType());
  636. ++expected_code;
  637. }
  638. options = subnet->getCfgOption()->getAll(87654321);
  639. ASSERT_TRUE(options);
  640. ASSERT_EQ(7, options->size());
  641. // Validate codes of options added to isc option space.
  642. expected_code = 105;
  643. for (OptionContainer::const_iterator option_desc = options->begin();
  644. option_desc != options->end(); ++option_desc) {
  645. ASSERT_TRUE(option_desc->option_);
  646. EXPECT_EQ(expected_code, option_desc->option_->getType());
  647. ++expected_code;
  648. }
  649. // Try to get options from a non-existing option space.
  650. options = subnet->getCfgOption()->getAll(1111111);
  651. ASSERT_TRUE(options);
  652. EXPECT_TRUE(options->empty());
  653. }
  654. // This test verifies that inRange() and inPool() methods work properly.
  655. TEST(Subnet6Test, inRangeinPool) {
  656. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8::"), 32, 1, 2, 3, 4));
  657. // this one is in subnet
  658. Pool6Ptr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8::10"),
  659. IOAddress("2001:db8::20")));
  660. subnet->addPool(pool1);
  661. // 192.1.1.1 belongs to the subnet...
  662. EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::1")));
  663. // ... but it does not belong to any pool within
  664. EXPECT_FALSE(subnet->inPool(Lease::TYPE_NA, IOAddress("2001:db8::1")));
  665. // the last address that is in range, but out of pool
  666. EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::f")));
  667. EXPECT_FALSE(subnet->inPool(Lease::TYPE_NA, IOAddress("2001:db8::f")));
  668. // the first address that is in range, in pool
  669. EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::10")));
  670. EXPECT_TRUE (subnet->inPool(Lease::TYPE_NA, IOAddress("2001:db8::10")));
  671. // let's try something in the middle as well
  672. EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::18")));
  673. EXPECT_TRUE (subnet->inPool(Lease::TYPE_NA, IOAddress("2001:db8::18")));
  674. // the last address that is in range, in pool
  675. EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::20")));
  676. EXPECT_TRUE (subnet->inPool(Lease::TYPE_NA, IOAddress("2001:db8::20")));
  677. // the first address that is in range, but out of pool
  678. EXPECT_TRUE(subnet->inRange(IOAddress("2001:db8::21")));
  679. EXPECT_FALSE(subnet->inPool(Lease::TYPE_NA, IOAddress("2001:db8::21")));
  680. }
  681. // This test checks if the toText() method returns text representation
  682. TEST(Subnet6Test, toText) {
  683. Subnet6 subnet(IOAddress("2001:db8::"), 32, 1, 2, 3, 4);
  684. EXPECT_EQ("2001:db8::/32", subnet.toText());
  685. }
  686. // This test checks if the get() method returns proper parameters
  687. TEST(Subnet6Test, get) {
  688. Subnet6 subnet(IOAddress("2001:db8::"), 32, 1, 2, 3, 4);
  689. EXPECT_EQ("2001:db8::", subnet.get().first.toText());
  690. EXPECT_EQ(32, subnet.get().second);
  691. }
  692. // This trivial test checks if interface name is stored properly
  693. // in Subnet6 objects.
  694. TEST(Subnet6Test, iface) {
  695. Subnet6 subnet(IOAddress("2001:db8::"), 32, 1, 2, 3, 4);
  696. EXPECT_TRUE(subnet.getIface().empty());
  697. subnet.setIface("en1");
  698. EXPECT_EQ("en1", subnet.getIface());
  699. }
  700. // This trivial test checks if the interface-id option can be set and
  701. // later retrieved for a subnet6 object.
  702. TEST(Subnet6Test, interfaceId) {
  703. // Create as subnet to add options to it.
  704. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  705. EXPECT_FALSE(subnet->getInterfaceId());
  706. OptionPtr option(new Option(Option::V6, D6O_INTERFACE_ID, OptionBuffer(10, 0xFF)));
  707. subnet->setInterfaceId(option);
  708. EXPECT_EQ(option, subnet->getInterfaceId());
  709. }
  710. // Checks if last allocated address/prefix is stored/retrieved properly
  711. TEST(Subnet6Test, lastAllocated) {
  712. IOAddress ia("2001:db8:1::1");
  713. IOAddress ta("2001:db8:1::abcd");
  714. IOAddress pd("2001:db8:1::1234:5678");
  715. IOAddress last("2001:db8:1::ffff:ffff:ffff:ffff");
  716. Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 64, 1, 2, 3, 4));
  717. // Check initial conditions (all should be set to the last address in range)
  718. EXPECT_EQ(last.toText(), subnet->getLastAllocated(Lease::TYPE_NA).toText());
  719. EXPECT_EQ(last.toText(), subnet->getLastAllocated(Lease::TYPE_TA).toText());
  720. EXPECT_EQ(last.toText(), subnet->getLastAllocated(Lease::TYPE_PD).toText());
  721. // Now set last allocated for IA
  722. EXPECT_NO_THROW(subnet->setLastAllocated(Lease::TYPE_NA, ia));
  723. EXPECT_EQ(ia.toText(), subnet->getLastAllocated(Lease::TYPE_NA).toText());
  724. // TA and PD should be unchanged
  725. EXPECT_EQ(last.toText(), subnet->getLastAllocated(Lease::TYPE_TA).toText());
  726. EXPECT_EQ(last.toText(), subnet->getLastAllocated(Lease::TYPE_PD).toText());
  727. // Now set TA and PD
  728. EXPECT_NO_THROW(subnet->setLastAllocated(Lease::TYPE_TA, ta));
  729. EXPECT_NO_THROW(subnet->setLastAllocated(Lease::TYPE_PD, pd));
  730. EXPECT_EQ(ia.toText(), subnet->getLastAllocated(Lease::TYPE_NA).toText());
  731. EXPECT_EQ(ta.toText(), subnet->getLastAllocated(Lease::TYPE_TA).toText());
  732. EXPECT_EQ(pd.toText(), subnet->getLastAllocated(Lease::TYPE_PD).toText());
  733. // No, you can't set the last allocated IPv4 address in IPv6 subnet
  734. EXPECT_THROW(subnet->setLastAllocated(Lease::TYPE_V4, ia), BadValue);
  735. }
  736. };