option_copy_unittest.cc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. // Copyright (C) 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 <asiolink/io_address.h>
  8. #include <dhcp/dhcp6.h>
  9. #include <dhcp/opaque_data_tuple.h>
  10. #include <dhcp/option.h>
  11. #include <dhcp/option_custom.h>
  12. #include <dhcp/option_definition.h>
  13. #include <dhcp/option_int.h>
  14. #include <dhcp/option_int_array.h>
  15. #include <dhcp/option_opaque_data_tuples.h>
  16. #include <dhcp/option_string.h>
  17. #include <dhcp/option_vendor.h>
  18. #include <dhcp/option_vendor_class.h>
  19. #include <dhcp/option4_addrlst.h>
  20. #include <dhcp/option4_client_fqdn.h>
  21. #include <dhcp/option6_addrlst.h>
  22. #include <dhcp/option6_client_fqdn.h>
  23. #include <dhcp/option6_ia.h>
  24. #include <dhcp/option6_iaaddr.h>
  25. #include <dhcp/option6_iaprefix.h>
  26. #include <dhcp/option6_status_code.h>
  27. #include <util/buffer.h>
  28. #include <boost/pointer_cast.hpp>
  29. #include <gtest/gtest.h>
  30. using namespace std;
  31. using namespace isc;
  32. using namespace isc::asiolink;
  33. using namespace isc::dhcp;
  34. using namespace isc::util;
  35. namespace {
  36. /// @brief Type of the "copy" operation to be performed in a test.
  37. ///
  38. /// Possible operations are:
  39. /// - copy construction,
  40. /// - cloning with Option::clone,
  41. /// - assignment.
  42. enum OpType {
  43. COPY,
  44. CLONE,
  45. ASSIGN
  46. };
  47. /// @brief Generic test for deep copy of an option.
  48. ///
  49. /// This test can use one of the three supported operations to deep copy
  50. /// an option: copy construction, cloning or assignment.
  51. ///
  52. /// After copying the option the following parameters checked if they
  53. /// have been copied (copied by the Option class):
  54. /// - universe,
  55. /// - option type,
  56. /// - encapsulated space,
  57. /// - data.
  58. ///
  59. /// This test also checks that the sub options have been copied by checking
  60. /// that:
  61. /// - options' types match,
  62. /// - binary representations are equal,
  63. /// - pointers to the options are unequal (to make sure that the option has
  64. /// been copied, rather than the pointer).
  65. ///
  66. /// @param op_type Copy operation to be performed.
  67. /// @param option Source option.
  68. /// @param option_copy Destination option. Note that this option may be
  69. /// initially set to a non-null value. For the "copy" and "clone" operations
  70. /// the pointer will be reset, so there is no sense to initialize this
  71. /// object to a non-null value. However, for the assignment testing it is
  72. /// recommended to initialize the option_copy to point to an option having
  73. /// different parameters to verify that all parameters have been overridden
  74. /// by the assignment operation.
  75. template<typename OptionType>
  76. void testCopyAssign(const OpType& op_type,
  77. boost::shared_ptr<OptionType>& option,
  78. boost::shared_ptr<OptionType>& option_copy) {
  79. // Set the encapsulated to 'foo' because tests usually don't set that
  80. // value.
  81. option->setEncapsulatedSpace("foo");
  82. // Create two sub options of different types to later check that they
  83. // are copied.
  84. OptionUint16Ptr sub1 = OptionUint16Ptr(new OptionUint16(Option::V4, 10, 234));
  85. Option4AddrLstPtr sub2 =
  86. Option4AddrLstPtr(new Option4AddrLst(11, IOAddress("192.0.2.3")));
  87. option->addOption(sub1);
  88. option->addOption(sub2);
  89. // Copy option by copy construction, cloning or assignment.
  90. switch (op_type) {
  91. case COPY:
  92. option_copy.reset(new OptionType(*option));
  93. break;
  94. case CLONE:
  95. option_copy = boost::dynamic_pointer_cast<OptionType>(option->clone());
  96. ASSERT_TRUE(option_copy);
  97. break;
  98. case ASSIGN:
  99. option_copy->setEncapsulatedSpace("bar");
  100. *option_copy = *option;
  101. break;
  102. default:
  103. ADD_FAILURE() << "unsupported operation";
  104. return;
  105. }
  106. // Verify that basic parameters have been copied.
  107. EXPECT_EQ(option->getUniverse(), option_copy->getUniverse());
  108. EXPECT_EQ(option->getType(), option_copy->getType());
  109. EXPECT_EQ(option->len(), option_copy->len());
  110. EXPECT_EQ(option->getEncapsulatedSpace(), option_copy->getEncapsulatedSpace());
  111. EXPECT_TRUE(std::equal(option->getData().begin(), option->getData().end(),
  112. option_copy->getData().begin()));
  113. // Retrieve sub options so as they can be compared.
  114. const OptionCollection& option_subs = option->getOptions();
  115. const OptionCollection& option_copy_subs = option_copy->getOptions();
  116. ASSERT_EQ(option_subs.size(), option_copy_subs.size());
  117. // Iterate over source options.
  118. OptionCollection::const_iterator it_copy = option_copy_subs.begin();
  119. for (OptionCollection::const_iterator it = option_subs.begin();
  120. it != option_subs.end(); ++it, ++it_copy) {
  121. // The option codes should be equal in both containers.
  122. EXPECT_EQ(it->first, it_copy->first);
  123. // Pointers must be unequal because the expectation is that options
  124. // are copied, rather than pointers.
  125. EXPECT_NE(it->second, it_copy->second);
  126. Option* opt_ptr = it->second.get();
  127. Option* opt_copy_ptr = it_copy->second.get();
  128. // The C++ types must match.
  129. EXPECT_TRUE(typeid(*opt_ptr) == typeid(*opt_copy_ptr));
  130. }
  131. // Final check is to compare their binary representations.
  132. std::vector<uint8_t> buf = option->toBinary(true);
  133. std::vector<uint8_t> buf_copy = option_copy->toBinary(true);
  134. ASSERT_EQ(buf.size(), buf_copy.size());
  135. EXPECT_TRUE(std::equal(buf_copy.begin(), buf_copy.end(), buf.begin()));
  136. }
  137. // **************************** Option ***************************
  138. /// @brief Test deep copy of option encapsulated by Option type.
  139. ///
  140. /// @param op_type Copy operation type.
  141. void testOption(const OpType& op_type) {
  142. OptionBuffer buf(10, 1);
  143. OptionPtr option(new Option(Option::V4, 1, buf));
  144. OptionPtr option_copy(new Option(Option::V6, 1000));
  145. ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
  146. // Save binary representation of the original option. We will
  147. // be later comparing it with a copied option to make sure that
  148. // modification of the original option doesn't affect the copy.
  149. std::vector<uint8_t> binary_copy = option_copy->toBinary(true);
  150. // Modify the original option.
  151. OptionBuffer buf_modified(10, 2);
  152. option->setData(buf_modified.begin(), buf_modified.end());
  153. // Retrieve the binary representation of the copy to verify that
  154. // it hasn't been modified.
  155. std::vector<uint8_t> binary_copy_after = option_copy->toBinary(true);
  156. ASSERT_EQ(binary_copy.size(), binary_copy_after.size());
  157. EXPECT_TRUE(std::equal(binary_copy_after.begin(), binary_copy_after.end(),
  158. binary_copy.begin()));
  159. }
  160. TEST(OptionCopyTest, optionConstructor) {
  161. testOption(COPY);
  162. }
  163. TEST(OptionCopyTest, optionClone) {
  164. testOption(CLONE);
  165. }
  166. TEST(OptionCopyTest, optionAssignment) {
  167. testOption(ASSIGN);
  168. }
  169. // **************************** OptionInt ***************************
  170. /// @brief Test deep copy of option encapsulated by OptionInt type.
  171. ///
  172. /// @param op_type Copy operation type.
  173. void testOptionInt(const OpType& op_type) {
  174. OptionUint16Ptr option(new OptionUint16(Option::V4, 1, 12345));
  175. OptionUint16Ptr option_copy(new OptionUint16(Option::V6, 10, 11111));
  176. ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
  177. // Modify value in the original option.
  178. option->setValue(9);
  179. // The value in the copy should not be affected.
  180. EXPECT_EQ(12345, option_copy->getValue());
  181. }
  182. TEST(OptionCopyTest, optionIntConstructor) {
  183. testOptionInt(COPY);
  184. }
  185. TEST(OptionCopyTest, optionIntClone) {
  186. testOptionInt(CLONE);
  187. }
  188. TEST(OptionCopyTest, optionIntAssignment) {
  189. testOptionInt(ASSIGN);
  190. }
  191. // ************************* OptionIntArray ***************************
  192. /// @brief Test deep copy of option encapsulated by OptionIntArray type.
  193. ///
  194. /// @param op_type Copy operation type.
  195. void testOptionIntArray(const OpType& op_type) {
  196. OptionUint32ArrayPtr option(new OptionUint32Array(Option::V4, 1));;
  197. option->addValue(2345);
  198. option->addValue(3456);
  199. OptionUint32ArrayPtr option_copy(new OptionUint32Array(Option::V6, 10));
  200. option_copy->addValue(5678);
  201. option_copy->addValue(6789);
  202. ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
  203. // Modify the values in the original option.
  204. option->setValues(std::vector<uint32_t>(2, 7));
  205. // The values in the copy should not be affected.
  206. std::vector<uint32_t> values_copy = option_copy->getValues();
  207. ASSERT_EQ(2, values_copy.size());
  208. EXPECT_EQ(2345, values_copy[0]);
  209. EXPECT_EQ(3456, values_copy[1]);
  210. }
  211. TEST(OptionCopyTest, optionIntArrayConstructor) {
  212. testOptionIntArray(COPY);
  213. }
  214. TEST(OptionCopyTest, optionIntArrayClone) {
  215. testOptionIntArray(CLONE);
  216. }
  217. TEST(OptionCopyTest, optionIntArrayAssignment) {
  218. testOptionIntArray(ASSIGN);
  219. }
  220. // ************************* Option4AddrLst ***************************
  221. /// @brief Test deep copy of option encapsulated by Option4AddrLst or
  222. /// Option6AddrLst type.
  223. ///
  224. /// @param op_type Copy operation type.
  225. /// @param option_address Address carried in the source option.
  226. /// @param option_copy_address Address carried in the destination option.
  227. /// @param option_modified_address Address to which the original address
  228. /// is modified to check that this modification doesn't affect option
  229. /// copy.
  230. /// @tparam OptionType Option4AddrLst or Option6AddrLst.
  231. template<typename OptionType>
  232. void testOptionAddrLst(const OpType& op_type,
  233. const IOAddress& option_address,
  234. const IOAddress& option_copy_address,
  235. const IOAddress& option_modified_address) {
  236. typedef boost::shared_ptr<OptionType> OptionTypePtr;
  237. OptionTypePtr option(new OptionType(1, option_address));
  238. OptionTypePtr option_copy(new OptionType(10, option_copy_address));
  239. ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
  240. // Modify the address in the original option.
  241. option->setAddress(option_modified_address);
  242. // The address in the copy should not be affected.
  243. typename OptionType::AddressContainer addrs_copy = option_copy->getAddresses();
  244. ASSERT_EQ(1, addrs_copy.size());
  245. EXPECT_EQ(option_address.toText(), addrs_copy[0].toText());
  246. }
  247. /// @brief Test deep copy of option encapsulated by Option4AddrLst type.
  248. ///
  249. /// @param op_type Copy operation type.
  250. void testOption4AddrLst(const OpType& op_type) {
  251. testOptionAddrLst<Option4AddrLst>(op_type,
  252. IOAddress("127.0.0.1"),
  253. IOAddress("192.0.2.111"),
  254. IOAddress("127.0.0.1"));
  255. }
  256. TEST(OptionCopyTest, option4AddrLstConstructor) {
  257. testOption4AddrLst(COPY);
  258. }
  259. TEST(OptionCopyTest, option4AddrLstClone) {
  260. testOption4AddrLst(CLONE);
  261. }
  262. TEST(OptionCopyTest, option4AddrLstAssignment) {
  263. testOption4AddrLst(ASSIGN);
  264. }
  265. // ************************* Option6AddrLst ***************************
  266. /// @brief Test deep copy of option encapsulated by Option6AddrLst type.
  267. ///
  268. /// @param op_type Copy operation type.
  269. void testOption6AddrLst(const OpType& op_type) {
  270. testOptionAddrLst<Option6AddrLst>(op_type,
  271. IOAddress("2001:db8:1::2"),
  272. IOAddress("3001::cafe"),
  273. IOAddress("3000:1::1"));
  274. }
  275. TEST(OptionCopyTest, option6AddrLstConstructor) {
  276. testOption6AddrLst(COPY);
  277. }
  278. TEST(OptionCopyTest, option6AddrLstClone) {
  279. testOption6AddrLst(CLONE);
  280. }
  281. TEST(OptionCopyTest, option6AddrLstAssignment) {
  282. testOption6AddrLst(ASSIGN);
  283. }
  284. // *************************** Option6IA ***************************
  285. /// @brief Test deep copy of option encapsulated by Option6IA type.
  286. ///
  287. /// @param op_type Copy operation type.
  288. void testOption6IA(const OpType& op_type) {
  289. Option6IAPtr option(new Option6IA(D6O_IA_NA, 1234));
  290. option->setT1(1000);
  291. option->setT2(2000);
  292. Option6IAPtr option_copy(new Option6IA(D6O_IA_PD, 5678));
  293. ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
  294. // Modify the values in the original option.
  295. option->setT1(3000);
  296. option->setT2(4000);
  297. option->setIAID(5678);
  298. // The values in the copy should not be affected.
  299. EXPECT_EQ(1000, option_copy->getT1());
  300. EXPECT_EQ(2000, option_copy->getT2());
  301. EXPECT_EQ(1234, option_copy->getIAID());
  302. }
  303. TEST(OptionCopyTest, option6IAConstructor) {
  304. testOption6IA(COPY);
  305. }
  306. TEST(OptionCopyTest, option6IAClone) {
  307. testOption6IA(CLONE);
  308. }
  309. TEST(OptionCopyTest, option6IAAssignment) {
  310. testOption6IA(ASSIGN);
  311. }
  312. // *************************** Option6IAAddr ***************************
  313. /// @brief Test deep copy of option encapsulated by Option6IAAddr type.
  314. ///
  315. /// @param op_type Copy operation type.
  316. void testOption6IAAddr(const OpType& op_type) {
  317. Option6IAAddrPtr option(new Option6IAAddr(D6O_IAADDR,
  318. IOAddress("2001:db8:1::1"),
  319. 60, 90));
  320. Option6IAAddrPtr option_copy(new Option6IAAddr(D6O_IAADDR,
  321. IOAddress("2001:db8:1::2"),
  322. 50, 80));
  323. ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
  324. // Modify the values in the original option.
  325. option->setAddress(IOAddress("2001:db8:1::3"));
  326. option->setPreferred(1000);
  327. option->setValid(2000);
  328. // The values in the copy should not be affected.
  329. EXPECT_EQ("2001:db8:1::1", option_copy->getAddress().toText());
  330. EXPECT_EQ(60, option_copy->getPreferred());
  331. EXPECT_EQ(90, option_copy->getValid());
  332. }
  333. TEST(OptionCopyTest, option6IAAddrConstructor) {
  334. testOption6IAAddr(COPY);
  335. }
  336. TEST(OptionCopyTest, option6IAAddrClone) {
  337. testOption6IAAddr(CLONE);
  338. }
  339. TEST(OptionCopyTest, option6IAAddrAssignment) {
  340. testOption6IAAddr(ASSIGN);
  341. }
  342. // *************************** Option6IAPrefix ***************************
  343. /// @brief Test deep copy of option encapsulated by Option6IAPrefix type.
  344. ///
  345. /// @param op_type Copy operation type.
  346. void testOption6IAPrefix(const OpType& op_type) {
  347. Option6IAPrefixPtr option(new Option6IAPrefix(D6O_IAPREFIX,
  348. IOAddress("3000::"),
  349. 64, 60, 90));
  350. Option6IAPrefixPtr option_copy(new Option6IAPrefix(D6O_IAPREFIX,
  351. IOAddress("3001::"),
  352. 48, 50, 80));
  353. ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
  354. // Modify the values in the original option.
  355. option->setPrefix(IOAddress("3002::"), 32);
  356. option->setPreferred(1000);
  357. option->setValid(2000);
  358. // The values in the copy should not be affected.
  359. EXPECT_EQ("3000::", option_copy->getAddress().toText());
  360. EXPECT_EQ(64, option_copy->getLength());
  361. EXPECT_EQ(60, option_copy->getPreferred());
  362. EXPECT_EQ(90, option_copy->getValid());
  363. }
  364. TEST(OptionCopyTest, option6IAPrefixConstructor) {
  365. testOption6IAPrefix(COPY);
  366. }
  367. TEST(OptionCopyTest, option6IAPrefixClone) {
  368. testOption6IAPrefix(CLONE);
  369. }
  370. TEST(OptionCopyTest, option6IAPrefixAssignment) {
  371. testOption6IAPrefix(ASSIGN);
  372. }
  373. // *************************** Option6StatusCode ***************************
  374. /// @brief Test deep copy of option encapsulated by Option6StatusCode type.
  375. ///
  376. /// @param op_type Copy operation type.
  377. void testOption6StatusCode(const OpType& op_type) {
  378. Option6StatusCodePtr option(new Option6StatusCode(STATUS_NoBinding,
  379. "no binding"));
  380. Option6StatusCodePtr option_copy(new Option6StatusCode(STATUS_Success,
  381. "success"));
  382. ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
  383. // Modify the values in the original option.
  384. option->setStatusCode(STATUS_NoAddrsAvail);
  385. option->setStatusMessage("foo");
  386. // The values in the copy should not be affected.
  387. EXPECT_EQ(STATUS_NoBinding, option_copy->getStatusCode());
  388. EXPECT_EQ("no binding", option_copy->getStatusMessage());
  389. }
  390. TEST(OptionCopyTest, option6StatusCodeConstructor) {
  391. testOption6StatusCode(COPY);
  392. }
  393. TEST(OptionCopyTest, option6StatusCodeClone) {
  394. testOption6StatusCode(CLONE);
  395. }
  396. TEST(OptionCopyTest, option6StatusCodeAssignment) {
  397. testOption6StatusCode(ASSIGN);
  398. }
  399. // *************************** OptionString ***************************
  400. /// @brief Test deep copy of option encapsulated by OptionString type.
  401. ///
  402. /// @param op_type Copy operation type.
  403. void testOptionString(const OpType& op_type) {
  404. OptionStringPtr option(new OptionString(Option::V4, 1, "option value"));
  405. OptionStringPtr option_copy(new OptionString(Option::V6, 10,
  406. "another value"));
  407. ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
  408. // Modify the string in the original option.
  409. option->setValue("foo");
  410. // The string in the copy should not be affected.
  411. EXPECT_EQ("option value", option_copy->getValue());
  412. }
  413. TEST(OptionCopyTest, optionStringConstructor) {
  414. testOptionString(COPY);
  415. }
  416. TEST(OptionCopyTest, optionStringClone) {
  417. testOptionString(CLONE);
  418. }
  419. TEST(OptionCopyTest, optionStringAssignment) {
  420. testOptionString(ASSIGN);
  421. }
  422. // *************************** OptionVendor ***************************
  423. /// @brief Test deep copy of option encapsulated by OptionVendor type.
  424. ///
  425. /// @param op_type Copy operation type.
  426. void testOptionVendor(const OpType& op_type) {
  427. OptionVendorPtr option(new OptionVendor(Option::V4, 2986));
  428. OptionVendorPtr option_copy(new OptionVendor(Option::V6, 1111));
  429. ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
  430. // Modify the vendor id in the original option.
  431. option->setVendorId(2222);
  432. // The vendor id in the copy should not be affected.
  433. EXPECT_EQ(2986, option_copy->getVendorId());
  434. }
  435. TEST(OptionCopyTest, optionVendorConstructor) {
  436. testOptionVendor(COPY);
  437. }
  438. TEST(OptionCopyTest, optionVendorClone) {
  439. testOptionVendor(CLONE);
  440. }
  441. TEST(OptionCopyTest, optionVendorAssignment) {
  442. testOptionVendor(ASSIGN);
  443. }
  444. // *********************** OptionVendorClass ***************************
  445. /// @brief Test deep copy of option encapsulated by OptionVendorClass type.
  446. ///
  447. /// @param op_type Copy operation type.
  448. void testOptionVendorClass(const OpType& op_type) {
  449. // Create a DHCPv4 option with a single tuple.
  450. OptionVendorClassPtr option(new OptionVendorClass(Option::V4, 2986));
  451. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
  452. tuple = "vendor-class-value";
  453. option->setTuple(0, tuple);
  454. // Create a DHCPv6 option with a single tuple.
  455. OptionVendorClassPtr option_copy(new OptionVendorClass(Option::V6,
  456. 1111));
  457. OpaqueDataTuple tuple_copy(OpaqueDataTuple::LENGTH_2_BYTES);
  458. tuple = "vendor-class-assigned";
  459. option_copy->addTuple(tuple_copy);
  460. ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
  461. // Modify the tuple in the original option and add one more tuple.
  462. tuple = "modified-vendor-class-value";
  463. option->setTuple(0, tuple);
  464. tuple = "another-modified-vendor-class-value";
  465. option->addTuple(tuple);
  466. // That change shouldn't affect the original option. It should still
  467. // contain a single tuple with the original value.
  468. ASSERT_EQ(1, option_copy->getTuplesNum());
  469. tuple = option_copy->getTuple(0);
  470. EXPECT_TRUE(tuple.equals("vendor-class-value"));
  471. }
  472. TEST(OptionCopyTest, optionVendorClassConstructor) {
  473. testOptionVendorClass(COPY);
  474. }
  475. TEST(OptionCopyTest, optionVendorClassClone) {
  476. testOptionVendorClass(CLONE);
  477. }
  478. TEST(OptionCopyTest, optionVendorClassAssignment) {
  479. testOptionVendorClass(ASSIGN);
  480. }
  481. // ************************** Option4ClientFqdn ***************************
  482. /// @brief Test deep copy of option encapsulated by Option4ClientFqdn or
  483. /// Option6ClientFqdn type.
  484. ///
  485. /// @param op_type Copy operation type.
  486. /// @param option Option to be copied.
  487. /// @param option_copy Destination option. Note that this option may be
  488. /// initially set to a non-null value. For the "copy" and "clone" operations
  489. /// the pointer will be reset, so there is no sense to initialize this
  490. /// object to a non-null value. However, for the assignment testing it is
  491. /// recommended to initialize the option_copy to point to an option having
  492. /// different parameters to verify that all parameters have been overridden
  493. /// by the assignment operation.
  494. ///
  495. /// @tparam OptionType Option4ClientFqdn or Option6ClientFqdn.
  496. template<typename OptionType>
  497. void testOptionClientFqdn(const OpType& op_type,
  498. boost::shared_ptr<OptionType>& option,
  499. boost::shared_ptr<OptionType>& option_copy) {
  500. ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
  501. // Modify the values in the original option.
  502. option->setDomainName("newname", OptionType::PARTIAL);
  503. option->setFlag(OptionType::FLAG_S, false);
  504. option->setFlag(OptionType::FLAG_N, true);
  505. // Rcode is carried on the in the DHCPv4 Client FQDN option.
  506. // If the OptionType is pointing to a DHCPv6 option the dynamic
  507. // cast will result in NULL pointer and we'll not check the
  508. // RCODE.
  509. Option4ClientFqdnPtr option4 =
  510. boost::dynamic_pointer_cast<Option4ClientFqdn>(option);
  511. if (option4) {
  512. option4->setRcode(64);
  513. }
  514. // Verify that common parameters haven't been modified in the
  515. // copied option by the change in the original option.
  516. EXPECT_EQ("myname.example.org.", option_copy->getDomainName());
  517. EXPECT_EQ(OptionType::FULL, option_copy->getDomainNameType());
  518. EXPECT_TRUE(option_copy->getFlag(OptionType::FLAG_S));
  519. EXPECT_FALSE(option_copy->getFlag(OptionType::FLAG_N));
  520. // If we're dealing with DHCPv4 Client FQDN, we also need to
  521. // test RCODE.
  522. Option4ClientFqdnPtr option_copy4 =
  523. boost::dynamic_pointer_cast<Option4ClientFqdn>(option_copy);
  524. if (option_copy4) {
  525. EXPECT_EQ(255, option_copy4->getRcode().first.getCode());
  526. EXPECT_EQ(255, option_copy4->getRcode().second.getCode());
  527. }
  528. }
  529. /// @brief Test deep copy of option encapsulated by Option4ClientFqdn type.
  530. ///
  531. /// @param op_type Copy operation type.
  532. void testOption4ClientFqdn(const OpType& op_type) {
  533. Option4ClientFqdnPtr
  534. option(new Option4ClientFqdn(Option4ClientFqdn::FLAG_S,
  535. Option4ClientFqdn::Rcode(255),
  536. "myname.example.org"));
  537. Option4ClientFqdnPtr
  538. option_copy(new Option4ClientFqdn(Option4ClientFqdn::FLAG_O,
  539. Option4ClientFqdn::Rcode(0),
  540. "other.example.org"));
  541. ASSERT_NO_FATAL_FAILURE(testOptionClientFqdn<Option4ClientFqdn>(op_type, option,
  542. option_copy));
  543. }
  544. TEST(OptionCopyTest, option4ClientFqdnConstructor) {
  545. testOption4ClientFqdn(COPY);
  546. }
  547. TEST(OptionCopyTest, option4ClientFqdnClone) {
  548. testOption4ClientFqdn(CLONE);
  549. }
  550. TEST(OptionCopyTest, option4ClientFqdnAssignment) {
  551. testOption4ClientFqdn(ASSIGN);
  552. }
  553. // ************************** Option6ClientFqdn ***************************
  554. /// @brief Test deep copy of option encapsulated by Option6ClientFqdn type.
  555. ///
  556. /// @param op_type Copy operation type.
  557. void testOption6ClientFqdn(const OpType& op_type) {
  558. Option6ClientFqdnPtr
  559. option(new Option6ClientFqdn(Option6ClientFqdn::FLAG_S,
  560. "myname.example.org"));
  561. Option6ClientFqdnPtr
  562. option_copy(new Option6ClientFqdn(Option6ClientFqdn::FLAG_O,
  563. "other.example.org"));
  564. ASSERT_NO_FATAL_FAILURE(testOptionClientFqdn<Option6ClientFqdn>(op_type, option,
  565. option_copy));
  566. }
  567. TEST(OptionCopyTest, option6ClientFqdnConstructor) {
  568. testOption6ClientFqdn(COPY);
  569. }
  570. TEST(OptionCopyTest, option6ClientFqdnClone) {
  571. testOption6ClientFqdn(CLONE);
  572. }
  573. TEST(OptionCopyTest, option6ClientFqdnAssignment) {
  574. testOption6ClientFqdn(ASSIGN);
  575. }
  576. // **************************** OptionCustom ***************************
  577. /// @brief Test deep copy of option encapsulated by OptionCustom type.
  578. ///
  579. /// @param op_type Copy operation type.
  580. void testOptionCustom(const OpType& op_type) {
  581. // Create option with a single field carrying 16-bits integer.
  582. OptionDefinition def("foo", 1, "uint16", true);
  583. OptionCustomPtr option(new OptionCustom(def, Option::V4));
  584. option->addArrayDataField<uint16_t>(5555);
  585. // Create option with two fields carrying IPv4 address and 32-bit
  586. // integer.
  587. OptionDefinition def_copy("bar", 10, "record");
  588. def_copy.addRecordField("ipv4-address");
  589. def_copy.addRecordField("uint32");
  590. OptionCustomPtr option_copy(new OptionCustom(def_copy, Option::V6));
  591. option_copy->writeAddress(IOAddress("192.0.0.2"));
  592. option_copy->writeInteger<uint32_t>(12, 1);
  593. ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
  594. // Modify the original option value.
  595. option->writeInteger<uint16_t>(1000);
  596. // The copied option should not be affected.
  597. ASSERT_EQ(1, option_copy->getDataFieldsNum());
  598. EXPECT_EQ(5555, option_copy->readInteger<uint16_t>());
  599. }
  600. TEST(OptionCopyTest, optionCustomConstructor) {
  601. testOptionCustom(COPY);
  602. }
  603. TEST(OptionCopyTest, optionCustomClone) {
  604. testOptionCustom(CLONE);
  605. }
  606. TEST(OptionCopyTest, optionCustomAssignment) {
  607. testOptionCustom(ASSIGN);
  608. }
  609. // ************************ OptionOpaqueDataTuples ***********************
  610. /// @brief Test deep copy of option encapsulated by OptionOpaqueDataTuples type.
  611. ///
  612. /// @param op_type Copy operation type.
  613. void testOptionOpaqueDataTuples(const OpType& op_type) {
  614. OptionOpaqueDataTuplesPtr option(new OptionOpaqueDataTuples(Option::V4, 1));
  615. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
  616. tuple = "a string";
  617. option->addTuple(tuple);
  618. tuple = "another string";
  619. option->addTuple(tuple);
  620. OptionOpaqueDataTuplesPtr option_copy(new OptionOpaqueDataTuples(Option::V6, 10));
  621. OpaqueDataTuple tuple_copy(OpaqueDataTuple::LENGTH_2_BYTES);
  622. tuple_copy = "copy string";
  623. option_copy->addTuple(tuple_copy);
  624. ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
  625. // Modify the value in the first tuple and add one more tuple.
  626. tuple = "modified-first-tuple";
  627. option->setTuple(0, tuple);
  628. tuple = "modified-second-tuple";
  629. option->setTuple(1, tuple);
  630. // This should not affect the values in the original option.
  631. ASSERT_EQ(2, option_copy->getTuplesNum());
  632. EXPECT_TRUE(option_copy->getTuple(0).equals("a string"));
  633. EXPECT_TRUE(option_copy->getTuple(1).equals("another string"));
  634. }
  635. TEST(OptionCopyTest, optionOpaqueDataTuplesConstructor) {
  636. testOptionOpaqueDataTuples(COPY);
  637. }
  638. TEST(OptionCopyTest, optionOpaqueDataTuplesClone) {
  639. testOptionOpaqueDataTuples(CLONE);
  640. }
  641. TEST(OptionCopyTest, optionOpaqueDataTuplesAssign) {
  642. testOptionOpaqueDataTuples(ASSIGN);
  643. }
  644. }