C++ Utilities: tests/conversiontests.cpp Source File

C++ Utilities 5.34.0 Useful C++ classes and routines such as argument parser, IO and conversion utilities

Loading...
Searching...
No Matches
conversiontests.cpp
Go to the documentation of this file.
1#include "../conversion/binaryconversion.h"
2#include "../conversion/stringbuilder.h"
3#include "../conversion/stringconversion.h"
4#include "../tests/testutils.h"
5
6using namespace CppUtilities;
7
8#include <cppunit/TestFixture.h>
9#include <cppunit/extensions/HelperMacros.h>
10
11#include <functional>
12#include <initializer_list>
13#include <random>
14#include <sstream>
15
16#ifdef CPP_UTILITIES_USE_STANDARD_FILESYSTEM
17#include <filesystem>
18#endif
19
20using namespace std;
21
22using namespace CPPUNIT_NS;
23
24// compile-time checks for binary conversion
25static_assert(toSynchsafeInt(255) == 383, "toSynchsafeInt()");
26static_assert(toNormalInt(383) == 255, "toNormalInt()");
27static_assert(swapOrder(static_cast<std::uint16_t>(0xABCD)) == 0xCDAB, "swapOrder(std::uint16_t)");
28static_assert(swapOrder(static_cast<std::uint32_t>(0xABCDEF12u)) == 0x12EFCDABu, "swapOrder(std::uint32_t)");
29static_assert(swapOrder(static_cast<std::uint64_t>(0xABCDEF1234567890ul)) == 0x9078563412EFCDABul, "swapOrder(std::uint64_t)");
30static_assert(swapOrder(static_cast<std::int16_t>(0xABCD)) == static_cast<std::int16_t>(0xCDAB), "swapOrder(std::int16_t)");
31static_assert(swapOrder(static_cast<std::int32_t>(0xABCDEF12)) == 0x12EFCDAB, "swapOrder(std::int32_t)");
32static_assert(swapOrder(static_cast<std::int64_t>(0xABCDEF1234567890l)) == static_cast<std::int64_t>(0x9078563412EFCDABl), "swapOrder(std::int64_t)");
33
37 class ConversionTests : public TestFixture {
38 CPPUNIT_TEST_SUITE(ConversionTests);
39 CPPUNIT_TEST(testConversionException);
40 CPPUNIT_TEST(testEndianness);
41 CPPUNIT_TEST(testBinaryConversions);
42 CPPUNIT_TEST(testSwapOrderFunctions);
43 CPPUNIT_TEST(testStringEncodingConversions);
44 CPPUNIT_TEST(testStringConversions);
45 CPPUNIT_TEST(testStringBuilder);
46 CPPUNIT_TEST_SUITE_END();
47
48public:
49 ConversionTests();
50
51 void setUp()
52 {
53 }
54 void tearDown()
55 {
56 }
57
58 void testConversionException();
59 void testEndianness();
60 void testBinaryConversions();
61 void testSwapOrderFunctions();
62 void testStringEncodingConversions();
63 void testStringConversions();
64 void testStringBuilder();
65
66private:
67 template <typename intType>
68 void testConversion(const char *message, function<void(intType, char *)> vice, function<intType(const char *)> verca, intType min, intType max);
69
70 char m_buff[8];
71 random_device m_randomDevice;
72 mt19937 m_randomEngine;
73};
74
75CPPUNIT_TEST_SUITE_REGISTRATION(ConversionTests);
76
77ConversionTests::ConversionTests()
78 : m_randomDevice()
79 , m_randomEngine(m_randomDevice())
80{
81}
82
83 void ConversionTests::testConversionException()
84{
85 CPPUNIT_ASSERT(!strcmp("unable to convert", ConversionException().what()));
86}
87
91 void ConversionTests::testEndianness()
92{
93 union {
94 uint32_t integer;
95 char characters[4];
96 } test = { 0x01020304 };
97#if defined(CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN)
98 // test whether macro definitions are consistent
99 CPPUNIT_ASSERT(CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN == true);
100 CPPUNIT_ASSERT(CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN == false);
101 // test whether byte order assumption is correct
102 CPPUNIT_ASSERT_MESSAGE("Byte order assumption (big-endian) is wrong", test.characters[0] == 0x01);
103#elif defined(CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN)
104 // test whether macro definitions are consistent
105 CPPUNIT_ASSERT(CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN == false);
106 CPPUNIT_ASSERT(CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN == true);
107 // test whether byte order assumption is correct
108 CPPUNIT_ASSERT_MESSAGE("Byte order assumption (little-endian) is wrong", test.characters[0] == 0x04);
109#else
110 CPPUNIT_FAIL("There is not valid byte order assumption");
111#endif
112}
113
114template <typename intType>
115void ConversionTests::testConversion(
116 const char *message, function<void(intType, char *)> vice, function<intType(const char *)> versa, intType min, intType max)
117{
118 const intType random = uniform_int_distribution<intType>(min, max)(m_randomEngine);
119 stringstream msg;
120 msg << message << '(' << hex << '0' << 'x' << random << ')';
121 vice(random, m_buff);
122 CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.str(), random, versa(m_buff));
123}
124
125#define TEST_TYPE(endianness, function) decltype(endianness::function(m_buff))
126
127#define TEST_CONVERSION(function, endianness) \
128 testConversion<TEST_TYPE(endianness, function)>("testing " #endianness "::" #function, \
129 static_cast<void (*)(TEST_TYPE(endianness, function), char *)>(&endianness::getBytes), endianness::function, \
130 numeric_limits<TEST_TYPE(endianness, function)>::min(), numeric_limits<TEST_TYPE(endianness, function)>::max())
131
132#define TEST_BE_CONVERSION(function) TEST_CONVERSION(function, BE)
133
134#define TEST_LE_CONVERSION(function) TEST_CONVERSION(function, LE)
135
136#define TEST_CUSTOM_CONVERSION(vice, versa, endianness, min, max) \
137 testConversion<TEST_TYPE(endianness, versa)>("testing " #versa " (" #endianness ")", \
138 static_cast<void (*)(TEST_TYPE(endianness, versa), char *)>(&endianness::vice), endianness::versa, min, max)
139
146 void ConversionTests::testBinaryConversions()
147{
148 // test to...() / getBytes() with random numbers
149 for (auto b = 1; b < 100; ++b) {
150 TEST_BE_CONVERSION(toUInt16);
151 TEST_BE_CONVERSION(toUInt32);
152 TEST_BE_CONVERSION(toUInt64);
153 TEST_LE_CONVERSION(toUInt16);
154 TEST_LE_CONVERSION(toUInt32);
155 TEST_LE_CONVERSION(toUInt64);
156 TEST_BE_CONVERSION(toInt16);
157 TEST_BE_CONVERSION(toInt32);
158 TEST_BE_CONVERSION(toInt64);
159 TEST_LE_CONVERSION(toInt16);
160 TEST_LE_CONVERSION(toInt32);
161 TEST_LE_CONVERSION(toInt64);
162 TEST_CUSTOM_CONVERSION(getBytes24, toUInt24, BE, 0, 0xFFFFFF);
163 TEST_CUSTOM_CONVERSION(getBytes24, toUInt24, LE, 0, 0xFFFFFF);
164 }
165}
166
170 void ConversionTests::testSwapOrderFunctions()
171{
172 CPPUNIT_ASSERT(swapOrder(static_cast<std::uint16_t>(0x7825)) == 0x2578);
173 CPPUNIT_ASSERT(swapOrder(static_cast<std::uint32_t>(0x12345678)) == 0x78563412);
174 CPPUNIT_ASSERT(swapOrder(static_cast<std::uint64_t>(0x1122334455667788)) == 0x8877665544332211);
175}
176
180 void assertEqual(const char *message, const std::uint8_t *expectedValues, size_t expectedSize, const StringData &actualValues)
181{
182 // check whether number of elements matches
183 CPPUNIT_ASSERT_EQUAL_MESSAGE(message, expectedSize, actualValues.second);
184 // check whether contents match
185 auto *end = expectedValues + expectedSize;
186 auto *i = reinterpret_cast<std::uint8_t *>(actualValues.first.get());
187 for (; expectedValues != end; ++expectedValues, ++i) {
188 CPPUNIT_ASSERT_EQUAL_MESSAGE(message, asHexNumber(*expectedValues), asHexNumber(*i));
189 }
190}
191
192#if CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN == true
193#define LE_STR_FOR_ENDIANNESS(name) name##LE##String
194#define BE_STR_FOR_ENDIANNESS(name) name##BE##String
195#elif CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN == true
196#define LE_STR_FOR_ENDIANNESS(name) name##BE##String
197#define BE_STR_FOR_ENDIANNESS(name) name##LE##String
198#endif
199
204
209
213 void ConversionTests::testStringEncodingConversions()
214{
215#ifndef CPP_UTILITIES_NO_ICONV
216 // define test string "ABCD" for the different encodings
217 const std::uint8_t simpleString[] = { 'A', 'B', 'C', 'D' };
218 const std::uint16_t simpleUtf16LEString[] = { 0x0041, 0x0042, 0x0043, 0x0044 };
219 const std::uint16_t simpleUtf16BEString[] = { 0x4100, 0x4200, 0x4300, 0x4400 };
220 // define test string "ABÖCD" for the different encodings
221 const std::uint8_t latin1String[] = { 'A', 'B', 0xD6, 'C', 'D' };
222 const std::uint8_t utf8String[] = { 'A', 'B', 0xC3, 0x96, 'C', 'D' };
223 const std::uint16_t utf16LEString[] = { 0x0041, 0x0042, 0x00D6, 0x0043, 0x0044 };
224 const std::uint16_t utf16BEString[] = { 0x4100, 0x4200, 0xD600, 0x4300, 0x4400 };
225 // test conversion to UTF-8
226 assertEqual("Latin-1 to UTF-8 (simple)", simpleString, 4, convertLatin1ToUtf8(reinterpret_cast<const char *>(simpleString), 4));
227 assertEqual("Latin-1 to UTF-8", utf8String, 6, convertLatin1ToUtf8(reinterpret_cast<const char *>(latin1String), 5));
228 assertEqual(
229 "UTF-16LE to UTF-8 (simple)", simpleString, 4, convertUtf16LEToUtf8(reinterpret_cast<const char *>(LE_STR_FOR_ENDIANNESS(simpleUtf16)), 8));
230 assertEqual("UTF-16LE to UTF-8", utf8String, 6, convertUtf16LEToUtf8(reinterpret_cast<const char *>(LE_STR_FOR_ENDIANNESS(utf16)), 10));
231 assertEqual(
232 "UTF-16BE to UTF-8 (simple)", simpleString, 4, convertUtf16BEToUtf8(reinterpret_cast<const char *>(BE_STR_FOR_ENDIANNESS(simpleUtf16)), 8));
233 assertEqual("UTF-16BE to UTF-8", utf8String, 6, convertUtf16BEToUtf8(reinterpret_cast<const char *>(BE_STR_FOR_ENDIANNESS(utf16)), 10));
234 // test conversion from UTF-8
235 assertEqual("UTF-8 to Latin-1 (simple)", simpleString, 4, convertUtf8ToLatin1(reinterpret_cast<const char *>(simpleString), 4));
236 assertEqual("UTF-8 to Latin-1", latin1String, 5, convertUtf8ToLatin1(reinterpret_cast<const char *>(utf8String), 6));
237 assertEqual("UTF-8 to UFT-16LE (simple)", reinterpret_cast<const std::uint8_t *>(LE_STR_FOR_ENDIANNESS(simpleUtf16)), 8,
238 convertUtf8ToUtf16LE(reinterpret_cast<const char *>(simpleString), 4));
239 assertEqual("UTF-8 to UFT-16LE", reinterpret_cast<const std::uint8_t *>(LE_STR_FOR_ENDIANNESS(utf16)), 10,
240 convertUtf8ToUtf16LE(reinterpret_cast<const char *>(utf8String), 6));
241 assertEqual("UTF-8 to UFT-16BE (simple)", reinterpret_cast<const std::uint8_t *>(BE_STR_FOR_ENDIANNESS(simpleUtf16)), 8,
242 convertUtf8ToUtf16BE(reinterpret_cast<const char *>(simpleString), 4));
243 assertEqual("UTF-8 to UFT-16BE", reinterpret_cast<const std::uint8_t *>(BE_STR_FOR_ENDIANNESS(utf16)), 10,
244 convertUtf8ToUtf16BE(reinterpret_cast<const char *>(utf8String), 6));
245 CPPUNIT_ASSERT_THROW(convertString("invalid charset", "UTF-8", "foo", 3, 1.0f), ConversionException);
246#endif
247}
248
252 void ConversionTests::testStringConversions()
253{
254 // stringToNumber() / numberToString() with zero and random numbers
255 CPPUNIT_ASSERT_EQUAL("0"s, numberToString<unsigned int>(0));
256 CPPUNIT_ASSERT_EQUAL("0"s, numberToString<signed int>(0));
257 uniform_int_distribution<std::int64_t> randomDistSigned(numeric_limits<std::int64_t>::min());
258 uniform_int_distribution<std::uint64_t> randomDistUnsigned(0);
259 const string stringMsg("string"), wideStringMsg("wide string"), bufferMsg("buffer");
260 for (std::uint8_t b = 1; b < 100; ++b) {
261 auto signedRandom = randomDistSigned(m_randomEngine);
262 auto unsignedRandom = randomDistUnsigned(m_randomEngine);
263 for (const auto base : initializer_list<std::uint8_t>{ 2, 8, 10, 16 }) {
264 const auto asString = numberToString<std::uint64_t, string>(unsignedRandom, base);
265 const auto asWideString = numberToString<std::uint64_t, wstring>(unsignedRandom, base);
266 CPPUNIT_ASSERT_EQUAL_MESSAGE(stringMsg, unsignedRandom, stringToNumber<std::uint64_t>(asString, base));
267 CPPUNIT_ASSERT_EQUAL_MESSAGE(wideStringMsg, unsignedRandom, stringToNumber<std::uint64_t>(asWideString, base));
268 CPPUNIT_ASSERT_EQUAL_MESSAGE(bufferMsg, unsignedRandom, bufferToNumber<std::uint64_t>(asString.data(), asString.size(), base));
269 }
270 for (const auto base : initializer_list<std::uint8_t>{ 10 }) {
271 const auto asString = numberToString<std::int64_t, string>(signedRandom, static_cast<string::value_type>(base));
272 const auto asWideString = numberToString<std::int64_t, wstring>(signedRandom, base);
273 CPPUNIT_ASSERT_EQUAL_MESSAGE(stringMsg, signedRandom, stringToNumber<std::int64_t>(asString, base));
274 CPPUNIT_ASSERT_EQUAL_MESSAGE(wideStringMsg, signedRandom, stringToNumber<std::int64_t>(asWideString, base));
275 CPPUNIT_ASSERT_EQUAL_MESSAGE(bufferMsg, signedRandom, bufferToNumber<std::int64_t>(asString.data(), asString.size(), base));
276 }
277 }
278
279 // stringToNumber() with spaces at the beginning, leading zeroes, different types and other corner cases
280 CPPUNIT_ASSERT_EQUAL(1, stringToNumber<std::int32_t>("01"));
281 CPPUNIT_ASSERT_EQUAL(1, stringToNumber<std::int32_t>(L"01"s));
282 CPPUNIT_ASSERT_EQUAL(1, stringToNumber<std::int32_t>(u"01"s));
283 CPPUNIT_ASSERT_EQUAL(-23, stringToNumber<std::int32_t>(" - 023"s));
284 CPPUNIT_ASSERT_EQUAL(-23, bufferToNumber<std::int32_t>(" - 023", 6));
285 CPPUNIT_ASSERT_EQUAL(1u, stringToNumber<std::uint32_t>("01"));
286 CPPUNIT_ASSERT_EQUAL(1u, stringToNumber<std::uint32_t>(L"01"s));
287 CPPUNIT_ASSERT_EQUAL(1u, stringToNumber<std::uint32_t>(u"01"s));
288 CPPUNIT_ASSERT_EQUAL(23u, stringToNumber<std::uint32_t>(" 023"s));
289 CPPUNIT_ASSERT_EQUAL(23u, bufferToNumber<std::uint32_t>(" 023", 5));
290 CPPUNIT_ASSERT_EQUAL(255u, stringToNumber<std::uint32_t>("fF", 16));
291 CPPUNIT_ASSERT_THROW_MESSAGE("character out of range", stringToNumber<std::uint32_t>("fF", 15), ConversionException);
292 CPPUNIT_ASSERT_THROW_MESSAGE("invalid character", stringToNumber<std::uint32_t>("(", 15), ConversionException);
293#ifdef __GNUC__ // overflow detection only supported on GCC and Clang
294 CPPUNIT_ASSERT_THROW_MESSAGE("overflow", stringToNumber<std::uint32_t>("100000000", 16), ConversionException);
295 CPPUNIT_ASSERT_THROW_MESSAGE("underflow", stringToNumber<std::int32_t>("-80000001", 16), ConversionException);
296 CPPUNIT_ASSERT_EQUAL_MESSAGE("positive limit", 0xFFFFFFFFu, stringToNumber<std::uint32_t>("FFFFFFFF", 16));
297 CPPUNIT_ASSERT_EQUAL_MESSAGE("negative limit", -2147483647, stringToNumber<std::int32_t>("-2147483647", 10));
298#endif
299
300 // stringToNumber() / numberToString() with floating point numbers
301 CPPUNIT_ASSERT_EQUAL(1.5f, stringToNumber<float>(numberToString(1.5f)));
302 CPPUNIT_ASSERT_EQUAL(1.5, stringToNumber<double>(numberToString(1.5)));
303 CPPUNIT_ASSERT_EQUAL(-10.25, stringToNumber<double>("-10.25"));
304
305 // interpretIntegerAsString()
306 CPPUNIT_ASSERT_EQUAL("TEST"s, interpretIntegerAsString<std::uint32_t>(0x54455354));
307
308 // splitString() / joinStrings()
309 CPPUNIT_ASSERT_EQUAL_MESSAGE("empty string", vector<string>({ string() }), splitString<vector<string>>(string(), ","));
310 CPPUNIT_ASSERT_EQUAL_MESSAGE(
311 "empty string (simple)", vector<string_view>({ string_view() }), splitStringSimple<vector<string_view>>(string_view(), ","));
312 vector<string> splitTestExpected({ "1", "2,3" });
313 vector<string> splitTestActual = splitString<vector<string>>("1,2,3"s, ","s, EmptyPartsTreat::Keep, 2);
314 CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual);
315 splitTestActual = splitStringSimple<vector<string>>("1,2,3"s, ","s, 2);
316 CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual);
317 splitTestExpected = { "12", "34", "56", "" };
318 splitTestActual = splitString<vector<string>>("12,34,56,"s, ","s);
319 CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual);
320 splitTestActual = splitStringSimple<vector<string>>("12,34,56,"s, ","s);
321 CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual);
322 splitTestExpected = { "1", "2,3", "4,,5" };
323 splitTestActual = splitString<vector<string>>("1,2,,3,4,,5"s, ","s, EmptyPartsTreat::Merge, 3);
324 CPPUNIT_ASSERT_EQUAL(splitTestExpected, splitTestActual);
325 string splitJoinTest = joinStrings(splitString<vector<string>>(",a,,ab,ABC,s"s, ","s, EmptyPartsTreat::Keep), " "s, false, "("s, ")"s);
326 CPPUNIT_ASSERT_EQUAL("() (a) () (ab) (ABC) (s)"s, splitJoinTest);
327 splitJoinTest = joinStrings(splitString<vector<string>>(",a,,ab,ABC,s"s, ","s, EmptyPartsTreat::Keep), " "s, true, "("s, ")"s);
328 CPPUNIT_ASSERT_EQUAL("(a) (ab) (ABC) (s)"s, splitJoinTest);
329 splitJoinTest = joinStrings(splitStringSimple<vector<string>>(",a,,ab,ABC,s"s, ","s), " "s, true, "("s, ")"s);
330 CPPUNIT_ASSERT_EQUAL("(a) (ab) (ABC) (s)"s, splitJoinTest);
331 splitJoinTest = joinStrings(splitString<vector<string>>(",a,,ab,ABC,s"s, ","s, EmptyPartsTreat::Omit), " "s, false, "("s, ")"s);
332 CPPUNIT_ASSERT_EQUAL("(a) (ab) (ABC) (s)"s, splitJoinTest);
333 splitJoinTest = joinStrings(splitString<vector<string>>(",a,,ab,ABC,s"s, ","s, EmptyPartsTreat::Merge), " "s, false, "("s, ")"s);
334 CPPUNIT_ASSERT_EQUAL("(a,ab) (ABC) (s)"s, splitJoinTest);
335
336 // findAndReplace()
337 string findReplaceTest("findAndReplace()");
338 findAndReplace<string>(findReplaceTest, "And", "Or");
339 CPPUNIT_ASSERT_EQUAL("findOrReplace()"s, findReplaceTest);
340
341 // startsWith()
342 CPPUNIT_ASSERT(!startsWith(findReplaceTest, "findAnd"));
343 CPPUNIT_ASSERT(startsWith(findReplaceTest, "findOr"));
344 CPPUNIT_ASSERT(!startsWith(findReplaceTest, "findAnd"s));
345 CPPUNIT_ASSERT(startsWith(findReplaceTest, "findOr"s));
346 CPPUNIT_ASSERT(startsWith("test"s, "test"s));
347 CPPUNIT_ASSERT(startsWith("test"s, "test"));
348 CPPUNIT_ASSERT(!startsWith("test"s, "tests"s));
349 CPPUNIT_ASSERT(!startsWith("test"s, "tests"));
350
351 // endsWith()
352 CPPUNIT_ASSERT(!endsWith(findReplaceTest, "AndReplace()"));
353 CPPUNIT_ASSERT(endsWith(findReplaceTest, "OrReplace()"));
354 CPPUNIT_ASSERT(!endsWith(findReplaceTest, "AndReplace()"s));
355 CPPUNIT_ASSERT(endsWith(findReplaceTest, "OrReplace()"s));
356 CPPUNIT_ASSERT(endsWith("test"s, "test"s));
357 CPPUNIT_ASSERT(endsWith("test"s, "test"));
358 CPPUNIT_ASSERT(!endsWith("test"s, " test"s));
359 CPPUNIT_ASSERT(!endsWith("test"s, " test"));
360
361 // containsSubstrings()
362 CPPUNIT_ASSERT(containsSubstrings<string>("this string contains foo and bar", { "foo", "bar" }));
363 CPPUNIT_ASSERT(!containsSubstrings<string>("this string contains foo and bar", { "bar", "foo" }));
364
365 // truncateString()
366 string truncateTest("foo bar ");
367 truncateString(truncateTest, ' ');
368 CPPUNIT_ASSERT_EQUAL("foo"s, truncateTest);
369
370 // encodeBase64() / decodeBase64() with random data
371 std::uniform_int_distribution<int> randomDistChar;
372 std::uint8_t originalBase64Data[4047];
373 for (std::uint8_t &c : originalBase64Data) {
374 c = static_cast<std::uint8_t>(randomDistChar(m_randomEngine) & 0xFF);
375 }
376 auto encodedBase64Data = encodeBase64(originalBase64Data, sizeof(originalBase64Data));
377 auto decodedBase64Data = decodeBase64(encodedBase64Data.data(), static_cast<std::uint32_t>(encodedBase64Data.size()));
378 CPPUNIT_ASSERT(decodedBase64Data.second == sizeof(originalBase64Data));
379 for (unsigned int i = 0; i < sizeof(originalBase64Data); ++i) {
380 CPPUNIT_ASSERT(decodedBase64Data.first[i] == originalBase64Data[i]);
381 }
382 // test padding
383 encodedBase64Data = encodeBase64(originalBase64Data, sizeof(originalBase64Data) - 1);
384 CPPUNIT_ASSERT_EQUAL('=', encodedBase64Data.at(encodedBase64Data.size() - 1));
385 CPPUNIT_ASSERT_NO_THROW(decodeBase64(encodedBase64Data.data(), static_cast<std::uint32_t>(encodedBase64Data.size())));
386 encodedBase64Data = encodeBase64(originalBase64Data, sizeof(originalBase64Data) - 2);
387 CPPUNIT_ASSERT_EQUAL('=', encodedBase64Data.at(encodedBase64Data.size() - 1));
388 CPPUNIT_ASSERT_EQUAL('=', encodedBase64Data.at(encodedBase64Data.size() - 2));
389 CPPUNIT_ASSERT_NO_THROW(decodeBase64(encodedBase64Data.data(), static_cast<std::uint32_t>(encodedBase64Data.size())));
390 // test check for invalid size
391 CPPUNIT_ASSERT_THROW(decodeBase64(encodedBase64Data.data(), 3), ConversionException);
392
393 // dataSizeToString(), bitrateToString()
394 CPPUNIT_ASSERT_EQUAL("512 bytes"s, dataSizeToString(512ull));
395 CPPUNIT_ASSERT_EQUAL("2.50 KiB"s, dataSizeToString((2048ull + 512ull)));
396 CPPUNIT_ASSERT_EQUAL("2.50 KiB (2560 byte)"s, dataSizeToString((2048ull + 512ull), true));
397 CPPUNIT_ASSERT_EQUAL("2.50 MiB"s, dataSizeToString((2048ull + 512ull) * 1024ull));
398 CPPUNIT_ASSERT_EQUAL("2.50 GiB"s, dataSizeToString((2048ull + 512ull) * 1024ull * 1024ull));
399 CPPUNIT_ASSERT_EQUAL("2.50 TiB"s, dataSizeToString((2048ull + 512ull) * 1024ull * 1024ull * 1024ull));
400 CPPUNIT_ASSERT_EQUAL("128 bit/s"s, bitrateToString(0.128, false));
401 CPPUNIT_ASSERT_EQUAL("128 kbit/s"s, bitrateToString(128.0, false));
402 CPPUNIT_ASSERT_EQUAL("128 Mbit/s"s, bitrateToString(128.0 * 1e3, false));
403 CPPUNIT_ASSERT_EQUAL("128 Gbit/s"s, bitrateToString(128.0 * 1e6, false));
404 CPPUNIT_ASSERT_EQUAL("16 byte/s"s, bitrateToString(0.128, true));
405 CPPUNIT_ASSERT_EQUAL("16 KiB/s"s, bitrateToString(128.0, true));
406 CPPUNIT_ASSERT_EQUAL("16 MiB/s"s, bitrateToString(128.0 * 1e3, true));
407 CPPUNIT_ASSERT_EQUAL("16 GiB/s"s, bitrateToString(128.0 * 1e6, true));
408}
409
411
412struct ConvertibleToString {
413 operator std::string() const;
414};
415
416struct StringThatDoesNotLikeToBeCopiedOrMoved : public std::string {
417 explicit StringThatDoesNotLikeToBeCopiedOrMoved(const char *value)
418 : std::string(value)
419 {
420 }
421 // delete copy and move c'tor so if argsToString() would invoke one it would be a compile time error
422 // caveat: argsToString() might still construct an std::string() unnoticed.
423 [[noreturn]] StringThatDoesNotLikeToBeCopiedOrMoved(const StringThatDoesNotLikeToBeCopiedOrMoved &other) = delete;
424 [[noreturn]] StringThatDoesNotLikeToBeCopiedOrMoved(StringThatDoesNotLikeToBeCopiedOrMoved &&other) = delete;
425};
426
428
429 void ConversionTests::testStringBuilder()
430{
431 // check whether type traits work as expected
432 static_assert(Helper::IsStringType<std::string, std::string>::value);
433 static_assert(!Helper::IsStringType<std::string, std::wstring>::value);
434 static_assert(Helper::IsStringType<std::wstring, std::wstring>::value);
435 static_assert(Helper::IsStringViewType<std::string, std::string_view>::value);
436 static_assert(!Helper::IsStringViewType<std::wstring, std::string_view>::value);
437 static_assert(Helper::IsStringViewType<std::wstring, std::wstring_view>::value);
438 static_assert(Helper::IsConvertibleToConstStringRef<std::string, ConvertibleToString>::value);
439#ifdef CPP_UTILITIES_USE_STANDARD_FILESYSTEM
440 static_assert(!Helper::IsConvertibleToConstStringRef<std::filesystem::path::string_type, std::filesystem::path>::value,
441 "conversion via native() preferred");
442#endif
443 static_assert(
444 !Helper::IsConvertibleToConstStringRef<std::string, std::string>::value, "yes, in this context this should not be considered convertible");
445 static_assert(!Helper::IsConvertibleToConstStringRef<std::wstring, ConvertibleToString>::value);
446#ifdef CPP_UTILITIES_USE_STANDARD_FILESYSTEM
447 static_assert(Helper::IsConvertibleToConstStringRefViaNative<std::filesystem::path::string_type, std::filesystem::path>::value);
448#endif
449 static_assert(!Helper::IsConvertibleToConstStringRefViaNative<std::string, std::string>::value);
450
451 // conversion of string-tuple to string (the actual string builder)
452 const tuple<const char *, string, int, const char *> tuple("string1", "string2", 1234, "string3");
453 CPPUNIT_ASSERT_EQUAL("string1string21234string3"s, tupleToString(tuple));
454 CPPUNIT_ASSERT_EQUAL("foobarfoo2bar2"s, tupleToString("foo"s % "bar" % "foo2"s % "bar2"));
455 CPPUNIT_ASSERT_EQUAL("v2.3.0"s, argsToString("v2.", 3, '.', 0));
456 CPPUNIT_ASSERT_EQUAL("v2.3.0"s, argsToString('v', make_tuple(2, '.', 3, '.', 0)));
457#ifdef CPP_UTILITIES_USE_STANDARD_FILESYSTEM
458 if constexpr (std::is_same_v<std::filesystem::path::value_type, std::string::value_type>) {
459 CPPUNIT_ASSERT_EQUAL("path: foo"s, argsToString("path: ", std::filesystem::path("foo")));
460 }
461#endif
462
463 // construction of string-tuple and final conversion to string works
464 CPPUNIT_ASSERT_EQUAL_MESSAGE("result can be passed to any function taking a std::string"s, "123456789"s, "12" % string("34") % '5' % 67 + "89");
465 constexpr double velocityExample = 27.0;
466 CPPUNIT_ASSERT_EQUAL_MESSAGE("real-word example"s, "velocity: 27 km/h (7.5 m/s)"s,
467 "velocity: " % numberToString(velocityExample) % " km/h (" % numberToString(velocityExample / 3.6) + " m/s)");
468 CPPUNIT_ASSERT_EQUAL_MESSAGE(
469 "regular + operator still works (no problems with ambiguity)"s, "regular + still works"s, "regular"s + " + still works");
470 CPPUNIT_ASSERT_EQUAL_MESSAGE("using string_view", "foobar123"s, "foo"sv % "bar"sv + 123);
471
472 // check that for the internal tuple construction no copies are made
473 auto str = StringThatDoesNotLikeToBeCopiedOrMoved(" happen ");
474 const auto str2 = StringThatDoesNotLikeToBeCopiedOrMoved("for this");
475 CPPUNIT_ASSERT_EQUAL("no copy/move should happen for this!"s,
476 argsToString(StringThatDoesNotLikeToBeCopiedOrMoved("no copy/move should"), str, str2, StringThatDoesNotLikeToBeCopiedOrMoved("!")));
477}
binaryconversion.h
ConversionTests
The ConversionTests class tests classes and functions provided by the files inside the conversion dir...
Definition conversiontests.cpp:37
ConversionTests::testSwapOrderFunctions
void testSwapOrderFunctions()
Tests swap order functions.
Definition conversiontests.cpp:170
ConversionTests::testBinaryConversions
void testBinaryConversions()
Tests most important binary conversions.
Definition conversiontests.cpp:146
ConversionTests::ConversionTests
ConversionTests()
Definition conversiontests.cpp:77
ConversionTests::testStringBuilder
void testStringBuilder()
Definition conversiontests.cpp:429
ConversionTests::testStringEncodingConversions
void testStringEncodingConversions()
Tests string encoding conversions.
Definition conversiontests.cpp:213
ConversionTests::testConversionException
void testConversionException()
Definition conversiontests.cpp:83
ConversionTests::setUp
void setUp()
Definition conversiontests.cpp:51
ConversionTests::testEndianness
void testEndianness()
Tests whether macros for endianness are correct.
Definition conversiontests.cpp:91
ConversionTests::testStringConversions
void testStringConversions()
Tests miscellaneous string conversions.
Definition conversiontests.cpp:252
ConversionTests::tearDown
void tearDown()
Definition conversiontests.cpp:54
CppUtilities::ConversionException
The ConversionException class is thrown by the various conversion functions of this library when a co...
Definition conversionexception.h:11
assertEqual
void assertEqual(const char *message, const std::uint8_t *expectedValues, size_t expectedSize, const StringData &actualValues)
Internally used for string encoding tests to check results.
Definition conversiontests.cpp:180
TEST_BE_CONVERSION
#define TEST_BE_CONVERSION(function)
Definition conversiontests.cpp:132
TEST_LE_CONVERSION
#define TEST_LE_CONVERSION(function)
Definition conversiontests.cpp:134
TEST_CUSTOM_CONVERSION
#define TEST_CUSTOM_CONVERSION(vice, versa, endianness, min, max)
Definition conversiontests.cpp:136
CPPUNIT_TEST_SUITE_REGISTRATION
CPPUNIT_TEST_SUITE_REGISTRATION(ConversionTests)
CppUtilities::BE
Encapsulates binary conversion functions using the big endian byte order.
Definition binaryconversion.h:208
CppUtilities::LE
Encapsulates binary conversion functions using the little endian byte order.
Definition binaryconversion.h:219
CppUtilities
Contains all utilities provided by the c++utilities library.
Definition argumentparser.h:18
CppUtilities::findAndReplace
void findAndReplace(StringType1 &str, const StringType2 &find, const StringType3 &replace)
Replaces all occurrences of find with relpace in the specified str.
Definition stringconversion.h:380
CppUtilities::convertUtf8ToUtf16BE
CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16BE(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-8 string to UTF-16 (big-endian).
Definition stringconversion.cpp:179
CppUtilities::convertString
CPP_UTILITIES_EXPORT StringData convertString(const char *fromCharset, const char *toCharset, const char *inputBuffer, std::size_t inputBufferSize, float outputBufferSizeFactor=1.0f)
Converts the specified string from one character set to another.
Definition stringconversion.cpp:152
CppUtilities::StringData
std::pair< std::unique_ptr< char[], StringDataDeleter >, std::size_t > StringData
Type used to return string encoding conversion result.
Definition stringconversion.h:57
CppUtilities::numberToString
StringType numberToString(IntegralType number, BaseType base=10)
Converts the given number to its equivalent string representation using the specified base.
Definition stringconversion.h:434
CppUtilities::toNormalInt
CPP_UTILITIES_EXPORT constexpr std::uint32_t toNormalInt(std::uint32_t synchsafeInt)
Returns a normal 32-bit integer converted from a 32-bit synchsafe integer.
Definition binaryconversion.h:131
CppUtilities::convertLatin1ToUtf8
CPP_UTILITIES_EXPORT StringData convertLatin1ToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified Latin-1 string to UTF-8.
Definition stringconversion.cpp:197
CppUtilities::convertUtf16LEToUtf8
CPP_UTILITIES_EXPORT StringData convertUtf16LEToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-16 (little-endian) string to UTF-8.
Definition stringconversion.cpp:170
CppUtilities::EmptyPartsTreat::Keep
@ Keep
Definition stringconversion.h:158
CppUtilities::EmptyPartsTreat::Omit
@ Omit
Definition stringconversion.h:159
CppUtilities::EmptyPartsTreat::Merge
@ Merge
Definition stringconversion.h:160
CppUtilities::joinStrings
ReturnType joinStrings(const Container &strings, Detail::StringParamForContainer< Container > delimiter=Detail::StringParamForContainer< Container >(), bool omitEmpty=false, Detail::StringParamForContainer< Container > leftClosure=Detail::StringParamForContainer< Container >(), Detail::StringParamForContainer< Container > rightClosure=Detail::StringParamForContainer< Container >())
Joins the given strings using the specified delimiter.
Definition stringconversion.h:111
CppUtilities::swapOrder
CPP_UTILITIES_EXPORT constexpr std::uint16_t swapOrder(std::uint16_t value)
Swaps the byte order of the specified 16-bit unsigned integer.
Definition binaryconversion.h:149
CppUtilities::startsWith
bool startsWith(const StringType &str, const StringType &phrase)
Returns whether str starts with phrase.
Definition stringconversion.h:274
CppUtilities::stringToNumber
IntegralType stringToNumber(const StringType &string, BaseType base=10)
Converts the given string to an unsigned/signed number assuming string uses the specified base.
Definition stringconversion.h:605
CppUtilities::truncateString
CPP_UTILITIES_EXPORT void truncateString(std::string &str, char terminationChar='\0')
Truncates all characters after the first occurrence of the specified terminationChar and the terminat...
Definition stringconversion.cpp:303
CppUtilities::convertUtf16BEToUtf8
CPP_UTILITIES_EXPORT StringData convertUtf16BEToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-16 (big-endian) string to UTF-8.
Definition stringconversion.cpp:188
CppUtilities::splitStringSimple
Container splitStringSimple(Detail::StringParamForContainer< Container > string, Detail::StringParamForContainer< Container > delimiter, int maxParts=-1)
Splits the given string (which might also be a string view) at the specified delimiter.
Definition stringconversion.h:225
CppUtilities::argsToString
StringType argsToString(Args &&...args)
Definition stringbuilder.h:260
CppUtilities::containsSubstrings
bool containsSubstrings(const StringType &str, std::initializer_list< StringType > substrings)
Returns whether str contains the specified substrings.
Definition stringconversion.h:347
CppUtilities::max
constexpr T max(T first, T second)
Returns the greatest of the given items.
Definition math.h:96
CppUtilities::tupleToString
StringType tupleToString(const std::tuple< Args... > &tuple)
Concatenates all strings hold by the specified tuple.
Definition stringbuilder.h:252
CppUtilities::asHexNumber
AsHexNumber< T > asHexNumber(const T &value)
Wraps a value to be printed using the hex system in the error case when asserted with cppunit (or sim...
Definition testutils.h:258
CppUtilities::convertUtf8ToLatin1
CPP_UTILITIES_EXPORT StringData convertUtf8ToLatin1(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-8 string to Latin-1.
Definition stringconversion.cpp:206
CppUtilities::interpretIntegerAsString
std::string interpretIntegerAsString(T integer, int startOffset=0)
Interprets the given integer at the specified position as std::string using the specified byte order.
Definition stringconversion.h:727
CppUtilities::endsWith
bool endsWith(const StringType &str, const StringType &phrase)
Returns whether str ends with phrase.
Definition stringconversion.h:311
CppUtilities::toSynchsafeInt
CPP_UTILITIES_EXPORT constexpr std::uint32_t toSynchsafeInt(std::uint32_t normalInt)
Returns a 32-bit synchsafe integer converted from a normal 32-bit integer.
Definition binaryconversion.h:121
CppUtilities::convertUtf8ToUtf16LE
CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16LE(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-8 string to UTF-16 (little-endian).
Definition stringconversion.cpp:161
CppUtilities::bitrateToString
CPP_UTILITIES_EXPORT std::string bitrateToString(double speedInKbitsPerSecond, bool useByteInsteadOfBits=false)
Converts the specified bitrate in kbit/s to its equivalent std::string representation.
Definition stringconversion.cpp:348
CppUtilities::min
constexpr T min(T first, T second)
Returns the smallest of the given items.
Definition math.h:84
CppUtilities::encodeBase64
CPP_UTILITIES_EXPORT std::string encodeBase64(const std::uint8_t *data, std::uint32_t dataSize)
Encodes the specified data to Base64.
Definition stringconversion.cpp:387
CppUtilities::dataSizeToString
CPP_UTILITIES_EXPORT std::string dataSizeToString(std::uint64_t sizeInByte, bool includeByte=false)
Converts the specified data size in byte to its equivalent std::string representation.
Definition stringconversion.cpp:316
CppUtilities::bufferToNumber
IntegralType bufferToNumber(const CharType *string, std::size_t size, BaseType base=10)
Converts the given string of size characters to an unsigned numeric value using the specified base.
Definition stringconversion.h:556
CppUtilities::decodeBase64
CPP_UTILITIES_EXPORT std::pair< std::unique_ptr< std::uint8_t[]>, std::uint32_t > decodeBase64(const char *encodedStr, const std::uint32_t strSize)
Decodes the specified Base64 encoded string.
Definition stringconversion.cpp:427
CppUtilities::splitString
Container splitString(Detail::StringParamForContainer< Container > string, Detail::StringParamForContainer< Container > delimiter, EmptyPartsTreat emptyPartsRole=EmptyPartsTreat::Keep, int maxParts=-1)
Splits the given string at the specified delimiter.
Definition stringconversion.h:173
std
STL namespace.
stringbuilder.h
stringconversion.h
testutils.h
i
constexpr int i
Definition traitstests.cpp:106