blob: a129c1a88ea46c848b75cb7b71d4e80c06115c89 [file] [log] [blame]
Alexander Afanasyev8828ca62015-07-02 13:40:09 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento38a061d2018-02-15 22:45:48 -05002/*
Davide Pesaventodf8fd8a2022-02-21 20:04:21 -05003 * Copyright (c) 2013-2022 Regents of the University of California.
Alexander Afanasyev8828ca62015-07-02 13:40:09 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * 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.
20 */
21
Davide Pesavento7e780642018-11-24 15:51:34 -050022#include "ndn-cxx/util/string-helper.hpp"
23#include "ndn-cxx/encoding/buffer.hpp"
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070024
Davide Pesavento7e780642018-11-24 15:51:34 -050025#include "tests/boost-test.hpp"
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070026
Davide Pesavento38a061d2018-02-15 22:45:48 -050027#include <cctype>
28#include <cstring>
Davide Pesavento21a4ea52019-12-22 13:35:37 -050029
30#if BOOST_VERSION >= 105900
31#include <boost/test/tools/output_test_stream.hpp>
32#else
Davide Pesavento7e780642018-11-24 15:51:34 -050033#include <boost/test/output_test_stream.hpp>
Davide Pesavento21a4ea52019-12-22 13:35:37 -050034#endif
Davide Pesavento38a061d2018-02-15 22:45:48 -050035
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070036namespace ndn {
37namespace util {
Davide Pesaventodf8fd8a2022-02-21 20:04:21 -050038namespace tests {
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070039
Davide Pesavento38a061d2018-02-15 22:45:48 -050040using boost::test_tools::output_test_stream;
41
Davide Pesaventoeee3e822016-11-26 19:19:34 +010042BOOST_AUTO_TEST_SUITE(Util)
43BOOST_AUTO_TEST_SUITE(TestStringHelper)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070044
Davide Pesaventoe78eeca2017-02-23 23:22:32 -050045BOOST_AUTO_TEST_CASE(PrintHex)
46{
Davide Pesavento38a061d2018-02-15 22:45:48 -050047 output_test_stream os;
Davide Pesaventoe78eeca2017-02-23 23:22:32 -050048
49 printHex(os, 0);
50 BOOST_CHECK(os.is_equal("0x0"));
51
52 printHex(os, 42);
53 BOOST_CHECK(os.is_equal("0x2a"));
54
55 printHex(os, 2748, true);
56 BOOST_CHECK(os.is_equal("0xABC"));
57
58 printHex(os, static_cast<uint64_t>(-1));
59 BOOST_CHECK(os.is_equal("0xffffffffffffffff"));
60
61 printHex(os, ~0U, true);
62 BOOST_CHECK(os.is_equal("0xFFFFFFFF"));
63
64 printHex(os, ~0ULL, true);
65 BOOST_CHECK(os.is_equal("0xFFFFFFFFFFFFFFFF"));
66}
67
68BOOST_AUTO_TEST_CASE(AsHex)
69{
70 using ndn::AsHex;
Davide Pesavento38a061d2018-02-15 22:45:48 -050071 output_test_stream os;
Davide Pesaventoe78eeca2017-02-23 23:22:32 -050072
73 os << AsHex{0};
74 BOOST_CHECK(os.is_equal("0x0"));
75
76 os << AsHex{42};
77 BOOST_CHECK(os.is_equal("0x2a"));
78
79 os << std::uppercase << AsHex{~0U};
80 BOOST_CHECK(os.is_equal("0xFFFFFFFF"));
81
82 os << std::nouppercase << AsHex{~0U};
83 BOOST_CHECK(os.is_equal("0xffffffff"));
84}
85
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070086BOOST_AUTO_TEST_CASE(ToHex)
87{
Davide Pesaventodf8fd8a2022-02-21 20:04:21 -050088 const std::string test = "Hello, world!";
89 BOOST_CHECK_EQUAL(toHex({reinterpret_cast<const uint8_t*>(test.data()), test.size()}),
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070090 "48656C6C6F2C20776F726C6421");
Davide Pesaventodf8fd8a2022-02-21 20:04:21 -050091 BOOST_CHECK_EQUAL(toHex({reinterpret_cast<const uint8_t*>(test.data()), test.size()}, false),
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070092 "48656c6c6f2c20776f726c6421");
Davide Pesaventodf8fd8a2022-02-21 20:04:21 -050093 BOOST_CHECK_EQUAL(toHex({}), "");
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070094
95 Buffer buffer(test.data(), test.size());
96 BOOST_CHECK_EQUAL(toHex(buffer, false), "48656c6c6f2c20776f726c6421");
Davide Pesaventofdda2412017-01-28 18:53:51 -050097 BOOST_CHECK_EQUAL(toHex(Buffer{}), "");
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070098}
99
Davide Pesavento38a061d2018-02-15 22:45:48 -0500100BOOST_AUTO_TEST_CASE(FromHex)
101{
Davide Pesaventodf8fd8a2022-02-21 20:04:21 -0500102 BOOST_TEST(fromHex("")->empty());
103 const uint8_t expected1[] = {
104 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21
105 };
106 BOOST_TEST(*fromHex("48656c6c6f2c20776f726c6421") == expected1, boost::test_tools::per_element());
107 const uint8_t expected2[] = {0x01, 0x2a, 0x3b, 0xc4, 0xde, 0xfa, 0xb5, 0xcd, 0xef};
108 BOOST_TEST(*fromHex("012a3Bc4defAB5CdEF") == expected2, boost::test_tools::per_element());
Davide Pesavento38a061d2018-02-15 22:45:48 -0500109
110 BOOST_CHECK_THROW(fromHex("1"), StringHelperError);
111 BOOST_CHECK_THROW(fromHex("zz"), StringHelperError);
112 BOOST_CHECK_THROW(fromHex("00az"), StringHelperError);
113 BOOST_CHECK_THROW(fromHex("1234z"), StringHelperError);
114}
115
116BOOST_AUTO_TEST_CASE(ToHexChar)
117{
118 static const std::vector<std::pair<unsigned int, char>> hexMap{
119 {0, '0'}, {1, '1'}, {2, '2'}, {3, '3'}, {4, '4'}, {5, '5'}, {6, '6'}, {7, '7'},
120 {8, '8'}, {9, '9'}, {10, 'A'}, {11, 'B'}, {12, 'C'}, {13, 'D'}, {14, 'E'}, {15, 'F'}
121 };
122
123 for (const auto& i : hexMap) {
124 BOOST_CHECK_EQUAL(toHexChar(i.first), i.second);
125 BOOST_CHECK_EQUAL(toHexChar(i.first + 16), i.second);
126 BOOST_CHECK_EQUAL(toHexChar(i.first + 32), i.second);
127 BOOST_CHECK_EQUAL(toHexChar(i.first + 240), i.second);
128 BOOST_CHECK_EQUAL(toHexChar(i.first, false), std::tolower(static_cast<unsigned char>(i.second)));
129 }
130}
131
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700132BOOST_AUTO_TEST_CASE(FromHexChar)
133{
134 // for (int ch = 0; ch <= std::numeric_limits<uint8_t>::max(); ++ch) {
135 // std::cout << "{0x" << std::hex << ch << ", "
136 // << std::dec << fromHexChar(static_cast<char>(ch)) << "}, ";
137 // if (ch % 8 == 7)
138 // std::cout << std::endl;
139 // }
Davide Pesavento03115ce2017-01-27 01:17:55 -0500140 static const std::vector<std::pair<char, int>> hexMap{
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700141 {0x0, -1}, {0x1, -1}, {0x2, -1}, {0x3, -1}, {0x4, -1}, {0x5, -1}, {0x6, -1}, {0x7, -1},
142 {0x8, -1}, {0x9, -1}, {0xa, -1}, {0xb, -1}, {0xc, -1}, {0xd, -1}, {0xe, -1}, {0xf, -1},
143 {0x10, -1}, {0x11, -1}, {0x12, -1}, {0x13, -1}, {0x14, -1}, {0x15, -1}, {0x16, -1}, {0x17, -1},
144 {0x18, -1}, {0x19, -1}, {0x1a, -1}, {0x1b, -1}, {0x1c, -1}, {0x1d, -1}, {0x1e, -1}, {0x1f, -1},
145 {0x20, -1}, {0x21, -1}, {0x22, -1}, {0x23, -1}, {0x24, -1}, {0x25, -1}, {0x26, -1}, {0x27, -1},
146 {0x28, -1}, {0x29, -1}, {0x2a, -1}, {0x2b, -1}, {0x2c, -1}, {0x2d, -1}, {0x2e, -1}, {0x2f, -1},
147 {0x30, 0}, {0x31, 1}, {0x32, 2}, {0x33, 3}, {0x34, 4}, {0x35, 5}, {0x36, 6}, {0x37, 7},
148 {0x38, 8}, {0x39, 9}, {0x3a, -1}, {0x3b, -1}, {0x3c, -1}, {0x3d, -1}, {0x3e, -1}, {0x3f, -1},
149 {0x40, -1}, {0x41, 10}, {0x42, 11}, {0x43, 12}, {0x44, 13}, {0x45, 14}, {0x46, 15}, {0x47, -1},
150 {0x48, -1}, {0x49, -1}, {0x4a, -1}, {0x4b, -1}, {0x4c, -1}, {0x4d, -1}, {0x4e, -1}, {0x4f, -1},
151 {0x50, -1}, {0x51, -1}, {0x52, -1}, {0x53, -1}, {0x54, -1}, {0x55, -1}, {0x56, -1}, {0x57, -1},
152 {0x58, -1}, {0x59, -1}, {0x5a, -1}, {0x5b, -1}, {0x5c, -1}, {0x5d, -1}, {0x5e, -1}, {0x5f, -1},
153 {0x60, -1}, {0x61, 10}, {0x62, 11}, {0x63, 12}, {0x64, 13}, {0x65, 14}, {0x66, 15}, {0x67, -1},
154 {0x68, -1}, {0x69, -1}, {0x6a, -1}, {0x6b, -1}, {0x6c, -1}, {0x6d, -1}, {0x6e, -1}, {0x6f, -1},
155 {0x70, -1}, {0x71, -1}, {0x72, -1}, {0x73, -1}, {0x74, -1}, {0x75, -1}, {0x76, -1}, {0x77, -1},
156 {0x78, -1}, {0x79, -1}, {0x7a, -1}, {0x7b, -1}, {0x7c, -1}, {0x7d, -1}, {0x7e, -1}, {0x7f, -1},
157 {0x80, -1}, {0x81, -1}, {0x82, -1}, {0x83, -1}, {0x84, -1}, {0x85, -1}, {0x86, -1}, {0x87, -1},
158 {0x88, -1}, {0x89, -1}, {0x8a, -1}, {0x8b, -1}, {0x8c, -1}, {0x8d, -1}, {0x8e, -1}, {0x8f, -1},
159 {0x90, -1}, {0x91, -1}, {0x92, -1}, {0x93, -1}, {0x94, -1}, {0x95, -1}, {0x96, -1}, {0x97, -1},
160 {0x98, -1}, {0x99, -1}, {0x9a, -1}, {0x9b, -1}, {0x9c, -1}, {0x9d, -1}, {0x9e, -1}, {0x9f, -1},
161 {0xa0, -1}, {0xa1, -1}, {0xa2, -1}, {0xa3, -1}, {0xa4, -1}, {0xa5, -1}, {0xa6, -1}, {0xa7, -1},
162 {0xa8, -1}, {0xa9, -1}, {0xaa, -1}, {0xab, -1}, {0xac, -1}, {0xad, -1}, {0xae, -1}, {0xaf, -1},
163 {0xb0, -1}, {0xb1, -1}, {0xb2, -1}, {0xb3, -1}, {0xb4, -1}, {0xb5, -1}, {0xb6, -1}, {0xb7, -1},
164 {0xb8, -1}, {0xb9, -1}, {0xba, -1}, {0xbb, -1}, {0xbc, -1}, {0xbd, -1}, {0xbe, -1}, {0xbf, -1},
165 {0xc0, -1}, {0xc1, -1}, {0xc2, -1}, {0xc3, -1}, {0xc4, -1}, {0xc5, -1}, {0xc6, -1}, {0xc7, -1},
166 {0xc8, -1}, {0xc9, -1}, {0xca, -1}, {0xcb, -1}, {0xcc, -1}, {0xcd, -1}, {0xce, -1}, {0xcf, -1},
167 {0xd0, -1}, {0xd1, -1}, {0xd2, -1}, {0xd3, -1}, {0xd4, -1}, {0xd5, -1}, {0xd6, -1}, {0xd7, -1},
168 {0xd8, -1}, {0xd9, -1}, {0xda, -1}, {0xdb, -1}, {0xdc, -1}, {0xdd, -1}, {0xde, -1}, {0xdf, -1},
169 {0xe0, -1}, {0xe1, -1}, {0xe2, -1}, {0xe3, -1}, {0xe4, -1}, {0xe5, -1}, {0xe6, -1}, {0xe7, -1},
170 {0xe8, -1}, {0xe9, -1}, {0xea, -1}, {0xeb, -1}, {0xec, -1}, {0xed, -1}, {0xee, -1}, {0xef, -1},
171 {0xf0, -1}, {0xf1, -1}, {0xf2, -1}, {0xf3, -1}, {0xf4, -1}, {0xf5, -1}, {0xf6, -1}, {0xf7, -1},
172 {0xf8, -1}, {0xf9, -1}, {0xfa, -1}, {0xfb, -1}, {0xfc, -1}, {0xfd, -1}, {0xfe, -1}, {0xff, -1}
173 };
Davide Pesavento03115ce2017-01-27 01:17:55 -0500174
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700175 for (const auto& item : hexMap) {
Davide Pesavento03115ce2017-01-27 01:17:55 -0500176 BOOST_CHECK_EQUAL(fromHexChar(item.first), item.second);
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700177 }
178}
179
Davide Pesavento38a061d2018-02-15 22:45:48 -0500180BOOST_AUTO_TEST_CASE(Escape)
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700181{
Davide Pesavento38a061d2018-02-15 22:45:48 -0500182 BOOST_CHECK_EQUAL(escape(""), "");
183 BOOST_CHECK_EQUAL(escape("foo42"), "foo42");
184 BOOST_CHECK_EQUAL(escape("foo%bar"), "foo%25bar");
185 BOOST_CHECK_EQUAL(escape("lower UPPER"), "lower%20UPPER");
186 BOOST_CHECK_EQUAL(escape("-._~"), "-._~");
187 BOOST_CHECK_EQUAL(escape(":/?#[]@"), "%3A%2F%3F%23%5B%5D%40");
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700188
Davide Pesavento38a061d2018-02-15 22:45:48 -0500189 output_test_stream os;
190 const char str[] = "\x01\x2a\x3b\xc4\xde\xfa\xb5\xcd\xef";
191 escape(os, str, std::strlen(str));
192 BOOST_CHECK(os.is_equal("%01%2A%3B%C4%DE%FA%B5%CD%EF"));
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700193}
194
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700195BOOST_AUTO_TEST_CASE(Unescape)
196{
Davide Pesavento38a061d2018-02-15 22:45:48 -0500197 BOOST_CHECK_EQUAL(unescape(""), "");
198 BOOST_CHECK_EQUAL(unescape("Hello%01, world!%AA "), "Hello\x01, world!\xAA ");
199 BOOST_CHECK_EQUAL(unescape("Bad %ZZ (not a hex value)"), "Bad %ZZ (not a hex value)");
200 BOOST_CHECK_EQUAL(unescape("Bad %a (should be two hex chars)"), "Bad %a (should be two hex chars)");
201 BOOST_CHECK_EQUAL(unescape("Bad %a"), "Bad %a");
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700202
Davide Pesavento38a061d2018-02-15 22:45:48 -0500203 output_test_stream os;
204 const char str[] = "%01%2a%3B%c4%de%fA%B5%Cd%EF";
205 unescape(os, str, std::strlen(str));
206 BOOST_CHECK(os.is_equal("\x01\x2a\x3b\xc4\xde\xfa\xb5\xcd\xef"));
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700207}
208
Davide Pesaventoeee3e822016-11-26 19:19:34 +0100209BOOST_AUTO_TEST_SUITE_END() // TestStringHelper
210BOOST_AUTO_TEST_SUITE_END() // Util
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700211
Davide Pesaventodf8fd8a2022-02-21 20:04:21 -0500212} // namespace tests
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700213} // namespace util
214} // namespace ndn