opaque_data_tuple_unittest.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. // Copyright (C) 2014, 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 <dhcp/opaque_data_tuple.h>
  16. #include <util/buffer.h>
  17. #include <gtest/gtest.h>
  18. #include <algorithm>
  19. #include <sstream>
  20. #include <vector>
  21. using namespace isc;
  22. using namespace isc::dhcp;
  23. using namespace isc::util;
  24. namespace {
  25. // This test checks that when the default constructor is called, the data buffer
  26. // is empty.
  27. TEST(OpaqueDataTuple, constructor) {
  28. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
  29. // There should be no data in the tuple.
  30. EXPECT_EQ(0, tuple.getLength());
  31. EXPECT_TRUE(tuple.getData().empty());
  32. EXPECT_TRUE(tuple.getText().empty());
  33. }
  34. // Test that the constructor which takes the buffer as argument parses the
  35. // wire data.
  36. TEST(OpaqueDataTuple, constructorParse1Byte) {
  37. const char wire_data[] = {
  38. 0x0B, // Length is 11
  39. 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
  40. 0x77, 0x6F, 0x72, 0x6C, 0x64 // world
  41. };
  42. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE, wire_data,
  43. wire_data + sizeof(wire_data));
  44. EXPECT_EQ(11, tuple.getLength());
  45. EXPECT_EQ("Hello world", tuple.getText());
  46. }
  47. // Test that the constructor which takes the buffer as argument parses the
  48. // wire data.
  49. TEST(OpaqueDataTuple, constructorParse2Bytes) {
  50. const char wire_data[] = {
  51. 0x00, 0x0B, // Length is 11
  52. 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
  53. 0x77, 0x6F, 0x72, 0x6C, 0x64 // world
  54. };
  55. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES, wire_data,
  56. wire_data + sizeof(wire_data));
  57. EXPECT_EQ(11, tuple.getLength());
  58. EXPECT_EQ("Hello world", tuple.getText());
  59. }
  60. // This test checks that it is possible to set the tuple data using raw buffer.
  61. TEST(OpaqueDataTuple, assignData) {
  62. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
  63. // Initially the tuple buffer should be empty.
  64. OpaqueDataTuple::Buffer buf = tuple.getData();
  65. ASSERT_TRUE(buf.empty());
  66. // Prepare some input data and assign to the tuple.
  67. const uint8_t data1[] = {
  68. 0xCA, 0xFE, 0xBE, 0xEF
  69. };
  70. tuple.assign(data1, sizeof(data1));
  71. // Tuple should now hold the data we assigned.
  72. ASSERT_EQ(sizeof(data1), tuple.getLength());
  73. buf = tuple.getData();
  74. EXPECT_TRUE(std::equal(buf.begin(), buf.end(), data1));
  75. // Prepare the other set of data and assign to the tuple.
  76. const uint8_t data2[] = {
  77. 1, 2, 3, 4, 5, 6
  78. };
  79. tuple.assign(data2, sizeof(data2));
  80. // The new data should have replaced the old data.
  81. ASSERT_EQ(sizeof(data2), tuple.getLength());
  82. buf = tuple.getData();
  83. EXPECT_TRUE(std::equal(buf.begin(), buf.end(), data2));
  84. }
  85. // This test checks that it is possible to append the data to the tuple using
  86. // raw buffer.
  87. TEST(OpaqueDataTuple, appendData) {
  88. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
  89. // Initially the tuple buffer should be empty.
  90. OpaqueDataTuple::Buffer buf = tuple.getData();
  91. ASSERT_TRUE(buf.empty());
  92. // Prepare some input data and append to the empty tuple.
  93. const uint8_t data1[] = {
  94. 0xCA, 0xFE, 0xBE, 0xEF
  95. };
  96. tuple.append(data1, sizeof(data1));
  97. // The tuple should now hold only the data we appended.
  98. ASSERT_EQ(sizeof(data1), tuple.getLength());
  99. buf = tuple.getData();
  100. EXPECT_TRUE(std::equal(buf.begin(), buf.end(), data1));
  101. // Prepare the new set of data and append.
  102. const uint8_t data2[] = {
  103. 1, 2, 3, 4, 5, 6
  104. };
  105. tuple.append(data2, sizeof(data2));
  106. // We expect that the tuple now has both sets of data we appended. In order
  107. // to verify that, we have to concatenate the input data1 and data2.
  108. std::vector<uint8_t> data12(data1, data1 + sizeof(data1));
  109. data12.insert(data12.end(), data2, data2 + sizeof(data2));
  110. // The size of the tuple should be a sum of data1 and data2 lengths.
  111. ASSERT_EQ(sizeof(data1) + sizeof(data2), tuple.getLength());
  112. buf = tuple.getData();
  113. EXPECT_TRUE(std::equal(buf.begin(), buf.end(), data12.begin()));
  114. }
  115. // This test checks that it is possible to assign the string to the tuple.
  116. TEST(OpaqueDataTuple, assignString) {
  117. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
  118. // Initially, the tuple should be empty.
  119. ASSERT_EQ(0, tuple.getLength());
  120. // Assign some string data.
  121. tuple.assign("Some string");
  122. // Verify that the data has been assigned.
  123. EXPECT_EQ(11, tuple.getLength());
  124. EXPECT_EQ("Some string", tuple.getText());
  125. // Assign some other string.
  126. tuple.assign("Different string");
  127. // The new string should have replaced the old string.
  128. EXPECT_EQ(16, tuple.getLength());
  129. EXPECT_EQ("Different string", tuple.getText());
  130. }
  131. // This test checks that it is possible to append the string to the tuple.
  132. TEST(OpaqueDataTuple, appendString) {
  133. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
  134. // Initially the tuple should be empty.
  135. ASSERT_EQ(0, tuple.getLength());
  136. // Append the string to it.
  137. tuple.append("First part");
  138. ASSERT_EQ(10, tuple.getLength());
  139. ASSERT_EQ("First part", tuple.getText());
  140. // Now append the other string.
  141. tuple.append(" and second part");
  142. EXPECT_EQ(26, tuple.getLength());
  143. // The resulting data in the tuple should be a concatenation of both
  144. // strings.
  145. EXPECT_EQ("First part and second part", tuple.getText());
  146. }
  147. // This test verifies that equals function correctly checks that the tuple
  148. // holds a given string but it doesn't hold the other. This test also
  149. // checks the assignment operator for the tuple.
  150. TEST(OpaqueDataTuple, equals) {
  151. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
  152. // Tuple is supposed to be empty so it is not equal xyz.
  153. EXPECT_FALSE(tuple.equals("xyz"));
  154. // Assign xyz.
  155. EXPECT_NO_THROW(tuple = "xyz");
  156. // The tuple should be equal xyz, but not abc.
  157. EXPECT_FALSE(tuple.equals("abc"));
  158. EXPECT_TRUE(tuple.equals("xyz"));
  159. // Assign abc to the tuple.
  160. EXPECT_NO_THROW(tuple = "abc");
  161. // It should be now opposite.
  162. EXPECT_TRUE(tuple.equals("abc"));
  163. EXPECT_FALSE(tuple.equals("xyz"));
  164. }
  165. // This test checks that the conversion of the data in the tuple to the string
  166. // is performed correctly.
  167. TEST(OpaqueDataTuple, getText) {
  168. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
  169. // Initially the tuple should be empty.
  170. ASSERT_TRUE(tuple.getText().empty());
  171. // ASCII representation of 'Hello world'.
  172. const char as_ascii[] = {
  173. 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
  174. 0x77, 0x6F, 0x72, 0x6C, 0x64 // world
  175. };
  176. // Assign it to the tuple.
  177. tuple.assign(as_ascii, sizeof(as_ascii));
  178. // Conversion to string should give as the original text.
  179. EXPECT_EQ("Hello world", tuple.getText());
  180. }
  181. // This test verifies the behavior of (in)equality and assignment operators.
  182. TEST(OpaqueDataTuple, operators) {
  183. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
  184. // Tuple should be empty initially.
  185. ASSERT_EQ(0, tuple.getLength());
  186. // Check assignment.
  187. EXPECT_NO_THROW(tuple = "Hello World");
  188. EXPECT_EQ(11, tuple.getLength());
  189. EXPECT_TRUE(tuple == "Hello World");
  190. EXPECT_TRUE(tuple != "Something else");
  191. // Assign something else to make sure it affects the tuple.
  192. EXPECT_NO_THROW(tuple = "Something else");
  193. EXPECT_EQ(14, tuple.getLength());
  194. EXPECT_TRUE(tuple == "Something else");
  195. EXPECT_TRUE(tuple != "Hello World");
  196. }
  197. // This test verifies that the tuple is inserted in the textual format to the
  198. // output stream.
  199. TEST(OpaqueDataTuple, operatorOutputStream) {
  200. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
  201. // The tuple should be empty initially.
  202. ASSERT_EQ(0, tuple.getLength());
  203. // The tuple is empty, so assigning its content to the output stream should
  204. // be no-op and result in the same text in the stream.
  205. std::ostringstream s;
  206. s << "Some text";
  207. EXPECT_NO_THROW(s << tuple);
  208. EXPECT_EQ("Some text", s.str());
  209. // Now, let's assign some text to the tuple and call operator again.
  210. // The new text should be added to the stream.
  211. EXPECT_NO_THROW(tuple = " and some other text");
  212. EXPECT_NO_THROW(s << tuple);
  213. EXPECT_EQ(s.str(), "Some text and some other text");
  214. }
  215. // This test verifies that the value of the tuple can be initialized from the
  216. // input stream.
  217. TEST(OpaqueDataTuple, operatorInputStream) {
  218. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
  219. // The tuple should be empty initially.
  220. ASSERT_EQ(0, tuple.getLength());
  221. // The input stream has some text. This text should be appended to the
  222. // tuple.
  223. std::istringstream s;
  224. s.str("Some text");
  225. EXPECT_NO_THROW(s >> tuple);
  226. EXPECT_EQ("Some text", tuple.getText());
  227. // Now, let's assign some other text to the stream. This new text should be
  228. // assigned to the tuple.
  229. s.str("And some other");
  230. EXPECT_NO_THROW(s >> tuple);
  231. EXPECT_EQ("And some other", tuple.getText());
  232. }
  233. // This test checks that the tuple is correctly encoded in the wire format when
  234. // the size of the length field is 1 byte.
  235. TEST(OpaqueDataTuple, pack1Byte) {
  236. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
  237. // Initially, the tuple should be empty.
  238. ASSERT_EQ(0, tuple.getLength());
  239. // The empty data doesn't make much sense, so the pack() should not
  240. // allow it.
  241. OutputBuffer out_buf(10);
  242. EXPECT_THROW(tuple.pack(out_buf), OpaqueDataTupleError);
  243. // Set the data for tuple.
  244. std::vector<uint8_t> data;
  245. for (uint8_t i = 0; i < 100; ++i) {
  246. data.push_back(i);
  247. }
  248. tuple.assign(data.begin(), data.size());
  249. // The pack should now succeed.
  250. ASSERT_NO_THROW(tuple.pack(out_buf));
  251. // The rendered buffer should be 101 bytes long - 1 byte for length,
  252. // 100 bytes for the actual data.
  253. ASSERT_EQ(101, out_buf.getLength());
  254. // Get the rendered data into the vector for convenience.
  255. std::vector<uint8_t>
  256. render_data(static_cast<const uint8_t*>(out_buf.getData()),
  257. static_cast<const uint8_t*>(out_buf.getData()) + 101);
  258. // The first byte is a length byte. It should hold the length of 100.
  259. EXPECT_EQ(100, render_data[0]);
  260. // Verify that the rendered data is correct.
  261. EXPECT_TRUE(std::equal(render_data.begin() + 1, render_data.end(),
  262. data.begin()));
  263. // Reset the output buffer for another test.
  264. out_buf.clear();
  265. // Fill in the tuple buffer so as it reaches maximum allowed length. The
  266. // maximum length is 255 when the size of the length field is one byte.
  267. for (uint8_t i = 100; i < 255; ++i) {
  268. data.push_back(i);
  269. }
  270. ASSERT_EQ(255, data.size());
  271. tuple.assign(data.begin(), data.size());
  272. // The pack() should be successful again.
  273. ASSERT_NO_THROW(tuple.pack(out_buf));
  274. // The rendered buffer should be 256 bytes long. The first byte holds the
  275. // opaque data length, the remaining bytes hold the actual data.
  276. ASSERT_EQ(256, out_buf.getLength());
  277. // Check that the data is correct.
  278. render_data.assign(static_cast<const uint8_t*>(out_buf.getData()),
  279. static_cast<const uint8_t*>(out_buf.getData()) + 256);
  280. EXPECT_EQ(255, render_data[0]);
  281. EXPECT_TRUE(std::equal(render_data.begin() + 1, render_data.end(),
  282. data.begin()));
  283. // Clear output buffer for another test.
  284. out_buf.clear();
  285. // Add one more value to the tuple. Now, the resulting buffer should exceed
  286. // the maximum length. An attempt to pack() should fail.
  287. data.push_back(255);
  288. tuple.assign(data.begin(), data.size());
  289. EXPECT_THROW(tuple.pack(out_buf), OpaqueDataTupleError);
  290. }
  291. // This test checks that the tuple is correctly encoded in the wire format when
  292. // the size of the length field is 2 bytes.
  293. TEST(OpaqueDataTuple, pack2Bytes) {
  294. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
  295. // Initially, the tuple should be empty.
  296. ASSERT_EQ(0, tuple.getLength());
  297. // The empty data doesn't make much sense, so the pack() should not
  298. // allow it.
  299. OutputBuffer out_buf(10);
  300. EXPECT_THROW(tuple.pack(out_buf), OpaqueDataTupleError);
  301. // Set the data for tuple.
  302. std::vector<uint8_t> data;
  303. for (unsigned i = 0; i < 512; ++i) {
  304. data.push_back(i & 0xff);
  305. }
  306. tuple.assign(data.begin(), data.size());
  307. // The pack should now succeed.
  308. ASSERT_NO_THROW(tuple.pack(out_buf));
  309. // The rendered buffer should be 514 bytes long - 2 bytes for length,
  310. // 512 bytes for the actual data.
  311. ASSERT_EQ(514, out_buf.getLength());
  312. // Get the rendered data into the vector for convenience.
  313. std::vector<uint8_t>
  314. render_data(static_cast<const uint8_t*>(out_buf.getData()),
  315. static_cast<const uint8_t*>(out_buf.getData()) + 514);
  316. // The first two bytes hold the length of 512.
  317. uint16_t len = (render_data[0] << 8) + render_data[1];
  318. EXPECT_EQ(512, len);
  319. // Verify that the rendered data is correct.
  320. EXPECT_TRUE(std::equal(render_data.begin() + 2, render_data.end(),
  321. data.begin()));
  322. // Without clearing the output buffer, try to do it again. The pack should
  323. // append the data to the current buffer.
  324. ASSERT_NO_THROW(tuple.pack(out_buf));
  325. EXPECT_EQ(1028, out_buf.getLength());
  326. // Check that we can render the buffer of the maximal allowed size.
  327. data.assign(65535, 1);
  328. ASSERT_NO_THROW(tuple.assign(data.begin(), data.size()));
  329. ASSERT_NO_THROW(tuple.pack(out_buf));
  330. out_buf.clear();
  331. // Append one additional byte. The total length of the tuple now exceeds
  332. // the maximal value. An attempt to render it should throw an exception.
  333. data.assign(1, 1);
  334. ASSERT_NO_THROW(tuple.append(data.begin(), data.size()));
  335. EXPECT_THROW(tuple.pack(out_buf), OpaqueDataTupleError);
  336. }
  337. // This test verifies that the tuple is decoded from the wire format.
  338. TEST(OpaqueDataTuple, unpack1Byte) {
  339. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
  340. const char wire_data[] = {
  341. 0x0B, // Length is 11
  342. 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
  343. 0x77, 0x6F, 0x72, 0x6C, 0x64 // world
  344. };
  345. ASSERT_NO_THROW(tuple.unpack(wire_data, wire_data + sizeof(wire_data)));
  346. EXPECT_EQ(11, tuple.getLength());
  347. EXPECT_EQ("Hello world", tuple.getText());
  348. }
  349. // This test verifies that the tuple having a length of 0, is decoded from
  350. // the wire format.
  351. TEST(OpaqueDataTuple, unpack1ByteZeroLength) {
  352. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
  353. EXPECT_NO_THROW(tuple = "Hello world");
  354. ASSERT_NE(tuple.getLength(), 0);
  355. const char wire_data[] = {
  356. 0
  357. };
  358. ASSERT_NO_THROW(tuple.unpack(wire_data, wire_data + sizeof(wire_data)));
  359. EXPECT_EQ(0, tuple.getLength());
  360. }
  361. // This test verfifies that exception is thrown if the empty buffer is being
  362. // parsed.
  363. TEST(OpaqueDataTuple, unpack1ByteEmptyBuffer) {
  364. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
  365. const char wire_data[] = {
  366. 1, 2, 3
  367. };
  368. EXPECT_THROW(tuple.unpack(wire_data, wire_data), OpaqueDataTupleError);
  369. }
  370. // This test verifies that exception is thrown when parsing truncated buffer.
  371. TEST(OpaqueDataTuple, unpack1ByteTruncatedBuffer) {
  372. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
  373. const char wire_data[] = {
  374. 10, 2, 3
  375. };
  376. EXPECT_THROW(tuple.unpack(wire_data, wire_data + sizeof(wire_data)),
  377. OpaqueDataTupleError);
  378. }
  379. // This test verifies that the tuple is decoded from the wire format.
  380. TEST(OpaqueDataTuple, unpack2Byte) {
  381. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
  382. std::vector<uint8_t> wire_data;
  383. // Set tuple length to 400 (0x190).
  384. wire_data.push_back(1);
  385. wire_data.push_back(0x90);
  386. // Fill in the buffer with some data.
  387. for (int i = 0; i < 400; ++i) {
  388. wire_data.push_back(i);
  389. }
  390. // The unpack shoud succeed.
  391. ASSERT_NO_THROW(tuple.unpack(wire_data.begin(), wire_data.end()));
  392. // The decoded length should be 400.
  393. ASSERT_EQ(400, tuple.getLength());
  394. // And the data should match.
  395. EXPECT_TRUE(std::equal(wire_data.begin() + 2, wire_data.end(),
  396. tuple.getData().begin()));
  397. }
  398. // This test verifies that the tuple having a length of 0, is decoded from
  399. // the wire format.
  400. TEST(OpaqueDataTuple, unpack2ByteZeroLength) {
  401. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
  402. // Set some data for the tuple.
  403. EXPECT_NO_THROW(tuple = "Hello world");
  404. ASSERT_NE(tuple.getLength(), 0);
  405. // The buffer holds just a length field with the value of 0.
  406. const char wire_data[] = {
  407. 0, 0
  408. };
  409. // The empty tuple should be successfully decoded.
  410. ASSERT_NO_THROW(tuple.unpack(wire_data, wire_data + sizeof(wire_data)));
  411. // The data should be replaced with an empty buffer.
  412. EXPECT_EQ(0, tuple.getLength());
  413. }
  414. // This test verifies that exception is thrown if the empty buffer is being
  415. // parsed.
  416. TEST(OpaqueDataTuple, unpack2ByteEmptyBuffer) {
  417. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
  418. // Initialize the input buffer with some data, just to avoid initializing
  419. // empty array.
  420. const char wire_data[] = {
  421. 1, 2, 3
  422. };
  423. // Pass empty buffer (first iterator equal to second iterator).
  424. // This should not be accepted.
  425. EXPECT_THROW(tuple.unpack(wire_data, wire_data), OpaqueDataTupleError);
  426. }
  427. // This test verifies that exception if thrown when parsing truncated buffer.
  428. TEST(OpaqueDataTuple, unpack2ByteTruncatedBuffer) {
  429. OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
  430. // Specify the data with the length of 10, but limit the buffer size to
  431. // 2 bytes.
  432. const char wire_data[] = {
  433. 0, 10, 2, 3
  434. };
  435. // This should fail because the buffer is truncated.
  436. EXPECT_THROW(tuple.unpack(wire_data, wire_data + sizeof(wire_data)),
  437. OpaqueDataTupleError);
  438. }
  439. } // anonymous namespace