blob: 8c15e51870641ccc9676d99bab3211f8148ea016 [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 Pesavento0c526032024-01-31 21:14:01 -05003 * Copyright (c) 2013-2024 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
Davide Pesavento0c526032024-01-31 21:14:01 -0500259BOOST_AUTO_TEST_CASE(FromStreamWhitespace,
260 * ut::description("test for bug #2728"))
Junxiao Shif0da7892015-04-04 22:16:16 -0700261{
Junxiao Shidc4277a2017-07-17 11:34:02 +0000262 const uint8_t PACKET[] = {
Junxiao Shif0da7892015-04-04 22:16:16 -0700263 0x06, 0x20, // Data
264 0x07, 0x11, // Name
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000265 0x08, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, // GenericNameComponent 'hello'
266 0x08, 0x01, 0x31, // GenericNameComponent '1'
267 0x08, 0x05, 0x77, 0x6f, 0x72, 0x6c, 0x64, // GenericNameComponent 'world'
Junxiao Shif0da7892015-04-04 22:16:16 -0700268 0x14, 0x00, // MetaInfo empty
269 0x15, 0x00, // Content empty
270 0x16, 0x05, // SignatureInfo
Junxiao Shidc4277a2017-07-17 11:34:02 +0000271 0x1b, 0x01, 0x01, // SignatureType RSA
272 0x1c, 0x00, // KeyLocator empty
Junxiao Shif0da7892015-04-04 22:16:16 -0700273 0x17, 0x00 // SignatureValue empty
274 };
275 // TLV-LENGTH of <Data> is 0x20 which happens to be ASCII whitespace
276
277 std::stringstream stream;
278 stream.write(reinterpret_cast<const char*>(PACKET), sizeof(PACKET));
279 stream.seekg(0);
280
Junxiao Shidc4277a2017-07-17 11:34:02 +0000281 Block b = Block::fromStream(stream);
282 BOOST_CHECK_EQUAL(b.type(), 6);
283 BOOST_CHECK_EQUAL(b.value_size(), 32);
284 b.parse();
Davide Pesavento6b330402019-04-24 00:14:01 -0400285 BOOST_CHECK_EQUAL(b.elements_size(), 5);
Junxiao Shif0da7892015-04-04 22:16:16 -0700286}
287
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000288BOOST_AUTO_TEST_CASE(FromStreamZeroLength)
Junxiao Shif0da7892015-04-04 22:16:16 -0700289{
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000290 const uint8_t BUFFER[] = {0x70, 0x00,
291 0x71, 0x03, 0x86, 0x11, 0x24,
292 0x72, 0x00};
Junxiao Shif0da7892015-04-04 22:16:16 -0700293
294 std::stringstream stream;
295 stream.write(reinterpret_cast<const char*>(BUFFER), sizeof(BUFFER));
296 stream.seekg(0);
297
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000298 Block b1 = Block::fromStream(stream);
299 BOOST_CHECK_EQUAL(b1.type(), 0x70);
300 BOOST_CHECK_EQUAL(b1.value_size(), 0);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500301 BOOST_CHECK_EQUAL(b1.value_bytes().size(), 0);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400302 BOOST_CHECK(b1.value() == nullptr);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000303
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000304 Block b2 = Block::fromStream(stream);
305 BOOST_CHECK_EQUAL(b2.type(), 0x71);
306 BOOST_CHECK_EQUAL(b2.value_size(), 3);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500307 BOOST_CHECK_EQUAL(b2.value_bytes().size(), 3);
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000308 const uint8_t EXPECTED_VALUE2[] = {0x86, 0x11, 0x24};
Davide Pesavento258d51a2022-02-27 21:26:28 -0500309 BOOST_TEST(b2.value_bytes() == EXPECTED_VALUE2, boost::test_tools::per_element());
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000310
311 Block b3 = Block::fromStream(stream);
312 BOOST_CHECK_EQUAL(b3.type(), 0x72);
313 BOOST_CHECK_EQUAL(b3.value_size(), 0);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500314 BOOST_CHECK_EQUAL(b3.value_bytes().size(), 0);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400315 BOOST_CHECK(b3.value() == nullptr);
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000316
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400317 BOOST_CHECK_EXCEPTION(Block::fromStream(stream), tlv::Error, [] (const auto& e) {
Davide Pesavento21b7f1b2023-04-28 23:21:02 -0400318 return e.what() == "Insufficient data during TLV parsing"sv;
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400319 });
Junxiao Shi760cc7b2017-07-22 19:17:49 +0000320}
321
322BOOST_AUTO_TEST_CASE(FromStreamPacketTooLarge)
323{
324 const uint8_t BUFFER[] = {0x07, 0xfe, 0x00, 0x01, 0x00, 0x00};
325
326 std::stringstream stream;
327 stream.write(reinterpret_cast<const char*>(BUFFER), sizeof(BUFFER));
328 for (int i = 0; i < 0x10000; ++i) {
329 stream.put('\0');
330 }
331 stream.seekg(0);
332
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400333 BOOST_CHECK_EXCEPTION(Block::fromStream(stream), tlv::Error, [] (const auto& e) {
Davide Pesavento21b7f1b2023-04-28 23:21:02 -0400334 return e.what() == "TLV-LENGTH from stream exceeds limit"sv;
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400335 });
Junxiao Shidc4277a2017-07-17 11:34:02 +0000336}
337
338BOOST_AUTO_TEST_CASE(FromWireBuffer)
339{
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500340 auto buffer = std::make_shared<Buffer>(TEST_BUFFER, sizeof(TEST_BUFFER));
Junxiao Shidc4277a2017-07-17 11:34:02 +0000341
Junxiao Shidc4277a2017-07-17 11:34:02 +0000342 bool isOk = false;
343 Block b;
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500344 std::tie(isOk, b) = Block::fromBuffer(buffer);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000345 BOOST_CHECK(isOk);
Davide Pesavento6b330402019-04-24 00:14:01 -0400346 BOOST_CHECK_EQUAL(b.type(), 66);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000347 BOOST_CHECK_EQUAL(b.size(), 3);
348 BOOST_CHECK_EQUAL(b.value_size(), 1);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500349 BOOST_CHECK_EQUAL(b.value_bytes().size(), 1);
350 BOOST_CHECK_EQUAL(*b.data(), 0x42);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000351 BOOST_CHECK_EQUAL(*b.value(), 0xfa);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500352 BOOST_CHECK_EQUAL(b.value_bytes().front(), 0xfa);
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500353 size_t offset = b.size();
Junxiao Shidc4277a2017-07-17 11:34:02 +0000354
355 std::tie(isOk, b) = Block::fromBuffer(buffer, offset);
356 BOOST_CHECK(isOk);
357 BOOST_CHECK_EQUAL(b.type(), 1);
358 BOOST_CHECK_EQUAL(b.size(), 3);
359 BOOST_CHECK_EQUAL(b.value_size(), 1);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500360 BOOST_CHECK_EQUAL(b.value_bytes().size(), 1);
361 BOOST_CHECK_EQUAL(*b.data(), 0x01);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000362 BOOST_CHECK_EQUAL(*b.value(), 0xfb);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500363 BOOST_CHECK_EQUAL(b.value_bytes().front(), 0xfb);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000364 offset += b.size();
365
366 std::tie(isOk, b) = Block::fromBuffer(buffer, offset);
Davide Pesavento6b330402019-04-24 00:14:01 -0400367 BOOST_CHECK(isOk);
368 BOOST_CHECK_EQUAL(b.type(), 0xffffffff);
369 BOOST_CHECK_EQUAL(b.size(), 6);
370 BOOST_CHECK_EQUAL(b.value_size(), 0);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500371 BOOST_CHECK_EQUAL(b.value_bytes().empty(), true);
372 BOOST_CHECK_EQUAL(*b.data(), 0xfe);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400373 BOOST_CHECK(b.value() == nullptr);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000374}
375
376BOOST_AUTO_TEST_CASE(FromRawBuffer)
377{
Junxiao Shidc4277a2017-07-17 11:34:02 +0000378 bool isOk = false;
379 Block b;
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500380 std::tie(isOk, b) = Block::fromBuffer(TEST_BUFFER);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000381 BOOST_CHECK(isOk);
Davide Pesavento6b330402019-04-24 00:14:01 -0400382 BOOST_CHECK_EQUAL(b.type(), 66);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000383 BOOST_CHECK_EQUAL(b.size(), 3);
384 BOOST_CHECK_EQUAL(b.value_size(), 1);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500385 BOOST_CHECK_EQUAL(b.value_bytes().size(), 1);
386 BOOST_CHECK_EQUAL(*b.data(), 0x42);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000387 BOOST_CHECK_EQUAL(*b.value(), 0xfa);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500388 BOOST_CHECK_EQUAL(b.value_bytes().front(), 0xfa);
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500389 auto offset = b.size();
Junxiao Shidc4277a2017-07-17 11:34:02 +0000390
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500391 std::tie(isOk, b) = Block::fromBuffer(make_span(TEST_BUFFER).subspan(offset));
Junxiao Shidc4277a2017-07-17 11:34:02 +0000392 BOOST_CHECK(isOk);
393 BOOST_CHECK_EQUAL(b.type(), 1);
394 BOOST_CHECK_EQUAL(b.size(), 3);
395 BOOST_CHECK_EQUAL(b.value_size(), 1);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500396 BOOST_CHECK_EQUAL(b.value_bytes().size(), 1);
397 BOOST_CHECK_EQUAL(*b.data(), 0x01);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000398 BOOST_CHECK_EQUAL(*b.value(), 0xfb);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500399 BOOST_CHECK_EQUAL(b.value_bytes().front(), 0xfb);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000400 offset += b.size();
401
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500402 std::tie(isOk, b) = Block::fromBuffer(make_span(TEST_BUFFER).subspan(offset));
Davide Pesavento6b330402019-04-24 00:14:01 -0400403 BOOST_CHECK(isOk);
404 BOOST_CHECK_EQUAL(b.type(), 0xffffffff);
405 BOOST_CHECK_EQUAL(b.size(), 6);
406 BOOST_CHECK_EQUAL(b.value_size(), 0);
Davide Pesavento258d51a2022-02-27 21:26:28 -0500407 BOOST_CHECK_EQUAL(b.value_bytes().empty(), true);
408 BOOST_CHECK_EQUAL(*b.data(), 0xfe);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400409 BOOST_CHECK(b.value() == nullptr);
Davide Pesavento6b330402019-04-24 00:14:01 -0400410}
411
Davide Pesavento1a4a7bf2020-12-04 22:30:46 -0500412static const Buffer MalformedInputs[] = {
413 {0x00, 0x00}, // invalid TLV type (zero)
414 {0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}, // TLV type too large
415 {0x01, 0xff, 0x42, 0x42}, // bad TLV length
416 {0x01, 0x02, 0x03}, // truncated TLV value
Davide Pesavento6b330402019-04-24 00:14:01 -0400417};
418
Davide Pesavento1a4a7bf2020-12-04 22:30:46 -0500419BOOST_DATA_TEST_CASE(Malformed, MalformedInputs)
Davide Pesavento6b330402019-04-24 00:14:01 -0400420{
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500421 // constructor from span
422 BOOST_CHECK_THROW(Block{sample}, tlv::Error);
Davide Pesavento6b330402019-04-24 00:14:01 -0400423
424 // fromStream()
425 std::stringstream stream;
Davide Pesavento1a4a7bf2020-12-04 22:30:46 -0500426 stream.write(sample.template get<char>(), sample.size());
Davide Pesavento6b330402019-04-24 00:14:01 -0400427 stream.seekg(0);
428 BOOST_CHECK_THROW(Block::fromStream(stream), tlv::Error);
429
430 // fromBuffer(), ConstBufferPtr overload
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500431 auto buf = std::make_shared<Buffer>(sample.begin(), sample.end());
Davide Pesavento6b330402019-04-24 00:14:01 -0400432 bool isOk;
433 Block b;
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500434 std::tie(isOk, b) = Block::fromBuffer(buf);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000435 BOOST_CHECK(!isOk);
Davide Pesavento6b330402019-04-24 00:14:01 -0400436 BOOST_CHECK(!b.isValid());
437
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500438 // fromBuffer(), span overload
439 std::tie(isOk, b) = Block::fromBuffer(sample);
Davide Pesavento6b330402019-04-24 00:14:01 -0400440 BOOST_CHECK(!isOk);
441 BOOST_CHECK(!b.isValid());
Junxiao Shif0da7892015-04-04 22:16:16 -0700442}
443
Davide Pesaventoeee3e822016-11-26 19:19:34 +0100444BOOST_AUTO_TEST_SUITE_END() // Construction
445
Davide Pesaventoa76ea9a2021-04-24 00:06:02 -0400446BOOST_AUTO_TEST_CASE(BlockFromValue)
447{
448 Block b1(301);
449 BOOST_CHECK_EXCEPTION(b1.blockFromValue(), Block::Error, [] (const auto& e) {
Davide Pesavento21b7f1b2023-04-28 23:21:02 -0400450 return e.what() == "Cannot construct block from empty TLV-VALUE"sv;
Davide Pesaventoa76ea9a2021-04-24 00:06:02 -0400451 });
452
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500453 Block b2(302, std::make_shared<Buffer>());
Davide Pesaventoa76ea9a2021-04-24 00:06:02 -0400454 BOOST_CHECK_EXCEPTION(b2.blockFromValue(), Block::Error, [] (const auto& e) {
Davide Pesavento21b7f1b2023-04-28 23:21:02 -0400455 return e.what() == "Cannot construct block from empty TLV-VALUE"sv;
Davide Pesaventoa76ea9a2021-04-24 00:06:02 -0400456 });
457
458 b1.encode();
459 Block b3(303, b1);
460 b3.encode();
461 Block nested = b3.blockFromValue();
462 BOOST_CHECK_EQUAL(nested.type(), 301);
463 BOOST_CHECK_EQUAL(nested.size(), 4);
464 BOOST_CHECK_EQUAL(nested.value_size(), 0);
465 BOOST_CHECK(nested == b1);
466}
467
Junxiao Shidc4277a2017-07-17 11:34:02 +0000468BOOST_AUTO_TEST_SUITE(SubElements)
469
470BOOST_AUTO_TEST_CASE(Parse)
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700471{
Junxiao Shidc4277a2017-07-17 11:34:02 +0000472 const uint8_t PACKET[] = {
473 0x06, 0x20, // Data
474 0x07, 0x11, // Name
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000475 0x08, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, // GenericNameComponent 'hello'
476 0x08, 0x01, 0x31, // GenericNameComponent '1'
477 0x08, 0x05, 0x77, 0x6f, 0x72, 0x6c, 0x64, // GenericNameComponent 'world'
Junxiao Shidc4277a2017-07-17 11:34:02 +0000478 0x14, 0x00, // MetaInfo empty
479 0x15, 0x00, // Content empty
480 0x16, 0x05, // SignatureInfo
481 0x1b, 0x01, 0x01, // SignatureType RSA
482 0x1c, 0x00, // KeyLocator empty
483 0x17, 0x00 // SignatureValue empty
484 };
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500485 Block data(PACKET);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000486 data.parse();
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700487
Junxiao Shidc4277a2017-07-17 11:34:02 +0000488 BOOST_CHECK_EQUAL(data.elements_size(), 5);
489 BOOST_CHECK_EQUAL(data.elements().at(0).type(), 0x07);
490 BOOST_CHECK_EQUAL(data.elements().at(0).elements().size(), 0); // parse is not recursive
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700491
Junxiao Shidc4277a2017-07-17 11:34:02 +0000492 BOOST_CHECK(data.get(0x15) == data.elements().at(2));
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400493 BOOST_CHECK_EXCEPTION(data.get(0x01), Block::Error, [] (const auto& e) {
Davide Pesavento21b7f1b2023-04-28 23:21:02 -0400494 return e.what() == "No sub-element of type 1 found in block of type 6"sv;
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400495 });
Junxiao Shidc4277a2017-07-17 11:34:02 +0000496
497 BOOST_CHECK(data.find(0x15) == data.elements_begin() + 2);
498 BOOST_CHECK(data.find(0x01) == data.elements_end());
Davide Pesavento6b330402019-04-24 00:14:01 -0400499
500 const uint8_t MALFORMED[] = {
501 // TLV-LENGTH of nested element is greater than TLV-LENGTH of enclosing element
502 0x05, 0x05, 0x07, 0x07, 0x08, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f
503 };
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500504 Block bad(MALFORMED);
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400505 BOOST_CHECK_EXCEPTION(bad.parse(), Block::Error, [] (const auto& e) {
Davide Pesavento21b7f1b2023-04-28 23:21:02 -0400506 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 -0400507 });
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700508}
509
Joao Pereira7476ebf2015-07-07 14:54:39 -0400510BOOST_AUTO_TEST_CASE(InsertBeginning)
511{
512 Block masterBlock(tlv::Name);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000513 Block firstBlock = makeStringBlock(tlv::GenericNameComponent, "firstName");
514 Block secondBlock = makeStringBlock(tlv::GenericNameComponent, "secondName");
515 Block thirdBlock = makeStringBlock(tlv::GenericNameComponent, "thirdName");
Joao Pereira7476ebf2015-07-07 14:54:39 -0400516
517 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 0);
518 masterBlock.push_back(secondBlock);
519 masterBlock.push_back(thirdBlock);
520 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 2);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000521 Block::element_const_iterator it = masterBlock.find(tlv::GenericNameComponent);
Joao Pereira7476ebf2015-07-07 14:54:39 -0400522 BOOST_CHECK_EQUAL(*it == secondBlock, true);
523
524 it = masterBlock.insert(it, firstBlock);
525
526 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 3);
527 BOOST_CHECK_EQUAL(*(it + 1) == secondBlock, true);
528 BOOST_CHECK_EQUAL(*(masterBlock.elements_begin()) == firstBlock, true);
529}
530
531BOOST_AUTO_TEST_CASE(InsertEnd)
532{
533 Block masterBlock(tlv::Name);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000534 Block firstBlock = makeStringBlock(tlv::GenericNameComponent, "firstName");
535 Block secondBlock = makeStringBlock(tlv::GenericNameComponent, "secondName");
536 Block thirdBlock = makeStringBlock(tlv::GenericNameComponent, "thirdName");
Joao Pereira7476ebf2015-07-07 14:54:39 -0400537
538 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 0);
539 masterBlock.push_back(firstBlock);
540 masterBlock.push_back(secondBlock);
541 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 2);
542 Block::element_const_iterator it = masterBlock.elements_end();
543 BOOST_CHECK_EQUAL(*(it - 1) == secondBlock, true);
544
545 it = masterBlock.insert(it, thirdBlock);
546
547 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 3);
548 BOOST_CHECK_EQUAL(*(it - 1) == secondBlock, true);
549 BOOST_CHECK_EQUAL(*(masterBlock.elements_end() - 1) == thirdBlock, true);
550}
551
552BOOST_AUTO_TEST_CASE(InsertMiddle)
553{
554 Block masterBlock(tlv::Name);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000555 Block firstBlock = makeStringBlock(tlv::GenericNameComponent, "firstName");
556 Block secondBlock = makeStringBlock(tlv::GenericNameComponent, "secondName");
557 Block thirdBlock = makeStringBlock(tlv::GenericNameComponent, "thirdName");
Joao Pereira7476ebf2015-07-07 14:54:39 -0400558
559 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 0);
560 masterBlock.push_back(firstBlock);
561 masterBlock.push_back(thirdBlock);
562 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 2);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000563 Block::element_const_iterator it = masterBlock.find(tlv::GenericNameComponent);
Joao Pereira7476ebf2015-07-07 14:54:39 -0400564 BOOST_CHECK_EQUAL(*it == firstBlock, true);
565
Junxiao Shidc4277a2017-07-17 11:34:02 +0000566 it = masterBlock.insert(it + 1, secondBlock);
Joao Pereira7476ebf2015-07-07 14:54:39 -0400567
568 BOOST_CHECK_EQUAL(*it == secondBlock, true);
569 BOOST_CHECK_EQUAL(*(it + 1) == thirdBlock, true);
570 BOOST_CHECK_EQUAL(*(it - 1) == firstBlock, true);
571}
572
573BOOST_AUTO_TEST_CASE(EraseSingleElement)
574{
575 Block masterBlock(tlv::Name);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000576 Block firstBlock = makeStringBlock(tlv::GenericNameComponent, "firstName");
577 Block secondBlock = makeStringBlock(tlv::GenericNameComponent, "secondName");
578 Block thirdBlock = makeStringBlock(tlv::GenericNameComponent, "thirdName");
Joao Pereira7476ebf2015-07-07 14:54:39 -0400579
580 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 0);
581 masterBlock.push_back(firstBlock);
582 masterBlock.push_back(secondBlock);
583 masterBlock.push_back(thirdBlock);
584 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 3);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000585 Block::element_const_iterator it = masterBlock.find(tlv::GenericNameComponent);
Joao Pereira7476ebf2015-07-07 14:54:39 -0400586 it++;
587 BOOST_CHECK_EQUAL(*it == secondBlock, true);
588
589 it = masterBlock.erase(it);
590
591 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 2);
592 BOOST_CHECK_EQUAL(*(it) == thirdBlock, true);
593 BOOST_CHECK_EQUAL(*(it - 1) == firstBlock, true);
594}
595
596BOOST_AUTO_TEST_CASE(EraseRange)
597{
598 Block masterBlock(tlv::Name);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000599 Block firstBlock = makeStringBlock(tlv::GenericNameComponent, "firstName");
600 Block secondBlock = makeStringBlock(tlv::GenericNameComponent, "secondName");
601 Block thirdBlock = makeStringBlock(tlv::GenericNameComponent, "thirdName");
602 Block fourthBlock = makeStringBlock(tlv::GenericNameComponent, "fourthName");
603 Block fifthBlock = makeStringBlock(tlv::GenericNameComponent, "fifthName");
604 Block sixthBlock = makeStringBlock(tlv::GenericNameComponent, "sixthName");
Joao Pereira7476ebf2015-07-07 14:54:39 -0400605
606 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 0);
607 masterBlock.push_back(firstBlock);
608 masterBlock.push_back(secondBlock);
609 masterBlock.push_back(thirdBlock);
610 masterBlock.push_back(fourthBlock);
611 masterBlock.push_back(fifthBlock);
612 masterBlock.push_back(sixthBlock);
613 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 6);
Junxiao Shi4ffbb9d2018-03-31 17:16:35 +0000614 Block::element_const_iterator itStart = masterBlock.find(tlv::GenericNameComponent);
Joao Pereira7476ebf2015-07-07 14:54:39 -0400615 itStart++;
616 Block::element_const_iterator itEnd = itStart + 3;
617 BOOST_CHECK_EQUAL(*itStart == secondBlock, true);
618 BOOST_CHECK_EQUAL(*itEnd == fifthBlock, true);
619
620 Block::element_const_iterator newIt = masterBlock.erase(itStart, itEnd);
621
622 BOOST_CHECK_EQUAL(masterBlock.elements_size(), 3);
623 BOOST_CHECK_EQUAL(*(newIt) == fifthBlock, true);
624 BOOST_CHECK_EQUAL(*(newIt - 1) == firstBlock, true);
625}
626
Eric Newberrya3d9fc02015-07-26 10:55:44 -0700627BOOST_AUTO_TEST_CASE(Remove)
628{
629 Block block(tlv::Data);
630 block.push_back(makeNonNegativeIntegerBlock(tlv::ContentType, 0));
631 block.push_back(makeNonNegativeIntegerBlock(tlv::FreshnessPeriod, 123));
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400632 block.push_back(makeStringBlock(tlv::Name, "/test-prefix"));
Eric Newberrya3d9fc02015-07-26 10:55:44 -0700633 block.push_back(makeNonNegativeIntegerBlock(tlv::ContentType, 2));
634 block.push_back(makeNonNegativeIntegerBlock(tlv::ContentType, 1));
635
636 BOOST_CHECK_EQUAL(5, block.elements_size());
Davide Pesavento6b330402019-04-24 00:14:01 -0400637 BOOST_CHECK_NO_THROW(block.remove(tlv::ContentType));
638 BOOST_REQUIRE_EQUAL(2, block.elements_size());
Eric Newberrya3d9fc02015-07-26 10:55:44 -0700639
Davide Pesavento6b330402019-04-24 00:14:01 -0400640 auto elements = block.elements();
Eric Newberrya3d9fc02015-07-26 10:55:44 -0700641 BOOST_CHECK_EQUAL(tlv::FreshnessPeriod, elements[0].type());
642 BOOST_CHECK_EQUAL(123, readNonNegativeInteger(elements[0]));
643 BOOST_CHECK_EQUAL(tlv::Name, elements[1].type());
Davide Pesavento5f6865c2021-04-23 23:24:11 -0400644 BOOST_CHECK_EQUAL(readString(elements[1]).compare("/test-prefix"), 0);
Eric Newberrya3d9fc02015-07-26 10:55:44 -0700645}
646
Junxiao Shidc4277a2017-07-17 11:34:02 +0000647BOOST_AUTO_TEST_SUITE_END() // SubElements
648
Davide Pesaventoa76ea9a2021-04-24 00:06:02 -0400649BOOST_AUTO_TEST_CASE(ToAsioConstBuffer)
650{
651 Block block = "0101A0"_block;
652 boost::asio::const_buffer buffer(block);
Davide Pesavento2f46d652023-11-09 23:40:01 -0500653 BOOST_CHECK_EQUAL(buffer.data(), block.data());
654 BOOST_CHECK_EQUAL(buffer.size(), block.size());
Davide Pesaventoa76ea9a2021-04-24 00:06:02 -0400655}
656
Junxiao Shidc4277a2017-07-17 11:34:02 +0000657BOOST_AUTO_TEST_CASE(Equality)
658{
Davide Pesaventob10024c2017-09-22 01:36:44 -0400659 const uint8_t one[] = {0x08, 0x00};
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500660 Block a(one);
661 Block b(one);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000662 BOOST_CHECK_EQUAL(a == b, true);
663 BOOST_CHECK_EQUAL(a != b, false);
664
Davide Pesaventob10024c2017-09-22 01:36:44 -0400665 const uint8_t two[] = {0x06, 0x00};
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500666 Block c(two);
667 Block d(one);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000668 BOOST_CHECK_EQUAL(c == d, false);
669 BOOST_CHECK_EQUAL(c != d, true);
670
Davide Pesaventob10024c2017-09-22 01:36:44 -0400671 const uint8_t three[] = {0x06, 0x01, 0xcc};
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500672 Block e(two);
673 Block f(three);
Junxiao Shidc4277a2017-07-17 11:34:02 +0000674 BOOST_CHECK_EQUAL(e == f, false);
675 BOOST_CHECK_EQUAL(e != f, true);
676}
677
Junxiao Shi72c0c642018-04-20 15:41:09 +0000678BOOST_AUTO_TEST_CASE(Print)
679{
680 // default constructed
681 Block b;
682 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(b), "[invalid]");
683
684 // zero length
685 b = "0700"_block;
686 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(b), "7[empty]");
687
688 // unparsed
689 b = "0E10FF7E4E6B3B21C902660F16ED589FCCCC"_block;
690 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(b),
691 "14[16]=FF7E4E6B3B21C902660F16ED589FCCCC");
692 // set and restore format flags
693 {
694 std::ostringstream oss;
695 oss << std::showbase << std::hex << 0xd23c4 << b << 0x4981e;
696 BOOST_CHECK_EQUAL(oss.str(), "0xd23c414[16]=FF7E4E6B3B21C902660F16ED589FCCCC0x4981e");
697 }
698
699 // parsed
700 b = "FD010808 0502CADD 59024E42"_block;
701 b.parse();
702 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(b),
703 "264[8]={5[2]=CADD,89[2]=4E42}");
704
705 // parsed then modified: print modified sub-elements
706 b = "FD010808 0502CADD 59024E42"_block;
707 b.parse();
708 b.erase(b.elements_begin());
709 b.push_back("10022386"_block);
710 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(b),
711 "264[8]={89[2]=4E42,16[2]=2386}");
712}
713
Junxiao Shi2b322eb2018-08-24 10:43:27 -0600714BOOST_AUTO_TEST_SUITE(BlockLiteral)
715
716BOOST_AUTO_TEST_CASE(Simple)
717{
Davide Pesavento6b330402019-04-24 00:14:01 -0400718 Block b0 = "4200"_block;
719 BOOST_CHECK_EQUAL(b0.type(), 0x42);
Junxiao Shi2b322eb2018-08-24 10:43:27 -0600720 BOOST_CHECK_EQUAL(b0.value_size(), 0);
721
722 Block b1 = "0101A0"_block;
723 BOOST_CHECK_EQUAL(b1.type(), 0x01);
724 BOOST_REQUIRE_EQUAL(b1.value_size(), 1);
725 BOOST_CHECK_EQUAL(b1.value()[0], 0xA0);
726}
727
728BOOST_AUTO_TEST_CASE(Comment)
729{
730 Block b0 = "a2b0c0d2eBf0G.B 1+"_block;
731 BOOST_CHECK_EQUAL(b0.type(), 0x20);
732 BOOST_REQUIRE_EQUAL(b0.value_size(), 2);
733 BOOST_CHECK_EQUAL(b0.value()[0], 0xB0);
734 BOOST_CHECK_EQUAL(b0.value()[1], 0xB1);
735}
736
737BOOST_AUTO_TEST_CASE(BadInput)
738{
739 BOOST_CHECK_THROW(""_block, std::invalid_argument);
740 BOOST_CHECK_THROW("1"_block, std::invalid_argument);
741 BOOST_CHECK_THROW("333"_block, std::invalid_argument);
Davide Pesavento6b330402019-04-24 00:14:01 -0400742 BOOST_CHECK_THROW("xx yy zz"_block, std::invalid_argument); // only comments
Junxiao Shi2b322eb2018-08-24 10:43:27 -0600743
Davide Pesavento6b330402019-04-24 00:14:01 -0400744 BOOST_CHECK_THROW("0000"_block, tlv::Error); // invalid type
745 BOOST_CHECK_THROW("0202C0"_block, tlv::Error); // truncated value
746 BOOST_CHECK_THROW("0201C0C1"_block, tlv::Error); // trailing garbage
Junxiao Shi2b322eb2018-08-24 10:43:27 -0600747}
748
749BOOST_AUTO_TEST_SUITE_END() // BlockLiteral
750
Davide Pesaventoeee3e822016-11-26 19:19:34 +0100751BOOST_AUTO_TEST_SUITE_END() // TestBlock
752BOOST_AUTO_TEST_SUITE_END() // Encoding
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800753
Davide Pesavento47ce2ee2023-05-09 01:33:33 -0400754} // namespace ndn::tests