Browse Source

Merge pull request #492 from zrax/string_tests

String tests
Adam Johnson 9 years ago
parent
commit
5b9f915e8e
  1. 13
      Sources/Plasma/CoreLib/HeadSpin.cpp
  2. 58
      Sources/Plasma/CoreLib/plFormat.cpp
  3. 4
      Sources/Plasma/CoreLib/plFormat.h
  4. 33
      Sources/Plasma/CoreLib/plString.cpp
  5. 1
      Sources/Tests/CoreTests/CMakeLists.txt
  6. 397
      Sources/Tests/CoreTests/test_plFormat.cpp
  7. 787
      Sources/Tests/CoreTests/test_plString.cpp

13
Sources/Plasma/CoreLib/HeadSpin.cpp

@ -139,8 +139,10 @@ void ErrorAssert(int line, const char* file, const char* fmt, ...)
} else
#endif // _MSC_VER
{
char str[] = "-------\nASSERTION FAILED:\nFile: %s Line: %i\nMessage: %s\n-------";
DebugMsg(str, file, line, msg);
DebugMsg("-------\nASSERTION FAILED:\nFile: %s Line: %i\nMessage: %s\n-------",
file, line, msg);
fflush(stderr);
DebugBreakAlways();
}
#endif // HS_DEBUGGING
@ -214,17 +216,16 @@ void DebugMsg(const char* fmt, ...)
va_list args;
va_start(args, fmt);
vsnprintf(msg, arrsize(msg), fmt, args);
fprintf(stderr, "%s\n", msg);
#ifdef _MSC_VER
if (DebugIsDebuggerPresent())
{
// Also print to the MSVC Output window
OutputDebugStringA(msg);
OutputDebugStringA("\n");
} else
#endif
{
fprintf(stderr, "%s\n", msg);
}
#endif
}
////////////////////////////////////////////////////////////////////////////

58
Sources/Plasma/CoreLib/plFormat.cpp

@ -45,6 +45,7 @@ Mead, WA 99021
#include "HeadSpin.h"
#include <cstdlib>
#include <cstring>
#include <type_traits>
#define BADCHAR_REPLACEMENT (0xFFFDul)
@ -120,11 +121,10 @@ namespace plFormat_Private
spec.fDigitClass = kDigitHexUpper;
break;
case '+':
spec.fDigitClass = kDigitDecAlwaysSigned;
spec.fAlwaysSigned = true;
break;
case 'd':
if (spec.fDigitClass != kDigitDecAlwaysSigned)
spec.fDigitClass = kDigitDec;
spec.fDigitClass = kDigitDec;
break;
case 'o':
spec.fDigitClass = kDigitOct;
@ -226,7 +226,8 @@ static void _formatNumeric(const plFormat_Private::FormatSpec &format,
plStringStream &output, _IType value,
int radix, bool upperCase = false)
{
char pad = format.fPadChar ? format.fPadChar : ' ';
static_assert(std::is_unsigned<_IType>::value,
"Signed numerics are currently only supported in Decimal formatting");
size_t format_size = 0;
_IType temp = value;
@ -238,9 +239,9 @@ static void _formatNumeric(const plFormat_Private::FormatSpec &format,
if (format_size == 0)
format_size = 1;
hsAssert(format_size < 64, "Format length too long");
hsAssert(format_size < 65, "Format length too long");
char buffer[64];
char buffer[65];
_IFormatNumeric_Impl<_IType>(buffer + format_size, value, radix, upperCase);
_formatString(format, output, buffer, format_size, plFormat_Private::kAlignRight);
}
@ -250,11 +251,11 @@ template <typename _IType>
static void _formatDecimal(const plFormat_Private::FormatSpec &format,
plStringStream &output, _IType value)
{
char pad = format.fPadChar ? format.fPadChar : ' ';
_IType abs = (value < 0) ? -value : value;
typedef typename std::make_unsigned<_IType>::type _UType;
_UType abs = (value < 0) ? -(_UType)value : value;
size_t format_size = 0;
_IType temp = abs;
_UType temp = abs;
while (temp) {
++format_size;
temp /= 10;
@ -263,21 +264,18 @@ static void _formatDecimal(const plFormat_Private::FormatSpec &format,
if (format_size == 0)
format_size = 1;
if (value < 0 || format.fDigitClass == plFormat_Private::kDigitDecAlwaysSigned)
if (value < 0 || format.fAlwaysSigned)
++format_size;
hsAssert(format_size < 21, "Format length too long");
char buffer[21];
_IFormatNumeric_Impl<_IType>(buffer + format_size, abs, 10);
hsAssert(format_size < 24, "Format length too long");
int signPos = arrsize(buffer) - static_cast<int>(format_size);
hsAssert(signPos >= 0, "Format buffer not large enough for sign");
char buffer[24];
_IFormatNumeric_Impl<_UType>(buffer + format_size, abs, 10);
if (value < 0)
buffer[signPos] = '-';
else if (format.fDigitClass == plFormat_Private::kDigitDecAlwaysSigned)
buffer[signPos] = '+';
buffer[0] = '-';
else if (format.fAlwaysSigned)
buffer[0] = '+';
_formatString(format, output, buffer, format_size, plFormat_Private::kAlignRight);
}
@ -294,9 +292,7 @@ static void _formatChar(const plFormat_Private::FormatSpec &format,
// Yanked from plString
if (ch > 0x10FFFF) {
hsAssert(0, "Unicode character out of range");
// Character out of range; Use U+FFFD instead for release builds
// Character out of range; Use U+FFFD instead
format_size = 3;
utf8[0] = 0xE0 | ((BADCHAR_REPLACEMENT >> 12) & 0x0F);
utf8[1] = 0x80 | ((BADCHAR_REPLACEMENT >> 6) & 0x3F);
@ -343,7 +339,6 @@ static void _formatChar(const plFormat_Private::FormatSpec &format,
_formatNumeric<_utype>(format, output, value, 16, true); \
break; \
case plFormat_Private::kDigitDec: \
case plFormat_Private::kDigitDecAlwaysSigned: \
case plFormat_Private::kDigitDefault: \
_formatDecimal<_stype>(format, output, value); \
break; \
@ -372,7 +367,6 @@ static void _formatChar(const plFormat_Private::FormatSpec &format,
_formatNumeric<_utype>(format, output, value, 16, true); \
break; \
case plFormat_Private::kDigitDec: \
case plFormat_Private::kDigitDecAlwaysSigned: \
case plFormat_Private::kDigitDefault: \
_formatDecimal<_utype>(format, output, value); \
break; \
@ -405,6 +399,10 @@ PL_FORMAT_IMPL(double)
size_t end = 0;
format_buffer[end++] = '%';
if (format.fAlwaysSigned)
format_buffer[end++] = '+';
if (format.fPrecision >= 0) {
int count = snprintf(format_buffer + end, arrsize(format_buffer) - end,
".%d", format.fPrecision);
@ -462,7 +460,6 @@ PL_FORMAT_IMPL(char)
_formatNumeric<unsigned char>(format, output, value, 16, true);
break;
case plFormat_Private::kDigitDec:
case plFormat_Private::kDigitDecAlwaysSigned:
_formatDecimal<signed char>(format, output, value);
break;
case plFormat_Private::kDigitChar:
@ -479,20 +476,19 @@ PL_FORMAT_IMPL(wchar_t)
{
switch (format.fDigitClass) {
case plFormat_Private::kDigitBin:
_formatNumeric<wchar_t>(format, output, value, 2);
_formatNumeric<uint32_t>(format, output, value, 2);
break;
case plFormat_Private::kDigitOct:
_formatNumeric<wchar_t>(format, output, value, 8);
_formatNumeric<uint32_t>(format, output, value, 8);
break;
case plFormat_Private::kDigitHex:
_formatNumeric<wchar_t>(format, output, value, 16, false);
_formatNumeric<uint32_t>(format, output, value, 16, false);
break;
case plFormat_Private::kDigitHexUpper:
_formatNumeric<wchar_t>(format, output,value, 16, true);
_formatNumeric<uint32_t>(format, output, value, 16, true);
break;
case plFormat_Private::kDigitDec:
case plFormat_Private::kDigitDecAlwaysSigned:
_formatDecimal<wchar_t>(format, output, value);
_formatDecimal<uint32_t>(format, output, value);
break;
case plFormat_Private::kDigitChar:
case plFormat_Private::kDigitDefault:

4
Sources/Plasma/CoreLib/plFormat.h

@ -65,7 +65,7 @@ Mead, WA 99021
* `<` | Align left
* `>` | Align right
* `NNN` | Pad to NNN characters (minimum - can be more)
* `+` | Show a '+' char for positive signed values (decimal only)
* `+` | Show a '+' char for positive signed values (decimal / float only)
* `_C` | Use C as the pad character (only '\001'..'\177' supported for now)
* `x` | Hex (lower-case)
* `X` | Hex (upper-case)
@ -95,7 +95,6 @@ namespace plFormat_Private
{
kDigitDefault, /**< Default digit formatting */
kDigitDec, /**< Format as decimal integer */
kDigitDecAlwaysSigned, /**< Same as `kDigitDec`, but include a '+' for positive numbers too */
kDigitHex, /**< Hex integer (assume unsigned) */
kDigitHexUpper, /**< Hex integer with upper-case digits */
kDigitOct, /**< Octal integer (assume unsigned) */
@ -118,6 +117,7 @@ namespace plFormat_Private
int fPrecision = -1; /**< Requested precision for floating-point */
char fPadChar = 0; /**< Explicit padding char (default is space) */
bool fAlwaysSigned = false; /**< Show + for positive numbers (dec/float) */
Alignment fAlignment = kAlignDefault; /**< Requested pad alignment */
DigitClass fDigitClass = kDigitDefault; /**< Requested int formatting */
FloatClass fFloatClass = kFloatDefault; /**< Requested float formatting */

33
Sources/Plasma/CoreLib/plString.cpp

@ -171,18 +171,24 @@ void plString::IConvertFromUtf16(const uint16_t *utf16, size_t size)
plUniChar unichar = 0x10000;
if (sp + 1 >= utf16 + size) {
hsAssert(0, "Incomplete surrogate pair in UTF-16 data");
// Incomplete surrogate pair
unichar = BADCHAR_REPLACEMENT;
} else if (*sp < 0xDC00) {
unichar += (*sp++ & 0x3FF) << 10;
hsAssert(*sp >= 0xDC00 && *sp <= 0xDFFF,
"Invalid surrogate pair in UTF-16 data");
unichar += (*sp & 0x3FF);
if (*sp < 0xDC00 || *sp > 0xDFFF) {
// Invalid surrogate pair
unichar = BADCHAR_REPLACEMENT;
} else {
unichar += (*sp & 0x3FF);
}
} else {
unichar += (*sp++ & 0x3FF);
hsAssert(*sp >= 0xD800 && *sp < 0xDC00,
"Invalid surrogate pair in UTF-16 data");
unichar += (*sp & 0x3FF) << 10;
if (*sp < 0xD800 || *sp >= 0xDC00) {
// Invalid surrogate pair
unichar = BADCHAR_REPLACEMENT;
} else {
unichar += (*sp & 0x3FF) << 10;
}
}
*dp++ = 0xF0 | ((unichar >> 18) & 0x07);
*dp++ = 0x80 | ((unichar >> 12) & 0x3F);
@ -229,8 +235,8 @@ void plString::IConvertFromUtf32(const plUniChar *ustr, size_t size)
const plUniChar *sp = ustr;
while (sp < ustr + size) {
if (*sp > 0x10FFFF) {
hsAssert(0, "UTF-32 character out of range");
convlen += 3; // Use U+FFFD for release builds
// Invalid character gets replaced with U+FFFD
convlen += 3;
}
else if (*sp > 0xFFFF)
convlen += 4;
@ -299,9 +305,9 @@ void plString::IConvertFromIso8859_1(const char *astr, size_t size)
char *dp = utf8;
sp = astr;
while (sp < astr + size) {
if (*astr & 0x80) {
*dp++ = 0xC0 | ((*sp >> 6) & 0x1F);
*dp++ = 0x80 | ((*sp ) & 0x3F);
if (*sp & 0x80) {
*dp++ = 0xC0 | ((uint8_t(*sp) >> 6) & 0x1F);
*dp++ = 0x80 | ((uint8_t(*sp) ) & 0x3F);
} else {
*dp++ = *sp;
}
@ -347,6 +353,7 @@ plStringBuffer<uint16_t> plString::ToUtf16() const
unichar |= (*sp++ & 0x3F) << 12;
unichar |= (*sp++ & 0x3F) << 6;
unichar |= (*sp++ & 0x3F);
unichar -= 0x10000;
*dp++ = 0xD800 | ((unichar >> 10) & 0x3FF);
*dp++ = 0xDC00 | ((unichar ) & 0x3FF);
@ -424,7 +431,7 @@ plStringBuffer<char> plString::ToIso8859_1() const
} else {
unichar = *sp++;
}
*dp++ = (unichar < 0xFF) ? unichar : '?';
*dp++ = (unichar < 0x100) ? unichar : '?';
}
astr[convlen] = 0;

1
Sources/Tests/CoreTests/CMakeLists.txt

@ -4,6 +4,7 @@ include_directories(../../Plasma/CoreLib)
SET(CoreLibTest_SOURCES
test_plString.cpp
test_plFormat.cpp
test_plCmdParser.cpp
)

397
Sources/Tests/CoreTests/test_plFormat.cpp

@ -0,0 +1,397 @@
#include "plFormat.h"
#include "plFileSystem.h"
#include <gtest/gtest.h>
#include <string>
#include <limits>
TEST(plFormat, Escapes)
{
EXPECT_EQ(plString("{x"), plFormat("{{{}", "x"));
EXPECT_EQ(plString("x{"), plFormat("{}{{", "x"));
EXPECT_EQ(plString("{{{{"), plFormat("{{{}{{{{", "{"));
EXPECT_EQ(plString("{xxx{{yyy{"), plFormat("{{{}{{{{{}{{", "xxx", "yyy"));
}
TEST(plFormat, Errors)
{
// Ensure these get printed to the console
ErrorEnableGui(false);
EXPECT_DEATH(plFormat("{}", 1, 2),
"Message: Too many actual parameters for format string");
EXPECT_DEATH(plFormat("{} {}", 1),
"Message: Not enough actual parameters for format string");
EXPECT_DEATH(plFormat("{", 1),
"Message: Unterminated format specifier");
EXPECT_DEATH(plFormat("{.", 1),
"Message: Unterminated format specifier");
EXPECT_DEATH(plFormat("{_", 1),
"Message: Unterminated format specifier");
EXPECT_DEATH(plFormat(nullptr, 1),
"Message: Passed a null format string");
}
TEST(plFormat, Strings)
{
EXPECT_EQ(plString("TEST"), plFormat("{}", "TEST"));
EXPECT_EQ(plString("xxTESTxx"), plFormat("xx{}xx", "TEST"));
EXPECT_EQ(plString("xxTESTxx"), plFormat("xx{2}xx", "TEST"));
EXPECT_EQ(plString("xxTESTxx"), plFormat("xx{>2}xx", "TEST"));
EXPECT_EQ(plString("xxTESTxx"), plFormat("xx{<2}xx", "TEST"));
EXPECT_EQ(plString("xxTESTxx"), plFormat("xx{_-2}xx", "TEST"));
EXPECT_EQ(plString("xxTEST xx"), plFormat("xx{6}xx", "TEST"));
EXPECT_EQ(plString("xxTEST xx"), plFormat("xx{<6}xx", "TEST"));
EXPECT_EQ(plString("xx TESTxx"), plFormat("xx{>6}xx", "TEST"));
EXPECT_EQ(plString("xxTEST--xx"), plFormat("xx{_-6}xx", "TEST"));
EXPECT_EQ(plString("xxTEST--xx"), plFormat("xx{<_-6}xx", "TEST"));
EXPECT_EQ(plString("xx--TESTxx"), plFormat("xx{>_-6}xx", "TEST"));
EXPECT_EQ(plString("xxONE TWO THREExx"), plFormat("xx{5}{<5}{>7}xx", "ONE", "TWO", "THREE"));
// Ensure braces are parsed properly within padding chars
EXPECT_EQ(plString("xxTEST}}xx"), plFormat("xx{_}6}xx", "TEST"));
EXPECT_EQ(plString("xxTEST}}xx"), plFormat("xx{6_}}xx", "TEST"));
EXPECT_EQ(plString("xxTEST{{xx"), plFormat("xx{_{6}xx", "TEST"));
EXPECT_EQ(plString("xxTEST{{xx"), plFormat("xx{6_{}xx", "TEST"));
}
TEST(plFormat, StringClasses)
{
// These should be handled just like normal const char* string params
// (see above), so just need to test that the wrappers are working
EXPECT_EQ(plString("xxTESTxx"), plFormat("xx{}xx", L"TEST"));
EXPECT_EQ(plString("xxTESTxx"), plFormat("xx{}xx", plString("TEST")));
EXPECT_EQ(plString("xxTESTxx"), plFormat("xx{}xx", std::string("TEST")));
EXPECT_EQ(plString("xxTESTxx"), plFormat("xx{}xx", std::wstring(L"TEST")));
EXPECT_EQ(plString("xx/dev/nullxx"), plFormat("xx{}xx", plFileName("/dev/null")));
EXPECT_EQ(plString(R"(xxC:\Users\Nobodyxx)"),
plFormat("xx{}xx", plFileName(R"(C:\Users\Nobody)")));
}
TEST(plFormat, Char)
{
EXPECT_EQ(plString("xxAxx"), plFormat("xx{}xx", 'A'));
EXPECT_EQ(plString("xxAxx"), plFormat("xx{c}xx", (signed char)'A'));
EXPECT_EQ(plString("xxAxx"), plFormat("xx{c}xx", (unsigned char)'A'));
// UTF-8 encoding of wide (16-bit) char
EXPECT_EQ(plString("xx\xef\xbf\xbexx"), plFormat("xx{}xx", L'\ufffe'));
EXPECT_EQ(plString("xx\xe7\xbf\xbexx"), plFormat("xx{c}xx", (short)0x7ffe));
EXPECT_EQ(plString("xx\xef\xbf\xbexx"), plFormat("xx{c}xx", (unsigned short)0xfffe));
// UTF-8 encoding of UCS4 (32-bit) char
EXPECT_EQ(plString("xx\xf4\x8f\xbf\xbfxx"), plFormat("xx{c}xx", (int)0x10ffff));
EXPECT_EQ(plString("xx\xf4\x8f\xbf\xbfxx"), plFormat("xx{c}xx", (unsigned int)0x10ffff));
EXPECT_EQ(plString("xx\xf4\x8f\xbf\xbfxx"), plFormat("xx{c}xx", (long)0x10ffff));
EXPECT_EQ(plString("xx\xf4\x8f\xbf\xbfxx"), plFormat("xx{c}xx", (unsigned long)0x10ffff));
EXPECT_EQ(plString("xx\xf4\x8f\xbf\xbfxx"), plFormat("xx{c}xx", (int64_t)0x10ffff));
EXPECT_EQ(plString("xx\xf4\x8f\xbf\xbfxx"), plFormat("xx{c}xx", (uint64_t)0x10ffff));
}
TEST(plFormat, Decimal)
{
EXPECT_EQ(plString("xx1234xx"), plFormat("xx{}xx", 1234));
EXPECT_EQ(plString("xx1234xx"), plFormat("xx{d}xx", 1234));
EXPECT_EQ(plString("xx1234xx"), plFormat("xx{2}xx", 1234));
EXPECT_EQ(plString("xx1234xx"), plFormat("xx{>2}xx", 1234));
EXPECT_EQ(plString("xx1234xx"), plFormat("xx{<2}xx", 1234));
EXPECT_EQ(plString("xx 1234xx"), plFormat("xx{6}xx", 1234));
EXPECT_EQ(plString("xx 1234xx"), plFormat("xx{>6}xx", 1234));
EXPECT_EQ(plString("xx1234 xx"), plFormat("xx{<6}xx", 1234));
// Character types
EXPECT_EQ(plString("xx0xx"), plFormat("xx{d}xx", '\0'));
EXPECT_EQ(plString("xx65xx"), plFormat("xx{d}xx", 'A'));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{d}xx", L'\0'));
EXPECT_EQ(plString("xx65xx"), plFormat("xx{d}xx", L'A'));
EXPECT_EQ(plString("xx32767xx"), plFormat("xx{d}xx", L'\u7fff'));
// Numeric char types
EXPECT_EQ(plString("xx0xx"), plFormat("xx{}xx", (signed char)0));
EXPECT_EQ(plString("xx127xx"), plFormat("xx{}xx", std::numeric_limits<signed char>::max()));
EXPECT_EQ(plString("xx+127xx"), plFormat("xx{+}xx", std::numeric_limits<signed char>::max()));
EXPECT_EQ(plString("xx-128xx"), plFormat("xx{}xx", std::numeric_limits<signed char>::min()));
EXPECT_EQ(plString("xx-128xx"), plFormat("xx{+}xx", std::numeric_limits<signed char>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{}xx", (unsigned char)0));
EXPECT_EQ(plString("xx255xx"), plFormat("xx{}xx", std::numeric_limits<unsigned char>::max()));
EXPECT_EQ(plString("xx+255xx"), plFormat("xx{+}xx", std::numeric_limits<unsigned char>::max()));
// 16-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{}xx", (short)0));
EXPECT_EQ(plString("xx32767xx"), plFormat("xx{}xx", std::numeric_limits<short>::max()));
EXPECT_EQ(plString("xx+32767xx"), plFormat("xx{+}xx", std::numeric_limits<short>::max()));
EXPECT_EQ(plString("xx-32768xx"), plFormat("xx{}xx", std::numeric_limits<short>::min()));
EXPECT_EQ(plString("xx-32768xx"), plFormat("xx{+}xx", std::numeric_limits<short>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{}xx", (unsigned short)0));
EXPECT_EQ(plString("xx65535xx"), plFormat("xx{}xx", std::numeric_limits<unsigned short>::max()));
EXPECT_EQ(plString("xx+65535xx"), plFormat("xx{+}xx", std::numeric_limits<unsigned short>::max()));
// 32-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{}xx", (int)0));
EXPECT_EQ(plString("xx2147483647xx"), plFormat("xx{}xx", std::numeric_limits<int>::max()));
EXPECT_EQ(plString("xx+2147483647xx"), plFormat("xx{+}xx", std::numeric_limits<int>::max()));
EXPECT_EQ(plString("xx-2147483648xx"), plFormat("xx{}xx", std::numeric_limits<int>::min()));
EXPECT_EQ(plString("xx-2147483648xx"), plFormat("xx{+}xx", std::numeric_limits<int>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{}xx", (unsigned int)0));
EXPECT_EQ(plString("xx4294967295xx"), plFormat("xx{}xx", std::numeric_limits<unsigned int>::max()));
EXPECT_EQ(plString("xx+4294967295xx"), plFormat("xx{+}xx", std::numeric_limits<unsigned int>::max()));
// 64-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{}xx", (int64_t)0));
EXPECT_EQ(plString("xx9223372036854775807xx"), plFormat("xx{}xx", std::numeric_limits<int64_t>::max()));
EXPECT_EQ(plString("xx+9223372036854775807xx"), plFormat("xx{+}xx", std::numeric_limits<int64_t>::max()));
EXPECT_EQ(plString("xx-9223372036854775808xx"), plFormat("xx{}xx", std::numeric_limits<int64_t>::min()));
EXPECT_EQ(plString("xx-9223372036854775808xx"), plFormat("xx{+}xx", std::numeric_limits<int64_t>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{}xx", (uint64_t)0));
EXPECT_EQ(plString("xx18446744073709551615xx"), plFormat("xx{}xx", std::numeric_limits<uint64_t>::max()));
EXPECT_EQ(plString("xx+18446744073709551615xx"), plFormat("xx{+}xx", std::numeric_limits<uint64_t>::max()));
}
TEST(plFormat, Hex)
{
EXPECT_EQ(plString("xx4d2xx"), plFormat("xx{x}xx", 1234));
EXPECT_EQ(plString("xx4d2xx"), plFormat("xx{x}xx", 1234));
EXPECT_EQ(plString("xx4d2xx"), plFormat("xx{2x}xx", 1234));
EXPECT_EQ(plString("xx4d2xx"), plFormat("xx{>2x}xx", 1234));
EXPECT_EQ(plString("xx4d2xx"), plFormat("xx{<2x}xx", 1234));
EXPECT_EQ(plString("xx 4d2xx"), plFormat("xx{6x}xx", 1234));
EXPECT_EQ(plString("xx 4d2xx"), plFormat("xx{>6x}xx", 1234));
EXPECT_EQ(plString("xx4d2 xx"), plFormat("xx{<6x}xx", 1234));
// Character types
EXPECT_EQ(plString("xx0xx"), plFormat("xx{x}xx", '\0'));
EXPECT_EQ(plString("xx41xx"), plFormat("xx{x}xx", 'A'));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{x}xx", L'\0'));
EXPECT_EQ(plString("xx41xx"), plFormat("xx{x}xx", L'A'));
EXPECT_EQ(plString("xx7fffxx"), plFormat("xx{x}xx", L'\u7fff'));
// Numeric char types
EXPECT_EQ(plString("xx0xx"), plFormat("xx{x}xx", (signed char)0));
EXPECT_EQ(plString("xx7fxx"), plFormat("xx{x}xx", std::numeric_limits<signed char>::max()));
EXPECT_EQ(plString("xx80xx"), plFormat("xx{x}xx", std::numeric_limits<signed char>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{x}xx", (unsigned char)0));
EXPECT_EQ(plString("xxffxx"), plFormat("xx{x}xx", std::numeric_limits<unsigned char>::max()));
// 16-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{x}xx", (short)0));
EXPECT_EQ(plString("xx7fffxx"), plFormat("xx{x}xx", std::numeric_limits<short>::max()));
EXPECT_EQ(plString("xx8000xx"), plFormat("xx{x}xx", std::numeric_limits<short>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{x}xx", (unsigned short)0));
EXPECT_EQ(plString("xxffffxx"), plFormat("xx{x}xx", std::numeric_limits<unsigned short>::max()));
// 32-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{x}xx", (int)0));
EXPECT_EQ(plString("xx7fffffffxx"), plFormat("xx{x}xx", std::numeric_limits<int>::max()));
EXPECT_EQ(plString("xx80000000xx"), plFormat("xx{x}xx", std::numeric_limits<int>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{x}xx", (unsigned int)0));
EXPECT_EQ(plString("xxffffffffxx"), plFormat("xx{x}xx", std::numeric_limits<unsigned int>::max()));
// 64-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{x}xx", (int64_t)0));
EXPECT_EQ(plString("xx7fffffffffffffffxx"), plFormat("xx{x}xx", std::numeric_limits<int64_t>::max()));
EXPECT_EQ(plString("xx8000000000000000xx"), plFormat("xx{x}xx", std::numeric_limits<int64_t>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{x}xx", (uint64_t)0));
EXPECT_EQ(plString("xxffffffffffffffffxx"), plFormat("xx{x}xx", std::numeric_limits<uint64_t>::max()));
}
TEST(plFormat, HexUpper)
{
EXPECT_EQ(plString("xx4D2xx"), plFormat("xx{X}xx", 1234));
EXPECT_EQ(plString("xx4D2xx"), plFormat("xx{X}xx", 1234));
EXPECT_EQ(plString("xx4D2xx"), plFormat("xx{2X}xx", 1234));
EXPECT_EQ(plString("xx4D2xx"), plFormat("xx{>2X}xx", 1234));
EXPECT_EQ(plString("xx4D2xx"), plFormat("xx{<2X}xx", 1234));
EXPECT_EQ(plString("xx 4D2xx"), plFormat("xx{6X}xx", 1234));
EXPECT_EQ(plString("xx 4D2xx"), plFormat("xx{>6X}xx", 1234));
EXPECT_EQ(plString("xx4D2 xx"), plFormat("xx{<6X}xx", 1234));
// Character types
EXPECT_EQ(plString("xx0xx"), plFormat("xx{X}xx", '\0'));
EXPECT_EQ(plString("xx41xx"), plFormat("xx{X}xx", 'A'));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{X}xx", L'\0'));
EXPECT_EQ(plString("xx41xx"), plFormat("xx{X}xx", L'A'));
EXPECT_EQ(plString("xx7FFFxx"), plFormat("xx{X}xx", L'\u7fff'));
// Numeric char types
EXPECT_EQ(plString("xx0xx"), plFormat("xx{X}xx", (signed char)0));
EXPECT_EQ(plString("xx7Fxx"), plFormat("xx{X}xx", std::numeric_limits<signed char>::max()));
EXPECT_EQ(plString("xx80xx"), plFormat("xx{X}xx", std::numeric_limits<signed char>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{X}xx", (unsigned char)0));
EXPECT_EQ(plString("xxFFxx"), plFormat("xx{X}xx", std::numeric_limits<unsigned char>::max()));
// 16-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{X}xx", (short)0));
EXPECT_EQ(plString("xx7FFFxx"), plFormat("xx{X}xx", std::numeric_limits<short>::max()));
EXPECT_EQ(plString("xx8000xx"), plFormat("xx{X}xx", std::numeric_limits<short>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{X}xx", (unsigned short)0));
EXPECT_EQ(plString("xxFFFFxx"), plFormat("xx{X}xx", std::numeric_limits<unsigned short>::max()));
// 32-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{X}xx", (int)0));
EXPECT_EQ(plString("xx7FFFFFFFxx"), plFormat("xx{X}xx", std::numeric_limits<int>::max()));
EXPECT_EQ(plString("xx80000000xx"), plFormat("xx{X}xx", std::numeric_limits<int>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{X}xx", (unsigned int)0));
EXPECT_EQ(plString("xxFFFFFFFFxx"), plFormat("xx{X}xx", std::numeric_limits<unsigned int>::max()));
// 64-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{X}xx", (int64_t)0));
EXPECT_EQ(plString("xx7FFFFFFFFFFFFFFFxx"), plFormat("xx{X}xx", std::numeric_limits<int64_t>::max()));
EXPECT_EQ(plString("xx8000000000000000xx"), plFormat("xx{X}xx", std::numeric_limits<int64_t>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{X}xx", (uint64_t)0));
EXPECT_EQ(plString("xxFFFFFFFFFFFFFFFFxx"), plFormat("xx{X}xx", std::numeric_limits<uint64_t>::max()));
}
TEST(plFormat, Octal)
{
EXPECT_EQ(plString("xx2322xx"), plFormat("xx{o}xx", 1234));
EXPECT_EQ(plString("xx2322xx"), plFormat("xx{o}xx", 1234));
EXPECT_EQ(plString("xx2322xx"), plFormat("xx{2o}xx", 1234));
EXPECT_EQ(plString("xx2322xx"), plFormat("xx{>2o}xx", 1234));
EXPECT_EQ(plString("xx2322xx"), plFormat("xx{<2o}xx", 1234));
EXPECT_EQ(plString("xx 2322xx"), plFormat("xx{6o}xx", 1234));
EXPECT_EQ(plString("xx 2322xx"), plFormat("xx{>6o}xx", 1234));
EXPECT_EQ(plString("xx2322 xx"), plFormat("xx{<6o}xx", 1234));
// Character types
EXPECT_EQ(plString("xx0xx"), plFormat("xx{o}xx", '\0'));
EXPECT_EQ(plString("xx101xx"), plFormat("xx{o}xx", 'A'));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{o}xx", L'\0'));
EXPECT_EQ(plString("xx101xx"), plFormat("xx{o}xx", L'A'));
EXPECT_EQ(plString("xx77777xx"), plFormat("xx{o}xx", L'\u7fff'));
// Numeric char types
EXPECT_EQ(plString("xx0xx"), plFormat("xx{o}xx", (signed char)0));
EXPECT_EQ(plString("xx177xx"), plFormat("xx{o}xx", std::numeric_limits<signed char>::max()));
EXPECT_EQ(plString("xx200xx"), plFormat("xx{o}xx", std::numeric_limits<signed char>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{o}xx", (unsigned char)0));
EXPECT_EQ(plString("xx377xx"), plFormat("xx{o}xx", std::numeric_limits<unsigned char>::max()));
// 16-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{o}xx", (short)0));
EXPECT_EQ(plString("xx77777xx"), plFormat("xx{o}xx", std::numeric_limits<short>::max()));
EXPECT_EQ(plString("xx100000xx"), plFormat("xx{o}xx", std::numeric_limits<short>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{o}xx", (unsigned short)0));
EXPECT_EQ(plString("xx177777xx"), plFormat("xx{o}xx", std::numeric_limits<unsigned short>::max()));
// 32-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{o}xx", (int)0));
EXPECT_EQ(plString("xx17777777777xx"), plFormat("xx{o}xx", std::numeric_limits<int>::max()));
EXPECT_EQ(plString("xx20000000000xx"), plFormat("xx{o}xx", std::numeric_limits<int>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{o}xx", (unsigned int)0));
EXPECT_EQ(plString("xx37777777777xx"), plFormat("xx{o}xx", std::numeric_limits<unsigned int>::max()));
// 64-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{o}xx", (int64_t)0));
EXPECT_EQ(plString("xx777777777777777777777xx"), plFormat("xx{o}xx", std::numeric_limits<int64_t>::max()));
EXPECT_EQ(plString("xx1000000000000000000000xx"), plFormat("xx{o}xx", std::numeric_limits<int64_t>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{o}xx", (uint64_t)0));
EXPECT_EQ(plString("xx1777777777777777777777xx"), plFormat("xx{o}xx", std::numeric_limits<uint64_t>::max()));
}
TEST(plFormat, Binary)
{
EXPECT_EQ(plString("xx10011010010xx"), plFormat("xx{b}xx", 1234));
EXPECT_EQ(plString("xx10011010010xx"), plFormat("xx{b}xx", 1234));
EXPECT_EQ(plString("xx10011010010xx"), plFormat("xx{2b}xx", 1234));
EXPECT_EQ(plString("xx10011010010xx"), plFormat("xx{>2b}xx", 1234));
EXPECT_EQ(plString("xx10011010010xx"), plFormat("xx{<2b}xx", 1234));
EXPECT_EQ(plString("xx 10011010010xx"), plFormat("xx{16b}xx", 1234));
EXPECT_EQ(plString("xx 10011010010xx"), plFormat("xx{>16b}xx", 1234));
EXPECT_EQ(plString("xx10011010010 xx"), plFormat("xx{<16b}xx", 1234));
// Character types
EXPECT_EQ(plString("xx0xx"), plFormat("xx{b}xx", '\0'));
EXPECT_EQ(plString("xx1000001xx"), plFormat("xx{b}xx", 'A'));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{b}xx", L'\0'));
EXPECT_EQ(plString("xx1000001xx"), plFormat("xx{b}xx", L'A'));
EXPECT_EQ(plString("xx111111111111111xx"), plFormat("xx{b}xx", L'\u7fff'));
// Numeric char types
EXPECT_EQ(plString("xx0xx"), plFormat("xx{b}xx", (signed char)0));
EXPECT_EQ(plString("xx1111111xx"), plFormat("xx{b}xx", std::numeric_limits<signed char>::max()));
EXPECT_EQ(plString("xx10000000xx"), plFormat("xx{b}xx", std::numeric_limits<signed char>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{b}xx", (unsigned char)0));
EXPECT_EQ(plString("xx11111111xx"), plFormat("xx{b}xx", std::numeric_limits<unsigned char>::max()));
// 16-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{b}xx", (short)0));
EXPECT_EQ(plString("xx111111111111111xx"), plFormat("xx{b}xx", std::numeric_limits<short>::max()));
EXPECT_EQ(plString("xx1000000000000000xx"), plFormat("xx{b}xx", std::numeric_limits<short>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{b}xx", (unsigned short)0));
EXPECT_EQ(plString("xx1111111111111111xx"), plFormat("xx{b}xx", std::numeric_limits<unsigned short>::max()));
// 32-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{b}xx", (int)0));
EXPECT_EQ(plString("xx1111111111111111111111111111111xx"),
plFormat("xx{b}xx", std::numeric_limits<int>::max()));
EXPECT_EQ(plString("xx10000000000000000000000000000000xx"),
plFormat("xx{b}xx", std::numeric_limits<int>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{b}xx", (unsigned int)0));
EXPECT_EQ(plString("xx11111111111111111111111111111111xx"),
plFormat("xx{b}xx", std::numeric_limits<unsigned int>::max()));
// 64-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{b}xx", (int64_t)0));
EXPECT_EQ(plString("xx111111111111111111111111111111111111111111111111111111111111111xx"),
plFormat("xx{b}xx", std::numeric_limits<int64_t>::max()));
EXPECT_EQ(plString("xx1000000000000000000000000000000000000000000000000000000000000000xx"),
plFormat("xx{b}xx", std::numeric_limits<int64_t>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{b}xx", (uint64_t)0));
EXPECT_EQ(plString("xx1111111111111111111111111111111111111111111111111111111111111111xx"),
plFormat("xx{b}xx", std::numeric_limits<uint64_t>::max()));
}
TEST(plFormat, FloatingPoint)
{
// The actual formatting is handled by libc, so we just need to test
// that the flags get passed along properly.
EXPECT_EQ(plString("xx1.5xx"), plFormat("xx{}xx", 1.5));
EXPECT_EQ(plString("xx+1.5xx"), plFormat("xx{+}xx", 1.5));
EXPECT_EQ(plString("xx-1.5xx"), plFormat("xx{}xx", -1.5));
EXPECT_EQ(plString("xx-1.5xx"), plFormat("xx{+}xx", -1.5));
// Padding
EXPECT_EQ(plString("xx 1.50xx"), plFormat("xx{6.2f}xx", 1.5));
EXPECT_EQ(plString("xx -1.50xx"), plFormat("xx{6.2f}xx", -1.5));
EXPECT_EQ(plString("xx1.50 xx"), plFormat("xx{<6.2f}xx", 1.5));
EXPECT_EQ(plString("xx-1.50 xx"), plFormat("xx{<6.2f}xx", -1.5));
// Fixed notation
EXPECT_EQ(plString("xx3.14xx"), plFormat("xx{.2f}xx", 3.14159));
EXPECT_EQ(plString("xx3.141590xx"), plFormat("xx{.6f}xx", 3.14159));
EXPECT_EQ(plString("xx16384.00xx"), plFormat("xx{.2f}xx", 16384.0));
EXPECT_EQ(plString("xx0.01xx"), plFormat("xx{.2f}xx", 1.0 / 128));
// MSVC uses 3 digits for the exponent, whereas GCC uses two :/
#ifdef _MSC_VER
# define EXTRA_DIGIT "0"
#else
# define EXTRA_DIGIT ""
#endif
// Scientific notation (MSVC uses 3 digits for the exponent)
EXPECT_EQ(plString("xx3.14e+" EXTRA_DIGIT "00xx"), plFormat("xx{.2e}xx", 3.14159));
EXPECT_EQ(plString("xx3.141590e+" EXTRA_DIGIT "00xx"), plFormat("xx{.6e}xx", 3.14159));
EXPECT_EQ(plString("xx1.64e+" EXTRA_DIGIT "04xx"), plFormat("xx{.2e}xx", 16384.0));
EXPECT_EQ(plString("xx7.81e-" EXTRA_DIGIT "03xx"), plFormat("xx{.2e}xx", 1.0 / 128));
// Scientific notation (upper-case E)
EXPECT_EQ(plString("xx3.14E+" EXTRA_DIGIT "00xx"), plFormat("xx{.2E}xx", 3.14159));
EXPECT_EQ(plString("xx3.141590E+" EXTRA_DIGIT "00xx"), plFormat("xx{.6E}xx", 3.14159));
EXPECT_EQ(plString("xx1.64E+" EXTRA_DIGIT "04xx"), plFormat("xx{.2E}xx", 16384.0));
EXPECT_EQ(plString("xx7.81E-" EXTRA_DIGIT "03xx"), plFormat("xx{.2E}xx", 1.0 / 128));
// Automatic (based on input)
EXPECT_EQ(plString("xx3.1xx"), plFormat("xx{.2}xx", 3.14159));
EXPECT_EQ(plString("xx3.14159xx"), plFormat("xx{.6}xx", 3.14159));
EXPECT_EQ(plString("xx1.6e+" EXTRA_DIGIT "04xx"), plFormat("xx{.2}xx", 16384.0));
EXPECT_EQ(plString("xx0.0078xx"), plFormat("xx{.2}xx", 1.0 / 128));
}
TEST(plFormat, Booleans)
{
// This basically just uses the string formatter with constant strings
EXPECT_EQ(plString("xxtrue xx"), plFormat("xx{5}xx", true));
EXPECT_EQ(plString("xxfalsexx"), plFormat("xx{5}xx", false));
}

787
Sources/Tests/CoreTests/test_plString.cpp

@ -1,278 +1,629 @@
#include <plString.h>
#include <HeadSpin.h>
#include "plString.h"
#include <gtest/gtest.h>
#include <wchar.h>
TEST(PlStringTest,ToUtf16)
static const plUniChar test_data[] = {
0x20, 0x7f, /* Normal ASCII chars */
0xff, 0x100, /* 8-bit boundary chars */
0x7fff, /* UTF-8 2-byte boundary */
0xffff, 0x10000, /* 16-bit boundary chars */
0x10020, 0x40000, /* Non-edge UTF-16 surrogate pairs */
0x10ffff, /* Highest Unicode character */
0 /* Null terminator */
};
/* UTF-8 version of above test data */
static const char utf8_test_data[] =
"\x20" "\x7f"
"\xc3\xbf" "\xc4\x80"
"\xe7\xbf\xbf"
"\xef\xbf\xbf" "\xf0\x90\x80\x80"
"\xf0\x90\x80\xa0" "\xf1\x80\x80\x80"
"\xf4\x8f\xbf\xbf";
static const size_t utf8_test_data_length = arrsize(utf8_test_data) - 1;
/* UTF-16 version of test data */
static const uint16_t utf16_test_data[] = {
0x20, 0x7f,
0xff, 0x100,
0x7fff,
0xffff,
/* surrogate pairs for chars >0xffff */
0xd800, 0xdc00,
0xd800, 0xdc20,
0xd8c0, 0xdc00,
0xdbff, 0xdfff,
0
};
/* Utility for comparing plUniChar buffers */
template <typename _Ch>
static int T_strcmp(const _Ch *left, const _Ch *right)
{
uint16_t text[] = {0x0061,0x0062,0x0063,0x0064}; //abcd as in utf16
plStringBuffer<uint16_t> expected = plStringBuffer<uint16_t>(text,arrsize(text));
plStringBuffer<uint16_t> output = plString("abcd").ToUtf16();
EXPECT_EQ(expected.GetSize(), output.GetSize()); //not really a good test
for ( ;; ) {
if (*left != *right)
return *left - *right;
if (*left == 0)
return (*right == 0) ? 0 : -1;
if (*right == 0)
return 1;
++left;
++right;
}
}
TEST(PlStringTest,ToWchar)
TEST(plString, TestHelpers)
{
wchar_t text[] =L"abcd\u00E9";
plStringBuffer<wchar_t> expected = plStringBuffer<wchar_t>(text,arrsize(text));
plStringBuffer<wchar_t> output = plString("abcd\xC3\xA9").ToWchar();
EXPECT_STREQ(expected.GetData(),output.GetData());
/* Ensure the utilities for testing the module function properly */
EXPECT_EQ(0, T_strcmp("abc", "abc"));
EXPECT_LT(0, T_strcmp("abc", "aba"));
EXPECT_GT(0, T_strcmp("abc", "abe"));
EXPECT_LT(0, T_strcmp("abc", "ab"));
EXPECT_GT(0, T_strcmp("abc", "abcd"));
EXPECT_EQ(0, T_strcmp("", ""));
EXPECT_GT(0, T_strcmp("", "a"));
EXPECT_LT(0, T_strcmp("a", ""));
}
TEST(PlStringTest,ToIso8859_1)
TEST(plString, Utility)
{
char text[] ="abcde";
plStringBuffer<char> expected = plStringBuffer<char>(text,arrsize(text));
plStringBuffer<char> output = plString("abcde").ToIso8859_1();
EXPECT_STREQ(expected.GetData(),output.GetData());
// Special plString::Null constant
EXPECT_EQ(plString::Null, plString(""));
EXPECT_EQ(plString::Null, plString{});
EXPECT_EQ(0, plString::Null.GetSize());
EXPECT_EQ(true, plString::Null.IsEmpty());
EXPECT_EQ(true, plString::Null.IsNull());
// Short and Long string length
EXPECT_EQ(4, plString("1234").GetSize());
EXPECT_EQ(32, plString("12345678901234567890123456789012").GetSize());
// plStrings store data as UTF-8 internally
EXPECT_EQ(utf8_test_data_length, plString(utf8_test_data).GetSize());
}
TEST(PlStringTest,FindChar)
TEST(plString, StackStrings)
{
plString input = plString("abCdcBAeab");
int result=0;
//available char, case sensitive
result = input.Find('B',plString::kCaseSensitive);
EXPECT_EQ(5,result);
//available char, case insensitive
result = input.Find('B',plString::kCaseInsensitive);
EXPECT_EQ(1,result);
//unavailable char, case sensitive
result = input.Find('f',plString::kCaseSensitive);
EXPECT_EQ(-1,result);
//unavailable char, case insensitive
result=0;
result = input.Find('f',plString::kCaseInsensitive);
EXPECT_EQ(-1,result);
plString input1 = plString("abCdcBÁèab");
//available accented char, case sensitive
result = input1.Find('Á',plString::kCaseSensitive);
EXPECT_EQ(7,result);
//available accented char, case insensitive
result = input1.Find('è',plString::kCaseInsensitive);
EXPECT_EQ(9,result);
char stack_buf[256];
strcpy(stack_buf, "Test");
plString test(stack_buf);
EXPECT_EQ(plString("Test"), test);
EXPECT_EQ(strlen("Test"), test.GetSize());
strcpy(stack_buf, "operator=");
test = stack_buf;
EXPECT_EQ(plString("operator="), test);
EXPECT_EQ(strlen("operator="), test.GetSize());
}
TEST(PlStringTest,FindLast)
TEST(plString, ConvertUtf8)
{
plString input = plString("abCdcBAeab");
int result=0;
//available char, case sensitive
result = input.FindLast('B',plString::kCaseSensitive);
EXPECT_EQ(5,result);
//available char, case insensitive
result = input.FindLast('B',plString::kCaseInsensitive);
EXPECT_EQ(9,result);
//unavailable char, case sensitive
result = input.FindLast('f',plString::kCaseSensitive);
EXPECT_EQ(-1,result);
//unavailable char, case insensitive
result=0;
result = input.FindLast('f',plString::kCaseInsensitive);
EXPECT_EQ(-1,result);
plString input1 = plString("éeÉß");
//available accented char, case sensitive
result = input1.FindLast('e',plString::kCaseSensitive);
EXPECT_EQ(2,result);
//available accented char, case insensitive
result = input1.FindLast('ß',plString::kCaseInsensitive);
EXPECT_EQ(6,result);
// From UTF-8 to plString
plString from_utf8 = plString::FromUtf8(utf8_test_data);
EXPECT_STREQ(utf8_test_data, from_utf8.c_str());
EXPECT_EQ(utf8_test_data_length, from_utf8.GetSize());
plUnicodeBuffer unicode = from_utf8.GetUnicodeArray();
EXPECT_EQ(0, T_strcmp(test_data, unicode.GetData()));
// From plString to UTF-8
plString to_utf8 = plString::FromUtf32(test_data);
EXPECT_STREQ(utf8_test_data, to_utf8.c_str());
// Empty strings
plString empty = plString::FromUtf8("");
EXPECT_EQ(0, empty.GetSize());
EXPECT_EQ(0, T_strcmp(empty.c_str(), ""));
const plUniChar empty_data[] = { 0 };
empty = plString::FromUtf32(empty_data);
EXPECT_EQ(0, empty.GetSize());
EXPECT_EQ(0, T_strcmp(empty.c_str(), ""));
}
TEST(PlStringTest,FindString)
TEST(plString, ConvertUtf16)
{
plString input = plString("abABÁè");
int result=0;
//available string, case sensitive
result = input.Find("AB",plString::kCaseSensitive);
EXPECT_EQ(2,result);
//available string, case insensitive
result = input.Find("ab",plString::kCaseInsensitive);
EXPECT_EQ(0,result);
//unavailable string, case sensitive
result = input.Find("cd",plString::kCaseSensitive);
EXPECT_EQ(-1,result);
//unavailable string, case insensitive
result=0;
result = input.Find("cd",plString::kCaseInsensitive);
EXPECT_EQ(-1,result);
plString input1 = plString("àbéCdcBÀéab");
//available accented string, case sensitive
result = input1.Find("À",plString::kCaseSensitive);
EXPECT_EQ(9,result);
//the strnicmp method used does not support unicode
//available accented string, case insensitive
// result = input1.Find("À",plString::kCaseInsensitive);
// EXPECT_EQ(1,result);
// From UTF-16 to plString
plString from_utf16 = plString::FromUtf16(utf16_test_data);
EXPECT_EQ(utf8_test_data_length, from_utf16.GetSize());
plUnicodeBuffer unicode = from_utf16.GetUnicodeArray();
EXPECT_EQ(0, T_strcmp(test_data, unicode.GetData()));
// From plString to UTF-16
plStringBuffer<uint16_t> to_utf16 = plString::FromUtf32(test_data).ToUtf16();
EXPECT_EQ(0, T_strcmp(utf16_test_data, to_utf16.GetData()));
// Empty string
const uint16_t empty_data[] = { 0 };
plString empty = plString::FromUtf16(empty_data);
EXPECT_EQ(0, empty.GetSize());
EXPECT_EQ(0, T_strcmp(empty.c_str(), ""));
}
//TODO: test regex functions
TEST(PlStringTest,TrimLeft)
TEST(plString, ConvertIso8859_1)
{
plString input = plString("abcdefgh");
plString output = input.TrimLeft("abc");
plString expected = plString("defgh");
EXPECT_EQ(expected,output);
plString input1 = plString("abcdefgh");
plString output1 = input1.TrimLeft("bc");
EXPECT_EQ(input1,output1);
// From ISO-8859-1 to plString
const char latin1[] = "\x20\x7e\xa0\xff";
const plUniChar unicode_cp0[] = { 0x20, 0x7e, 0xa0, 0xff, 0 };
static const size_t latin1_utf8_length = 6;
plString from_latin1 = plString::FromIso8859_1(latin1);
EXPECT_EQ(latin1_utf8_length, from_latin1.GetSize());
plUnicodeBuffer unicode = from_latin1.GetUnicodeArray();
EXPECT_EQ(0, T_strcmp(unicode_cp0, unicode.GetData()));
// From plString to ISO-8859-1
plStringBuffer<char> to_latin1 = plString::FromUtf32(unicode_cp0).ToIso8859_1();
EXPECT_STREQ(latin1, to_latin1.GetData());
// Empty string
plString empty = plString::FromIso8859_1("");
EXPECT_EQ(0, empty.GetSize());
EXPECT_EQ(0, T_strcmp(empty.c_str(), ""));
}
TEST(PlStringTest,TrimRight)
TEST(plString, ConvertWchar)
{
plString input = plString("abcdefgh");
plString output = input.TrimRight("fgh");
plString expected = plString("abcde");
EXPECT_EQ(expected,output);
plString input1 = plString("abcdefgh");
plString output1 = input1.TrimRight("fg");
EXPECT_EQ(input1,output1);
// UTF-8 and UTF-16 are already tested, so just make sure we test
// wchar_t and L"" conversions
const wchar_t wtext[] = L"\x20\x7f\xff\u0100\uffff";
const plUniChar unicode_text[] = { 0x20, 0x7f, 0xff, 0x100, 0xffff, 0 };
static const size_t wtext_utf8_length = 9;
plString from_wchar = plString::FromWchar(wtext);
EXPECT_EQ(wtext_utf8_length, from_wchar.GetSize());
plUnicodeBuffer unicode = from_wchar.GetUnicodeArray();
EXPECT_EQ(0, T_strcmp(unicode_text, unicode.GetData()));
// From plString to wchar_t
plStringBuffer<wchar_t> to_wchar = plString::FromUtf32(unicode_text).ToWchar();
EXPECT_STREQ(wtext, to_wchar.GetData());
// Empty string
plString empty = plString::FromWchar(L"");
EXPECT_EQ(0, empty.GetSize());
EXPECT_EQ(0, T_strcmp(empty.c_str(), ""));
}
TEST(PlStringTest,Trim)
TEST(plString, ConvertInvalid)
{
plString input = plString("abcdefba");
plString output = input.Trim("ab");
plString expected = plString("cdef");
EXPECT_EQ(expected,output);
plString input1 = plString("abcdefba");
plString output1 = input1.Trim("f");
EXPECT_EQ(input1,output1);
// The following should encode replacement characters for invalid chars
const plUniChar unicode_replacement[] = { 0xfffd, 0 };
const char latin1_replacement[] = "?";
// Character outside of Unicode specification range
const plUniChar too_big_c[] = { 0xffffff, 0 };
plUnicodeBuffer too_big = plString::FromUtf32(too_big_c).GetUnicodeArray();
EXPECT_EQ(0, T_strcmp(unicode_replacement, too_big.GetData()));
// Invalid surrogate pairs
const uint16_t incomplete_surr_c[] = { 0xd800, 0 };
plString incomplete_surr = plString::FromUtf16(incomplete_surr_c);
EXPECT_EQ(0, T_strcmp(unicode_replacement,
incomplete_surr.GetUnicodeArray().GetData()));
const uint16_t double_low_c[] = { 0xd800, 0xd801, 0 };
plString double_low = plString::FromUtf16(double_low_c);
EXPECT_EQ(0, T_strcmp(unicode_replacement, double_low.GetUnicodeArray().GetData()));
const uint16_t bad_combo_c[] = { 0xdc00, 0x20, 0 };
plString bad_combo = plString::FromUtf16(double_low_c);
EXPECT_EQ(0, T_strcmp(unicode_replacement, bad_combo.GetUnicodeArray().GetData()));
// ISO-8859-1 doesn't have \ufffd, so it uses '?' instead
const plUniChar non_latin1_c[] = { 0x1ff, 0 };
plStringBuffer<char> non_latin1 = plString::FromUtf32(non_latin1_c).ToIso8859_1();
EXPECT_STREQ(latin1_replacement, non_latin1.GetData());
}
TEST(PlStringTest,Substr)
TEST(plString, Concatenation)
{
plString input = plString("abcdefgh");
//start > size returns null
plString output = input.Substr(15,1);
EXPECT_EQ(plString::Null,output);
//start<0
plString output1 =input.Substr(-3,3);
plString expected1 = plString("fgh");
EXPECT_EQ(expected1,output1);
//start+size>size string
plString output2 =input.Substr(4,6);
plString expected2 = plString("efgh");
EXPECT_EQ(expected2,output2);
//start =0 size = length string
plString output3 =input.Substr(0,input.GetSize());
EXPECT_EQ(input,output3);
//normal case
plString output4 =input.Substr(1,3);
plString expected4 = plString("bcd");
EXPECT_EQ(expected4,output4);
// If this changes, this test may need to be updated to match
ASSERT_EQ(16, SSO_CHARS);
plString expected_short = "xxxxyyy";
plString input1 = "xxxx";
plString input2 = "yyy";
plString expected_long = "xxxxxxxxxxyyyyyyyyy";
plString input3 = "xxxxxxxxxx";
plString input4 = "yyyyyyyyy";
// plString + plString
EXPECT_EQ(expected_short, input1 + input2);
EXPECT_EQ(expected_long, input3 + input4);
EXPECT_EQ(input1, input1 + plString());
EXPECT_EQ(input1, plString() + input1);
// plstring + const char*
EXPECT_EQ(expected_short, input1 + input2.c_str());
EXPECT_EQ(expected_short, input1.c_str() + input2);
EXPECT_EQ(expected_long, input3 + input4.c_str());
EXPECT_EQ(expected_long, input3.c_str() + input4);
EXPECT_EQ(input1, input1 + "");
EXPECT_EQ(input1, "" + input1);
}
TEST(PlStringTest,Replace)
TEST(plString, Compare)
{
plString input = plString("abcdabcd");
plString output = input.Replace("ab","cd");
plString expected = plString("cdcdcdcd");
EXPECT_EQ(expected,output);
plString output1 = input.Replace("a","cd");
plString expected1 = plString("cdbcdcdbcd");
EXPECT_EQ(expected1,output1);
// Same length, case sensitive
EXPECT_EQ(0, plString("abc").Compare("abc", plString::kCaseSensitive));
EXPECT_GT(0, plString("abc").Compare("abd", plString::kCaseSensitive));
EXPECT_LT(0, plString("abc").Compare("abb", plString::kCaseSensitive));
EXPECT_GT(0, plString("abC").Compare("abc", plString::kCaseSensitive));
EXPECT_GT(0, plString("Abc").Compare("abc", plString::kCaseSensitive));
EXPECT_EQ(0, plString().Compare("", plString::kCaseSensitive));
// Same length, case insensitive
EXPECT_EQ(0, plString("abc").Compare("abc", plString::kCaseInsensitive));
EXPECT_EQ(0, plString("abc").Compare("ABC", plString::kCaseInsensitive));
EXPECT_GT(0, plString("abc").Compare("abD", plString::kCaseInsensitive));
EXPECT_LT(0, plString("abc").Compare("abB", plString::kCaseInsensitive));
EXPECT_EQ(0, plString().Compare("", plString::kCaseInsensitive));
// Mismatched length, case sensitive
EXPECT_LT(0, plString("abc").Compare("ab", plString::kCaseSensitive));
EXPECT_GT(0, plString("abc").Compare("abcd", plString::kCaseSensitive));
EXPECT_LT(0, plString("abc").Compare("", plString::kCaseSensitive));
EXPECT_GT(0, plString("").Compare("abc", plString::kCaseSensitive));
// Mismatched length, case insensitive
EXPECT_LT(0, plString("abc").Compare("Ab", plString::kCaseInsensitive));
EXPECT_GT(0, plString("abc").Compare("Abcd", plString::kCaseInsensitive));
EXPECT_LT(0, plString("abc").Compare("", plString::kCaseInsensitive));
EXPECT_GT(0, plString().Compare("abc", plString::kCaseInsensitive));
}
TEST(plString, CompareN)
{
// Same length, case sensitive
EXPECT_EQ(0, plString("abcXX").CompareN("abcYY", 3, plString::kCaseSensitive));
EXPECT_GT(0, plString("abcXX").CompareN("abdYY", 3, plString::kCaseSensitive));
EXPECT_LT(0, plString("abcXX").CompareN("abbYY", 3, plString::kCaseSensitive));
EXPECT_GT(0, plString("abCXX").CompareN("abcYY", 3, plString::kCaseSensitive));
EXPECT_GT(0, plString("AbcXX").CompareN("abcYY", 3, plString::kCaseSensitive));
// Same length, case insensitive
EXPECT_EQ(0, plString("abcXX").CompareN("abcYY", 3, plString::kCaseInsensitive));
EXPECT_EQ(0, plString("abcXX").CompareN("ABCYY", 3, plString::kCaseInsensitive));
EXPECT_GT(0, plString("abcXX").CompareN("abDYY", 3, plString::kCaseInsensitive));
EXPECT_LT(0, plString("abcXX").CompareN("abBYY", 3, plString::kCaseInsensitive));
// Mismatched length, case sensitive
EXPECT_LT(0, plString("abc").CompareN("ab", 3, plString::kCaseSensitive));
EXPECT_GT(0, plString("abc").CompareN("abcd", 4, plString::kCaseSensitive));
EXPECT_LT(0, plString("abc").CompareN("", 3, plString::kCaseSensitive));
EXPECT_GT(0, plString("").CompareN("abc", 3, plString::kCaseSensitive));
// Mismatched length, case insensitive
EXPECT_LT(0, plString("abc").CompareN("Ab", 3, plString::kCaseInsensitive));
EXPECT_GT(0, plString("abc").CompareN("Abcd", 4, plString::kCaseInsensitive));
EXPECT_LT(0, plString("abc").CompareN("", 3, plString::kCaseInsensitive));
EXPECT_GT(0, plString().CompareN("abc", 3, plString::kCaseInsensitive));
}
TEST(PlStringTest,ToUpper)
TEST(plString, FindChar)
{
plString input = plString("abCDe");
plString output = input.ToUpper();
plString expected = plString("ABCDE");
EXPECT_EQ(expected,output);
// Available char, case sensitive
EXPECT_EQ(0, plString("Aaaaaaaa").Find('A', plString::kCaseSensitive));
EXPECT_EQ(0, plString("AaaaAaaa").Find('A', plString::kCaseSensitive));
EXPECT_EQ(4, plString("aaaaAaaa").Find('A', plString::kCaseSensitive));
EXPECT_EQ(7, plString("aaaaaaaA").Find('A', plString::kCaseSensitive));
// Available char, case insensitive
EXPECT_EQ(0, plString("Abbbbbbb").Find('A', plString::kCaseInsensitive));
EXPECT_EQ(0, plString("AbbbAbbb").Find('A', plString::kCaseInsensitive));
EXPECT_EQ(4, plString("bbbbAbbb").Find('A', plString::kCaseInsensitive));
EXPECT_EQ(7, plString("bbbbbbbA").Find('A', plString::kCaseInsensitive));
EXPECT_EQ(0, plString("abbbbbbb").Find('A', plString::kCaseInsensitive));
EXPECT_EQ(0, plString("abbbabbb").Find('A', plString::kCaseInsensitive));
EXPECT_EQ(4, plString("bbbbabbb").Find('A', plString::kCaseInsensitive));
EXPECT_EQ(7, plString("bbbbbbba").Find('A', plString::kCaseInsensitive));
EXPECT_EQ(0, plString("Abbbbbbb").Find('a', plString::kCaseInsensitive));
EXPECT_EQ(0, plString("AbbbAbbb").Find('a', plString::kCaseInsensitive));
EXPECT_EQ(4, plString("bbbbAbbb").Find('a', plString::kCaseInsensitive));
EXPECT_EQ(7, plString("bbbbbbbA").Find('a', plString::kCaseInsensitive));
// Unavailable char
EXPECT_EQ(-1, plString("AaaaAaaa").Find('C', plString::kCaseSensitive));
EXPECT_EQ(-1, plString("caaacaaa").Find('C', plString::kCaseSensitive));
EXPECT_EQ(-1, plString("AaaaAaaa").Find('C', plString::kCaseInsensitive));
// Empty string
EXPECT_EQ(-1, plString().Find('A', plString::kCaseSensitive));
EXPECT_EQ(-1, plString().Find('A', plString::kCaseInsensitive));
}
TEST(PlStringTest,ToLower)
TEST(plString, FindLast)
{
plString input = plString("aBcDe");
plString output = input.ToLower();
plString expected = plString("abcde");
EXPECT_EQ(expected,output);
// Available char, case sensitive
EXPECT_EQ(0, plString("Aaaaaaaa").FindLast('A', plString::kCaseSensitive));
EXPECT_EQ(4, plString("AaaaAaaa").FindLast('A', plString::kCaseSensitive));
EXPECT_EQ(4, plString("aaaaAaaa").FindLast('A', plString::kCaseSensitive));
EXPECT_EQ(7, plString("aaaaaaaA").FindLast('A', plString::kCaseSensitive));
// Available char, case insensitive
EXPECT_EQ(0, plString("Abbbbbbb").FindLast('A', plString::kCaseInsensitive));
EXPECT_EQ(4, plString("AbbbAbbb").FindLast('A', plString::kCaseInsensitive));
EXPECT_EQ(4, plString("bbbbAbbb").FindLast('A', plString::kCaseInsensitive));
EXPECT_EQ(7, plString("bbbbbbbA").FindLast('A', plString::kCaseInsensitive));
EXPECT_EQ(0, plString("abbbbbbb").FindLast('A', plString::kCaseInsensitive));
EXPECT_EQ(4, plString("abbbabbb").FindLast('A', plString::kCaseInsensitive));
EXPECT_EQ(4, plString("bbbbabbb").FindLast('A', plString::kCaseInsensitive));
EXPECT_EQ(7, plString("bbbbbbba").FindLast('A', plString::kCaseInsensitive));
EXPECT_EQ(0, plString("Abbbbbbb").FindLast('a', plString::kCaseInsensitive));
EXPECT_EQ(4, plString("AbbbAbbb").FindLast('a', plString::kCaseInsensitive));
EXPECT_EQ(4, plString("bbbbAbbb").FindLast('a', plString::kCaseInsensitive));
EXPECT_EQ(7, plString("bbbbbbbA").FindLast('a', plString::kCaseInsensitive));
// Unavailable char
EXPECT_EQ(-1, plString("AaaaAaaa").FindLast('C', plString::kCaseSensitive));
EXPECT_EQ(-1, plString("caaacaaa").FindLast('C', plString::kCaseSensitive));
EXPECT_EQ(-1, plString("AaaaAaaa").FindLast('C', plString::kCaseInsensitive));
// Empty string
EXPECT_EQ(-1, plString().FindLast('A', plString::kCaseSensitive));
EXPECT_EQ(-1, plString().FindLast('A', plString::kCaseInsensitive));
}
TEST(PlStringTest,Tokenize)
TEST(plString, FindString)
{
std::vector<plString> expected;
expected.push_back(plString("a"));
expected.push_back(plString("b"));
expected.push_back(plString("c"));
expected.push_back(plString("d"));
expected.push_back(plString("è"));
// Available string, case sensitive
EXPECT_EQ(0, plString("ABCDabcd").Find("ABCD", plString::kCaseSensitive));
EXPECT_EQ(4, plString("abcdABCDABCDabcd").Find("ABCD", plString::kCaseSensitive));
EXPECT_EQ(4, plString("abcdABCDabcd").Find("ABCD", plString::kCaseSensitive));
EXPECT_EQ(4, plString("abcdABCD").Find("ABCD", plString::kCaseSensitive));
// Available string, case insensitive
EXPECT_EQ(0, plString("ABCDxxxx").Find("ABCD", plString::kCaseInsensitive));
EXPECT_EQ(4, plString("xxxxABCDABCDxxxx").Find("ABCD", plString::kCaseInsensitive));
EXPECT_EQ(4, plString("xxxxABCDxxxx").Find("ABCD", plString::kCaseInsensitive));
EXPECT_EQ(4, plString("xxxxABCD").Find("ABCD", plString::kCaseInsensitive));
EXPECT_EQ(0, plString("abcdxxxx").Find("ABCD", plString::kCaseInsensitive));
EXPECT_EQ(4, plString("xxxxabcdABCDxxxx").Find("ABCD", plString::kCaseInsensitive));
EXPECT_EQ(4, plString("xxxxabcdxxxx").Find("ABCD", plString::kCaseInsensitive));
EXPECT_EQ(4, plString("xxxxabcd").Find("ABCD", plString::kCaseInsensitive));
EXPECT_EQ(0, plString("ABCDxxxx").Find("abcd", plString::kCaseInsensitive));
EXPECT_EQ(4, plString("xxxxABCDabcdxxxx").Find("abcd", plString::kCaseInsensitive));
EXPECT_EQ(4, plString("xxxxABCDxxxx").Find("abcd", plString::kCaseInsensitive));
EXPECT_EQ(4, plString("xxxxABCD").Find("abcd", plString::kCaseInsensitive));
// Unavailable string
EXPECT_EQ(-1, plString("xxxx").Find("ABCD", plString::kCaseSensitive));
EXPECT_EQ(-1, plString("xxxx").Find("ABCD", plString::kCaseInsensitive));
// Empty string
EXPECT_EQ(-1, plString().Find("AAAA", plString::kCaseSensitive));
EXPECT_EQ(-1, plString().Find("AAAA", plString::kCaseInsensitive));
// Unicode substring
plString haystack;
haystack = plString("xxxx") + plString::FromUtf32(test_data);
EXPECT_EQ(4, haystack.Find(utf8_test_data, plString::kCaseSensitive));
EXPECT_EQ(4, haystack.Find(utf8_test_data, plString::kCaseInsensitive));
haystack = plString::FromUtf32(test_data) + plString("xxxx");
EXPECT_EQ(0, haystack.Find(utf8_test_data, plString::kCaseSensitive));
EXPECT_EQ(0, haystack.Find(utf8_test_data, plString::kCaseInsensitive));
haystack = plString("xxxx") + plString::FromUtf32(test_data) + plString("xxxx");
EXPECT_EQ(4, haystack.Find(utf8_test_data, plString::kCaseSensitive));
EXPECT_EQ(4, haystack.Find(utf8_test_data, plString::kCaseInsensitive));
}
plString input = plString("a\t\tb\n;c-d;è");
std::vector<plString> output = input.Tokenize("\t\n-;");
EXPECT_EQ(expected,output);
//TODO: test regex functions
TEST(plString, Trim)
{
EXPECT_EQ(plString("xxx "), plString(" xxx ").TrimLeft(" \t\r\n"));
EXPECT_EQ(plString("xxx\t"), plString("\txxx\t").TrimLeft(" \t\r\n"));
EXPECT_EQ(plString("xxx\r\n"), plString("\r\nxxx\r\n").TrimLeft(" \t\r\n"));
EXPECT_EQ(plString(" xxx "), plString(" xxx ").TrimLeft("abc"));
EXPECT_EQ(plString(" xxx "), plString(" xxx ").TrimLeft("x"));
EXPECT_EQ(plString(" xxx"), plString(" xxx ").TrimRight(" \t\r\n"));
EXPECT_EQ(plString("\txxx"), plString("\txxx\t").TrimRight(" \t\r\n"));
EXPECT_EQ(plString("\r\nxxx"), plString("\r\nxxx\r\n").TrimRight(" \t\r\n"));
EXPECT_EQ(plString(" xxx "), plString(" xxx ").TrimRight("abc"));
EXPECT_EQ(plString(" xxx "), plString(" xxx ").TrimRight("x"));
EXPECT_EQ(plString("xxx"), plString(" xxx ").Trim(" \t\r\n"));
EXPECT_EQ(plString("xxx"), plString("\txxx\t").Trim(" \t\r\n"));
EXPECT_EQ(plString("xxx"), plString("\r\nxxx\r\n").Trim(" \t\r\n"));
EXPECT_EQ(plString(" xxx "), plString(" xxx ").Trim("abc"));
EXPECT_EQ(plString(" xxx "), plString(" xxx ").Trim("x"));
}
TEST(PlStringTest,Split)
TEST(plString, Substrings)
{
std::vector<plString> expected;
expected.push_back(plString("a"));
expected.push_back(plString("b"));
expected.push_back(plString("c"));
expected.push_back(plString("d"));
expected.push_back(plString("è"));
plString input = plString("a-b-c-d-è");
std::vector<plString> output = input.Split("-",4);
EXPECT_EQ(expected,output);
EXPECT_EQ(plString("AAA"), plString("AAA").Left(3));
EXPECT_EQ(plString("AAA"), plString("AAAxxxx").Left(3));
EXPECT_EQ(plString("A"), plString("A").Left(3));
EXPECT_EQ(plString(""), plString("").Left(3));
EXPECT_EQ(plString("AAA"), plString("AAA").Right(3));
EXPECT_EQ(plString("AAA"), plString("xxxxAAA").Right(3));
EXPECT_EQ(plString("A"), plString("A").Right(3));
EXPECT_EQ(plString(""), plString("").Right(3));
EXPECT_EQ(plString("AAA"), plString("AAAxxxx").Substr(0, 3));
EXPECT_EQ(plString("AAA"), plString("xxxxAAA").Substr(4, 3));
EXPECT_EQ(plString("AAA"), plString("xxAAAxx").Substr(2, 3));
EXPECT_EQ(plString(""), plString("AAAA").Substr(2, 0));
EXPECT_EQ(plString("AA"), plString("AAAA").Substr(2, 4));
EXPECT_EQ(plString(""), plString("AAAA").Substr(6, 4));
EXPECT_EQ(plString("AAAA"), plString("AAAA").Substr(0, 4));
EXPECT_EQ(plString(""), plString("").Substr(0, 4));
// Negative indexes start from the right
EXPECT_EQ(plString("AAA"), plString("xxxxAAA").Substr(-3, 3));
EXPECT_EQ(plString("AAA"), plString("xxAAAxx").Substr(-5, 3));
EXPECT_EQ(plString("AAA"), plString("xxxxAAA").Substr(-3, 6));
EXPECT_EQ(plString("AAA"), plString("AAAxxxx").Substr(-10, 3));
EXPECT_EQ(plString("AAA"), plString("AAA").Substr(-10, 10));
}
TEST(PlStringTest,Fill)
TEST(plString, Replace)
{
plString expected = plString("aaaaa");
plString output = plString::Fill(5,'a');
EXPECT_EQ(expected,output);
EXPECT_EQ(plString("xxYYxx"), plString("xxAAxx").Replace("A", "Y"));
EXPECT_EQ(plString("xxAAxx"), plString("xxAAxx").Replace("XX", "Y"));
EXPECT_EQ(plString("xxxx"), plString("xxAAxx").Replace("A", ""));
EXPECT_EQ(plString("xxREPLACExx"), plString("xxFINDxx").Replace("FIND", "REPLACE"));
EXPECT_EQ(plString("xxREPLACExxREPLACExx"), plString("xxFINDxxFINDxx").Replace("FIND", "REPLACE"));
EXPECT_EQ(plString("YYxx"), plString("AAxx").Replace("A", "Y"));
EXPECT_EQ(plString("AAxx"), plString("AAxx").Replace("XX", "Y"));
EXPECT_EQ(plString("xx"), plString("AAxx").Replace("A", ""));
EXPECT_EQ(plString("REPLACExx"), plString("FINDxx").Replace("FIND", "REPLACE"));
EXPECT_EQ(plString("REPLACExxREPLACExx"), plString("FINDxxFINDxx").Replace("FIND", "REPLACE"));
EXPECT_EQ(plString("xxYY"), plString("xxAA").Replace("A", "Y"));
EXPECT_EQ(plString("xxAA"), plString("xxAA").Replace("XX", "Y"));
EXPECT_EQ(plString("xx"), plString("xxAA").Replace("A", ""));
EXPECT_EQ(plString("xxREPLACE"), plString("xxFIND").Replace("FIND", "REPLACE"));
EXPECT_EQ(plString("xxREPLACExxREPLACE"), plString("xxFINDxxFIND").Replace("FIND", "REPLACE"));
EXPECT_EQ(plString("YY"), plString("AA").Replace("A", "Y"));
EXPECT_EQ(plString("AA"), plString("AA").Replace("XX", "Y"));
EXPECT_EQ(plString(""), plString("AA").Replace("A", ""));
EXPECT_EQ(plString("REPLACE"), plString("FIND").Replace("FIND", "REPLACE"));
EXPECT_EQ(plString("REPLACExxREPLACE"), plString("FINDxxFIND").Replace("FIND", "REPLACE"));
}
//overload operator+
TEST(PlStringTest,Addition)
TEST(plString, CaseConvert)
{
plString expected = "abcde";
plString input1 = "ab";
plString input2 = "cde";
/* Edge cases:
* '@' = 'A' - 1
* '[' = 'Z' + 1
* '`' = 'a' - 1
* '{' = 'z' + 1
*/
EXPECT_EQ(plString("AAZZ"), plString("aazz").ToUpper());
EXPECT_EQ(plString("AAZZ"), plString("AAZZ").ToUpper());
EXPECT_EQ(plString("@AZ[`AZ{"), plString("@AZ[`az{").ToUpper());
EXPECT_EQ(plString(""), plString("").ToUpper());
EXPECT_EQ(plString("aazz"), plString("aazz").ToLower());
EXPECT_EQ(plString("aazz"), plString("AAZZ").ToLower());
EXPECT_EQ(plString("@az[`az{"), plString("@AZ[`az{").ToLower());
EXPECT_EQ(plString(""), plString("").ToLower());
}
//plstring+plstring
plString output = input1+input2;
EXPECT_EQ(expected,output);
TEST(plString, Tokenize)
{
std::vector<plString> expected1;
expected1.push_back("aaa");
expected1.push_back("b");
expected1.push_back("ccc");
expected1.push_back("d");
expected1.push_back("èèè");
const plString input1("aaa\t\tb\n;ccc-d;èèè");
EXPECT_EQ(expected1, input1.Tokenize("\t\n-;"));
std::vector<plString> expected2;
expected2.push_back("aaa\t\tb\n");
expected2.push_back("ccc-d");
expected2.push_back("èèè");
EXPECT_EQ(expected2, input1.Tokenize(";"));
std::vector<plString> expected3;
expected3.push_back(input1);
EXPECT_EQ(expected3, input1.Tokenize("x"));
const plString input2("\t;aaa\t\tb\n;ccc-d;èèè--");
EXPECT_EQ(expected1, input2.Tokenize("\t\n-;"));
// Tokenize will return an empty vector if there are no tokens in the input
EXPECT_EQ(std::vector<plString>{}, plString("\t;\n;").Tokenize("\t\n-;"));
EXPECT_EQ(std::vector<plString>{}, plString("").Tokenize("\t\n-;"));
}
//plstring+char*
plString output1 = input1 + input2.c_str();
EXPECT_EQ(expected,output1);
TEST(plString, Split)
{
std::vector<plString> expected1;
expected1.push_back("aaa");
expected1.push_back("b");
expected1.push_back("ccc");
expected1.push_back("d");
expected1.push_back("èèè");
const plString input1("aaa-b-ccc-d-èèè");
EXPECT_EQ(expected1, input1.Split("-"));
EXPECT_EQ(expected1, input1.Split("-", 4));
EXPECT_EQ(expected1, input1.Split("-", 10));
const plString input2("aaa#SEP#b#SEP#ccc#SEP#d#SEP#èèè");
EXPECT_EQ(expected1, input2.Split("#SEP#"));
EXPECT_EQ(expected1, input2.Split("#SEP#", 4));
EXPECT_EQ(expected1, input2.Split("#SEP#", 10));
std::vector<plString> expected2;
expected2.push_back("aaa");
expected2.push_back("b");
expected2.push_back("ccc-d-èèè");
EXPECT_EQ(expected2, input1.Split("-", 2));
std::vector<plString> expected3;
expected3.push_back(input1);
EXPECT_EQ(expected3, input1.Split("-", 0));
EXPECT_EQ(expected3, input1.Split("x"));
EXPECT_EQ(expected3, input1.Split("x", 4));
std::vector<plString> expected4;
expected4.push_back("");
expected4.push_back("aaa");
expected4.push_back("b");
expected4.push_back("ccc");
expected4.push_back("d");
expected4.push_back("èèè");
expected4.push_back("");
const plString input3("-aaa-b-ccc-d-èèè-");
EXPECT_EQ(expected4, input3.Split("-"));
EXPECT_EQ(expected4, input3.Split("-", 6));
EXPECT_EQ(expected4, input3.Split("-", 10));
std::vector<plString> expected5;
expected5.push_back("");
expected5.push_back("");
expected5.push_back("");
expected5.push_back("");
expected5.push_back("");
const plString input4("----");
EXPECT_EQ(expected5, input4.Split("-"));
EXPECT_EQ(expected5, input4.Split("-", 4));
EXPECT_EQ(expected5, input4.Split("-", 10));
std::vector<plString> expected6;
expected6.push_back("");
expected6.push_back("");
expected6.push_back("--");
EXPECT_EQ(expected6, input4.Split("-", 2));
std::vector<plString> expected7;
expected7.push_back("");
expected7.push_back("");
expected7.push_back("");
EXPECT_EQ(expected7, input4.Split("--"));
std::vector<plString> expected8;
expected8.push_back("");
expected8.push_back("--");
EXPECT_EQ(expected8, input4.Split("--", 1));
// Split never provides an empty vector, even for empty input
std::vector<plString> expected9;
expected9.push_back(plString::Null);
EXPECT_EQ(expected9, plString("").Split("-"));
EXPECT_EQ(expected9, plString("").Split("-", 4));
}
//char*+plstring
plString output2 = input1.c_str() + input2;
EXPECT_EQ(expected,output2);
TEST(plString, Fill)
{
EXPECT_EQ(plString(""), plString::Fill(0, 'a'));
EXPECT_EQ(plString("aaaaa"), plString::Fill(5, 'a'));
EXPECT_EQ(plString("aaaaaaaaaaaaaaaaaaaa"), plString::Fill(20, 'a'));
}

Loading…
Cancel
Save