libdhcp_unittest.cc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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 <util/buffer.h>
  20. #include <dhcp/libdhcp.h>
  21. #include "config.h"
  22. using namespace std;
  23. using namespace isc;
  24. using namespace isc::dhcp;
  25. using namespace isc::util;
  26. namespace {
  27. class LibDhcpTest : public ::testing::Test {
  28. public:
  29. LibDhcpTest() {
  30. }
  31. };
  32. static const uint8_t packed[] = {
  33. 0, 12, 0, 5, 100, 101, 102, 103, 104, // opt1 (9 bytes)
  34. 0, 13, 0, 3, 105, 106, 107, // opt2 (7 bytes)
  35. 0, 14, 0, 2, 108, 109, // opt3 (6 bytes)
  36. 1, 0, 0, 4, 110, 111, 112, 113, // opt4 (8 bytes)
  37. 1, 1, 0, 1, 114 // opt5 (5 bytes)
  38. };
  39. TEST(LibDhcpTest, packOptions6) {
  40. boost::shared_array<uint8_t> buf(new uint8_t[512]);
  41. isc::dhcp::Option::Option6Collection opts; // list of options
  42. // generate content for options
  43. for (int i = 0; i < 64; i++) {
  44. buf[i]=i+100;
  45. }
  46. boost::shared_ptr<Option> opt1(new Option(Option::V6, 12, buf, 0, 5));
  47. boost::shared_ptr<Option> opt2(new Option(Option::V6, 13, buf, 5, 3));
  48. boost::shared_ptr<Option> opt3(new Option(Option::V6, 14, buf, 8, 2));
  49. boost::shared_ptr<Option> opt4(new Option(Option::V6,256, buf,10, 4));
  50. boost::shared_ptr<Option> opt5(new Option(Option::V6,257, buf,14, 1));
  51. opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt1));
  52. opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt2));
  53. opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt3));
  54. opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt4));
  55. opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt5));
  56. unsigned int offset;
  57. EXPECT_NO_THROW ({
  58. offset = LibDHCP::packOptions6(buf, 512, 100, opts);
  59. });
  60. EXPECT_EQ(135, offset); // options should take 35 bytes
  61. EXPECT_EQ(0, memcmp(&buf[100], packed, 35) );
  62. }
  63. TEST(LibDhcpTest, unpackOptions6) {
  64. // just couple of random options
  65. // Option is used as a simple option implementation
  66. // More advanced uses are validated in tests dedicated for
  67. // specific derived classes.
  68. isc::dhcp::Option::Option6Collection options; // list of options
  69. // we can't use packed directly, as shared_array would try to
  70. // free it eventually
  71. boost::shared_array<uint8_t> buf(new uint8_t[512]);
  72. memcpy(&buf[0], packed, 35);
  73. unsigned int offset;
  74. EXPECT_NO_THROW ({
  75. offset = LibDHCP::unpackOptions6(buf, 512, 0, 35, options);
  76. });
  77. EXPECT_EQ(35, offset); // parsed first 35 bytes (offset 0..34)
  78. EXPECT_EQ(options.size(), 5); // there should be 5 options
  79. isc::dhcp::Option::Option6Collection::const_iterator x = options.find(12);
  80. ASSERT_FALSE(x == options.end()); // option 1 should exist
  81. EXPECT_EQ(12, x->second->getType()); // this should be option 12
  82. ASSERT_EQ(9, x->second->len()); // it should be of length 9
  83. EXPECT_EQ(0, memcmp(&x->second->getData()[0], packed+4, 5)); // data len=5
  84. x = options.find(13);
  85. ASSERT_FALSE(x == options.end()); // option 13 should exist
  86. EXPECT_EQ(13, x->second->getType()); // this should be option 13
  87. ASSERT_EQ(7, x->second->len()); // it should be of length 7
  88. EXPECT_EQ(0, memcmp(&x->second->getData()[0], packed+13, 3)); // data len=3
  89. x = options.find(14);
  90. ASSERT_FALSE(x == options.end()); // option 3 should exist
  91. EXPECT_EQ(14, x->second->getType()); // this should be option 14
  92. ASSERT_EQ(6, x->second->len()); // it should be of length 6
  93. EXPECT_EQ(0, memcmp(&x->second->getData()[0], packed+20, 2)); // data len=2
  94. x = options.find(256);
  95. ASSERT_FALSE(x == options.end()); // option 256 should exist
  96. EXPECT_EQ(256, x->second->getType()); // this should be option 256
  97. ASSERT_EQ(8, x->second->len()); // it should be of length 7
  98. EXPECT_EQ(0, memcmp(&x->second->getData()[0], packed+26, 4)); // data len=4
  99. x = options.find(257);
  100. ASSERT_FALSE(x == options.end()); // option 257 should exist
  101. EXPECT_EQ(257, x->second->getType()); // this should be option 257
  102. ASSERT_EQ(5, x->second->len()); // it should be of length 5
  103. EXPECT_EQ(0, memcmp(&x->second->getData()[0], packed+34, 1)); // data len=1
  104. x = options.find(0);
  105. EXPECT_TRUE(x == options.end()); // option 0 not found
  106. x = options.find(1); // 1 is htons(256) on little endians. Worth checking
  107. EXPECT_TRUE(x == options.end()); // option 1 not found
  108. x = options.find(2);
  109. EXPECT_TRUE(x == options.end()); // option 2 not found
  110. x = options.find(32000);
  111. EXPECT_TRUE(x == options.end()); // option 32000 not found
  112. }
  113. static uint8_t v4Opts[] = {
  114. 12, 3, 0, 1, 2,
  115. 13, 3, 10, 11, 12,
  116. 14, 3, 20, 21, 22,
  117. 254, 3, 30, 31, 32,
  118. 128, 3, 40, 41, 42
  119. };
  120. TEST(LibDhcpTest, packOptions4) {
  121. vector<uint8_t> payload[5];
  122. for (int i = 0; i < 5; i++) {
  123. payload[i].resize(3);
  124. payload[i][0] = i*10;
  125. payload[i][1] = i*10+1;
  126. payload[i][2] = i*10+2;
  127. }
  128. boost::shared_ptr<Option> opt1(new Option(Option::V4, 12, payload[0]));
  129. boost::shared_ptr<Option> opt2(new Option(Option::V4, 13, payload[1]));
  130. boost::shared_ptr<Option> opt3(new Option(Option::V4, 14, payload[2]));
  131. boost::shared_ptr<Option> opt4(new Option(Option::V4,254, payload[3]));
  132. boost::shared_ptr<Option> opt5(new Option(Option::V4,128, payload[4]));
  133. isc::dhcp::Option::Option6Collection opts; // list of options
  134. opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt1));
  135. opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt2));
  136. opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt3));
  137. opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt4));
  138. opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt5));
  139. vector<uint8_t> expVect(v4Opts, v4Opts + sizeof(v4Opts));
  140. OutputBuffer buf(100);
  141. EXPECT_NO_THROW (
  142. LibDHCP::packOptions(buf, opts);
  143. );
  144. ASSERT_EQ(buf.getLength(), sizeof(v4Opts));
  145. EXPECT_EQ(0, memcmp(v4Opts, buf.getData(), sizeof(v4Opts)));
  146. }
  147. TEST(LibDhcpTest, unpackOptions4) {
  148. vector<uint8_t> packed(v4Opts, v4Opts + sizeof(v4Opts));
  149. isc::dhcp::Option::Option6Collection options; // list of options
  150. ASSERT_NO_THROW(
  151. LibDHCP::unpackOptions4(packed, options);
  152. );
  153. isc::dhcp::Option::Option6Collection::const_iterator x = options.find(12);
  154. ASSERT_FALSE(x == options.end()); // option 1 should exist
  155. EXPECT_EQ(12, x->second->getType()); // this should be option 12
  156. ASSERT_EQ(3, x->second->getData().size()); // it should be of length 3
  157. EXPECT_EQ(5, x->second->len()); // total option length 5
  158. EXPECT_EQ(0, memcmp(&x->second->getData()[0], v4Opts+2, 3)); // data len=3
  159. x = options.find(13);
  160. ASSERT_FALSE(x == options.end()); // option 1 should exist
  161. EXPECT_EQ(13, x->second->getType()); // this should be option 13
  162. ASSERT_EQ(3, x->second->getData().size()); // it should be of length 3
  163. EXPECT_EQ(5, x->second->len()); // total option length 5
  164. EXPECT_EQ(0, memcmp(&x->second->getData()[0], v4Opts+7, 3)); // data len=3
  165. x = options.find(14);
  166. ASSERT_FALSE(x == options.end()); // option 3 should exist
  167. EXPECT_EQ(14, x->second->getType()); // this should be option 14
  168. ASSERT_EQ(3, x->second->getData().size()); // it should be of length 3
  169. EXPECT_EQ(5, x->second->len()); // total option length 5
  170. EXPECT_EQ(0, memcmp(&x->second->getData()[0], v4Opts+12, 3)); // data len=3
  171. x = options.find(254);
  172. ASSERT_FALSE(x == options.end()); // option 3 should exist
  173. EXPECT_EQ(254, x->second->getType()); // this should be option 254
  174. ASSERT_EQ(3, x->second->getData().size()); // it should be of length 3
  175. EXPECT_EQ(5, x->second->len()); // total option length 5
  176. EXPECT_EQ(0, memcmp(&x->second->getData()[0], v4Opts+17, 3)); // data len=3
  177. x = options.find(128);
  178. ASSERT_FALSE(x == options.end()); // option 3 should exist
  179. EXPECT_EQ(128, x->second->getType()); // this should be option 254
  180. ASSERT_EQ(3, x->second->getData().size()); // it should be of length 3
  181. EXPECT_EQ(5, x->second->len()); // total option length 5
  182. EXPECT_EQ(0, memcmp(&x->second->getData()[0], v4Opts+22, 3)); // data len=3
  183. x = options.find(0);
  184. EXPECT_TRUE(x == options.end()); // option 0 not found
  185. x = options.find(1);
  186. EXPECT_TRUE(x == options.end()); // option 1 not found
  187. x = options.find(2);
  188. EXPECT_TRUE(x == options.end()); // option 2 not found
  189. }
  190. }