tile/tile/base/string_test.cc
2025-01-09 21:46:03 +08:00

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