option_unittest.cc 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. // Copyright (C) 2011 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 <iostream>
  16. #include <sstream>
  17. #include <arpa/inet.h>
  18. #include <gtest/gtest.h>
  19. #include <boost/shared_ptr.hpp>
  20. #include "dhcp/dhcp6.h"
  21. #include "dhcp/option.h"
  22. using namespace std;
  23. using namespace isc;
  24. using namespace isc::dhcp;
  25. namespace {
  26. class OptionTest : public ::testing::Test {
  27. public:
  28. OptionTest() {
  29. }
  30. };
  31. // v4 is not really implemented yet. A simple test will do for now
  32. TEST_F(OptionTest, basic4) {
  33. Option* opt = new Option(Option::V4, 17);
  34. EXPECT_EQ(17, opt->getType());
  35. EXPECT_EQ(NULL, opt->getData());
  36. EXPECT_EQ(2, opt->len()); // just v4 header
  37. EXPECT_NO_THROW(
  38. delete opt;
  39. );
  40. }
  41. // tests simple constructor
  42. TEST_F(OptionTest, basic6) {
  43. Option* opt = new Option(Option::V6, 1);
  44. EXPECT_EQ(1, opt->getType());
  45. EXPECT_EQ(NULL, opt->getData());
  46. EXPECT_EQ(4, opt->len()); // just v6 header
  47. EXPECT_NO_THROW(
  48. delete opt;
  49. );
  50. }
  51. // tests contructor used in pkt reception
  52. // option contains actual data
  53. TEST_F(OptionTest, data1) {
  54. boost::shared_array<uint8_t> buf(new uint8_t[32]);
  55. for (int i = 0; i < 32; i++)
  56. buf[i] = 100+i;
  57. Option* opt = new Option(Option::V6, 333, //type
  58. buf,
  59. 3, // offset
  60. 7); // 7 bytes of data
  61. EXPECT_EQ(333, opt->getType());
  62. ASSERT_EQ(&buf[3], opt->getData());
  63. ASSERT_EQ(11, opt->len());
  64. EXPECT_EQ(0, memcmp(&buf[3], opt->getData(), 7) );
  65. int offset = opt->pack(buf, 32, 20);
  66. EXPECT_EQ(31, offset);
  67. EXPECT_EQ(buf[20], 333/256); // type
  68. EXPECT_EQ(buf[21], 333%256);
  69. EXPECT_EQ(buf[22], 0); // len
  70. EXPECT_EQ(buf[23], 7);
  71. // payload
  72. EXPECT_EQ(0, memcmp(&buf[3], &buf[24], 7) );
  73. EXPECT_NO_THROW(
  74. delete opt;
  75. );
  76. }
  77. // another text that tests the same thing, just
  78. // with different input parameters
  79. TEST_F(OptionTest, data2) {
  80. boost::shared_array<uint8_t> simple_buf(new uint8_t[128]);
  81. for (int i = 0; i < 128; i++)
  82. simple_buf[i] = 0;
  83. simple_buf[0] = 0xa1;
  84. simple_buf[1] = 0xa2;
  85. simple_buf[2] = 0xa3;
  86. simple_buf[3] = 0xa4;
  87. // create an option (unpack content)
  88. Option* opt = new Option(Option::V6,
  89. D6O_CLIENTID,
  90. simple_buf,
  91. 0,
  92. 4);
  93. // pack this option again in the same buffer, but in
  94. // different place
  95. int offset18 = opt->pack(simple_buf, 128, 10);
  96. // 4 bytes header + 4 bytes content
  97. EXPECT_EQ(8, opt->len());
  98. EXPECT_EQ(D6O_CLIENTID, opt->getType());
  99. EXPECT_EQ(offset18, 18);
  100. // check if pack worked properly:
  101. // if option type is correct
  102. EXPECT_EQ(D6O_CLIENTID, simple_buf[10]*256 + simple_buf[11]);
  103. // if option length is correct
  104. EXPECT_EQ(4, simple_buf[12]*256 + simple_buf[13]);
  105. // if option content is correct
  106. EXPECT_EQ(0, memcmp(&simple_buf[0], &simple_buf[14],4));
  107. EXPECT_NO_THROW(
  108. delete opt;
  109. );
  110. }
  111. // check that an option can contain 2 suboptions:
  112. // opt1
  113. // +----opt2
  114. // |
  115. // +----opt3
  116. //
  117. TEST_F(OptionTest, suboptions1) {
  118. boost::shared_array<uint8_t> buf(new uint8_t[128]);
  119. for (int i=0; i<128; i++)
  120. buf[i] = 100+i;
  121. Option* opt1 = new Option(Option::V6, 65535, //type
  122. buf,
  123. 0, // offset
  124. 3); // 3 bytes of data
  125. boost::shared_ptr<Option> opt2(new Option(Option::V6, 13));
  126. boost::shared_ptr<Option> opt3(new Option(Option::V6, 7,
  127. buf,
  128. 3, // offset
  129. 5)); // 5 bytes of data
  130. opt1->addOption(opt2);
  131. opt1->addOption(opt3);
  132. // opt2 len = 4 (just header)
  133. // opt3 len = 9 4(header)+5(data)
  134. // opt1 len = 7 + suboptions() = 7 + 4 + 9 = 20
  135. EXPECT_EQ(4, opt2->len());
  136. EXPECT_EQ(9, opt3->len());
  137. EXPECT_EQ(20, opt1->len());
  138. uint8_t expected[] = {
  139. 0xff, 0xff, 0, 16, 100, 101, 102,
  140. 0, 7, 0, 5, 103, 104, 105, 106, 107,
  141. 0, 13, 0, 0 // no data at all
  142. };
  143. int offset = opt1->pack(buf, 128, 20);
  144. EXPECT_EQ(40, offset);
  145. // payload
  146. EXPECT_EQ(0, memcmp(&buf[20], expected, 20) );
  147. EXPECT_NO_THROW(
  148. delete opt1;
  149. );
  150. }
  151. // check that an option can contain 2 suboptions:
  152. // opt1
  153. // +----opt2
  154. // |
  155. // +----opt3
  156. //
  157. TEST_F(OptionTest, suboptions2) {
  158. boost::shared_array<uint8_t> buf(new uint8_t[128]);
  159. for (int i=0; i<128; i++)
  160. buf[i] = 100+i;
  161. Option* opt1 = new Option(Option::V6, 65535, //type
  162. buf,
  163. 0, // offset
  164. 3); // 3 bytes of data
  165. boost::shared_ptr<Option> opt2(new Option(Option::V6, 13));
  166. boost::shared_ptr<Option> opt3(new Option(Option::V6, 7,
  167. buf,
  168. 3, // offset
  169. 5)); // 5 bytes of data
  170. opt1->addOption(opt2);
  171. opt2->addOption(opt3);
  172. // opt3 len = 9 4(header)+5(data)
  173. // opt2 len = 4 (just header) + len(opt3)
  174. // opt1 len = 7 + len(opt2)
  175. uint8_t expected[] = {
  176. 0xff, 0xff, 0, 16, 100, 101, 102,
  177. 0, 13, 0, 9,
  178. 0, 7, 0, 5, 103, 104, 105, 106, 107,
  179. };
  180. int offset = opt1->pack(buf, 128, 20);
  181. EXPECT_EQ(40, offset);
  182. // payload
  183. EXPECT_EQ(0, memcmp(&buf[20], expected, 20) );
  184. EXPECT_NO_THROW(
  185. delete opt1;
  186. );
  187. }
  188. TEST_F(OptionTest, addgetdel) {
  189. boost::shared_array<uint8_t> buf(new uint8_t[128]);
  190. for (int i=0; i<128; i++)
  191. buf[i] = 100+i;
  192. Option* parent = new Option(Option::V6, 65535); //type
  193. boost::shared_ptr<Option> opt1(new Option(Option::V6, 1));
  194. boost::shared_ptr<Option> opt2(new Option(Option::V6, 2));
  195. boost::shared_ptr<Option> opt3(new Option(Option::V6, 2));
  196. parent->addOption(opt1);
  197. parent->addOption(opt2);
  198. // getOption() test
  199. EXPECT_EQ(opt1, parent->getOption(1));
  200. EXPECT_EQ(opt2, parent->getOption(2));
  201. // expect NULL
  202. EXPECT_EQ(boost::shared_ptr<Option>(), parent->getOption(4));
  203. // now there are 2 options of type 2
  204. parent->addOption(opt3);
  205. // let's delete one of them
  206. EXPECT_EQ(true, parent->delOption(2));
  207. // there still should be the other option 2
  208. EXPECT_NE(boost::shared_ptr<Option>(), parent->getOption(2));
  209. // let's delete the other option 2
  210. EXPECT_EQ(true, parent->delOption(2));
  211. // no more options with type=2
  212. EXPECT_EQ(boost::shared_ptr<Option>(), parent->getOption(2));
  213. // let's try to delete - should fail
  214. EXPECT_TRUE(false == parent->delOption(2));
  215. }
  216. }
  217. TEST_F(OptionTest, toText) {
  218. boost::shared_array<uint8_t> buf(new uint8_t[3]);
  219. buf[0] = 0;
  220. buf[1] = 0xf;
  221. buf[2] = 0xff;
  222. boost::shared_ptr<Option> opt(new Option(Option::V6, 258,
  223. buf, 0, 3));
  224. EXPECT_EQ("type=258, len=3: 00:0f:ff", opt->toText());
  225. }