blob: f6b245e1634006b82a9a6c06c6dc080d528bcc22 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shidb7464d2017-07-13 03:11:17 +00002/*
Davide Pesavento5c803b92019-02-02 19:23:48 -05003 * Copyright (c) 2013-2019 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyev233750e2014-02-16 00:50:07 -080020 */
21
Davide Pesavento7e780642018-11-24 15:51:34 -050022#include "ndn-cxx/encoding/block.hpp"
23#include "ndn-cxx/encoding/block-helpers.hpp"
Alexander Afanasyev233750e2014-02-16 00:50:07 -080024
Davide Pesavento7e780642018-11-24 15:51:34 -050025#include "tests/boost-test.hpp"
26
Junxiao Shi72c0c642018-04-20 15:41:09 +000027#include <boost/lexical_cast.hpp>
Davide Pesavento6b330402019-04-24 00:14:01 -040028#include <boost/mpl/vector.hpp>
29
Junxiao Shidc4277a2017-07-17 11:34:02 +000030#include <cstring>
31#include <sstream>
Davide Pesaventoeee3e822016-11-26 19:19:34 +010032
Alexander Afanasyev233750e2014-02-16 00:50:07 -080033namespace ndn {
Alexander Afanasyev74633892015-02-08 18:08:46 -080034namespace tests {
Alexander Afanasyev233750e2014-02-16 00:50:07 -080035
Davide Pesaventoeee3e822016-11-26 19:19:34 +010036BOOST_AUTO_TEST_SUITE(Encoding)
37BOOST_AUTO_TEST_SUITE(TestBlock)
Alexander Afanasyev233750e2014-02-16 00:50:07 -080038
Junxiao Shidc4277a2017-07-17 11:34:02 +000039BOOST_AUTO_TEST_SUITE(Construction)
40
41static const uint8_t TEST_BUFFER[] = {
Davide Pesavento6b330402019-04-24 00:14:01 -040042 0x42, 0x01, 0xfa,
43 0x01, 0x01, 0xfb,
44 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, // bug #4726
Alexander Afanasyev74633892015-02-08 18:08:46 -080045};
Alexander Afanasyev2d0b4572014-02-24 16:02:12 -080046
Davide Pesavento6b330402019-04-24 00:14:01 -040047BOOST_AUTO_TEST_CASE(Default)
Alexander Afanasyev74633892015-02-08 18:08:46 -080048{
Junxiao Shidc4277a2017-07-17 11:34:02 +000049 Block b;
Davide Pesavento6b330402019-04-24 00:14:01 -040050
51 BOOST_CHECK_EQUAL(b.isValid(), false);
Junxiao Shidc4277a2017-07-17 11:34:02 +000052 BOOST_CHECK_EQUAL(b.empty(), true);
Davide Pesavento6b330402019-04-24 00:14:01 -040053 BOOST_CHECK_EQUAL(b.type(), tlv::Invalid);
54 BOOST_CHECK_EQUAL(b.hasValue(), false);
55 BOOST_CHECK_EQUAL(b.value_size(), 0);
56 BOOST_CHECK(b.value() == nullptr);
57
58 BOOST_CHECK_THROW(b.size(), Block::Error);
59 BOOST_CHECK_THROW(b.begin(), Block::Error);
60 BOOST_CHECK_THROW(b.end(), Block::Error);
61 BOOST_CHECK_THROW(b.wire(), Block::Error);
62 BOOST_CHECK_THROW(b.blockFromValue(), Block::Error);
Alexander Afanasyev74633892015-02-08 18:08:46 -080063}
Alexander Afanasyev937aa782014-03-21 13:17:57 -070064
Junxiao Shidc4277a2017-07-17 11:34:02 +000065BOOST_AUTO_TEST_CASE(FromEncodingBuffer)
Alexander Afanasyev74633892015-02-08 18:08:46 -080066{
Junxiao Shidc4277a2017-07-17 11:34:02 +000067 EncodingBuffer encoder;
Davide Pesavento5c803b92019-02-02 19:23:48 -050068 BOOST_CHECK_THROW(Block{encoder}, tlv::Error);
69
70 const uint8_t VALUE[] = {0x11, 0x12, 0x13, 0x14};
Junxiao Shidc4277a2017-07-17 11:34:02 +000071 size_t length = encoder.prependByteArray(VALUE, sizeof(VALUE));
72 encoder.prependVarNumber(length);
73 encoder.prependVarNumber(0xe0);
74
75 Block b = encoder.block();
76 BOOST_CHECK_EQUAL(b.type(), 0xe0);
77 BOOST_CHECK_EQUAL(b.value_size(), sizeof(VALUE));
78 BOOST_CHECK_EQUAL_COLLECTIONS(b.value_begin(), b.value_end(),
79 VALUE, VALUE + sizeof(VALUE));
80
81 b = Block(encoder);
82 BOOST_CHECK_EQUAL(b.type(), 0xe0);
83 BOOST_CHECK_EQUAL(b.value_size(), sizeof(VALUE));
84 BOOST_CHECK_EQUAL_COLLECTIONS(b.value_begin(), b.value_end(),
85 VALUE, VALUE + sizeof(VALUE));
Alexander Afanasyev74633892015-02-08 18:08:46 -080086}
Alexander Afanasyev937aa782014-03-21 13:17:57 -070087
Davide Pesaventoeee3e822016-11-26 19:19:34 +010088BOOST_AUTO_TEST_CASE(FromBlock)
Alexander Afanasyev4448d292015-08-09 20:11:37 -070089{
Davide Pesavento5c803b92019-02-02 19:23:48 -050090 const uint8_t BUFFER[] = {0x80, 0x06, 0x81, 0x01, 0x01, 0x82, 0x01, 0x01};
91 Block block(BUFFER, sizeof(BUFFER));
Alexander Afanasyev4448d292015-08-09 20:11:37 -070092
93 Block derivedBlock(block, block.begin(), block.end());
94 BOOST_CHECK_EQUAL(derivedBlock.wire(), block.wire()); // pointers should match
95 BOOST_CHECK(derivedBlock == block); // blocks should match
96
97 derivedBlock = Block(block, block.begin() + 2, block.begin() + 5);
98 BOOST_CHECK(derivedBlock.begin() == block.begin() + 2);
Davide Pesavento5c803b92019-02-02 19:23:48 -050099 BOOST_CHECK(derivedBlock == Block(BUFFER + 2, 3));
Alexander Afanasyev4448d292015-08-09 20:11:37 -0700100
Davide Pesavento5c803b92019-02-02 19:23:48 -0500101 Buffer otherBuffer(BUFFER, sizeof(BUFFER));
Junxiao Shidb7464d2017-07-13 03:11:17 +0000102 BOOST_CHECK_THROW(Block(block, otherBuffer.begin(), block.end()), std::invalid_argument);
103 BOOST_CHECK_THROW(Block(block, block.begin(), otherBuffer.end()), std::invalid_argument);
104 BOOST_CHECK_THROW(Block(block, otherBuffer.begin(), otherBuffer.end()), std::invalid_argument);
Alexander Afanasyev4448d292015-08-09 20:11:37 -0700105}
106
Davide Pesaventoeee3e822016-11-26 19:19:34 +0100107BOOST_AUTO_TEST_CASE(FromBlockCopyOnWriteModifyOriginal)
Eric Newberry6235aac2015-08-13 16:03:47 -0700108{
Junxiao Shidc4277a2017-07-17 11:34:02 +0000109 const uint8_t BUFFER[] = {
Eric Newberry6235aac2015-08-13 16:03:47 -0700110 0x05, 0x0b, 0x07, 0x03, 0x01, 0x02, 0x03, 0x0a, 0x04, 0x04, 0x05, 0x06, 0x07,
111 };
112
Junxiao Shidc4277a2017-07-17 11:34:02 +0000113 Block b1(BUFFER, sizeof(BUFFER));
Eric Newberry6235aac2015-08-13 16:03:47 -0700114
Junxiao Shidc4277a2017-07-17 11:34:02 +0000115 Block b2(b1, b1.begin(), b1.end());
116 auto buf2 = b2.getBuffer();
Eric Newberry6235aac2015-08-13 16:03:47 -0700117
Junxiao Shidc4277a2017-07-17 11:34:02 +0000118 b1.parse();
119 b1.remove(tlv::Name);
120 b1.encode();
Eric Newberry6235aac2015-08-13 16:03:47 -0700121
Junxiao Shidc4277a2017-07-17 11:34:02 +0000122 b2.parse();
Eric Newberry6235aac2015-08-13 16:03:47 -0700123
Junxiao Shidc4277a2017-07-17 11:34:02 +0000124 BOOST_CHECK_EQUAL_COLLECTIONS(b2.begin(), b2.end(), BUFFER, BUFFER + sizeof(BUFFER));
125 BOOST_CHECK_EQUAL(buf2, b2.getBuffer());
Eric Newberry6235aac2015-08-13 16:03:47 -0700126}
127
Davide Pesaventoeee3e822016-11-26 19:19:34 +0100128BOOST_AUTO_TEST_CASE(FromBlockCopyOnWriteModifyCopy)
Eric Newberry6235aac2015-08-13 16:03:47 -0700129{
Junxiao Shidc4277a2017-07-17 11:34:02 +0000130 const uint8_t BUFFER[] = {
Eric Newberry6235aac2015-08-13 16:03:47 -0700131 0x05, 0x0b, 0x07, 0x03, 0x01, 0x02, 0x03, 0x0a, 0x04, 0x04, 0x05, 0x06, 0x07,
132 };
133
Junxiao Shidc4277a2017-07-17 11:34:02 +0000134 Block b1(BUFFER, sizeof(BUFFER));
135 auto buf1 = b1.getBuffer();
Eric Newberry6235aac2015-08-13 16:03:47 -0700136
Junxiao Shidc4277a2017-07-17 11:34:02 +0000137 Block b2(b1, b1.begin(), b1.end());
Eric Newberry6235aac2015-08-13 16:03:47 -0700138
Junxiao Shidc4277a2017-07-17 11:34:02 +0000139 b2.parse();
140 b2.remove(tlv::Name);
141 b2.encode();
Eric Newberry6235aac2015-08-13 16:03:47 -0700142
Junxiao Shidc4277a2017-07-17 11:34:02 +0000143 b1.parse();
144 BOOST_CHECK_EQUAL_COLLECTIONS(b1.begin(), b1.end(), BUFFER, BUFFER + sizeof(BUFFER));
145 BOOST_CHECK_EQUAL(buf1, b1.getBuffer());
Eric Newberry6235aac2015-08-13 16:03:47 -0700146}
147
Junxiao Shidc4277a2017-07-17 11:34:02 +0000148BOOST_AUTO_TEST_CASE(FromType)
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800149{
Junxiao Shidc4277a2017-07-17 11:34:02 +0000150 Block b1(4);
Davide Pesavento6b330402019-04-24 00:14:01 -0400151 BOOST_CHECK_EQUAL(b1.isValid(), true);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000152 BOOST_CHECK_EQUAL(b1.type(), 4);
153 BOOST_CHECK_EQUAL(b1.size(), 2); // 1-octet TLV-TYPE and 1-octet TLV-LENGTH
Davide Pesavento5c803b92019-02-02 19:23:48 -0500154 BOOST_CHECK_EQUAL(b1.hasValue(), false);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000155 BOOST_CHECK_EQUAL(b1.value_size(), 0);
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800156
Junxiao Shidc4277a2017-07-17 11:34:02 +0000157 Block b2(258);
Davide Pesavento6b330402019-04-24 00:14:01 -0400158 BOOST_CHECK_EQUAL(b2.isValid(), true);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000159 BOOST_CHECK_EQUAL(b2.type(), 258);
160 BOOST_CHECK_EQUAL(b2.size(), 4); // 3-octet TLV-TYPE and 1-octet TLV-LENGTH
Davide Pesavento5c803b92019-02-02 19:23:48 -0500161 BOOST_CHECK_EQUAL(b2.hasValue(), false);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000162 BOOST_CHECK_EQUAL(b2.value_size(), 0);
Davide Pesavento6b330402019-04-24 00:14:01 -0400163
164 Block b3(tlv::Invalid);
165 BOOST_CHECK_EQUAL(b3.isValid(), false);
166 BOOST_CHECK_EQUAL(b3.type(), tlv::Invalid);
167 BOOST_CHECK_EQUAL(b3.hasValue(), false);
168 BOOST_CHECK_EQUAL(b3.value_size(), 0);
169 BOOST_CHECK(b3.value() == nullptr);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700170}
171
Davide Pesavento5c803b92019-02-02 19:23:48 -0500172BOOST_AUTO_TEST_CASE(FromTypeAndBuffer)
173{
174 const uint8_t VALUE[] = {0x11, 0x12, 0x13, 0x14};
175 auto bufferPtr = make_shared<Buffer>(VALUE, sizeof(VALUE));
176
177 Block b(42, bufferPtr);
Davide Pesavento6b330402019-04-24 00:14:01 -0400178 BOOST_CHECK_EQUAL(b.isValid(), true);
Davide Pesavento5c803b92019-02-02 19:23:48 -0500179 BOOST_CHECK_EQUAL(b.type(), 42);
180 BOOST_CHECK_EQUAL(b.size(), 6);
181 BOOST_CHECK_EQUAL(b.hasValue(), true);
182 BOOST_CHECK_EQUAL(b.value_size(), sizeof(VALUE));
183}
184
185BOOST_AUTO_TEST_CASE(FromTypeAndBlock)
186{
187 const uint8_t BUFFER[] = {0x80, 0x06, 0x81, 0x01, 0x01, 0x82, 0x01, 0x01};
188 Block nested(BUFFER, sizeof(BUFFER));
189
190 Block b(84, nested);
Davide Pesavento6b330402019-04-24 00:14:01 -0400191 BOOST_CHECK_EQUAL(b.isValid(), true);
Davide Pesavento5c803b92019-02-02 19:23:48 -0500192 BOOST_CHECK_EQUAL(b.type(), 84);
193 BOOST_CHECK_EQUAL(b.size(), 10);
194 BOOST_CHECK_EQUAL(b.hasValue(), true);
195 BOOST_CHECK_EQUAL(b.value_size(), sizeof(BUFFER));
196}
197
Junxiao Shif0da7892015-04-04 22:16:16 -0700198BOOST_AUTO_TEST_CASE(FromStream)
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700199{
Junxiao Shidc4277a2017-07-17 11:34:02 +0000200 std::stringstream stream;
201 stream.write(reinterpret_cast<const char*>(TEST_BUFFER), sizeof(TEST_BUFFER));
202 stream.seekg(0);
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700203
Junxiao Shidc4277a2017-07-17 11:34:02 +0000204 Block b = Block::fromStream(stream);
Davide Pesavento6b330402019-04-24 00:14:01 -0400205 BOOST_CHECK_EQUAL(b.type(), 66);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000206 BOOST_CHECK_EQUAL(b.size(), 3);
207 BOOST_CHECK_EQUAL(b.value_size(), 1);
Davide Pesavento6b330402019-04-24 00:14:01 -0400208 BOOST_CHECK_EQUAL(*b.wire(), 0x42);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000209 BOOST_CHECK_EQUAL(*b.value(), 0xfa);
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700210
Junxiao Shidc4277a2017-07-17 11:34:02 +0000211 b = Block::fromStream(stream);
212 BOOST_CHECK_EQUAL(b.type(), 1);
213 BOOST_CHECK_EQUAL(b.size(), 3);
214 BOOST_CHECK_EQUAL(b.value_size(), 1);
215 BOOST_CHECK_EQUAL(*b.wire(), 0x01);
216 BOOST_CHECK_EQUAL(*b.value(), 0xfb);
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700217
Davide Pesavento6b330402019-04-24 00:14:01 -0400218 b = Block::fromStream(stream);
219 BOOST_CHECK_EQUAL(b.type(), 0xffffffff);
220 BOOST_CHECK_EQUAL(b.size(), 6);
221 BOOST_CHECK_EQUAL(b.value_size(), 0);
222 BOOST_CHECK_EQUAL(*b.wire(), 0xfe);
223
224 BOOST_CHECK(stream.eof());
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600225 BOOST_CHECK_THROW(Block::fromStream(stream), tlv::Error);
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700226}
227
Junxiao Shif0da7892015-04-04 22:16:16 -0700228BOOST_AUTO_TEST_CASE(FromStreamWhitespace) // Bug 2728
229{
Junxiao Shidc4277a2017-07-17 11:34:02 +0000230 const uint8_t PACKET[] = {
Junxiao Shif0da7892015-04-04 22:16:16 -0700231 0x06, 0x20, // Data
232 0x07, 0x11, // Name
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000233 0x08, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, // GenericNameComponent 'hello'
234 0x08, 0x01, 0x31, // GenericNameComponent '1'
235 0x08, 0x05, 0x77, 0x6f, 0x72, 0x6c, 0x64, // GenericNameComponent 'world'
Junxiao Shif0da7892015-04-04 22:16:16 -0700236 0x14, 0x00, // MetaInfo empty
237 0x15, 0x00, // Content empty
238 0x16, 0x05, // SignatureInfo
Junxiao Shidc4277a2017-07-17 11:34:02 +0000239 0x1b, 0x01, 0x01, // SignatureType RSA
240 0x1c, 0x00, // KeyLocator empty
Junxiao Shif0da7892015-04-04 22:16:16 -0700241 0x17, 0x00 // SignatureValue empty
242 };
243 // TLV-LENGTH of <Data> is 0x20 which happens to be ASCII whitespace
244
245 std::stringstream stream;
246 stream.write(reinterpret_cast<const char*>(PACKET), sizeof(PACKET));
247 stream.seekg(0);
248
Junxiao Shidc4277a2017-07-17 11:34:02 +0000249 Block b = Block::fromStream(stream);
250 BOOST_CHECK_EQUAL(b.type(), 6);
251 BOOST_CHECK_EQUAL(b.value_size(), 32);
252 b.parse();
Davide Pesavento6b330402019-04-24 00:14:01 -0400253 BOOST_CHECK_EQUAL(b.elements_size(), 5);
Junxiao Shif0da7892015-04-04 22:16:16 -0700254}
255
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000256BOOST_AUTO_TEST_CASE(FromStreamZeroLength)
Junxiao Shif0da7892015-04-04 22:16:16 -0700257{
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000258 const uint8_t BUFFER[] = {0x70, 0x00,
259 0x71, 0x03, 0x86, 0x11, 0x24,
260 0x72, 0x00};
Junxiao Shif0da7892015-04-04 22:16:16 -0700261
262 std::stringstream stream;
263 stream.write(reinterpret_cast<const char*>(BUFFER), sizeof(BUFFER));
264 stream.seekg(0);
265
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000266 Block b1 = Block::fromStream(stream);
267 BOOST_CHECK_EQUAL(b1.type(), 0x70);
268 BOOST_CHECK_EQUAL(b1.value_size(), 0);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000269
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000270 Block b2 = Block::fromStream(stream);
271 BOOST_CHECK_EQUAL(b2.type(), 0x71);
272 BOOST_CHECK_EQUAL(b2.value_size(), 3);
273 const uint8_t EXPECTED_VALUE2[] = {0x86, 0x11, 0x24};
274 BOOST_CHECK_EQUAL_COLLECTIONS(b2.value_begin(), b2.value_end(),
275 EXPECTED_VALUE2, EXPECTED_VALUE2 + sizeof(EXPECTED_VALUE2));
276
277 Block b3 = Block::fromStream(stream);
278 BOOST_CHECK_EQUAL(b3.type(), 0x72);
279 BOOST_CHECK_EQUAL(b3.value_size(), 0);
280
281 BOOST_CHECK_THROW(Block::fromStream(stream), tlv::Error);
282}
283
284BOOST_AUTO_TEST_CASE(FromStreamPacketTooLarge)
285{
286 const uint8_t BUFFER[] = {0x07, 0xfe, 0x00, 0x01, 0x00, 0x00};
287
288 std::stringstream stream;
289 stream.write(reinterpret_cast<const char*>(BUFFER), sizeof(BUFFER));
290 for (int i = 0; i < 0x10000; ++i) {
291 stream.put('\0');
292 }
293 stream.seekg(0);
294
295 BOOST_CHECK_THROW(Block::fromStream(stream), tlv::Error);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000296}
297
298BOOST_AUTO_TEST_CASE(FromWireBuffer)
299{
Davide Pesavento6b330402019-04-24 00:14:01 -0400300 auto buffer = make_shared<Buffer>(TEST_BUFFER, sizeof(TEST_BUFFER));
Junxiao Shidc4277a2017-07-17 11:34:02 +0000301
302 size_t offset = 0;
303 bool isOk = false;
304 Block b;
305 std::tie(isOk, b) = Block::fromBuffer(buffer, offset);
306 BOOST_CHECK(isOk);
Davide Pesavento6b330402019-04-24 00:14:01 -0400307 BOOST_CHECK_EQUAL(b.type(), 66);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000308 BOOST_CHECK_EQUAL(b.size(), 3);
309 BOOST_CHECK_EQUAL(b.value_size(), 1);
Davide Pesavento6b330402019-04-24 00:14:01 -0400310 BOOST_CHECK_EQUAL(*b.wire(), 0x42);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000311 BOOST_CHECK_EQUAL(*b.value(), 0xfa);
312 offset += b.size();
313
314 std::tie(isOk, b) = Block::fromBuffer(buffer, offset);
315 BOOST_CHECK(isOk);
316 BOOST_CHECK_EQUAL(b.type(), 1);
317 BOOST_CHECK_EQUAL(b.size(), 3);
318 BOOST_CHECK_EQUAL(b.value_size(), 1);
319 BOOST_CHECK_EQUAL(*b.wire(), 0x01);
320 BOOST_CHECK_EQUAL(*b.value(), 0xfb);
321 offset += b.size();
322
323 std::tie(isOk, b) = Block::fromBuffer(buffer, offset);
Davide Pesavento6b330402019-04-24 00:14:01 -0400324 BOOST_CHECK(isOk);
325 BOOST_CHECK_EQUAL(b.type(), 0xffffffff);
326 BOOST_CHECK_EQUAL(b.size(), 6);
327 BOOST_CHECK_EQUAL(b.value_size(), 0);
328 BOOST_CHECK_EQUAL(*b.wire(), 0xfe);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000329}
330
331BOOST_AUTO_TEST_CASE(FromRawBuffer)
332{
333 size_t offset = 0;
334 bool isOk = false;
335 Block b;
336 std::tie(isOk, b) = Block::fromBuffer(TEST_BUFFER + offset, sizeof(TEST_BUFFER) - offset);
337 BOOST_CHECK(isOk);
Davide Pesavento6b330402019-04-24 00:14:01 -0400338 BOOST_CHECK_EQUAL(b.type(), 66);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000339 BOOST_CHECK_EQUAL(b.size(), 3);
340 BOOST_CHECK_EQUAL(b.value_size(), 1);
Davide Pesavento6b330402019-04-24 00:14:01 -0400341 BOOST_CHECK_EQUAL(*b.wire(), 0x42);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000342 BOOST_CHECK_EQUAL(*b.value(), 0xfa);
343 offset += b.size();
344
345 std::tie(isOk, b) = Block::fromBuffer(TEST_BUFFER + offset, sizeof(TEST_BUFFER) - offset);
346 BOOST_CHECK(isOk);
347 BOOST_CHECK_EQUAL(b.type(), 1);
348 BOOST_CHECK_EQUAL(b.size(), 3);
349 BOOST_CHECK_EQUAL(b.value_size(), 1);
350 BOOST_CHECK_EQUAL(*b.wire(), 0x01);
351 BOOST_CHECK_EQUAL(*b.value(), 0xfb);
352 offset += b.size();
353
354 std::tie(isOk, b) = Block::fromBuffer(TEST_BUFFER + offset, sizeof(TEST_BUFFER) - offset);
Davide Pesavento6b330402019-04-24 00:14:01 -0400355 BOOST_CHECK(isOk);
356 BOOST_CHECK_EQUAL(b.type(), 0xffffffff);
357 BOOST_CHECK_EQUAL(b.size(), 6);
358 BOOST_CHECK_EQUAL(b.value_size(), 0);
359 BOOST_CHECK_EQUAL(*b.wire(), 0xfe);
360}
361
362template<typename T>
363struct MalformedInput
364{
365 static const std::vector<uint8_t> INPUT;
366};
367
368template<>
369const std::vector<uint8_t> MalformedInput<struct TlvTypeZero>::INPUT{
370 0x00, 0x00
371};
372template<>
373const std::vector<uint8_t> MalformedInput<struct TlvTypeTooLarge>::INPUT{
374 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
375};
376template<>
377const std::vector<uint8_t> MalformedInput<struct BadTlvLength>::INPUT{
378 0x01, 0xff, 0x42, 0x42
379};
380template<>
381const std::vector<uint8_t> MalformedInput<struct TruncatedTlvValue>::INPUT{
382 0x01, 0x02, 0x03
383};
384
385using MalformedInputs = boost::mpl::vector<
386 MalformedInput<TlvTypeZero>,
387 MalformedInput<TlvTypeTooLarge>,
388 MalformedInput<BadTlvLength>,
389 MalformedInput<TruncatedTlvValue>
390>;
391
392BOOST_AUTO_TEST_CASE_TEMPLATE(Malformed, T, MalformedInputs)
393{
394 // constructor from raw buffer
395 BOOST_CHECK_THROW(Block(T::INPUT.data(), T::INPUT.size()), tlv::Error);
396
397 // fromStream()
398 std::stringstream stream;
399 stream.write(reinterpret_cast<const char*>(T::INPUT.data()), T::INPUT.size());
400 stream.seekg(0);
401 BOOST_CHECK_THROW(Block::fromStream(stream), tlv::Error);
402
403 // fromBuffer(), ConstBufferPtr overload
404 auto buf = make_shared<Buffer>(T::INPUT.begin(), T::INPUT.end());
405 bool isOk;
406 Block b;
407 std::tie(isOk, b) = Block::fromBuffer(buf, 0);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000408 BOOST_CHECK(!isOk);
Davide Pesavento6b330402019-04-24 00:14:01 -0400409 BOOST_CHECK(!b.isValid());
410
411 // fromBuffer(), raw buffer overload
412 std::tie(isOk, b) = Block::fromBuffer(T::INPUT.data(), T::INPUT.size());
413 BOOST_CHECK(!isOk);
414 BOOST_CHECK(!b.isValid());
Junxiao Shif0da7892015-04-04 22:16:16 -0700415}
416
Davide Pesaventoeee3e822016-11-26 19:19:34 +0100417BOOST_AUTO_TEST_SUITE_END() // Construction
418
Junxiao Shidc4277a2017-07-17 11:34:02 +0000419BOOST_AUTO_TEST_SUITE(SubElements)
420
421BOOST_AUTO_TEST_CASE(Parse)
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700422{
Junxiao Shidc4277a2017-07-17 11:34:02 +0000423 const uint8_t PACKET[] = {
424 0x06, 0x20, // Data
425 0x07, 0x11, // Name
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000426 0x08, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, // GenericNameComponent 'hello'
427 0x08, 0x01, 0x31, // GenericNameComponent '1'
428 0x08, 0x05, 0x77, 0x6f, 0x72, 0x6c, 0x64, // GenericNameComponent 'world'
Junxiao Shidc4277a2017-07-17 11:34:02 +0000429 0x14, 0x00, // MetaInfo empty
430 0x15, 0x00, // Content empty
431 0x16, 0x05, // SignatureInfo
432 0x1b, 0x01, 0x01, // SignatureType RSA
433 0x1c, 0x00, // KeyLocator empty
434 0x17, 0x00 // SignatureValue empty
435 };
Junxiao Shidc4277a2017-07-17 11:34:02 +0000436 Block data(PACKET, sizeof(PACKET));
437 data.parse();
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700438
Junxiao Shidc4277a2017-07-17 11:34:02 +0000439 BOOST_CHECK_EQUAL(data.elements_size(), 5);
440 BOOST_CHECK_EQUAL(data.elements().at(0).type(), 0x07);
441 BOOST_CHECK_EQUAL(data.elements().at(0).elements().size(), 0); // parse is not recursive
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700442
Junxiao Shidc4277a2017-07-17 11:34:02 +0000443 BOOST_CHECK(data.get(0x15) == data.elements().at(2));
444 BOOST_CHECK_THROW(data.get(0x01), Block::Error);
445
446 BOOST_CHECK(data.find(0x15) == data.elements_begin() + 2);
447 BOOST_CHECK(data.find(0x01) == data.elements_end());
Davide Pesavento6b330402019-04-24 00:14:01 -0400448
449 const uint8_t MALFORMED[] = {
450 // TLV-LENGTH of nested element is greater than TLV-LENGTH of enclosing element
451 0x05, 0x05, 0x07, 0x07, 0x08, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f
452 };
453 Block bad(MALFORMED, sizeof(MALFORMED));
454 BOOST_CHECK_THROW(bad.parse(), Block::Error);
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700455}
456
Joao Pereira7476ebf2015-07-07 14:54:39 -0400457BOOST_AUTO_TEST_CASE(InsertBeginning)
458{
459 Block masterBlock(tlv::Name);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000460 Block firstBlock = makeStringBlock(tlv::GenericNameComponent, "firstName");
461 Block secondBlock = makeStringBlock(tlv::GenericNameComponent, "secondName");
462 Block thirdBlock = makeStringBlock(tlv::GenericNameComponent, "thirdName");
Joao Pereira7476ebf2015-07-07 14:54:39 -0400463
464 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 0);
465 masterBlock.push_back(secondBlock);
466 masterBlock.push_back(thirdBlock);
467 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 2);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000468 Block::element_const_iterator it = masterBlock.find(tlv::GenericNameComponent);
Joao Pereira7476ebf2015-07-07 14:54:39 -0400469 BOOST_CHECK_EQUAL(*it == secondBlock, true);
470
471 it = masterBlock.insert(it, firstBlock);
472
473 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 3);
474 BOOST_CHECK_EQUAL(*(it + 1) == secondBlock, true);
475 BOOST_CHECK_EQUAL(*(masterBlock.elements_begin()) == firstBlock, true);
476}
477
478BOOST_AUTO_TEST_CASE(InsertEnd)
479{
480 Block masterBlock(tlv::Name);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000481 Block firstBlock = makeStringBlock(tlv::GenericNameComponent, "firstName");
482 Block secondBlock = makeStringBlock(tlv::GenericNameComponent, "secondName");
483 Block thirdBlock = makeStringBlock(tlv::GenericNameComponent, "thirdName");
Joao Pereira7476ebf2015-07-07 14:54:39 -0400484
485 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 0);
486 masterBlock.push_back(firstBlock);
487 masterBlock.push_back(secondBlock);
488 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 2);
489 Block::element_const_iterator it = masterBlock.elements_end();
490 BOOST_CHECK_EQUAL(*(it - 1) == secondBlock, true);
491
492 it = masterBlock.insert(it, thirdBlock);
493
494 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 3);
495 BOOST_CHECK_EQUAL(*(it - 1) == secondBlock, true);
496 BOOST_CHECK_EQUAL(*(masterBlock.elements_end() - 1) == thirdBlock, true);
497}
498
499BOOST_AUTO_TEST_CASE(InsertMiddle)
500{
501 Block masterBlock(tlv::Name);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000502 Block firstBlock = makeStringBlock(tlv::GenericNameComponent, "firstName");
503 Block secondBlock = makeStringBlock(tlv::GenericNameComponent, "secondName");
504 Block thirdBlock = makeStringBlock(tlv::GenericNameComponent, "thirdName");
Joao Pereira7476ebf2015-07-07 14:54:39 -0400505
506 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 0);
507 masterBlock.push_back(firstBlock);
508 masterBlock.push_back(thirdBlock);
509 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 2);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000510 Block::element_const_iterator it = masterBlock.find(tlv::GenericNameComponent);
Joao Pereira7476ebf2015-07-07 14:54:39 -0400511 BOOST_CHECK_EQUAL(*it == firstBlock, true);
512
Junxiao Shidc4277a2017-07-17 11:34:02 +0000513 it = masterBlock.insert(it + 1, secondBlock);
Joao Pereira7476ebf2015-07-07 14:54:39 -0400514
515 BOOST_CHECK_EQUAL(*it == secondBlock, true);
516 BOOST_CHECK_EQUAL(*(it + 1) == thirdBlock, true);
517 BOOST_CHECK_EQUAL(*(it - 1) == firstBlock, true);
518}
519
520BOOST_AUTO_TEST_CASE(EraseSingleElement)
521{
522 Block masterBlock(tlv::Name);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000523 Block firstBlock = makeStringBlock(tlv::GenericNameComponent, "firstName");
524 Block secondBlock = makeStringBlock(tlv::GenericNameComponent, "secondName");
525 Block thirdBlock = makeStringBlock(tlv::GenericNameComponent, "thirdName");
Joao Pereira7476ebf2015-07-07 14:54:39 -0400526
527 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 0);
528 masterBlock.push_back(firstBlock);
529 masterBlock.push_back(secondBlock);
530 masterBlock.push_back(thirdBlock);
531 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 3);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000532 Block::element_const_iterator it = masterBlock.find(tlv::GenericNameComponent);
Joao Pereira7476ebf2015-07-07 14:54:39 -0400533 it++;
534 BOOST_CHECK_EQUAL(*it == secondBlock, true);
535
536 it = masterBlock.erase(it);
537
538 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 2);
539 BOOST_CHECK_EQUAL(*(it) == thirdBlock, true);
540 BOOST_CHECK_EQUAL(*(it - 1) == firstBlock, true);
541}
542
543BOOST_AUTO_TEST_CASE(EraseRange)
544{
545 Block masterBlock(tlv::Name);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000546 Block firstBlock = makeStringBlock(tlv::GenericNameComponent, "firstName");
547 Block secondBlock = makeStringBlock(tlv::GenericNameComponent, "secondName");
548 Block thirdBlock = makeStringBlock(tlv::GenericNameComponent, "thirdName");
549 Block fourthBlock = makeStringBlock(tlv::GenericNameComponent, "fourthName");
550 Block fifthBlock = makeStringBlock(tlv::GenericNameComponent, "fifthName");
551 Block sixthBlock = makeStringBlock(tlv::GenericNameComponent, "sixthName");
Joao Pereira7476ebf2015-07-07 14:54:39 -0400552
553 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 0);
554 masterBlock.push_back(firstBlock);
555 masterBlock.push_back(secondBlock);
556 masterBlock.push_back(thirdBlock);
557 masterBlock.push_back(fourthBlock);
558 masterBlock.push_back(fifthBlock);
559 masterBlock.push_back(sixthBlock);
560 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 6);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000561 Block::element_const_iterator itStart = masterBlock.find(tlv::GenericNameComponent);
Joao Pereira7476ebf2015-07-07 14:54:39 -0400562 itStart++;
563 Block::element_const_iterator itEnd = itStart + 3;
564 BOOST_CHECK_EQUAL(*itStart == secondBlock, true);
565 BOOST_CHECK_EQUAL(*itEnd == fifthBlock, true);
566
567 Block::element_const_iterator newIt = masterBlock.erase(itStart, itEnd);
568
569 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 3);
570 BOOST_CHECK_EQUAL(*(newIt) == fifthBlock, true);
571 BOOST_CHECK_EQUAL(*(newIt - 1) == firstBlock, true);
572}
573
Eric Newberrya3d9fc02015-07-26 10:55:44 -0700574BOOST_AUTO_TEST_CASE(Remove)
575{
576 Block block(tlv::Data);
577 block.push_back(makeNonNegativeIntegerBlock(tlv::ContentType, 0));
578 block.push_back(makeNonNegativeIntegerBlock(tlv::FreshnessPeriod, 123));
579 block.push_back(makeStringBlock(tlv::Name, "ndn:/test-prefix"));
580 block.push_back(makeNonNegativeIntegerBlock(tlv::ContentType, 2));
581 block.push_back(makeNonNegativeIntegerBlock(tlv::ContentType, 1));
582
583 BOOST_CHECK_EQUAL(5, block.elements_size());
Davide Pesavento6b330402019-04-24 00:14:01 -0400584 BOOST_CHECK_NO_THROW(block.remove(tlv::ContentType));
585 BOOST_REQUIRE_EQUAL(2, block.elements_size());
Eric Newberrya3d9fc02015-07-26 10:55:44 -0700586
Davide Pesavento6b330402019-04-24 00:14:01 -0400587 auto elements = block.elements();
Eric Newberrya3d9fc02015-07-26 10:55:44 -0700588 BOOST_CHECK_EQUAL(tlv::FreshnessPeriod, elements[0].type());
589 BOOST_CHECK_EQUAL(123, readNonNegativeInteger(elements[0]));
590 BOOST_CHECK_EQUAL(tlv::Name, elements[1].type());
Davide Pesavento6b330402019-04-24 00:14:01 -0400591 BOOST_CHECK_EQUAL(readString(elements[1]).compare("ndn:/test-prefix"), 0);
Eric Newberrya3d9fc02015-07-26 10:55:44 -0700592}
593
Junxiao Shidc4277a2017-07-17 11:34:02 +0000594BOOST_AUTO_TEST_SUITE_END() // SubElements
595
596BOOST_AUTO_TEST_CASE(Equality)
597{
Davide Pesaventob10024c2017-09-22 01:36:44 -0400598 const uint8_t one[] = {0x08, 0x00};
599 Block a(one, sizeof(one));
600 Block b(one, sizeof(one));
Junxiao Shidc4277a2017-07-17 11:34:02 +0000601 BOOST_CHECK_EQUAL(a == b, true);
602 BOOST_CHECK_EQUAL(a != b, false);
603
Davide Pesaventob10024c2017-09-22 01:36:44 -0400604 const uint8_t two[] = {0x06, 0x00};
605 Block c(two, sizeof(two));
606 Block d(one, sizeof(one));
Junxiao Shidc4277a2017-07-17 11:34:02 +0000607 BOOST_CHECK_EQUAL(c == d, false);
608 BOOST_CHECK_EQUAL(c != d, true);
609
Davide Pesaventob10024c2017-09-22 01:36:44 -0400610 const uint8_t three[] = {0x06, 0x01, 0xcc};
611 Block e(two, sizeof(two));
612 Block f(three, sizeof(three));
Junxiao Shidc4277a2017-07-17 11:34:02 +0000613 BOOST_CHECK_EQUAL(e == f, false);
614 BOOST_CHECK_EQUAL(e != f, true);
615}
616
Junxiao Shi72c0c642018-04-20 15:41:09 +0000617BOOST_AUTO_TEST_CASE(Print)
618{
619 // default constructed
620 Block b;
621 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(b), "[invalid]");
622
623 // zero length
624 b = "0700"_block;
625 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(b), "7[empty]");
626
627 // unparsed
628 b = "0E10FF7E4E6B3B21C902660F16ED589FCCCC"_block;
629 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(b),
630 "14[16]=FF7E4E6B3B21C902660F16ED589FCCCC");
631 // set and restore format flags
632 {
633 std::ostringstream oss;
634 oss << std::showbase << std::hex << 0xd23c4 << b << 0x4981e;
635 BOOST_CHECK_EQUAL(oss.str(), "0xd23c414[16]=FF7E4E6B3B21C902660F16ED589FCCCC0x4981e");
636 }
637
638 // parsed
639 b = "FD010808 0502CADD 59024E42"_block;
640 b.parse();
641 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(b),
642 "264[8]={5[2]=CADD,89[2]=4E42}");
643
644 // parsed then modified: print modified sub-elements
645 b = "FD010808 0502CADD 59024E42"_block;
646 b.parse();
647 b.erase(b.elements_begin());
648 b.push_back("10022386"_block);
649 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(b),
650 "264[8]={89[2]=4E42,16[2]=2386}");
651}
652
Junxiao Shi2b322eb2018-08-24 10:43:27 -0600653BOOST_AUTO_TEST_SUITE(BlockLiteral)
654
655BOOST_AUTO_TEST_CASE(Simple)
656{
Davide Pesavento6b330402019-04-24 00:14:01 -0400657 Block b0 = "4200"_block;
658 BOOST_CHECK_EQUAL(b0.type(), 0x42);
Junxiao Shi2b322eb2018-08-24 10:43:27 -0600659 BOOST_CHECK_EQUAL(b0.value_size(), 0);
660
661 Block b1 = "0101A0"_block;
662 BOOST_CHECK_EQUAL(b1.type(), 0x01);
663 BOOST_REQUIRE_EQUAL(b1.value_size(), 1);
664 BOOST_CHECK_EQUAL(b1.value()[0], 0xA0);
665}
666
667BOOST_AUTO_TEST_CASE(Comment)
668{
669 Block b0 = "a2b0c0d2eBf0G.B 1+"_block;
670 BOOST_CHECK_EQUAL(b0.type(), 0x20);
671 BOOST_REQUIRE_EQUAL(b0.value_size(), 2);
672 BOOST_CHECK_EQUAL(b0.value()[0], 0xB0);
673 BOOST_CHECK_EQUAL(b0.value()[1], 0xB1);
674}
675
676BOOST_AUTO_TEST_CASE(BadInput)
677{
678 BOOST_CHECK_THROW(""_block, std::invalid_argument);
679 BOOST_CHECK_THROW("1"_block, std::invalid_argument);
680 BOOST_CHECK_THROW("333"_block, std::invalid_argument);
Davide Pesavento6b330402019-04-24 00:14:01 -0400681 BOOST_CHECK_THROW("xx yy zz"_block, std::invalid_argument); // only comments
Junxiao Shi2b322eb2018-08-24 10:43:27 -0600682
Davide Pesavento6b330402019-04-24 00:14:01 -0400683 BOOST_CHECK_THROW("0000"_block, tlv::Error); // invalid type
684 BOOST_CHECK_THROW("0202C0"_block, tlv::Error); // truncated value
685 BOOST_CHECK_THROW("0201C0C1"_block, tlv::Error); // trailing garbage
Junxiao Shi2b322eb2018-08-24 10:43:27 -0600686}
687
688BOOST_AUTO_TEST_SUITE_END() // BlockLiteral
689
Davide Pesaventoeee3e822016-11-26 19:19:34 +0100690BOOST_AUTO_TEST_SUITE_END() // TestBlock
691BOOST_AUTO_TEST_SUITE_END() // Encoding
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800692
Alexander Afanasyev74633892015-02-08 18:08:46 -0800693} // namespace tests
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800694} // namespace ndn