338 lines
9.9 KiB
C++
338 lines
9.9 KiB
C++
#include "tile/base/string.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
#include "tile/base/internal/logging.h"
|
|
#include "tile/base/random.h"
|
|
|
|
#include <cmath>
|
|
|
|
namespace tile {
|
|
TEST(String, TryParseIntegral)
|
|
{
|
|
ASSERT_FALSE(TryParse<int>(std::string(123456, 'a')));
|
|
ASSERT_FALSE(TryParse<int>(""));
|
|
ASSERT_FALSE(TryParse<int>("a"));
|
|
ASSERT_FALSE(TryParse<int>("1-2"));
|
|
|
|
ASSERT_FALSE(TryParse<std::int8_t>(std::to_string(INT8_MAX + 1LL)));
|
|
ASSERT_FALSE(TryParse<std::int8_t>(std::to_string(INT8_MIN - 1LL)));
|
|
ASSERT_FALSE(TryParse<std::uint8_t>(std::to_string(UINT8_MAX + 1LL)));
|
|
ASSERT_FALSE(TryParse<std::uint8_t>("-1"));
|
|
|
|
ASSERT_FALSE(TryParse<std::int16_t>(std::to_string(INT16_MAX + 1LL)));
|
|
ASSERT_FALSE(TryParse<std::int16_t>(std::to_string(INT16_MIN - 1LL)));
|
|
ASSERT_FALSE(TryParse<std::uint16_t>(std::to_string(UINT16_MAX + 1LL)));
|
|
ASSERT_FALSE(TryParse<std::uint16_t>("-1"));
|
|
|
|
ASSERT_FALSE(TryParse<std::int32_t>(std::to_string(INT32_MAX + 1LL)));
|
|
ASSERT_FALSE(TryParse<std::int32_t>(std::to_string(INT32_MIN - 1LL)));
|
|
ASSERT_FALSE(TryParse<std::uint32_t>(std::to_string(UINT32_MAX + 1LL)));
|
|
ASSERT_FALSE(TryParse<std::uint32_t>("-1"));
|
|
|
|
ASSERT_FALSE(TryParse<std::int64_t>(std::to_string(INT64_MAX + 1ULL)));
|
|
ASSERT_FALSE(TryParse<std::int64_t>(std::to_string(INT64_MIN) + "0"));
|
|
ASSERT_FALSE(TryParse<std::uint64_t>(std::to_string(UINT64_MAX) + "0"));
|
|
// FIXME: TryParse<std::uint64_t>("-1") should return false.
|
|
// ASSERT_FALSE(TryParse<std::uint64_t>("-1"));
|
|
|
|
ASSERT_TRUE(TryParse<int>("0"));
|
|
ASSERT_TRUE(TryParse<std::int64_t>(std::to_string(INT64_MAX)));
|
|
ASSERT_TRUE(TryParse<std::int8_t>("0"));
|
|
ASSERT_TRUE(TryParse<std::uint8_t>("0"));
|
|
ASSERT_TRUE(TryParse<std::int16_t>("0"));
|
|
ASSERT_TRUE(TryParse<std::uint16_t>("0"));
|
|
ASSERT_TRUE(TryParse<std::int32_t>("0"));
|
|
ASSERT_TRUE(TryParse<std::uint32_t>("0"));
|
|
ASSERT_TRUE(TryParse<std::int64_t>("0"));
|
|
ASSERT_TRUE(TryParse<std::uint64_t>("0"));
|
|
|
|
for (int i = -100; i != 100; ++i) {
|
|
auto rc = TryParse<int>(std::to_string(i));
|
|
ASSERT_TRUE(rc);
|
|
ASSERT_EQ(*rc, i);
|
|
}
|
|
for (int i = 0; i != 100000; ++i) {
|
|
auto x = Random<std::int64_t>();
|
|
auto rc = TryParse<std::int64_t>(std::to_string(x));
|
|
ASSERT_TRUE(rc);
|
|
ASSERT_EQ(x, *rc);
|
|
}
|
|
for (int i = 0; i != 100000; ++i) {
|
|
auto x = Random<std::uint64_t>();
|
|
auto rc = TryParse<std::uint64_t>(std::to_string(x));
|
|
ASSERT_TRUE(rc);
|
|
ASSERT_EQ(x, *rc);
|
|
}
|
|
}
|
|
|
|
TEST(String, TryParseFloatingPoint)
|
|
{
|
|
ASSERT_FALSE(TryParse<float>(""));
|
|
ASSERT_FALSE(TryParse<double>(""));
|
|
ASSERT_FALSE(TryParse<long double>(""));
|
|
ASSERT_FALSE(TryParse<double>("a"));
|
|
ASSERT_FALSE(TryParse<long double>("a"));
|
|
|
|
ASSERT_TRUE(TryParse<float>(std::to_string(HUGE_VALF)));
|
|
ASSERT_TRUE(TryParse<float>(std::to_string(-HUGE_VALF)));
|
|
ASSERT_TRUE(TryParse<double>(std::to_string(HUGE_VAL)));
|
|
ASSERT_TRUE(TryParse<double>(std::to_string(-HUGE_VAL)));
|
|
ASSERT_TRUE(TryParse<long double>(std::to_string(HUGE_VALL)));
|
|
ASSERT_TRUE(TryParse<long double>(std::to_string(-HUGE_VALL)));
|
|
|
|
for (int i = 0; i != 100000; ++i) {
|
|
auto x = 1.0 * Random() * Random();
|
|
{
|
|
auto rc = TryParse<float>(std::to_string(x));
|
|
ASSERT_TRUE(rc);
|
|
ASSERT_NEAR(x, *rc, fabs(x + *rc) / 2 * 1e-5);
|
|
}
|
|
{
|
|
auto rc = TryParse<double>(std::to_string(x));
|
|
ASSERT_TRUE(rc);
|
|
ASSERT_NEAR(x, *rc, fabs(x + *rc) / 2 * 1e-5);
|
|
}
|
|
{
|
|
auto rc = TryParse<long double>(std::to_string(x));
|
|
ASSERT_TRUE(rc);
|
|
ASSERT_NEAR(x, *rc, fabsl(x + *rc) / 2 * 1e-5);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST(String, TryParseBool)
|
|
{
|
|
ASSERT_FALSE(TryParse<bool>(""));
|
|
ASSERT_FALSE(TryParse<bool>(".."));
|
|
ASSERT_TRUE(TryParse<bool>("2"));
|
|
|
|
ASSERT_TRUE(TryParse<bool>("1"));
|
|
ASSERT_TRUE(TryParse<bool>("0"));
|
|
ASSERT_TRUE(TryParse<bool>("y"));
|
|
ASSERT_TRUE(TryParse<bool>("n"));
|
|
ASSERT_TRUE(TryParse<bool>("Y"));
|
|
ASSERT_TRUE(TryParse<bool>("N"));
|
|
ASSERT_TRUE(TryParse<bool>("Yes"));
|
|
ASSERT_TRUE(TryParse<bool>("nO"));
|
|
ASSERT_TRUE(TryParse<bool>("TRue"));
|
|
ASSERT_TRUE(TryParse<bool>("faLse"));
|
|
|
|
ASSERT_TRUE(*TryParse<bool>("1"));
|
|
ASSERT_FALSE(*TryParse<bool>("0"));
|
|
ASSERT_TRUE(*TryParse<bool>("y"));
|
|
ASSERT_FALSE(*TryParse<bool>("n"));
|
|
ASSERT_TRUE(*TryParse<bool>("Y"));
|
|
ASSERT_FALSE(*TryParse<bool>("N"));
|
|
ASSERT_TRUE(*TryParse<bool>("yeS"));
|
|
ASSERT_FALSE(*TryParse<bool>("No"));
|
|
ASSERT_TRUE(*TryParse<bool>("tRUe"));
|
|
ASSERT_FALSE(*TryParse<bool>("falsE"));
|
|
}
|
|
|
|
TEST(String, StartsWith)
|
|
{
|
|
ASSERT_TRUE(StartsWith("asdf", "asdf"));
|
|
ASSERT_TRUE(StartsWith("asdf", "asd"));
|
|
ASSERT_TRUE(StartsWith("asdf", "as"));
|
|
ASSERT_TRUE(StartsWith("asdf", "a"));
|
|
ASSERT_TRUE(StartsWith("asdf", ""));
|
|
ASSERT_TRUE(StartsWith("", ""));
|
|
ASSERT_TRUE(!StartsWith("asdf", "b"));
|
|
ASSERT_TRUE(!StartsWith("", "b"));
|
|
}
|
|
|
|
TEST(String, EndsWith)
|
|
{
|
|
ASSERT_TRUE(EndsWith("asdf", "asdf"));
|
|
ASSERT_TRUE(EndsWith("asdf", "sdf"));
|
|
ASSERT_TRUE(EndsWith("asdf", "df"));
|
|
ASSERT_TRUE(EndsWith("asdf", "f"));
|
|
ASSERT_TRUE(EndsWith("asdf", ""));
|
|
ASSERT_TRUE(EndsWith("", ""));
|
|
ASSERT_TRUE(!EndsWith("asdf", "b"));
|
|
ASSERT_TRUE(!EndsWith("", "b"));
|
|
}
|
|
|
|
TEST(String, Replace)
|
|
{
|
|
ASSERT_EQ("//////", Replace("////////////", "//", "/"));
|
|
ASSERT_EQ("aabb", Replace("bbbb", "b", "a", 2));
|
|
ASSERT_EQ("/././././", Replace("/.//.//.//./", "//", "/"));
|
|
ASSERT_EQ("/.//./././", Replace("/.///.//.//./", "//", "/"));
|
|
ASSERT_EQ("abbb", Replace("bbbb", "b", "a", 1));
|
|
ASSERT_EQ("//", Replace("//", "/", "/"));
|
|
ASSERT_EQ("", Replace("//", "/", ""));
|
|
ASSERT_EQ("//", Replace("///", "//", "/"));
|
|
}
|
|
|
|
TEST(String, Trim)
|
|
{
|
|
ASSERT_EQ("", Trim(""));
|
|
ASSERT_EQ("", Trim(" "));
|
|
ASSERT_EQ("", Trim(" "));
|
|
ASSERT_EQ("", Trim(" "));
|
|
ASSERT_EQ("aa", Trim("aa"));
|
|
ASSERT_EQ("aa", Trim(" aa"));
|
|
ASSERT_EQ("aa", Trim(" aa"));
|
|
ASSERT_EQ("aa", Trim("aa "));
|
|
ASSERT_EQ("aa", Trim("aa "));
|
|
ASSERT_EQ("aa", Trim(" aa "));
|
|
ASSERT_EQ("aa", Trim(" aa "));
|
|
ASSERT_EQ("aa", Trim(" aa "));
|
|
ASSERT_EQ("aa", Trim(" aa "));
|
|
ASSERT_EQ("a a", Trim(" a a "));
|
|
}
|
|
|
|
TEST(String, TrimByCustset)
|
|
{
|
|
static_assert(std::is_constructible<Slice, decltype("d")>::value, "");
|
|
static_assert(!std::is_constructible<Slice, int(int)>::value, "");
|
|
ASSERT_EQ(" ", Trim("abcd abcd", "abcd"));
|
|
ASSERT_EQ("abcd abc", Trim("abcd abcd", "d"));
|
|
ASSERT_EQ("abcd abcd ", Trim("abcd abcd ", "d"));
|
|
ASSERT_EQ(" abcd abcd ", Trim(" abcd abcd ", "ad"));
|
|
ASSERT_EQ("bcd abc", Trim(" abcd abcd ", "ad "));
|
|
}
|
|
|
|
TEST(String, Split1)
|
|
{
|
|
auto splited = Split("/a/b/c/d/e/f///g", '/');
|
|
ASSERT_EQ(7, splited.size());
|
|
ASSERT_EQ("a", splited[0]);
|
|
ASSERT_EQ("b", splited[1]);
|
|
ASSERT_EQ("c", splited[2]);
|
|
ASSERT_EQ("d", splited[3]);
|
|
ASSERT_EQ("e", splited[4]);
|
|
ASSERT_EQ("f", splited[5]);
|
|
ASSERT_EQ("g", splited[6]);
|
|
}
|
|
|
|
TEST(String, Split2)
|
|
{
|
|
auto splited = Split("a///g/", '/');
|
|
ASSERT_EQ(2, splited.size());
|
|
ASSERT_EQ(splited[0], "a");
|
|
ASSERT_EQ(splited[1], "g");
|
|
}
|
|
|
|
TEST(String, Split3)
|
|
{
|
|
auto splited = Split("/////a/g", '/');
|
|
ASSERT_EQ(2, splited.size());
|
|
ASSERT_EQ("a", splited[0]);
|
|
ASSERT_EQ("g", splited[1]);
|
|
}
|
|
|
|
TEST(String, Split4)
|
|
{
|
|
auto splited = Split("/////a/g///", '/');
|
|
ASSERT_EQ(2, splited.size());
|
|
ASSERT_EQ("a", splited[0]);
|
|
ASSERT_EQ("g", splited[1]);
|
|
}
|
|
|
|
TEST(String, Split5)
|
|
{
|
|
auto splited = Split("////a//g//", "//");
|
|
ASSERT_EQ(2, splited.size());
|
|
ASSERT_EQ("a", splited[0]);
|
|
ASSERT_EQ("g", splited[1]);
|
|
}
|
|
|
|
TEST(String, Split6)
|
|
{
|
|
auto splited = Split("//a//g", "//");
|
|
ASSERT_EQ(2, splited.size());
|
|
ASSERT_EQ("a", splited[0]);
|
|
ASSERT_EQ("g", splited[1]);
|
|
}
|
|
|
|
TEST(String, Split7)
|
|
{
|
|
auto splited = Split("a//g", "//");
|
|
ASSERT_EQ(2, splited.size());
|
|
ASSERT_EQ("a", splited[0]);
|
|
ASSERT_EQ("g", splited[1]);
|
|
}
|
|
|
|
TEST(String, Split8)
|
|
{
|
|
auto splited = Split("//", "//");
|
|
ASSERT_EQ(0, splited.size());
|
|
}
|
|
|
|
TEST(String, Split9)
|
|
{
|
|
auto splited = Split("", '/');
|
|
ASSERT_EQ(0, splited.size());
|
|
}
|
|
|
|
TEST(String, SplitWithLimit)
|
|
{
|
|
auto splited = Split("a/b/c/d/e/f/g", '/', false, 3);
|
|
ASSERT_EQ(3, splited.size());
|
|
ASSERT_EQ(splited[0], "a");
|
|
ASSERT_EQ(splited[1], "b");
|
|
ASSERT_EQ(splited[2], "c/d/e/f/g");
|
|
}
|
|
|
|
TEST(String, SplitKeepEmpty1)
|
|
{
|
|
auto splited = Split("///a//g///", '/', true);
|
|
ASSERT_EQ(9, splited.size());
|
|
ASSERT_EQ("", splited[0]);
|
|
ASSERT_EQ("", splited[1]);
|
|
ASSERT_EQ("", splited[2]);
|
|
ASSERT_EQ("a", splited[3]);
|
|
ASSERT_EQ("", splited[4]);
|
|
ASSERT_EQ("g", splited[5]);
|
|
ASSERT_EQ("", splited[6]);
|
|
ASSERT_EQ("", splited[7]);
|
|
ASSERT_EQ("", splited[8]);
|
|
}
|
|
|
|
TEST(String, SplitKeepEmpty2)
|
|
{
|
|
auto splited = Split("//", "//", true);
|
|
ASSERT_EQ(2, splited.size());
|
|
ASSERT_EQ("", splited[0]);
|
|
ASSERT_EQ("", splited[1]);
|
|
}
|
|
|
|
TEST(String, Join)
|
|
{
|
|
ASSERT_EQ("a\nbb\nccc", Join({"a", "bb", "ccc"}, "\n"));
|
|
ASSERT_EQ("a\n\nbb\nccc", Join({"a", "", "bb", "ccc"}, "\n"));
|
|
ASSERT_EQ("a\n\nbb\nccc", Join({"a", "", "bb", "ccc"}, "\n"));
|
|
std::vector<Slice> s = {"a", "", "bb", "ccc"};
|
|
ASSERT_EQ("a\n\nbb\nccc", Join(s, "\n"));
|
|
}
|
|
|
|
TEST(String, EqualsIgnoreCase)
|
|
{
|
|
ASSERT_TRUE(EqualsIgnoreCase("abc", "abc"));
|
|
ASSERT_TRUE(EqualsIgnoreCase("abc", "aBc"));
|
|
ASSERT_TRUE(EqualsIgnoreCase("abc", "ABC"));
|
|
ASSERT_FALSE(EqualsIgnoreCase("abc", "ab"));
|
|
ASSERT_FALSE(EqualsIgnoreCase("abc", "abcd"));
|
|
ASSERT_FALSE(EqualsIgnoreCase("abc", "d"));
|
|
}
|
|
|
|
TEST(String, ToUpper)
|
|
{
|
|
std::string s = "abCD";
|
|
ToUpper(&s);
|
|
ASSERT_EQ("ABCD", s);
|
|
ASSERT_EQ("ABCD", ToUpper("aBCd"));
|
|
}
|
|
|
|
TEST(String, ToLower)
|
|
{
|
|
std::string s = "abCD";
|
|
ToLower(&s);
|
|
ASSERT_EQ("abcd", s);
|
|
ASSERT_EQ("abcd", ToLower("aBCd"));
|
|
}
|
|
}// namespace tile
|