1 #include "../conversion/binaryconversion.h" 2 #include "../conversion/stringbuilder.h" 3 #include "../conversion/stringconversion.h" 4 #include "../tests/testutils.h" 6 #include <cppunit/TestFixture.h> 7 #include <cppunit/extensions/HelperMacros.h> 10 #include <initializer_list> 25 CPPUNIT_TEST(testEndianness);
26 CPPUNIT_TEST(testBinaryConversions);
27 CPPUNIT_TEST(testSwapOrderFunctions);
28 CPPUNIT_TEST(testStringEncodingConversions);
29 CPPUNIT_TEST(testStringConversions);
30 CPPUNIT_TEST(testStringBuilder);
31 CPPUNIT_TEST_SUITE_END();
43 void testEndianness();
44 void testBinaryConversions();
45 void testSwapOrderFunctions();
46 void testStringEncodingConversions();
47 void testStringConversions();
48 void testStringBuilder();
51 template <
typename intType>
52 void testConversion(
const char *message,
function<
void(intType,
char *)> vice,
function<intType(
const char *)> verca, intType min, intType max);
55 random_device m_randomDevice;
56 mt19937 m_randomEngine;
63 , m_randomEngine(m_randomDevice())
75 } test = { 0x01020304 };
76 #if defined(CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN) 78 CPPUNIT_ASSERT(CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN ==
true);
79 CPPUNIT_ASSERT(CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN ==
false);
81 CPPUNIT_ASSERT_MESSAGE(
"Byte order assumption (big-endian) is wrong", test.characters[0] == 0x01);
82 #elif defined(CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN) 84 CPPUNIT_ASSERT(CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN ==
false);
85 CPPUNIT_ASSERT(CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN ==
true);
87 CPPUNIT_ASSERT_MESSAGE(
"Byte order assumption (little-endian) is wrong", test.characters[0] == 0x04);
89 CPPUNIT_FAIL(
"There is not valid byte order assumption");
93 template <
typename intType>
94 void ConversionTests::testConversion(
95 const char *message,
function<
void(intType,
char *)> vice,
function<intType(
const char *)> versa, intType min, intType max)
97 const intType
random = uniform_int_distribution<intType>(min, max)(m_randomEngine);
99 msg << message <<
'(' << hex <<
'0' <<
'x' << random <<
')';
100 vice(random, m_buff);
101 CPPUNIT_ASSERT_MESSAGE(msg.str(), versa(m_buff) ==
random);
104 #define TEST_TYPE(endianness, function) decltype(endianness::function(m_buff)) 106 #define TEST_CONVERSION(function, endianness) \ 107 testConversion<TEST_TYPE(endianness, function)>("testing " #function, \ 108 static_cast<void (*)(TEST_TYPE(endianness, function), char *)>(&endianness::getBytes), endianness::function, \ 109 numeric_limits<TEST_TYPE(endianness, function)>::min(), numeric_limits<TEST_TYPE(endianness, function)>::max()) 111 #define TEST_BE_CONVERSION(function) TEST_CONVERSION(function, BE) 113 #define TEST_LE_CONVERSION(function) TEST_CONVERSION(function, LE) 115 #define TEST_CUSTOM_CONVERSION(vice, versa, endianness, min, max) \ 116 testConversion<TEST_TYPE(endianness, versa)>( \ 117 "testing " #versa, static_cast<void (*)(TEST_TYPE(endianness, versa), char *)>(&endianness::vice), endianness::versa, min, max) 128 for (
byte b = 1; b < 100; ++b) {
151 CPPUNIT_ASSERT(
swapOrder(static_cast<uint16>(0x7825)) == 0x2578);
152 CPPUNIT_ASSERT(
swapOrder(static_cast<uint32>(0x12345678)) == 0x78563412);
153 CPPUNIT_ASSERT(
swapOrder(static_cast<uint64>(0x1122334455667788)) == 0x8877665544332211);
162 CPPUNIT_ASSERT_EQUAL_MESSAGE(message, expectedSize, actualValues.second);
164 auto *end = expectedValues + expectedSize;
165 auto *i =
reinterpret_cast<byte *
>(actualValues.first.get());
166 for (; expectedValues != end; ++expectedValues, ++i) {
171 #if CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN == true 172 #define LE_STR_FOR_ENDIANNESS(name) name##LE##String 173 #define BE_STR_FOR_ENDIANNESS(name) name##BE##String 174 #elif CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN == true 175 #define LE_STR_FOR_ENDIANNESS(name) name##BE##String 176 #define BE_STR_FOR_ENDIANNESS(name) name##LE##String 195 const byte simpleString[] = {
'A',
'B',
'C',
'D' };
196 const uint16 simpleUtf16LEString[] = { 0x0041, 0x0042, 0x0043, 0x0044 };
197 const uint16 simpleUtf16BEString[] = { 0x4100, 0x4200, 0x4300, 0x4400 };
199 const byte latin1String[] = {
'A',
'B', 0xD6,
'C',
'D' };
200 const byte utf8String[] = {
'A',
'B', 0xC3, 0x96,
'C',
'D' };
201 const uint16 utf16LEString[] = { 0x0041, 0x0042, 0x00D6, 0x0043, 0x0044 };
202 const uint16 utf16BEString[] = { 0x4100, 0x4200, 0xD600, 0x4300, 0x4400 };
231 CPPUNIT_ASSERT_EQUAL(
string(
"0"), numberToString<unsigned int>(0));
232 CPPUNIT_ASSERT_EQUAL(
string(
"0"), numberToString<signed int>(0));
233 uniform_int_distribution<int64> randomDistSigned(numeric_limits<int64>::min());
234 uniform_int_distribution<uint64> randomDistUnsigned(0);
235 for (
byte b = 1; b < 100; ++b) {
236 auto signedRandom = randomDistSigned(m_randomEngine);
237 auto unsignedRandom = randomDistUnsigned(m_randomEngine);
238 for (
const auto base : initializer_list<byte>{ 2, 8, 10, 16 }) {
239 auto resultString = stringToNumber<uint64, string>(numberToString<uint64, string>(unsignedRandom, base), base);
240 auto resultWideString = stringToNumber<uint64, wstring>(numberToString<uint64, wstring>(unsignedRandom, base), base);
241 CPPUNIT_ASSERT_EQUAL(unsignedRandom, resultString);
242 CPPUNIT_ASSERT_EQUAL(unsignedRandom, resultWideString);
244 for (
const auto base : initializer_list<byte>{ 10 }) {
245 auto resultString = stringToNumber<int64, string>(numberToString<int64, string>(signedRandom, base), base);
246 auto resultWideString = stringToNumber<int64, wstring>(numberToString<int64, wstring>(signedRandom, base), base);
247 CPPUNIT_ASSERT_EQUAL(signedRandom, resultString);
248 CPPUNIT_ASSERT_EQUAL(signedRandom, resultWideString);
253 int32 res = stringToNumber<int32, string>(
"01");
254 CPPUNIT_ASSERT_EQUAL(1, res);
255 res = stringToNumber<int32, wstring>(L
"01");
256 CPPUNIT_ASSERT_EQUAL(1, res);
257 res = stringToNumber<int32, u16string>(u
"01");
258 CPPUNIT_ASSERT_EQUAL(1, res);
261 CPPUNIT_ASSERT(interpretIntegerAsString<uint32>(0x54455354) ==
"TEST");
264 string splitJoinTest =
joinStrings(
splitString<vector<string>>(
",a,,ab,ABC,s"s,
","s, EmptyPartsTreat::Keep),
" "s,
false,
"("s,
")"s);
265 CPPUNIT_ASSERT_EQUAL(
"() (a) () (ab) (ABC) (s)"s, splitJoinTest);
266 splitJoinTest =
joinStrings(
splitString<vector<string>>(
",a,,ab,ABC,s"s,
","s, EmptyPartsTreat::Keep),
" "s,
true,
"("s,
")"s);
267 CPPUNIT_ASSERT_EQUAL(
"(a) (ab) (ABC) (s)"s, splitJoinTest);
268 splitJoinTest =
joinStrings(
splitString<vector<string>>(
",a,,ab,ABC,s"s,
","s, EmptyPartsTreat::Omit),
" "s,
false,
"("s,
")"s);
269 CPPUNIT_ASSERT_EQUAL(
"(a) (ab) (ABC) (s)"s, splitJoinTest);
270 splitJoinTest =
joinStrings(
splitString<vector<string>>(
",a,,ab,ABC,s"s,
","s, EmptyPartsTreat::Merge),
" "s,
false,
"("s,
")"s);
271 CPPUNIT_ASSERT_EQUAL(
"(a,ab) (ABC) (s)"s, splitJoinTest);
274 string findReplaceTest(
"findAndReplace()");
275 findAndReplace<string>(findReplaceTest,
"And",
"Or");
276 CPPUNIT_ASSERT_EQUAL(
"findOrReplace()"s, findReplaceTest);
279 CPPUNIT_ASSERT(!startsWith<string>(findReplaceTest,
"findAnd"));
280 CPPUNIT_ASSERT(startsWith<string>(findReplaceTest,
"findOr"));
283 CPPUNIT_ASSERT(containsSubstrings<string>(
"this string contains foo and bar", {
"foo",
"bar" }));
284 CPPUNIT_ASSERT(!containsSubstrings<string>(
"this string contains foo and bar", {
"bar",
"foo" }));
287 uniform_int_distribution<byte> randomDistChar;
288 byte originalBase64Data[4047];
289 for (
byte &c : originalBase64Data) {
290 c = randomDistChar(m_randomEngine);
292 const auto encodedBase64Data =
encodeBase64(originalBase64Data,
sizeof(originalBase64Data));
293 auto decodedBase64Data =
decodeBase64(encodedBase64Data.data(), encodedBase64Data.size());
294 CPPUNIT_ASSERT(decodedBase64Data.second ==
sizeof(originalBase64Data));
295 for (
unsigned int i = 0; i <
sizeof(originalBase64Data); ++i) {
296 CPPUNIT_ASSERT(decodedBase64Data.first[i] == originalBase64Data[i]);
308 const tuple<const char *, string, int, const char *> tuple(
"string1",
"string2", 1234,
"string3");
309 CPPUNIT_ASSERT_EQUAL(
string(
"string1string21234string3"),
tupleToString(tuple));
310 CPPUNIT_ASSERT_EQUAL(
string(
"foobarfoo2bar2"),
tupleToString(
string(
"foo") %
"bar" %
string(
"foo2") %
"bar2"));
311 CPPUNIT_ASSERT_EQUAL(
string(
"v2.3.0"),
argsToString(
"v2.", 3,
'.', 0));
314 CPPUNIT_ASSERT_EQUAL_MESSAGE(
315 "result can be passed to any function taking a std::string"s,
"123456789"s,
functionTakingString(
"12" %
string(
"34") %
'5' % 67 +
"89"));
316 constexpr
double velocityExample = 27.0;
317 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"real-word example"s,
"velocity: 27 km/h (7.5 m/s)"s,
319 CPPUNIT_ASSERT_EQUAL_MESSAGE(
320 "regular + operator still works (no problems with ambiguity)"s,
"regular + still works"s,
"regular"s +
" + still works");
CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16LE(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-8 string to UTF-16 (little-endian).
CPP_UTILITIES_EXPORT std::string encodeBase64(const byte *data, uint32 dataSize)
Encodes the specified data to Base64.
void testSwapOrderFunctions()
Tests swap order functions.
CPP_UTILITIES_EXPORT StringData convertUtf16BEToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-16 (big-endian) string to UTF-8.
void testBinaryConversions()
Tests most important binary conversions.
constexpr StringType argsToString(Args &&... args)
#define TEST_LE_CONVERSION(function)
CPPUNIT_TEST_SUITE_REGISTRATION(ConversionTests)
void testStringConversions()
Tests miscellaneous string conversions.
StringType numberToString(IntegralType number, typename StringType::value_type base=10)
Converts the given number to its equivalent string representation using the specified base...
void testEndianness()
Tests whether macros for endianness are correct.
#define TEST_CUSTOM_CONVERSION(vice, versa, endianness, min, max)
CPP_UTILITIES_EXPORT int random(int lowerbounds, int upperbounds)
Returns a pseudo random number between lowerbounds and upperbounds.
#define BE_STR_FOR_ENDIANNESS(name)
Selects right string for big-endian checks.
CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16BE(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-8 string to UTF-16 (big-endian).
string functionTakingString(const string &str)
CPP_UTILITIES_EXPORT constexpr uint16 swapOrder(uint16 value)
Swaps the byte order of the specified 16-bit unsigned integer.
Contains classes and functions utilizing creating of test applications.
#define TEST_BE_CONVERSION(function)
CPP_UTILITIES_EXPORT StringData convertUtf8ToLatin1(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-8 string to Latin-1.
Contains several functions providing conversions between different data types.
std::pair< std::unique_ptr< char[], StringDataDeleter >, std::size_t > StringData
Type used to return string encoding conversion result.
CPP_UTILITIES_EXPORT StringData convertUtf16LEToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-16 (little-endian) string to UTF-8.
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...
void testStringEncodingConversions()
Tests string encoding conversions.
std::int32_t int32
signed 32-bit integer
void assertEqual(const char *message, const byte *expectedValues, size_t expectedSize, const StringData &actualValues)
Internally used for string encoding tests to check results.
Container::value_type joinStrings(const Container &strings, const typename Container::value_type &delimiter=typename Container::value_type(), bool omitEmpty=false, const typename Container::value_type &leftClosure=typename Container::value_type(), const typename Container::value_type &rightClosure=typename Container::value_type())
Joins the given strings using the specified delimiter.
std::uint8_t byte
unsigned byte
CPP_UTILITIES_EXPORT StringData convertLatin1ToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified Latin-1 string to UTF-8.
#define LE_STR_FOR_ENDIANNESS(name)
Selects right string for little-endian checks.
StringType tupleToString(const std::tuple< Args... > &tuple)
Concatenates all strings hold by the specified tuple.
Container splitString(const typename Container::value_type &string, const typename Container::value_type &delimiter, EmptyPartsTreat emptyPartsRole=EmptyPartsTreat::Keep, int maxParts=-1)
Splits the given string at the specified delimiter.
CPP_UTILITIES_EXPORT std::pair< std::unique_ptr< byte[]>, uint32 > decodeBase64(const char *encodedStr, const uint32 strSize)
Decodes the specified Base64 encoded string.
The ConversionTests class tests classes and methods of the ConversionUtilities namespace.
std::uint16_t uint16
unsigned 16-bit integer