blob: b4f2cf84f0708e3fa268a35b9ff5f70069f58806 [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 Pesavento152ef442023-04-22 02:02:29 -04003 * Copyright (c) 2013-2023 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
Davide Pesaventoa76ea9a2021-04-24 00:06:02 -040027#include <boost/asio/buffer.hpp>
Junxiao Shi72c0c642018-04-20 15:41:09 +000028#include <boost/lexical_cast.hpp>
Davide Pesavento1a4a7bf2020-12-04 22:30:46 -050029#include <boost/test/data/test_case.hpp>
Davide Pesavento6b330402019-04-24 00:14:01 -040030
Junxiao Shidc4277a2017-07-17 11:34:02 +000031#include <cstring>
32#include <sstream>
Davide Pesaventoeee3e822016-11-26 19:19:34 +010033
Davide Pesavento47ce2ee2023-05-09 01:33:33 -040034namespace ndn::tests {
Alexander Afanasyev233750e2014-02-16 00:50:07 -080035
Davide Pesavento152ef442023-04-22 02:02:29 -040036BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Block>));
37
Davide Pesaventoeee3e822016-11-26 19:19:34 +010038BOOST_AUTO_TEST_SUITE(Encoding)
39BOOST_AUTO_TEST_SUITE(TestBlock)
Alexander Afanasyev233750e2014-02-16 00:50:07 -080040
Junxiao Shidc4277a2017-07-17 11:34:02 +000041BOOST_AUTO_TEST_SUITE(Construction)
42
43static const uint8_t TEST_BUFFER[] = {
Davide Pesavento6b330402019-04-24 00:14:01 -040044 0x42, 0x01, 0xfa,
45 0x01, 0x01, 0xfb,
46 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, // bug #4726
Alexander Afanasyev74633892015-02-08 18:08:46 -080047};
Alexander Afanasyev2d0b4572014-02-24 16:02:12 -080048
Davide Pesavento6b330402019-04-24 00:14:01 -040049BOOST_AUTO_TEST_CASE(Default)
Alexander Afanasyev74633892015-02-08 18:08:46 -080050{
Junxiao Shidc4277a2017-07-17 11:34:02 +000051 Block b;
Davide Pesavento6b330402019-04-24 00:14:01 -040052
53 BOOST_CHECK_EQUAL(b.isValid(), false);
Davide Pesavento6b330402019-04-24 00:14:01 -040054 BOOST_CHECK_EQUAL(b.type(), tlv::Invalid);
55 BOOST_CHECK_EQUAL(b.hasValue(), false);
56 BOOST_CHECK_EQUAL(b.value_size(), 0);
Davide Pesavento258d51a2022-02-27 21:26:28 -050057 BOOST_CHECK_EQUAL(b.value_bytes().empty(), true);
Davide Pesavento6b330402019-04-24 00:14:01 -040058 BOOST_CHECK(b.value() == nullptr);
59
Davide Pesavento6b330402019-04-24 00:14:01 -040060 BOOST_CHECK_THROW(b.begin(), Block::Error);
61 BOOST_CHECK_THROW(b.end(), Block::Error);
Davide Pesavento258d51a2022-02-27 21:26:28 -050062 BOOST_CHECK_THROW(b.data(), Block::Error);
63 BOOST_CHECK_THROW(b.size(), Block::Error);
Davide Pesavento6b330402019-04-24 00:14:01 -040064 BOOST_CHECK_THROW(b.blockFromValue(), Block::Error);
Alexander Afanasyev74633892015-02-08 18:08:46 -080065}
Alexander Afanasyev937aa782014-03-21 13:17:57 -070066
Junxiao Shidc4277a2017-07-17 11:34:02 +000067BOOST_AUTO_TEST_CASE(FromEncodingBuffer)
Alexander Afanasyev74633892015-02-08 18:08:46 -080068{
Junxiao Shidc4277a2017-07-17 11:34:02 +000069 EncodingBuffer encoder;
Davide Pesavento5c803b92019-02-02 19:23:48 -050070 BOOST_CHECK_THROW(Block{encoder}, tlv::Error);
71
72 const uint8_t VALUE[] = {0x11, 0x12, 0x13, 0x14};
Davide Pesaventofbea4fc2022-02-08 07:26:04 -050073 size_t length = encoder.prependBytes(VALUE);
Junxiao Shidc4277a2017-07-17 11:34:02 +000074 encoder.prependVarNumber(length);
75 encoder.prependVarNumber(0xe0);
76
77 Block b = encoder.block();
78 BOOST_CHECK_EQUAL(b.type(), 0xe0);
79 BOOST_CHECK_EQUAL(b.value_size(), sizeof(VALUE));
80 BOOST_CHECK_EQUAL_COLLECTIONS(b.value_begin(), b.value_end(),
81 VALUE, VALUE + sizeof(VALUE));
82
83 b = Block(encoder);
84 BOOST_CHECK_EQUAL(b.type(), 0xe0);
85 BOOST_CHECK_EQUAL(b.value_size(), sizeof(VALUE));
86 BOOST_CHECK_EQUAL_COLLECTIONS(b.value_begin(), b.value_end(),
87 VALUE, VALUE + sizeof(VALUE));
Alexander Afanasyev74633892015-02-08 18:08:46 -080088}
Alexander Afanasyev937aa782014-03-21 13:17:57 -070089
Davide Pesaventoeee3e822016-11-26 19:19:34 +010090BOOST_AUTO_TEST_CASE(FromBlock)
Alexander Afanasyev4448d292015-08-09 20:11:37 -070091{
Davide Pesaventofbea4fc2022-02-08 07:26:04 -050092 const uint8_t buf[] = {0x80, 0x06, 0x81, 0x01, 0x01, 0x82, 0x01, 0x01};
93 Block block(buf);
Alexander Afanasyev4448d292015-08-09 20:11:37 -070094
95 Block derivedBlock(block, block.begin(), block.end());
Davide Pesavento258d51a2022-02-27 21:26:28 -050096 BOOST_CHECK_EQUAL(derivedBlock.data(), block.data()); // pointers should match
Davide Pesaventofbea4fc2022-02-08 07:26:04 -050097 BOOST_CHECK_EQUAL(derivedBlock, block); // blocks should match
Alexander Afanasyev4448d292015-08-09 20:11:37 -070098
99 derivedBlock = Block(block, block.begin() + 2, block.begin() + 5);
100 BOOST_CHECK(derivedBlock.begin() == block.begin() + 2);
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500101 BOOST_CHECK_EQUAL(derivedBlock, Block(make_span(buf + 2, 3)));
Alexander Afanasyev4448d292015-08-09 20:11:37 -0700102
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500103 Buffer otherBuffer(buf, sizeof(buf));
Junxiao Shidb7464d2017-07-13 03:11:17 +0000104 BOOST_CHECK_THROW(Block(block, otherBuffer.begin(), block.end()), std::invalid_argument);
105 BOOST_CHECK_THROW(Block(block, block.begin(), otherBuffer.end()), std::invalid_argument);
106 BOOST_CHECK_THROW(Block(block, otherBuffer.begin(), otherBuffer.end()), std::invalid_argument);
Alexander Afanasyev4448d292015-08-09 20:11:37 -0700107}
108
Davide Pesaventoeee3e822016-11-26 19:19:34 +0100109BOOST_AUTO_TEST_CASE(FromBlockCopyOnWriteModifyOriginal)
Eric Newberry6235aac2015-08-13 16:03:47 -0700110{
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500111 const uint8_t buf[] = {
Eric Newberry6235aac2015-08-13 16:03:47 -0700112 0x05, 0x0b, 0x07, 0x03, 0x01, 0x02, 0x03, 0x0a, 0x04, 0x04, 0x05, 0x06, 0x07,
113 };
114
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500115 Block b1(buf);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000116 Block b2(b1, b1.begin(), b1.end());
117 auto buf2 = b2.getBuffer();
Eric Newberry6235aac2015-08-13 16:03:47 -0700118
Junxiao Shidc4277a2017-07-17 11:34:02 +0000119 b1.parse();
120 b1.remove(tlv::Name);
121 b1.encode();
Eric Newberry6235aac2015-08-13 16:03:47 -0700122
Junxiao Shidc4277a2017-07-17 11:34:02 +0000123 b2.parse();
Davide Pesaventodf8fd8a2022-02-21 20:04:21 -0500124 BOOST_TEST(b2 == buf, boost::test_tools::per_element());
125 BOOST_TEST(buf2 == b2.getBuffer()); // check pointers
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{
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500130 const uint8_t buf[] = {
Eric Newberry6235aac2015-08-13 16:03:47 -0700131 0x05, 0x0b, 0x07, 0x03, 0x01, 0x02, 0x03, 0x0a, 0x04, 0x04, 0x05, 0x06, 0x07,
132 };
133
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500134 Block b1(buf);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000135 auto buf1 = b1.getBuffer();
Junxiao Shidc4277a2017-07-17 11:34:02 +0000136 Block b2(b1, b1.begin(), b1.end());
Eric Newberry6235aac2015-08-13 16:03:47 -0700137
Junxiao Shidc4277a2017-07-17 11:34:02 +0000138 b2.parse();
139 b2.remove(tlv::Name);
140 b2.encode();
Eric Newberry6235aac2015-08-13 16:03:47 -0700141
Junxiao Shidc4277a2017-07-17 11:34:02 +0000142 b1.parse();
Davide Pesaventodf8fd8a2022-02-21 20:04:21 -0500143 BOOST_TEST(b1 == buf, boost::test_tools::per_element());
144 BOOST_TEST(buf1 == b1.getBuffer()); // check pointers
Eric Newberry6235aac2015-08-13 16:03:47 -0700145}
146
Junxiao Shidc4277a2017-07-17 11:34:02 +0000147BOOST_AUTO_TEST_CASE(FromType)
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800148{
Junxiao Shidc4277a2017-07-17 11:34:02 +0000149 Block b1(4);
Davide Pesavento6b330402019-04-24 00:14:01 -0400150 BOOST_CHECK_EQUAL(b1.isValid(), true);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000151 BOOST_CHECK_EQUAL(b1.type(), 4);
152 BOOST_CHECK_EQUAL(b1.size(), 2); // 1-octet TLV-TYPE and 1-octet TLV-LENGTH
Davide Pesavento5c803b92019-02-02 19:23:48 -0500153 BOOST_CHECK_EQUAL(b1.hasValue(), false);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000154 BOOST_CHECK_EQUAL(b1.value_size(), 0);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500155 BOOST_CHECK_EQUAL(b1.value_bytes().empty(), true);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400156 BOOST_CHECK(b1.value() == nullptr);
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800157
Junxiao Shidc4277a2017-07-17 11:34:02 +0000158 Block b2(258);
Davide Pesavento6b330402019-04-24 00:14:01 -0400159 BOOST_CHECK_EQUAL(b2.isValid(), true);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000160 BOOST_CHECK_EQUAL(b2.type(), 258);
161 BOOST_CHECK_EQUAL(b2.size(), 4); // 3-octet TLV-TYPE and 1-octet TLV-LENGTH
Davide Pesavento5c803b92019-02-02 19:23:48 -0500162 BOOST_CHECK_EQUAL(b2.hasValue(), false);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000163 BOOST_CHECK_EQUAL(b2.value_size(), 0);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500164 BOOST_CHECK_EQUAL(b2.value_bytes().empty(), true);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400165 BOOST_CHECK(b2.value() == nullptr);
Davide Pesavento6b330402019-04-24 00:14:01 -0400166
167 Block b3(tlv::Invalid);
168 BOOST_CHECK_EQUAL(b3.isValid(), false);
169 BOOST_CHECK_EQUAL(b3.type(), tlv::Invalid);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400170 BOOST_CHECK_EXCEPTION(b3.size(), Block::Error, [] (const auto& e) {
Davide Pesavento21b7f1b2023-04-28 23:21:02 -0400171 return e.what() == "Cannot determine size of invalid block"sv;
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400172 });
Davide Pesavento6b330402019-04-24 00:14:01 -0400173 BOOST_CHECK_EQUAL(b3.hasValue(), false);
174 BOOST_CHECK_EQUAL(b3.value_size(), 0);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500175 BOOST_CHECK_EQUAL(b3.value_bytes().empty(), true);
Davide Pesavento6b330402019-04-24 00:14:01 -0400176 BOOST_CHECK(b3.value() == nullptr);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700177}
178
Davide Pesavento5c803b92019-02-02 19:23:48 -0500179BOOST_AUTO_TEST_CASE(FromTypeAndBuffer)
180{
181 const uint8_t VALUE[] = {0x11, 0x12, 0x13, 0x14};
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500182 auto bufferPtr = std::make_shared<Buffer>(VALUE, sizeof(VALUE));
Davide Pesavento5c803b92019-02-02 19:23:48 -0500183
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400184 Block b1(42, std::move(bufferPtr));
185 BOOST_CHECK_EQUAL(b1.isValid(), true);
186 BOOST_CHECK_EQUAL(b1.type(), 42);
187 BOOST_CHECK_EQUAL(b1.size(), 6);
188 BOOST_CHECK_EQUAL(b1.hasValue(), true);
189 BOOST_CHECK_EQUAL(b1.value_size(), sizeof(VALUE));
Davide Pesavento258d51a2022-02-27 21:26:28 -0500190 BOOST_CHECK_EQUAL(b1.value_bytes().size(), sizeof(VALUE));
191 BOOST_CHECK_EQUAL(b1.value_bytes().front(), 0x11);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400192 BOOST_CHECK(b1.value() != nullptr);
193
194 // empty buffer as TLV-VALUE
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500195 Block b2(63, std::make_shared<Buffer>());
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400196 BOOST_CHECK_EQUAL(b2.isValid(), true);
197 BOOST_CHECK_EQUAL(b2.type(), 63);
198 BOOST_CHECK_EQUAL(b2.size(), 2);
199 BOOST_CHECK_EQUAL(b2.hasValue(), true);
200 BOOST_CHECK_EQUAL(b2.value_size(), 0);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500201 BOOST_CHECK_EQUAL(b2.value_bytes().empty(), true);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400202 BOOST_CHECK(b2.value() == nullptr);
Davide Pesavento5c803b92019-02-02 19:23:48 -0500203}
204
205BOOST_AUTO_TEST_CASE(FromTypeAndBlock)
206{
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500207 const uint8_t buf[] = {0x80, 0x06, 0x81, 0x01, 0x01, 0x82, 0x01, 0x01};
208 Block nested(buf);
Davide Pesavento5c803b92019-02-02 19:23:48 -0500209
210 Block b(84, nested);
Davide Pesavento6b330402019-04-24 00:14:01 -0400211 BOOST_CHECK_EQUAL(b.isValid(), true);
Davide Pesavento5c803b92019-02-02 19:23:48 -0500212 BOOST_CHECK_EQUAL(b.type(), 84);
213 BOOST_CHECK_EQUAL(b.size(), 10);
214 BOOST_CHECK_EQUAL(b.hasValue(), true);
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500215 BOOST_CHECK_EQUAL(b.value_size(), sizeof(buf));
Davide Pesavento258d51a2022-02-27 21:26:28 -0500216 BOOST_CHECK_EQUAL(b.value_bytes().size(), sizeof(buf));
217 BOOST_CHECK_EQUAL(b.value_bytes().front(), 0x80);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400218 BOOST_CHECK(b.value() != nullptr);
Davide Pesavento5c803b92019-02-02 19:23:48 -0500219}
220
Junxiao Shif0da7892015-04-04 22:16:16 -0700221BOOST_AUTO_TEST_CASE(FromStream)
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700222{
Junxiao Shidc4277a2017-07-17 11:34:02 +0000223 std::stringstream stream;
224 stream.write(reinterpret_cast<const char*>(TEST_BUFFER), sizeof(TEST_BUFFER));
225 stream.seekg(0);
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700226
Junxiao Shidc4277a2017-07-17 11:34:02 +0000227 Block b = Block::fromStream(stream);
Davide Pesavento6b330402019-04-24 00:14:01 -0400228 BOOST_CHECK_EQUAL(b.type(), 66);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000229 BOOST_CHECK_EQUAL(b.size(), 3);
230 BOOST_CHECK_EQUAL(b.value_size(), 1);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500231 BOOST_CHECK_EQUAL(b.value_bytes().size(), 1);
232 BOOST_CHECK_EQUAL(*b.data(), 0x42);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000233 BOOST_CHECK_EQUAL(*b.value(), 0xfa);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500234 BOOST_CHECK_EQUAL(b.value_bytes().front(), 0xfa);
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700235
Junxiao Shidc4277a2017-07-17 11:34:02 +0000236 b = Block::fromStream(stream);
237 BOOST_CHECK_EQUAL(b.type(), 1);
238 BOOST_CHECK_EQUAL(b.size(), 3);
239 BOOST_CHECK_EQUAL(b.value_size(), 1);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500240 BOOST_CHECK_EQUAL(b.value_bytes().size(), 1);
241 BOOST_CHECK_EQUAL(*b.data(), 0x01);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000242 BOOST_CHECK_EQUAL(*b.value(), 0xfb);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500243 BOOST_CHECK_EQUAL(b.value_bytes().front(), 0xfb);
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700244
Davide Pesavento6b330402019-04-24 00:14:01 -0400245 b = Block::fromStream(stream);
246 BOOST_CHECK_EQUAL(b.type(), 0xffffffff);
247 BOOST_CHECK_EQUAL(b.size(), 6);
248 BOOST_CHECK_EQUAL(b.value_size(), 0);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500249 BOOST_CHECK_EQUAL(b.value_bytes().size(), 0);
250 BOOST_CHECK_EQUAL(*b.data(), 0xfe);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400251 BOOST_CHECK(b.value() == nullptr);
Davide Pesavento6b330402019-04-24 00:14:01 -0400252
253 BOOST_CHECK(stream.eof());
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400254 BOOST_CHECK_EXCEPTION(Block::fromStream(stream), tlv::Error, [] (const auto& e) {
Davide Pesavento21b7f1b2023-04-28 23:21:02 -0400255 return e.what() == "Insufficient data during TLV parsing"sv;
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400256 });
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700257}
258
Junxiao Shif0da7892015-04-04 22:16:16 -0700259BOOST_AUTO_TEST_CASE(FromStreamWhitespace) // Bug 2728
260{
Junxiao Shidc4277a2017-07-17 11:34:02 +0000261 const uint8_t PACKET[] = {
Junxiao Shif0da7892015-04-04 22:16:16 -0700262 0x06, 0x20, // Data
263 0x07, 0x11, // Name
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000264 0x08, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, // GenericNameComponent 'hello'
265 0x08, 0x01, 0x31, // GenericNameComponent '1'
266 0x08, 0x05, 0x77, 0x6f, 0x72, 0x6c, 0x64, // GenericNameComponent 'world'
Junxiao Shif0da7892015-04-04 22:16:16 -0700267 0x14, 0x00, // MetaInfo empty
268 0x15, 0x00, // Content empty
269 0x16, 0x05, // SignatureInfo
Junxiao Shidc4277a2017-07-17 11:34:02 +0000270 0x1b, 0x01, 0x01, // SignatureType RSA
271 0x1c, 0x00, // KeyLocator empty
Junxiao Shif0da7892015-04-04 22:16:16 -0700272 0x17, 0x00 // SignatureValue empty
273 };
274 // TLV-LENGTH of <Data> is 0x20 which happens to be ASCII whitespace
275
276 std::stringstream stream;
277 stream.write(reinterpret_cast<const char*>(PACKET), sizeof(PACKET));
278 stream.seekg(0);
279
Junxiao Shidc4277a2017-07-17 11:34:02 +0000280 Block b = Block::fromStream(stream);
281 BOOST_CHECK_EQUAL(b.type(), 6);
282 BOOST_CHECK_EQUAL(b.value_size(), 32);
283 b.parse();
Davide Pesavento6b330402019-04-24 00:14:01 -0400284 BOOST_CHECK_EQUAL(b.elements_size(), 5);
Junxiao Shif0da7892015-04-04 22:16:16 -0700285}
286
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000287BOOST_AUTO_TEST_CASE(FromStreamZeroLength)
Junxiao Shif0da7892015-04-04 22:16:16 -0700288{
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000289 const uint8_t BUFFER[] = {0x70, 0x00,
290 0x71, 0x03, 0x86, 0x11, 0x24,
291 0x72, 0x00};
Junxiao Shif0da7892015-04-04 22:16:16 -0700292
293 std::stringstream stream;
294 stream.write(reinterpret_cast<const char*>(BUFFER), sizeof(BUFFER));
295 stream.seekg(0);
296
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000297 Block b1 = Block::fromStream(stream);
298 BOOST_CHECK_EQUAL(b1.type(), 0x70);
299 BOOST_CHECK_EQUAL(b1.value_size(), 0);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500300 BOOST_CHECK_EQUAL(b1.value_bytes().size(), 0);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400301 BOOST_CHECK(b1.value() == nullptr);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000302
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000303 Block b2 = Block::fromStream(stream);
304 BOOST_CHECK_EQUAL(b2.type(), 0x71);
305 BOOST_CHECK_EQUAL(b2.value_size(), 3);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500306 BOOST_CHECK_EQUAL(b2.value_bytes().size(), 3);
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000307 const uint8_t EXPECTED_VALUE2[] = {0x86, 0x11, 0x24};
Davide Pesavento258d51a2022-02-27 21:26:28 -0500308 BOOST_TEST(b2.value_bytes() == EXPECTED_VALUE2, boost::test_tools::per_element());
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000309
310 Block b3 = Block::fromStream(stream);
311 BOOST_CHECK_EQUAL(b3.type(), 0x72);
312 BOOST_CHECK_EQUAL(b3.value_size(), 0);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500313 BOOST_CHECK_EQUAL(b3.value_bytes().size(), 0);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400314 BOOST_CHECK(b3.value() == nullptr);
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000315
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400316 BOOST_CHECK_EXCEPTION(Block::fromStream(stream), tlv::Error, [] (const auto& e) {
Davide Pesavento21b7f1b2023-04-28 23:21:02 -0400317 return e.what() == "Insufficient data during TLV parsing"sv;
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400318 });
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000319}
320
321BOOST_AUTO_TEST_CASE(FromStreamPacketTooLarge)
322{
323 const uint8_t BUFFER[] = {0x07, 0xfe, 0x00, 0x01, 0x00, 0x00};
324
325 std::stringstream stream;
326 stream.write(reinterpret_cast<const char*>(BUFFER), sizeof(BUFFER));
327 for (int i = 0; i < 0x10000; ++i) {
328 stream.put('\0');
329 }
330 stream.seekg(0);
331
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400332 BOOST_CHECK_EXCEPTION(Block::fromStream(stream), tlv::Error, [] (const auto& e) {
Davide Pesavento21b7f1b2023-04-28 23:21:02 -0400333 return e.what() == "TLV-LENGTH from stream exceeds limit"sv;
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400334 });
Junxiao Shidc4277a2017-07-17 11:34:02 +0000335}
336
337BOOST_AUTO_TEST_CASE(FromWireBuffer)
338{
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500339 auto buffer = std::make_shared<Buffer>(TEST_BUFFER, sizeof(TEST_BUFFER));
Junxiao Shidc4277a2017-07-17 11:34:02 +0000340
Junxiao Shidc4277a2017-07-17 11:34:02 +0000341 bool isOk = false;
342 Block b;
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500343 std::tie(isOk, b) = Block::fromBuffer(buffer);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000344 BOOST_CHECK(isOk);
Davide Pesavento6b330402019-04-24 00:14:01 -0400345 BOOST_CHECK_EQUAL(b.type(), 66);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000346 BOOST_CHECK_EQUAL(b.size(), 3);
347 BOOST_CHECK_EQUAL(b.value_size(), 1);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500348 BOOST_CHECK_EQUAL(b.value_bytes().size(), 1);
349 BOOST_CHECK_EQUAL(*b.data(), 0x42);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000350 BOOST_CHECK_EQUAL(*b.value(), 0xfa);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500351 BOOST_CHECK_EQUAL(b.value_bytes().front(), 0xfa);
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500352 size_t offset = b.size();
Junxiao Shidc4277a2017-07-17 11:34:02 +0000353
354 std::tie(isOk, b) = Block::fromBuffer(buffer, offset);
355 BOOST_CHECK(isOk);
356 BOOST_CHECK_EQUAL(b.type(), 1);
357 BOOST_CHECK_EQUAL(b.size(), 3);
358 BOOST_CHECK_EQUAL(b.value_size(), 1);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500359 BOOST_CHECK_EQUAL(b.value_bytes().size(), 1);
360 BOOST_CHECK_EQUAL(*b.data(), 0x01);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000361 BOOST_CHECK_EQUAL(*b.value(), 0xfb);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500362 BOOST_CHECK_EQUAL(b.value_bytes().front(), 0xfb);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000363 offset += b.size();
364
365 std::tie(isOk, b) = Block::fromBuffer(buffer, offset);
Davide Pesavento6b330402019-04-24 00:14:01 -0400366 BOOST_CHECK(isOk);
367 BOOST_CHECK_EQUAL(b.type(), 0xffffffff);
368 BOOST_CHECK_EQUAL(b.size(), 6);
369 BOOST_CHECK_EQUAL(b.value_size(), 0);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500370 BOOST_CHECK_EQUAL(b.value_bytes().empty(), true);
371 BOOST_CHECK_EQUAL(*b.data(), 0xfe);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400372 BOOST_CHECK(b.value() == nullptr);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000373}
374
375BOOST_AUTO_TEST_CASE(FromRawBuffer)
376{
Junxiao Shidc4277a2017-07-17 11:34:02 +0000377 bool isOk = false;
378 Block b;
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500379 std::tie(isOk, b) = Block::fromBuffer(TEST_BUFFER);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000380 BOOST_CHECK(isOk);
Davide Pesavento6b330402019-04-24 00:14:01 -0400381 BOOST_CHECK_EQUAL(b.type(), 66);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000382 BOOST_CHECK_EQUAL(b.size(), 3);
383 BOOST_CHECK_EQUAL(b.value_size(), 1);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500384 BOOST_CHECK_EQUAL(b.value_bytes().size(), 1);
385 BOOST_CHECK_EQUAL(*b.data(), 0x42);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000386 BOOST_CHECK_EQUAL(*b.value(), 0xfa);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500387 BOOST_CHECK_EQUAL(b.value_bytes().front(), 0xfa);
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500388 auto offset = b.size();
Junxiao Shidc4277a2017-07-17 11:34:02 +0000389
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500390 std::tie(isOk, b) = Block::fromBuffer(make_span(TEST_BUFFER).subspan(offset));
Junxiao Shidc4277a2017-07-17 11:34:02 +0000391 BOOST_CHECK(isOk);
392 BOOST_CHECK_EQUAL(b.type(), 1);
393 BOOST_CHECK_EQUAL(b.size(), 3);
394 BOOST_CHECK_EQUAL(b.value_size(), 1);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500395 BOOST_CHECK_EQUAL(b.value_bytes().size(), 1);
396 BOOST_CHECK_EQUAL(*b.data(), 0x01);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000397 BOOST_CHECK_EQUAL(*b.value(), 0xfb);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500398 BOOST_CHECK_EQUAL(b.value_bytes().front(), 0xfb);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000399 offset += b.size();
400
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500401 std::tie(isOk, b) = Block::fromBuffer(make_span(TEST_BUFFER).subspan(offset));
Davide Pesavento6b330402019-04-24 00:14:01 -0400402 BOOST_CHECK(isOk);
403 BOOST_CHECK_EQUAL(b.type(), 0xffffffff);
404 BOOST_CHECK_EQUAL(b.size(), 6);
405 BOOST_CHECK_EQUAL(b.value_size(), 0);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500406 BOOST_CHECK_EQUAL(b.value_bytes().empty(), true);
407 BOOST_CHECK_EQUAL(*b.data(), 0xfe);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400408 BOOST_CHECK(b.value() == nullptr);
Davide Pesavento6b330402019-04-24 00:14:01 -0400409}
410
Davide Pesavento1a4a7bf2020-12-04 22:30:46 -0500411static const Buffer MalformedInputs[] = {
412 {0x00, 0x00}, // invalid TLV type (zero)
413 {0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}, // TLV type too large
414 {0x01, 0xff, 0x42, 0x42}, // bad TLV length
415 {0x01, 0x02, 0x03}, // truncated TLV value
Davide Pesavento6b330402019-04-24 00:14:01 -0400416};
417
Davide Pesavento1a4a7bf2020-12-04 22:30:46 -0500418BOOST_DATA_TEST_CASE(Malformed, MalformedInputs)
Davide Pesavento6b330402019-04-24 00:14:01 -0400419{
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500420 // constructor from span
421 BOOST_CHECK_THROW(Block{sample}, tlv::Error);
Davide Pesavento6b330402019-04-24 00:14:01 -0400422
423 // fromStream()
424 std::stringstream stream;
Davide Pesavento1a4a7bf2020-12-04 22:30:46 -0500425 stream.write(sample.template get<char>(), sample.size());
Davide Pesavento6b330402019-04-24 00:14:01 -0400426 stream.seekg(0);
427 BOOST_CHECK_THROW(Block::fromStream(stream), tlv::Error);
428
429 // fromBuffer(), ConstBufferPtr overload
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500430 auto buf = std::make_shared<Buffer>(sample.begin(), sample.end());
Davide Pesavento6b330402019-04-24 00:14:01 -0400431 bool isOk;
432 Block b;
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500433 std::tie(isOk, b) = Block::fromBuffer(buf);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000434 BOOST_CHECK(!isOk);
Davide Pesavento6b330402019-04-24 00:14:01 -0400435 BOOST_CHECK(!b.isValid());
436
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500437 // fromBuffer(), span overload
438 std::tie(isOk, b) = Block::fromBuffer(sample);
Davide Pesavento6b330402019-04-24 00:14:01 -0400439 BOOST_CHECK(!isOk);
440 BOOST_CHECK(!b.isValid());
Junxiao Shif0da7892015-04-04 22:16:16 -0700441}
442
Davide Pesaventoeee3e822016-11-26 19:19:34 +0100443BOOST_AUTO_TEST_SUITE_END() // Construction
444
Davide Pesaventoa76ea9a2021-04-24 00:06:02 -0400445BOOST_AUTO_TEST_CASE(BlockFromValue)
446{
447 Block b1(301);
448 BOOST_CHECK_EXCEPTION(b1.blockFromValue(), Block::Error, [] (const auto& e) {
Davide Pesavento21b7f1b2023-04-28 23:21:02 -0400449 return e.what() == "Cannot construct block from empty TLV-VALUE"sv;
Davide Pesaventoa76ea9a2021-04-24 00:06:02 -0400450 });
451
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500452 Block b2(302, std::make_shared<Buffer>());
Davide Pesaventoa76ea9a2021-04-24 00:06:02 -0400453 BOOST_CHECK_EXCEPTION(b2.blockFromValue(), Block::Error, [] (const auto& e) {
Davide Pesavento21b7f1b2023-04-28 23:21:02 -0400454 return e.what() == "Cannot construct block from empty TLV-VALUE"sv;
Davide Pesaventoa76ea9a2021-04-24 00:06:02 -0400455 });
456
457 b1.encode();
458 Block b3(303, b1);
459 b3.encode();
460 Block nested = b3.blockFromValue();
461 BOOST_CHECK_EQUAL(nested.type(), 301);
462 BOOST_CHECK_EQUAL(nested.size(), 4);
463 BOOST_CHECK_EQUAL(nested.value_size(), 0);
464 BOOST_CHECK(nested == b1);
465}
466
Junxiao Shidc4277a2017-07-17 11:34:02 +0000467BOOST_AUTO_TEST_SUITE(SubElements)
468
469BOOST_AUTO_TEST_CASE(Parse)
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700470{
Junxiao Shidc4277a2017-07-17 11:34:02 +0000471 const uint8_t PACKET[] = {
472 0x06, 0x20, // Data
473 0x07, 0x11, // Name
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000474 0x08, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, // GenericNameComponent 'hello'
475 0x08, 0x01, 0x31, // GenericNameComponent '1'
476 0x08, 0x05, 0x77, 0x6f, 0x72, 0x6c, 0x64, // GenericNameComponent 'world'
Junxiao Shidc4277a2017-07-17 11:34:02 +0000477 0x14, 0x00, // MetaInfo empty
478 0x15, 0x00, // Content empty
479 0x16, 0x05, // SignatureInfo
480 0x1b, 0x01, 0x01, // SignatureType RSA
481 0x1c, 0x00, // KeyLocator empty
482 0x17, 0x00 // SignatureValue empty
483 };
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500484 Block data(PACKET);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000485 data.parse();
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700486
Junxiao Shidc4277a2017-07-17 11:34:02 +0000487 BOOST_CHECK_EQUAL(data.elements_size(), 5);
488 BOOST_CHECK_EQUAL(data.elements().at(0).type(), 0x07);
489 BOOST_CHECK_EQUAL(data.elements().at(0).elements().size(), 0); // parse is not recursive
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700490
Junxiao Shidc4277a2017-07-17 11:34:02 +0000491 BOOST_CHECK(data.get(0x15) == data.elements().at(2));
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400492 BOOST_CHECK_EXCEPTION(data.get(0x01), Block::Error, [] (const auto& e) {
Davide Pesavento21b7f1b2023-04-28 23:21:02 -0400493 return e.what() == "No sub-element of type 1 found in block of type 6"sv;
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400494 });
Junxiao Shidc4277a2017-07-17 11:34:02 +0000495
496 BOOST_CHECK(data.find(0x15) == data.elements_begin() + 2);
497 BOOST_CHECK(data.find(0x01) == data.elements_end());
Davide Pesavento6b330402019-04-24 00:14:01 -0400498
499 const uint8_t MALFORMED[] = {
500 // TLV-LENGTH of nested element is greater than TLV-LENGTH of enclosing element
501 0x05, 0x05, 0x07, 0x07, 0x08, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f
502 };
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500503 Block bad(MALFORMED);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400504 BOOST_CHECK_EXCEPTION(bad.parse(), Block::Error, [] (const auto& e) {
Davide Pesavento21b7f1b2023-04-28 23:21:02 -0400505 return e.what() == "TLV-LENGTH of sub-element of type 7 exceeds TLV-VALUE boundary of parent block"sv;
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400506 });
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700507}
508
Joao Pereira7476ebf2015-07-07 14:54:39 -0400509BOOST_AUTO_TEST_CASE(InsertBeginning)
510{
511 Block masterBlock(tlv::Name);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000512 Block firstBlock = makeStringBlock(tlv::GenericNameComponent, "firstName");
513 Block secondBlock = makeStringBlock(tlv::GenericNameComponent, "secondName");
514 Block thirdBlock = makeStringBlock(tlv::GenericNameComponent, "thirdName");
Joao Pereira7476ebf2015-07-07 14:54:39 -0400515
516 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 0);
517 masterBlock.push_back(secondBlock);
518 masterBlock.push_back(thirdBlock);
519 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 2);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000520 Block::element_const_iterator it = masterBlock.find(tlv::GenericNameComponent);
Joao Pereira7476ebf2015-07-07 14:54:39 -0400521 BOOST_CHECK_EQUAL(*it == secondBlock, true);
522
523 it = masterBlock.insert(it, firstBlock);
524
525 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 3);
526 BOOST_CHECK_EQUAL(*(it + 1) == secondBlock, true);
527 BOOST_CHECK_EQUAL(*(masterBlock.elements_begin()) == firstBlock, true);
528}
529
530BOOST_AUTO_TEST_CASE(InsertEnd)
531{
532 Block masterBlock(tlv::Name);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000533 Block firstBlock = makeStringBlock(tlv::GenericNameComponent, "firstName");
534 Block secondBlock = makeStringBlock(tlv::GenericNameComponent, "secondName");
535 Block thirdBlock = makeStringBlock(tlv::GenericNameComponent, "thirdName");
Joao Pereira7476ebf2015-07-07 14:54:39 -0400536
537 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 0);
538 masterBlock.push_back(firstBlock);
539 masterBlock.push_back(secondBlock);
540 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 2);
541 Block::element_const_iterator it = masterBlock.elements_end();
542 BOOST_CHECK_EQUAL(*(it - 1) == secondBlock, true);
543
544 it = masterBlock.insert(it, thirdBlock);
545
546 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 3);
547 BOOST_CHECK_EQUAL(*(it - 1) == secondBlock, true);
548 BOOST_CHECK_EQUAL(*(masterBlock.elements_end() - 1) == thirdBlock, true);
549}
550
551BOOST_AUTO_TEST_CASE(InsertMiddle)
552{
553 Block masterBlock(tlv::Name);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000554 Block firstBlock = makeStringBlock(tlv::GenericNameComponent, "firstName");
555 Block secondBlock = makeStringBlock(tlv::GenericNameComponent, "secondName");
556 Block thirdBlock = makeStringBlock(tlv::GenericNameComponent, "thirdName");
Joao Pereira7476ebf2015-07-07 14:54:39 -0400557
558 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 0);
559 masterBlock.push_back(firstBlock);
560 masterBlock.push_back(thirdBlock);
561 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 2);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000562 Block::element_const_iterator it = masterBlock.find(tlv::GenericNameComponent);
Joao Pereira7476ebf2015-07-07 14:54:39 -0400563 BOOST_CHECK_EQUAL(*it == firstBlock, true);
564
Junxiao Shidc4277a2017-07-17 11:34:02 +0000565 it = masterBlock.insert(it + 1, secondBlock);
Joao Pereira7476ebf2015-07-07 14:54:39 -0400566
567 BOOST_CHECK_EQUAL(*it == secondBlock, true);
568 BOOST_CHECK_EQUAL(*(it + 1) == thirdBlock, true);
569 BOOST_CHECK_EQUAL(*(it - 1) == firstBlock, true);
570}
571
572BOOST_AUTO_TEST_CASE(EraseSingleElement)
573{
574 Block masterBlock(tlv::Name);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000575 Block firstBlock = makeStringBlock(tlv::GenericNameComponent, "firstName");
576 Block secondBlock = makeStringBlock(tlv::GenericNameComponent, "secondName");
577 Block thirdBlock = makeStringBlock(tlv::GenericNameComponent, "thirdName");
Joao Pereira7476ebf2015-07-07 14:54:39 -0400578
579 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 0);
580 masterBlock.push_back(firstBlock);
581 masterBlock.push_back(secondBlock);
582 masterBlock.push_back(thirdBlock);
583 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 3);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000584 Block::element_const_iterator it = masterBlock.find(tlv::GenericNameComponent);
Joao Pereira7476ebf2015-07-07 14:54:39 -0400585 it++;
586 BOOST_CHECK_EQUAL(*it == secondBlock, true);
587
588 it = masterBlock.erase(it);
589
590 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 2);
591 BOOST_CHECK_EQUAL(*(it) == thirdBlock, true);
592 BOOST_CHECK_EQUAL(*(it - 1) == firstBlock, true);
593}
594
595BOOST_AUTO_TEST_CASE(EraseRange)
596{
597 Block masterBlock(tlv::Name);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000598 Block firstBlock = makeStringBlock(tlv::GenericNameComponent, "firstName");
599 Block secondBlock = makeStringBlock(tlv::GenericNameComponent, "secondName");
600 Block thirdBlock = makeStringBlock(tlv::GenericNameComponent, "thirdName");
601 Block fourthBlock = makeStringBlock(tlv::GenericNameComponent, "fourthName");
602 Block fifthBlock = makeStringBlock(tlv::GenericNameComponent, "fifthName");
603 Block sixthBlock = makeStringBlock(tlv::GenericNameComponent, "sixthName");
Joao Pereira7476ebf2015-07-07 14:54:39 -0400604
605 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 0);
606 masterBlock.push_back(firstBlock);
607 masterBlock.push_back(secondBlock);
608 masterBlock.push_back(thirdBlock);
609 masterBlock.push_back(fourthBlock);
610 masterBlock.push_back(fifthBlock);
611 masterBlock.push_back(sixthBlock);
612 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 6);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000613 Block::element_const_iterator itStart = masterBlock.find(tlv::GenericNameComponent);
Joao Pereira7476ebf2015-07-07 14:54:39 -0400614 itStart++;
615 Block::element_const_iterator itEnd = itStart + 3;
616 BOOST_CHECK_EQUAL(*itStart == secondBlock, true);
617 BOOST_CHECK_EQUAL(*itEnd == fifthBlock, true);
618
619 Block::element_const_iterator newIt = masterBlock.erase(itStart, itEnd);
620
621 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 3);
622 BOOST_CHECK_EQUAL(*(newIt) == fifthBlock, true);
623 BOOST_CHECK_EQUAL(*(newIt - 1) == firstBlock, true);
624}
625
Eric Newberrya3d9fc02015-07-26 10:55:44 -0700626BOOST_AUTO_TEST_CASE(Remove)
627{
628 Block block(tlv::Data);
629 block.push_back(makeNonNegativeIntegerBlock(tlv::ContentType, 0));
630 block.push_back(makeNonNegativeIntegerBlock(tlv::FreshnessPeriod, 123));
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400631 block.push_back(makeStringBlock(tlv::Name, "/test-prefix"));
Eric Newberrya3d9fc02015-07-26 10:55:44 -0700632 block.push_back(makeNonNegativeIntegerBlock(tlv::ContentType, 2));
633 block.push_back(makeNonNegativeIntegerBlock(tlv::ContentType, 1));
634
635 BOOST_CHECK_EQUAL(5, block.elements_size());
Davide Pesavento6b330402019-04-24 00:14:01 -0400636 BOOST_CHECK_NO_THROW(block.remove(tlv::ContentType));
637 BOOST_REQUIRE_EQUAL(2, block.elements_size());
Eric Newberrya3d9fc02015-07-26 10:55:44 -0700638
Davide Pesavento6b330402019-04-24 00:14:01 -0400639 auto elements = block.elements();
Eric Newberrya3d9fc02015-07-26 10:55:44 -0700640 BOOST_CHECK_EQUAL(tlv::FreshnessPeriod, elements[0].type());
641 BOOST_CHECK_EQUAL(123, readNonNegativeInteger(elements[0]));
642 BOOST_CHECK_EQUAL(tlv::Name, elements[1].type());
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400643 BOOST_CHECK_EQUAL(readString(elements[1]).compare("/test-prefix"), 0);
Eric Newberrya3d9fc02015-07-26 10:55:44 -0700644}
645
Junxiao Shidc4277a2017-07-17 11:34:02 +0000646BOOST_AUTO_TEST_SUITE_END() // SubElements
647
Davide Pesaventoa76ea9a2021-04-24 00:06:02 -0400648BOOST_AUTO_TEST_CASE(ToAsioConstBuffer)
649{
650 Block block = "0101A0"_block;
651 boost::asio::const_buffer buffer(block);
Davide Pesavento2f46d652023-11-09 23:40:01 -0500652 BOOST_CHECK_EQUAL(buffer.data(), block.data());
653 BOOST_CHECK_EQUAL(buffer.size(), block.size());
Davide Pesaventoa76ea9a2021-04-24 00:06:02 -0400654}
655
Junxiao Shidc4277a2017-07-17 11:34:02 +0000656BOOST_AUTO_TEST_CASE(Equality)
657{
Davide Pesaventob10024c2017-09-22 01:36:44 -0400658 const uint8_t one[] = {0x08, 0x00};
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500659 Block a(one);
660 Block b(one);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000661 BOOST_CHECK_EQUAL(a == b, true);
662 BOOST_CHECK_EQUAL(a != b, false);
663
Davide Pesaventob10024c2017-09-22 01:36:44 -0400664 const uint8_t two[] = {0x06, 0x00};
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500665 Block c(two);
666 Block d(one);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000667 BOOST_CHECK_EQUAL(c == d, false);
668 BOOST_CHECK_EQUAL(c != d, true);
669
Davide Pesaventob10024c2017-09-22 01:36:44 -0400670 const uint8_t three[] = {0x06, 0x01, 0xcc};
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500671 Block e(two);
672 Block f(three);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000673 BOOST_CHECK_EQUAL(e == f, false);
674 BOOST_CHECK_EQUAL(e != f, true);
675}
676
Junxiao Shi72c0c642018-04-20 15:41:09 +0000677BOOST_AUTO_TEST_CASE(Print)
678{
679 // default constructed
680 Block b;
681 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(b), "[invalid]");
682
683 // zero length
684 b = "0700"_block;
685 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(b), "7[empty]");
686
687 // unparsed
688 b = "0E10FF7E4E6B3B21C902660F16ED589FCCCC"_block;
689 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(b),
690 "14[16]=FF7E4E6B3B21C902660F16ED589FCCCC");
691 // set and restore format flags
692 {
693 std::ostringstream oss;
694 oss << std::showbase << std::hex << 0xd23c4 << b << 0x4981e;
695 BOOST_CHECK_EQUAL(oss.str(), "0xd23c414[16]=FF7E4E6B3B21C902660F16ED589FCCCC0x4981e");
696 }
697
698 // parsed
699 b = "FD010808 0502CADD 59024E42"_block;
700 b.parse();
701 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(b),
702 "264[8]={5[2]=CADD,89[2]=4E42}");
703
704 // parsed then modified: print modified sub-elements
705 b = "FD010808 0502CADD 59024E42"_block;
706 b.parse();
707 b.erase(b.elements_begin());
708 b.push_back("10022386"_block);
709 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(b),
710 "264[8]={89[2]=4E42,16[2]=2386}");
711}
712
Junxiao Shi2b322eb2018-08-24 10:43:27 -0600713BOOST_AUTO_TEST_SUITE(BlockLiteral)
714
715BOOST_AUTO_TEST_CASE(Simple)
716{
Davide Pesavento6b330402019-04-24 00:14:01 -0400717 Block b0 = "4200"_block;
718 BOOST_CHECK_EQUAL(b0.type(), 0x42);
Junxiao Shi2b322eb2018-08-24 10:43:27 -0600719 BOOST_CHECK_EQUAL(b0.value_size(), 0);
720
721 Block b1 = "0101A0"_block;
722 BOOST_CHECK_EQUAL(b1.type(), 0x01);
723 BOOST_REQUIRE_EQUAL(b1.value_size(), 1);
724 BOOST_CHECK_EQUAL(b1.value()[0], 0xA0);
725}
726
727BOOST_AUTO_TEST_CASE(Comment)
728{
729 Block b0 = "a2b0c0d2eBf0G.B 1+"_block;
730 BOOST_CHECK_EQUAL(b0.type(), 0x20);
731 BOOST_REQUIRE_EQUAL(b0.value_size(), 2);
732 BOOST_CHECK_EQUAL(b0.value()[0], 0xB0);
733 BOOST_CHECK_EQUAL(b0.value()[1], 0xB1);
734}
735
736BOOST_AUTO_TEST_CASE(BadInput)
737{
738 BOOST_CHECK_THROW(""_block, std::invalid_argument);
739 BOOST_CHECK_THROW("1"_block, std::invalid_argument);
740 BOOST_CHECK_THROW("333"_block, std::invalid_argument);
Davide Pesavento6b330402019-04-24 00:14:01 -0400741 BOOST_CHECK_THROW("xx yy zz"_block, std::invalid_argument); // only comments
Junxiao Shi2b322eb2018-08-24 10:43:27 -0600742
Davide Pesavento6b330402019-04-24 00:14:01 -0400743 BOOST_CHECK_THROW("0000"_block, tlv::Error); // invalid type
744 BOOST_CHECK_THROW("0202C0"_block, tlv::Error); // truncated value
745 BOOST_CHECK_THROW("0201C0C1"_block, tlv::Error); // trailing garbage
Junxiao Shi2b322eb2018-08-24 10:43:27 -0600746}
747
748BOOST_AUTO_TEST_SUITE_END() // BlockLiteral
749
Davide Pesaventoeee3e822016-11-26 19:19:34 +0100750BOOST_AUTO_TEST_SUITE_END() // TestBlock
751BOOST_AUTO_TEST_SUITE_END() // Encoding
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800752
Davide Pesavento47ce2ee2023-05-09 01:33:33 -0400753} // namespace ndn::tests