llvm-project/llvm/unittests/ADT/StringRefTest.cpp
Zachary Turner 65fd2fc7b4 [Support] Add StringRef::consumeInteger.
StringRef::getInteger() exists and treats the entire string as
an integer of the specified radix, failing if any invalid characters
are encountered or the number overflows.

Sometimes you might have something like "123456foo" and you want
to get the number 123456 and leave the string "foo" remaining.
This is similar to what would be possible by using the standard
runtime library functions strtoul et al and specifying an end
pointer.

This patch adds consumeInteger(), which does exactly that.  It
consumes as much as possible until an invalid character is found,
and modifies the StringRef in place so that upon return only
the portion of the StringRef after the number remains.

Differential Revision: https://reviews.llvm.org/D24778

llvm-svn: 282164
2016-09-22 15:05:19 +00:00

865 lines
27 KiB
C++

//===- llvm/unittest/ADT/StringRefTest.cpp - StringRef unit tests ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace llvm {
std::ostream &operator<<(std::ostream &OS, const StringRef &S) {
OS << S.str();
return OS;
}
std::ostream &operator<<(std::ostream &OS,
const std::pair<StringRef, StringRef> &P) {
OS << "(" << P.first << ", " << P.second << ")";
return OS;
}
}
namespace {
TEST(StringRefTest, Construction) {
EXPECT_EQ("", StringRef());
EXPECT_EQ("hello", StringRef("hello"));
EXPECT_EQ("hello", StringRef("hello world", 5));
EXPECT_EQ("hello", StringRef(std::string("hello")));
}
TEST(StringRefTest, Iteration) {
StringRef S("hello");
const char *p = "hello";
for (const char *it = S.begin(), *ie = S.end(); it != ie; ++it, ++p)
EXPECT_EQ(*it, *p);
}
TEST(StringRefTest, StringOps) {
const char *p = "hello";
EXPECT_EQ(p, StringRef(p, 0).data());
EXPECT_TRUE(StringRef().empty());
EXPECT_EQ((size_t) 5, StringRef("hello").size());
EXPECT_EQ(-1, StringRef("aab").compare("aad"));
EXPECT_EQ( 0, StringRef("aab").compare("aab"));
EXPECT_EQ( 1, StringRef("aab").compare("aaa"));
EXPECT_EQ(-1, StringRef("aab").compare("aabb"));
EXPECT_EQ( 1, StringRef("aab").compare("aa"));
EXPECT_EQ( 1, StringRef("\xFF").compare("\1"));
EXPECT_EQ(-1, StringRef("AaB").compare_lower("aAd"));
EXPECT_EQ( 0, StringRef("AaB").compare_lower("aab"));
EXPECT_EQ( 1, StringRef("AaB").compare_lower("AAA"));
EXPECT_EQ(-1, StringRef("AaB").compare_lower("aaBb"));
EXPECT_EQ(-1, StringRef("AaB").compare_lower("bb"));
EXPECT_EQ( 1, StringRef("aaBb").compare_lower("AaB"));
EXPECT_EQ( 1, StringRef("bb").compare_lower("AaB"));
EXPECT_EQ( 1, StringRef("AaB").compare_lower("aA"));
EXPECT_EQ( 1, StringRef("\xFF").compare_lower("\1"));
EXPECT_EQ(-1, StringRef("aab").compare_numeric("aad"));
EXPECT_EQ( 0, StringRef("aab").compare_numeric("aab"));
EXPECT_EQ( 1, StringRef("aab").compare_numeric("aaa"));
EXPECT_EQ(-1, StringRef("aab").compare_numeric("aabb"));
EXPECT_EQ( 1, StringRef("aab").compare_numeric("aa"));
EXPECT_EQ(-1, StringRef("1").compare_numeric("10"));
EXPECT_EQ( 0, StringRef("10").compare_numeric("10"));
EXPECT_EQ( 0, StringRef("10a").compare_numeric("10a"));
EXPECT_EQ( 1, StringRef("2").compare_numeric("1"));
EXPECT_EQ( 0, StringRef("llvm_v1i64_ty").compare_numeric("llvm_v1i64_ty"));
EXPECT_EQ( 1, StringRef("\xFF").compare_numeric("\1"));
EXPECT_EQ( 1, StringRef("V16").compare_numeric("V1_q0"));
EXPECT_EQ(-1, StringRef("V1_q0").compare_numeric("V16"));
EXPECT_EQ(-1, StringRef("V8_q0").compare_numeric("V16"));
EXPECT_EQ( 1, StringRef("V16").compare_numeric("V8_q0"));
EXPECT_EQ(-1, StringRef("V1_q0").compare_numeric("V8_q0"));
EXPECT_EQ( 1, StringRef("V8_q0").compare_numeric("V1_q0"));
}
TEST(StringRefTest, Operators) {
EXPECT_EQ("", StringRef());
EXPECT_TRUE(StringRef("aab") < StringRef("aad"));
EXPECT_FALSE(StringRef("aab") < StringRef("aab"));
EXPECT_TRUE(StringRef("aab") <= StringRef("aab"));
EXPECT_FALSE(StringRef("aab") <= StringRef("aaa"));
EXPECT_TRUE(StringRef("aad") > StringRef("aab"));
EXPECT_FALSE(StringRef("aab") > StringRef("aab"));
EXPECT_TRUE(StringRef("aab") >= StringRef("aab"));
EXPECT_FALSE(StringRef("aaa") >= StringRef("aab"));
EXPECT_EQ(StringRef("aab"), StringRef("aab"));
EXPECT_FALSE(StringRef("aab") == StringRef("aac"));
EXPECT_FALSE(StringRef("aab") != StringRef("aab"));
EXPECT_TRUE(StringRef("aab") != StringRef("aac"));
EXPECT_EQ('a', StringRef("aab")[1]);
}
TEST(StringRefTest, Substr) {
StringRef Str("hello");
EXPECT_EQ("lo", Str.substr(3));
EXPECT_EQ("", Str.substr(100));
EXPECT_EQ("hello", Str.substr(0, 100));
EXPECT_EQ("o", Str.substr(4, 10));
}
TEST(StringRefTest, Slice) {
StringRef Str("hello");
EXPECT_EQ("l", Str.slice(2, 3));
EXPECT_EQ("ell", Str.slice(1, 4));
EXPECT_EQ("llo", Str.slice(2, 100));
EXPECT_EQ("", Str.slice(2, 1));
EXPECT_EQ("", Str.slice(10, 20));
}
TEST(StringRefTest, Split) {
StringRef Str("hello");
EXPECT_EQ(std::make_pair(StringRef("hello"), StringRef("")),
Str.split('X'));
EXPECT_EQ(std::make_pair(StringRef("h"), StringRef("llo")),
Str.split('e'));
EXPECT_EQ(std::make_pair(StringRef(""), StringRef("ello")),
Str.split('h'));
EXPECT_EQ(std::make_pair(StringRef("he"), StringRef("lo")),
Str.split('l'));
EXPECT_EQ(std::make_pair(StringRef("hell"), StringRef("")),
Str.split('o'));
EXPECT_EQ(std::make_pair(StringRef("hello"), StringRef("")),
Str.rsplit('X'));
EXPECT_EQ(std::make_pair(StringRef("h"), StringRef("llo")),
Str.rsplit('e'));
EXPECT_EQ(std::make_pair(StringRef(""), StringRef("ello")),
Str.rsplit('h'));
EXPECT_EQ(std::make_pair(StringRef("hel"), StringRef("o")),
Str.rsplit('l'));
EXPECT_EQ(std::make_pair(StringRef("hell"), StringRef("")),
Str.rsplit('o'));
}
TEST(StringRefTest, Split2) {
SmallVector<StringRef, 5> parts;
SmallVector<StringRef, 5> expected;
expected.push_back("ab"); expected.push_back("c");
StringRef(",ab,,c,").split(parts, ",", -1, false);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back(""); expected.push_back("ab"); expected.push_back("");
expected.push_back("c"); expected.push_back("");
StringRef(",ab,,c,").split(parts, ",", -1, true);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back("");
StringRef("").split(parts, ",", -1, true);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
StringRef("").split(parts, ",", -1, false);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
StringRef(",").split(parts, ",", -1, false);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back(""); expected.push_back("");
StringRef(",").split(parts, ",", -1, true);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back("a"); expected.push_back("b");
StringRef("a,b").split(parts, ",", -1, true);
EXPECT_TRUE(parts == expected);
// Test MaxSplit
expected.clear(); parts.clear();
expected.push_back("a,,b,c");
StringRef("a,,b,c").split(parts, ",", 0, true);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back("a,,b,c");
StringRef("a,,b,c").split(parts, ",", 0, false);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back("a"); expected.push_back(",b,c");
StringRef("a,,b,c").split(parts, ",", 1, true);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back("a"); expected.push_back(",b,c");
StringRef("a,,b,c").split(parts, ",", 1, false);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back("a"); expected.push_back(""); expected.push_back("b,c");
StringRef("a,,b,c").split(parts, ",", 2, true);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back("a"); expected.push_back("b,c");
StringRef("a,,b,c").split(parts, ",", 2, false);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back("a"); expected.push_back(""); expected.push_back("b");
expected.push_back("c");
StringRef("a,,b,c").split(parts, ",", 3, true);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back("a"); expected.push_back("b"); expected.push_back("c");
StringRef("a,,b,c").split(parts, ",", 3, false);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back("a"); expected.push_back("b"); expected.push_back("c");
StringRef("a,,b,c").split(parts, ',', 3, false);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back("");
StringRef().split(parts, ",", 0, true);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back(StringRef());
StringRef("").split(parts, ",", 0, true);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
StringRef("").split(parts, ",", 0, false);
EXPECT_TRUE(parts == expected);
StringRef().split(parts, ",", 0, false);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back("a");
expected.push_back("");
expected.push_back("b");
expected.push_back("c,d");
StringRef("a,,b,c,d").split(parts, ",", 3, true);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back("");
StringRef().split(parts, ',', 0, true);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back(StringRef());
StringRef("").split(parts, ',', 0, true);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
StringRef("").split(parts, ',', 0, false);
EXPECT_TRUE(parts == expected);
StringRef().split(parts, ',', 0, false);
EXPECT_TRUE(parts == expected);
expected.clear(); parts.clear();
expected.push_back("a");
expected.push_back("");
expected.push_back("b");
expected.push_back("c,d");
StringRef("a,,b,c,d").split(parts, ',', 3, true);
EXPECT_TRUE(parts == expected);
}
TEST(StringRefTest, Trim) {
StringRef Str0("hello");
StringRef Str1(" hello ");
StringRef Str2(" hello ");
EXPECT_EQ(StringRef("hello"), Str0.rtrim());
EXPECT_EQ(StringRef(" hello"), Str1.rtrim());
EXPECT_EQ(StringRef(" hello"), Str2.rtrim());
EXPECT_EQ(StringRef("hello"), Str0.ltrim());
EXPECT_EQ(StringRef("hello "), Str1.ltrim());
EXPECT_EQ(StringRef("hello "), Str2.ltrim());
EXPECT_EQ(StringRef("hello"), Str0.trim());
EXPECT_EQ(StringRef("hello"), Str1.trim());
EXPECT_EQ(StringRef("hello"), Str2.trim());
EXPECT_EQ(StringRef("ello"), Str0.trim("hhhhhhhhhhh"));
EXPECT_EQ(StringRef(""), StringRef("").trim());
EXPECT_EQ(StringRef(""), StringRef(" ").trim());
EXPECT_EQ(StringRef("\0", 1), StringRef(" \0 ", 3).trim());
EXPECT_EQ(StringRef("\0\0", 2), StringRef("\0\0", 2).trim());
EXPECT_EQ(StringRef("x"), StringRef("\0\0x\0\0", 5).trim('\0'));
}
TEST(StringRefTest, StartsWith) {
StringRef Str("hello");
EXPECT_TRUE(Str.startswith(""));
EXPECT_TRUE(Str.startswith("he"));
EXPECT_FALSE(Str.startswith("helloworld"));
EXPECT_FALSE(Str.startswith("hi"));
}
TEST(StringRefTest, StartsWithLower) {
StringRef Str("heLLo");
EXPECT_TRUE(Str.startswith_lower(""));
EXPECT_TRUE(Str.startswith_lower("he"));
EXPECT_TRUE(Str.startswith_lower("hell"));
EXPECT_TRUE(Str.startswith_lower("HELlo"));
EXPECT_FALSE(Str.startswith_lower("helloworld"));
EXPECT_FALSE(Str.startswith_lower("hi"));
}
TEST(StringRefTest, ConsumeFront) {
StringRef Str("hello");
EXPECT_TRUE(Str.consume_front(""));
EXPECT_EQ("hello", Str);
EXPECT_TRUE(Str.consume_front("he"));
EXPECT_EQ("llo", Str);
EXPECT_FALSE(Str.consume_front("lloworld"));
EXPECT_EQ("llo", Str);
EXPECT_FALSE(Str.consume_front("lol"));
EXPECT_EQ("llo", Str);
EXPECT_TRUE(Str.consume_front("llo"));
EXPECT_EQ("", Str);
EXPECT_FALSE(Str.consume_front("o"));
EXPECT_TRUE(Str.consume_front(""));
}
TEST(StringRefTest, EndsWith) {
StringRef Str("hello");
EXPECT_TRUE(Str.endswith(""));
EXPECT_TRUE(Str.endswith("lo"));
EXPECT_FALSE(Str.endswith("helloworld"));
EXPECT_FALSE(Str.endswith("worldhello"));
EXPECT_FALSE(Str.endswith("so"));
}
TEST(StringRefTest, EndsWithLower) {
StringRef Str("heLLo");
EXPECT_TRUE(Str.endswith_lower(""));
EXPECT_TRUE(Str.endswith_lower("lo"));
EXPECT_TRUE(Str.endswith_lower("LO"));
EXPECT_TRUE(Str.endswith_lower("ELlo"));
EXPECT_FALSE(Str.endswith_lower("helloworld"));
EXPECT_FALSE(Str.endswith_lower("hi"));
}
TEST(StringRefTest, ConsumeBack) {
StringRef Str("hello");
EXPECT_TRUE(Str.consume_back(""));
EXPECT_EQ("hello", Str);
EXPECT_TRUE(Str.consume_back("lo"));
EXPECT_EQ("hel", Str);
EXPECT_FALSE(Str.consume_back("helhel"));
EXPECT_EQ("hel", Str);
EXPECT_FALSE(Str.consume_back("hle"));
EXPECT_EQ("hel", Str);
EXPECT_TRUE(Str.consume_back("hel"));
EXPECT_EQ("", Str);
EXPECT_FALSE(Str.consume_back("h"));
EXPECT_TRUE(Str.consume_back(""));
}
TEST(StringRefTest, Find) {
StringRef Str("hello");
EXPECT_EQ(2U, Str.find('l'));
EXPECT_EQ(StringRef::npos, Str.find('z'));
EXPECT_EQ(StringRef::npos, Str.find("helloworld"));
EXPECT_EQ(0U, Str.find("hello"));
EXPECT_EQ(1U, Str.find("ello"));
EXPECT_EQ(StringRef::npos, Str.find("zz"));
EXPECT_EQ(2U, Str.find("ll", 2));
EXPECT_EQ(StringRef::npos, Str.find("ll", 3));
EXPECT_EQ(0U, Str.find(""));
StringRef LongStr("hellx xello hell ello world foo bar hello");
EXPECT_EQ(36U, LongStr.find("hello"));
EXPECT_EQ(28U, LongStr.find("foo"));
EXPECT_EQ(12U, LongStr.find("hell", 2));
EXPECT_EQ(0U, LongStr.find(""));
EXPECT_EQ(3U, Str.rfind('l'));
EXPECT_EQ(StringRef::npos, Str.rfind('z'));
EXPECT_EQ(StringRef::npos, Str.rfind("helloworld"));
EXPECT_EQ(0U, Str.rfind("hello"));
EXPECT_EQ(1U, Str.rfind("ello"));
EXPECT_EQ(StringRef::npos, Str.rfind("zz"));
EXPECT_EQ(2U, Str.find_first_of('l'));
EXPECT_EQ(1U, Str.find_first_of("el"));
EXPECT_EQ(StringRef::npos, Str.find_first_of("xyz"));
EXPECT_EQ(1U, Str.find_first_not_of('h'));
EXPECT_EQ(4U, Str.find_first_not_of("hel"));
EXPECT_EQ(StringRef::npos, Str.find_first_not_of("hello"));
EXPECT_EQ(3U, Str.find_last_not_of('o'));
EXPECT_EQ(1U, Str.find_last_not_of("lo"));
EXPECT_EQ(StringRef::npos, Str.find_last_not_of("helo"));
}
TEST(StringRefTest, Count) {
StringRef Str("hello");
EXPECT_EQ(2U, Str.count('l'));
EXPECT_EQ(1U, Str.count('o'));
EXPECT_EQ(0U, Str.count('z'));
EXPECT_EQ(0U, Str.count("helloworld"));
EXPECT_EQ(1U, Str.count("hello"));
EXPECT_EQ(1U, Str.count("ello"));
EXPECT_EQ(0U, Str.count("zz"));
}
TEST(StringRefTest, EditDistance) {
StringRef Str("hello");
EXPECT_EQ(2U, Str.edit_distance("hill"));
}
TEST(StringRefTest, Misc) {
std::string Storage;
raw_string_ostream OS(Storage);
OS << StringRef("hello");
EXPECT_EQ("hello", OS.str());
}
TEST(StringRefTest, Hashing) {
EXPECT_EQ(hash_value(std::string()), hash_value(StringRef()));
EXPECT_EQ(hash_value(std::string()), hash_value(StringRef("")));
std::string S = "hello world";
hash_code H = hash_value(S);
EXPECT_EQ(H, hash_value(StringRef("hello world")));
EXPECT_EQ(H, hash_value(StringRef(S)));
EXPECT_NE(H, hash_value(StringRef("hello worl")));
EXPECT_EQ(hash_value(std::string("hello worl")),
hash_value(StringRef("hello worl")));
EXPECT_NE(H, hash_value(StringRef("hello world ")));
EXPECT_EQ(hash_value(std::string("hello world ")),
hash_value(StringRef("hello world ")));
EXPECT_EQ(H, hash_value(StringRef("hello world\0")));
EXPECT_NE(hash_value(std::string("ello worl")),
hash_value(StringRef("hello world").slice(1, -1)));
}
struct UnsignedPair {
const char *Str;
uint64_t Expected;
} Unsigned[] =
{ {"0", 0}
, {"255", 255}
, {"256", 256}
, {"65535", 65535}
, {"65536", 65536}
, {"4294967295", 4294967295ULL}
, {"4294967296", 4294967296ULL}
, {"18446744073709551615", 18446744073709551615ULL}
, {"042", 34}
, {"0x42", 66}
, {"0b101010", 42}
};
struct SignedPair {
const char *Str;
int64_t Expected;
} Signed[] =
{ {"0", 0}
, {"-0", 0}
, {"127", 127}
, {"128", 128}
, {"-128", -128}
, {"-129", -129}
, {"32767", 32767}
, {"32768", 32768}
, {"-32768", -32768}
, {"-32769", -32769}
, {"2147483647", 2147483647LL}
, {"2147483648", 2147483648LL}
, {"-2147483648", -2147483648LL}
, {"-2147483649", -2147483649LL}
, {"-9223372036854775808", -(9223372036854775807LL) - 1}
, {"042", 34}
, {"0x42", 66}
, {"0b101010", 42}
, {"-042", -34}
, {"-0x42", -66}
, {"-0b101010", -42}
};
TEST(StringRefTest, getAsInteger) {
uint8_t U8;
uint16_t U16;
uint32_t U32;
uint64_t U64;
for (size_t i = 0; i < array_lengthof(Unsigned); ++i) {
bool U8Success = StringRef(Unsigned[i].Str).getAsInteger(0, U8);
if (static_cast<uint8_t>(Unsigned[i].Expected) == Unsigned[i].Expected) {
ASSERT_FALSE(U8Success);
EXPECT_EQ(U8, Unsigned[i].Expected);
} else {
ASSERT_TRUE(U8Success);
}
bool U16Success = StringRef(Unsigned[i].Str).getAsInteger(0, U16);
if (static_cast<uint16_t>(Unsigned[i].Expected) == Unsigned[i].Expected) {
ASSERT_FALSE(U16Success);
EXPECT_EQ(U16, Unsigned[i].Expected);
} else {
ASSERT_TRUE(U16Success);
}
bool U32Success = StringRef(Unsigned[i].Str).getAsInteger(0, U32);
if (static_cast<uint32_t>(Unsigned[i].Expected) == Unsigned[i].Expected) {
ASSERT_FALSE(U32Success);
EXPECT_EQ(U32, Unsigned[i].Expected);
} else {
ASSERT_TRUE(U32Success);
}
bool U64Success = StringRef(Unsigned[i].Str).getAsInteger(0, U64);
if (static_cast<uint64_t>(Unsigned[i].Expected) == Unsigned[i].Expected) {
ASSERT_FALSE(U64Success);
EXPECT_EQ(U64, Unsigned[i].Expected);
} else {
ASSERT_TRUE(U64Success);
}
}
int8_t S8;
int16_t S16;
int32_t S32;
int64_t S64;
for (size_t i = 0; i < array_lengthof(Signed); ++i) {
bool S8Success = StringRef(Signed[i].Str).getAsInteger(0, S8);
if (static_cast<int8_t>(Signed[i].Expected) == Signed[i].Expected) {
ASSERT_FALSE(S8Success);
EXPECT_EQ(S8, Signed[i].Expected);
} else {
ASSERT_TRUE(S8Success);
}
bool S16Success = StringRef(Signed[i].Str).getAsInteger(0, S16);
if (static_cast<int16_t>(Signed[i].Expected) == Signed[i].Expected) {
ASSERT_FALSE(S16Success);
EXPECT_EQ(S16, Signed[i].Expected);
} else {
ASSERT_TRUE(S16Success);
}
bool S32Success = StringRef(Signed[i].Str).getAsInteger(0, S32);
if (static_cast<int32_t>(Signed[i].Expected) == Signed[i].Expected) {
ASSERT_FALSE(S32Success);
EXPECT_EQ(S32, Signed[i].Expected);
} else {
ASSERT_TRUE(S32Success);
}
bool S64Success = StringRef(Signed[i].Str).getAsInteger(0, S64);
if (static_cast<int64_t>(Signed[i].Expected) == Signed[i].Expected) {
ASSERT_FALSE(S64Success);
EXPECT_EQ(S64, Signed[i].Expected);
} else {
ASSERT_TRUE(S64Success);
}
}
}
static const char* BadStrings[] = {
"18446744073709551617" // value just over max
, "123456789012345678901" // value way too large
, "4t23v" // illegal decimal characters
, "0x123W56" // illegal hex characters
, "0b2" // illegal bin characters
, "08" // illegal oct characters
, "0o8" // illegal oct characters
, "-123" // negative unsigned value
};
TEST(StringRefTest, getAsUnsignedIntegerBadStrings) {
unsigned long long U64;
for (size_t i = 0; i < array_lengthof(BadStrings); ++i) {
bool IsBadNumber = StringRef(BadStrings[i]).getAsInteger(0, U64);
ASSERT_TRUE(IsBadNumber);
}
}
struct ConsumeUnsignedPair {
const char *Str;
uint64_t Expected;
const char *Leftover;
} ConsumeUnsigned[] = {
{"0", 0, ""},
{"255", 255, ""},
{"256", 256, ""},
{"65535", 65535, ""},
{"65536", 65536, ""},
{"4294967295", 4294967295ULL, ""},
{"4294967296", 4294967296ULL, ""},
{"255A376", 255, "A376"},
{"18446744073709551615", 18446744073709551615ULL, ""},
{"18446744073709551615ABC", 18446744073709551615ULL, "ABC"},
{"042", 34, ""},
{"0x42", 66, ""},
{"0x42-0x34", 66, "-0x34"},
{"0b101010", 42, ""},
{"0429F", 042, "9F"}, // Auto-sensed octal radix, invalid digit
{"0x42G12", 0x42, "G12"}, // Auto-sensed hex radix, invalid digit
{"0b10101020101", 42, "20101"}}; // Auto-sensed binary radix, invalid digit.
struct ConsumeSignedPair {
const char *Str;
int64_t Expected;
const char *Leftover;
} ConsumeSigned[] = {
{"0", 0, ""},
{"-0", 0, ""},
{"0-1", 0, "-1"},
{"-0-1", 0, "-1"},
{"127", 127, ""},
{"128", 128, ""},
{"127-1", 127, "-1"},
{"128-1", 128, "-1"},
{"-128", -128, ""},
{"-129", -129, ""},
{"-128-1", -128, "-1"},
{"-129-1", -129, "-1"},
{"32767", 32767, ""},
{"32768", 32768, ""},
{"32767-1", 32767, "-1"},
{"32768-1", 32768, "-1"},
{"-32768", -32768, ""},
{"-32769", -32769, ""},
{"-32768-1", -32768, "-1"},
{"-32769-1", -32769, "-1"},
{"2147483647", 2147483647LL, ""},
{"2147483648", 2147483648LL, ""},
{"2147483647-1", 2147483647LL, "-1"},
{"2147483648-1", 2147483648LL, "-1"},
{"-2147483648", -2147483648LL, ""},
{"-2147483649", -2147483649LL, ""},
{"-2147483648-1", -2147483648LL, "-1"},
{"-2147483649-1", -2147483649LL, "-1"},
{"-9223372036854775808", -(9223372036854775807LL) - 1, ""},
{"-9223372036854775808-1", -(9223372036854775807LL) - 1, "-1"},
{"042", 34, ""},
{"042-1", 34, "-1"},
{"0x42", 66, ""},
{"0x42-1", 66, "-1"},
{"0b101010", 42, ""},
{"0b101010-1", 42, "-1"},
{"-042", -34, ""},
{"-042-1", -34, "-1"},
{"-0x42", -66, ""},
{"-0x42-1", -66, "-1"},
{"-0b101010", -42, ""},
{"-0b101010-1", -42, "-1"}};
TEST(StringRefTest, consumeIntegerUnsigned) {
uint8_t U8;
uint16_t U16;
uint32_t U32;
uint64_t U64;
for (size_t i = 0; i < array_lengthof(ConsumeUnsigned); ++i) {
StringRef Str = ConsumeUnsigned[i].Str;
bool U8Success = Str.consumeInteger(0, U8);
if (static_cast<uint8_t>(ConsumeUnsigned[i].Expected) ==
ConsumeUnsigned[i].Expected) {
ASSERT_FALSE(U8Success);
EXPECT_EQ(U8, ConsumeUnsigned[i].Expected);
EXPECT_EQ(Str, ConsumeUnsigned[i].Leftover);
} else {
ASSERT_TRUE(U8Success);
}
Str = ConsumeUnsigned[i].Str;
bool U16Success = Str.consumeInteger(0, U16);
if (static_cast<uint16_t>(ConsumeUnsigned[i].Expected) ==
ConsumeUnsigned[i].Expected) {
ASSERT_FALSE(U16Success);
EXPECT_EQ(U16, ConsumeUnsigned[i].Expected);
EXPECT_EQ(Str, ConsumeUnsigned[i].Leftover);
} else {
ASSERT_TRUE(U16Success);
}
Str = ConsumeUnsigned[i].Str;
bool U32Success = Str.consumeInteger(0, U32);
if (static_cast<uint32_t>(ConsumeUnsigned[i].Expected) ==
ConsumeUnsigned[i].Expected) {
ASSERT_FALSE(U32Success);
EXPECT_EQ(U32, ConsumeUnsigned[i].Expected);
EXPECT_EQ(Str, ConsumeUnsigned[i].Leftover);
} else {
ASSERT_TRUE(U32Success);
}
Str = ConsumeUnsigned[i].Str;
bool U64Success = Str.consumeInteger(0, U64);
if (static_cast<uint64_t>(ConsumeUnsigned[i].Expected) ==
ConsumeUnsigned[i].Expected) {
ASSERT_FALSE(U64Success);
EXPECT_EQ(U64, ConsumeUnsigned[i].Expected);
EXPECT_EQ(Str, ConsumeUnsigned[i].Leftover);
} else {
ASSERT_TRUE(U64Success);
}
}
}
TEST(StringRefTest, consumeIntegerSigned) {
int8_t S8;
int16_t S16;
int32_t S32;
int64_t S64;
for (size_t i = 0; i < array_lengthof(ConsumeSigned); ++i) {
StringRef Str = ConsumeSigned[i].Str;
bool S8Success = Str.consumeInteger(0, S8);
if (static_cast<int8_t>(ConsumeSigned[i].Expected) ==
ConsumeSigned[i].Expected) {
ASSERT_FALSE(S8Success);
EXPECT_EQ(S8, ConsumeSigned[i].Expected);
EXPECT_EQ(Str, ConsumeSigned[i].Leftover);
} else {
ASSERT_TRUE(S8Success);
}
Str = ConsumeSigned[i].Str;
bool S16Success = Str.consumeInteger(0, S16);
if (static_cast<int16_t>(ConsumeSigned[i].Expected) ==
ConsumeSigned[i].Expected) {
ASSERT_FALSE(S16Success);
EXPECT_EQ(S16, ConsumeSigned[i].Expected);
EXPECT_EQ(Str, ConsumeSigned[i].Leftover);
} else {
ASSERT_TRUE(S16Success);
}
Str = ConsumeSigned[i].Str;
bool S32Success = Str.consumeInteger(0, S32);
if (static_cast<int32_t>(ConsumeSigned[i].Expected) ==
ConsumeSigned[i].Expected) {
ASSERT_FALSE(S32Success);
EXPECT_EQ(S32, ConsumeSigned[i].Expected);
EXPECT_EQ(Str, ConsumeSigned[i].Leftover);
} else {
ASSERT_TRUE(S32Success);
}
Str = ConsumeSigned[i].Str;
bool S64Success = Str.consumeInteger(0, S64);
if (static_cast<int64_t>(ConsumeSigned[i].Expected) ==
ConsumeSigned[i].Expected) {
ASSERT_FALSE(S64Success);
EXPECT_EQ(S64, ConsumeSigned[i].Expected);
EXPECT_EQ(Str, ConsumeSigned[i].Leftover);
} else {
ASSERT_TRUE(S64Success);
}
}
}
static const char *join_input[] = { "a", "b", "c" };
static const char join_result1[] = "a";
static const char join_result2[] = "a:b:c";
static const char join_result3[] = "a::b::c";
TEST(StringRefTest, joinStrings) {
std::vector<StringRef> v1;
std::vector<std::string> v2;
for (size_t i = 0; i < array_lengthof(join_input); ++i) {
v1.push_back(join_input[i]);
v2.push_back(join_input[i]);
}
bool v1_join1 = join(v1.begin(), v1.begin() + 1, ":") == join_result1;
EXPECT_TRUE(v1_join1);
bool v1_join2 = join(v1.begin(), v1.end(), ":") == join_result2;
EXPECT_TRUE(v1_join2);
bool v1_join3 = join(v1.begin(), v1.end(), "::") == join_result3;
EXPECT_TRUE(v1_join3);
bool v2_join1 = join(v2.begin(), v2.begin() + 1, ":") == join_result1;
EXPECT_TRUE(v2_join1);
bool v2_join2 = join(v2.begin(), v2.end(), ":") == join_result2;
EXPECT_TRUE(v2_join2);
bool v2_join3 = join(v2.begin(), v2.end(), "::") == join_result3;
EXPECT_TRUE(v2_join3);
}
TEST(StringRefTest, AllocatorCopy) {
BumpPtrAllocator Alloc;
// First test empty strings. We don't want these to allocate anything on the
// allocator.
StringRef StrEmpty = "";
StringRef StrEmptyc = StrEmpty.copy(Alloc);
EXPECT_TRUE(StrEmpty.equals(StrEmptyc));
EXPECT_EQ(StrEmptyc.data(), nullptr);
EXPECT_EQ(StrEmptyc.size(), 0u);
EXPECT_EQ(Alloc.getTotalMemory(), 0u);
StringRef Str1 = "hello";
StringRef Str2 = "bye";
StringRef Str1c = Str1.copy(Alloc);
StringRef Str2c = Str2.copy(Alloc);
EXPECT_TRUE(Str1.equals(Str1c));
EXPECT_NE(Str1.data(), Str1c.data());
EXPECT_TRUE(Str2.equals(Str2c));
EXPECT_NE(Str2.data(), Str2c.data());
}
TEST(StringRefTest, Drop) {
StringRef Test("StringRefTest::Drop");
StringRef Dropped = Test.drop_front(5);
EXPECT_EQ(Dropped, "gRefTest::Drop");
Dropped = Test.drop_back(5);
EXPECT_EQ(Dropped, "StringRefTest:");
Dropped = Test.drop_front(0);
EXPECT_EQ(Dropped, Test);
Dropped = Test.drop_back(0);
EXPECT_EQ(Dropped, Test);
Dropped = Test.drop_front(Test.size());
EXPECT_TRUE(Dropped.empty());
Dropped = Test.drop_back(Test.size());
EXPECT_TRUE(Dropped.empty());
}
TEST(StringRefTest, Take) {
StringRef Test("StringRefTest::Take");
StringRef Taken = Test.take_front(5);
EXPECT_EQ(Taken, "Strin");
Taken = Test.take_back(5);
EXPECT_EQ(Taken, ":Take");
Taken = Test.take_front(Test.size());
EXPECT_EQ(Taken, Test);
Taken = Test.take_back(Test.size());
EXPECT_EQ(Taken, Test);
Taken = Test.take_front(0);
EXPECT_TRUE(Taken.empty());
Taken = Test.take_back(0);
EXPECT_TRUE(Taken.empty());
}
} // end anonymous namespace