diff options
Diffstat (limited to 'Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp')
-rw-r--r-- | Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp | 550 |
1 files changed, 533 insertions, 17 deletions
diff --git a/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp b/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp index d5804f6b4..fdb701c90 100644 --- a/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp +++ b/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,7 +25,8 @@ #include "config.h" -#include <wtf/text/StringImpl.h> +#include <wtf/Hasher.h> +#include <wtf/text/SymbolImpl.h> #include <wtf/text/WTFString.h> namespace TestWebKitAPI { @@ -33,14 +34,14 @@ namespace TestWebKitAPI { TEST(WTF, StringImplCreationFromLiteral) { // Constructor using the template to determine the size. - RefPtr<StringImpl> stringWithTemplate = StringImpl::createFromLiteral("Template Literal"); + auto stringWithTemplate = StringImpl::createFromLiteral("Template Literal"); ASSERT_EQ(strlen("Template Literal"), stringWithTemplate->length()); ASSERT_TRUE(equal(stringWithTemplate.get(), "Template Literal")); ASSERT_TRUE(stringWithTemplate->is8Bit()); // Constructor taking the size explicitely. const char* programmaticStringData = "Explicit Size Literal"; - RefPtr<StringImpl> programmaticString = StringImpl::createFromLiteral(programmaticStringData, strlen(programmaticStringData)); + auto programmaticString = StringImpl::createFromLiteral(programmaticStringData, strlen(programmaticStringData)); ASSERT_EQ(strlen(programmaticStringData), programmaticString->length()); ASSERT_TRUE(equal(programmaticString.get(), programmaticStringData)); ASSERT_EQ(programmaticStringData, reinterpret_cast<const char*>(programmaticString->characters8())); @@ -48,27 +49,16 @@ TEST(WTF, StringImplCreationFromLiteral) // Constructor without explicit size. const char* stringWithoutLengthLiteral = "No Size Literal"; - RefPtr<StringImpl> programmaticStringNoLength = StringImpl::createFromLiteral(stringWithoutLengthLiteral); + auto programmaticStringNoLength = StringImpl::createFromLiteral(stringWithoutLengthLiteral); ASSERT_EQ(strlen(stringWithoutLengthLiteral), programmaticStringNoLength->length()); ASSERT_TRUE(equal(programmaticStringNoLength.get(), stringWithoutLengthLiteral)); ASSERT_EQ(stringWithoutLengthLiteral, reinterpret_cast<const char*>(programmaticStringNoLength->characters8())); ASSERT_TRUE(programmaticStringNoLength->is8Bit()); } -TEST(WTF, StringImplFromLiteralLoop16BitConversion) -{ - RefPtr<StringImpl> controlString = StringImpl::create("Template Literal"); - for (size_t i = 0; i < 10; ++i) { - RefPtr<StringImpl> string = StringImpl::createFromLiteral("Template Literal"); - - ASSERT_EQ(0, memcmp(controlString->deprecatedCharacters(), string->deprecatedCharacters(), controlString->length() * sizeof(UChar))); - ASSERT_TRUE(string->has16BitShadow()); - } -} - TEST(WTF, StringImplReplaceWithLiteral) { - RefPtr<StringImpl> testStringImpl = StringImpl::createFromLiteral("1224"); + auto testStringImpl = StringImpl::createFromLiteral("1224"); ASSERT_TRUE(testStringImpl->is8Bit()); // Cases for 8Bit source. @@ -110,4 +100,530 @@ TEST(WTF, StringImplReplaceWithLiteral) ASSERT_TRUE(equal(testStringImpl.get(), "r555sum555")); } +TEST(WTF, StringImplEqualIgnoringASCIICaseBasic) +{ + auto a = StringImpl::createFromLiteral("aBcDeFG"); + auto b = StringImpl::createFromLiteral("ABCDEFG"); + auto c = StringImpl::createFromLiteral("abcdefg"); + const char d[] = "aBcDeFG"; + auto empty = StringImpl::create(reinterpret_cast<const LChar*>("")); + auto shorter = StringImpl::createFromLiteral("abcdef"); + auto different = StringImpl::createFromLiteral("abcrefg"); + + // Identity. + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), a.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), b.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(c.ptr(), c.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), d)); + ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), d)); + ASSERT_TRUE(equalIgnoringASCIICase(c.ptr(), d)); + + // Transitivity. + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), b.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), c.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), c.ptr())); + + // Negative cases. + ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), empty.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), empty.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(c.ptr(), empty.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), shorter.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), shorter.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(c.ptr(), shorter.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), different.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), different.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(c.ptr(), different.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(empty.ptr(), d)); + ASSERT_FALSE(equalIgnoringASCIICase(shorter.ptr(), d)); + ASSERT_FALSE(equalIgnoringASCIICase(different.ptr(), d)); +} + +TEST(WTF, StringImplEqualIgnoringASCIICaseWithNull) +{ + auto reference = StringImpl::createFromLiteral("aBcDeFG"); + StringImpl* nullStringImpl = nullptr; + ASSERT_FALSE(equalIgnoringASCIICase(nullStringImpl, reference.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(reference.ptr(), nullStringImpl)); + ASSERT_TRUE(equalIgnoringASCIICase(nullStringImpl, nullStringImpl)); +} + +TEST(WTF, StringImplEqualIgnoringASCIICaseWithEmpty) +{ + auto a = StringImpl::create(reinterpret_cast<const LChar*>("")); + auto b = StringImpl::create(reinterpret_cast<const LChar*>("")); + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), b.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), a.ptr())); +} + +static Ref<StringImpl> stringFromUTF8(const char* characters) +{ + return String::fromUTF8(characters).releaseImpl().releaseNonNull(); +} + +TEST(WTF, StringImplEqualIgnoringASCIICaseWithLatin1Characters) +{ + auto a = stringFromUTF8("aBcéeFG"); + auto b = stringFromUTF8("ABCÉEFG"); + auto c = stringFromUTF8("ABCéEFG"); + auto d = stringFromUTF8("abcéefg"); + const char e[] = "aBcéeFG"; + + // Identity. + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), a.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), b.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(c.ptr(), c.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(d.ptr(), d.ptr())); + + // All combination. + ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), b.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), c.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), d.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), c.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), d.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(c.ptr(), d.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), e)); + ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), e)); + ASSERT_FALSE(equalIgnoringASCIICase(c.ptr(), e)); + ASSERT_FALSE(equalIgnoringASCIICase(d.ptr(), e)); +} + +TEST(WTF, StringImplFindIgnoringASCIICaseBasic) +{ + auto referenceA = stringFromUTF8("aBcéeFG"); + auto referenceB = stringFromUTF8("ABCÉEFG"); + + // Search the exact string. + EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(referenceA.ptr())); + EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(referenceB.ptr())); + + // A and B are distinct by the non-ascii character é/É. + EXPECT_EQ(static_cast<size_t>(notFound), referenceA->findIgnoringASCIICase(referenceB.ptr())); + EXPECT_EQ(static_cast<size_t>(notFound), referenceB->findIgnoringASCIICase(referenceA.ptr())); + + // Find the prefix. + EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("a").ptr())); + EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(stringFromUTF8("abcé").ptr())); + EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("A").ptr())); + EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr())); + EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("a").ptr())); + EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(stringFromUTF8("abcÉ").ptr())); + EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("A").ptr())); + EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr())); + + // Not a prefix. + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("x").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("accé").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("abcÉ").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("X").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ABDé").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("y").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("accÉ").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("abcé").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("Y").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ABdÉ").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr())); + + // Find the infix. + EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("cée").ptr())); + EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("ée").ptr())); + EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("cé").ptr())); + EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("c").ptr())); + EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("é").ptr())); + EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("Cée").ptr())); + EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éE").ptr())); + EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("Cé").ptr())); + EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("C").ptr())); + + EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("cÉe").ptr())); + EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("Ée").ptr())); + EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("cÉ").ptr())); + EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("c").ptr())); + EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("É").ptr())); + EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("CÉe").ptr())); + EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("ÉE").ptr())); + EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("CÉ").ptr())); + EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("C").ptr())); + + // Not an infix. + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("céd").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Ée").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("bé").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("x").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("É").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("CÉe").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("éd").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("CÉ").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Y").ptr())); + + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("cée").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("Éc").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("cé").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("W").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("é").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("bÉe").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éE").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("BÉ").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("z").ptr())); + + // Find the suffix. + EXPECT_EQ(static_cast<size_t>(6), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("g").ptr())); + EXPECT_EQ(static_cast<size_t>(4), referenceA->findIgnoringASCIICase(stringFromUTF8("efg").ptr())); + EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éefg").ptr())); + EXPECT_EQ(static_cast<size_t>(6), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("G").ptr())); + EXPECT_EQ(static_cast<size_t>(4), referenceA->findIgnoringASCIICase(stringFromUTF8("EFG").ptr())); + EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éEFG").ptr())); + + EXPECT_EQ(static_cast<size_t>(6), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("g").ptr())); + EXPECT_EQ(static_cast<size_t>(4), referenceB->findIgnoringASCIICase(stringFromUTF8("efg").ptr())); + EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("Éefg").ptr())); + EXPECT_EQ(static_cast<size_t>(6), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("G").ptr())); + EXPECT_EQ(static_cast<size_t>(4), referenceB->findIgnoringASCIICase(stringFromUTF8("EFG").ptr())); + EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("ÉEFG").ptr())); + + // Not a suffix. + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("X").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("edg").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Éefg").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("w").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("dFG").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ÉEFG").ptr())); + + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("Z").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ffg").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éefg").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("r").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("EgG").ptr())); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éEFG").ptr())); +} + +TEST(WTF, StringImplFindIgnoringASCIICaseWithValidOffset) +{ + auto reference = stringFromUTF8("ABCÉEFGaBcéeFG"); + EXPECT_EQ(static_cast<size_t>(0), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 0)); + EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 1)); + EXPECT_EQ(static_cast<size_t>(0), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 0)); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 1)); + EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr(), 0)); + EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr(), 1)); +} + +TEST(WTF, StringImplFindIgnoringASCIICaseWithInvalidOffset) +{ + auto reference = stringFromUTF8("ABCÉEFGaBcéeFG"); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 15)); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 16)); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 17)); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 42)); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), std::numeric_limits<unsigned>::max())); +} + +TEST(WTF, StringImplFindIgnoringASCIICaseOnNull) +{ + auto reference = stringFromUTF8("ABCÉEFG"); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr)); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 0)); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 3)); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 7)); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 8)); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 42)); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, std::numeric_limits<unsigned>::max())); +} + +TEST(WTF, StringImplFindIgnoringASCIICaseOnEmpty) +{ + auto reference = stringFromUTF8("ABCÉEFG"); + auto empty = StringImpl::create(reinterpret_cast<const LChar*>("")); + EXPECT_EQ(static_cast<size_t>(0), reference->findIgnoringASCIICase(empty.ptr())); + EXPECT_EQ(static_cast<size_t>(0), reference->findIgnoringASCIICase(empty.ptr(), 0)); + EXPECT_EQ(static_cast<size_t>(3), reference->findIgnoringASCIICase(empty.ptr(), 3)); + EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(empty.ptr(), 7)); + EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(empty.ptr(), 8)); + EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(empty.ptr(), 42)); + EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(empty.ptr(), std::numeric_limits<unsigned>::max())); +} + +TEST(WTF, StringImplFindIgnoringASCIICaseWithPatternLongerThanReference) +{ + auto reference = stringFromUTF8("ABCÉEFG"); + auto pattern = stringFromUTF8("XABCÉEFG"); + EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(pattern.ptr())); + EXPECT_EQ(static_cast<size_t>(1), pattern->findIgnoringASCIICase(reference.ptr())); +} + +TEST(WTF, StringImplStartsWithIgnoringASCIICaseBasic) +{ + auto reference = stringFromUTF8("aBcéX"); + auto referenceEquivalent = stringFromUTF8("AbCéx"); + + // Identity. + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(reference.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*reference.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(referenceEquivalent.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*referenceEquivalent.ptr())); + ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(reference.ptr())); + ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(*reference.ptr())); + ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(referenceEquivalent.ptr())); + ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(*referenceEquivalent.ptr())); + + // Proper prefixes. + auto aLower = StringImpl::createFromLiteral("a"); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(aLower.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*aLower.ptr())); + auto aUpper = StringImpl::createFromLiteral("A"); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(aUpper.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*aUpper.ptr())); + + auto abcLower = StringImpl::createFromLiteral("abc"); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcLower.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcLower.ptr())); + auto abcUpper = StringImpl::createFromLiteral("ABC"); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcUpper.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcUpper.ptr())); + + auto abcAccentLower = stringFromUTF8("abcé"); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcAccentLower.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcAccentLower.ptr())); + auto abcAccentUpper = stringFromUTF8("ABCé"); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcAccentUpper.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcAccentUpper.ptr())); + + // Negative cases. + auto differentFirstChar = stringFromUTF8("bBcéX"); + auto differentFirstCharProperPrefix = stringFromUTF8("CBcé"); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(differentFirstChar.ptr())); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*differentFirstChar.ptr())); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(differentFirstCharProperPrefix.ptr())); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*differentFirstCharProperPrefix.ptr())); + + auto uppercaseAccent = stringFromUTF8("aBcÉX"); + auto uppercaseAccentProperPrefix = stringFromUTF8("aBcÉX"); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(uppercaseAccent.ptr())); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*uppercaseAccent.ptr())); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(uppercaseAccentProperPrefix.ptr())); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*uppercaseAccentProperPrefix.ptr())); +} + +TEST(WTF, StringImplStartsWithIgnoringASCIICaseWithNull) +{ + auto reference = StringImpl::createFromLiteral("aBcDeFG"); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(nullptr)); + + auto empty = StringImpl::create(reinterpret_cast<const LChar*>("")); + ASSERT_FALSE(empty->startsWithIgnoringASCIICase(nullptr)); +} + +TEST(WTF, StringImplStartsWithIgnoringASCIICaseWithEmpty) +{ + auto reference = StringImpl::createFromLiteral("aBcDeFG"); + auto empty = StringImpl::create(reinterpret_cast<const LChar*>("")); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(empty.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*empty.ptr())); + ASSERT_TRUE(empty->startsWithIgnoringASCIICase(empty.ptr())); + ASSERT_TRUE(empty->startsWithIgnoringASCIICase(*empty.ptr())); + ASSERT_FALSE(empty->startsWithIgnoringASCIICase(reference.ptr())); + ASSERT_FALSE(empty->startsWithIgnoringASCIICase(*reference.ptr())); +} + +TEST(WTF, StartsWithLettersIgnoringASCIICase) +{ + String string("Test tEST"); + ASSERT_TRUE(startsWithLettersIgnoringASCIICase(string, "test t")); + ASSERT_TRUE(startsWithLettersIgnoringASCIICase(string, "test te")); + ASSERT_TRUE(startsWithLettersIgnoringASCIICase(string, "test test")); + ASSERT_FALSE(startsWithLettersIgnoringASCIICase(string, "test tex")); + + ASSERT_TRUE(startsWithLettersIgnoringASCIICase(string, "")); + ASSERT_TRUE(startsWithLettersIgnoringASCIICase(String(""), "")); + + ASSERT_FALSE(startsWithLettersIgnoringASCIICase(String(), "t")); + ASSERT_FALSE(startsWithLettersIgnoringASCIICase(String(), "")); +} + +TEST(WTF, StringImplEndsWithIgnoringASCIICaseBasic) +{ + auto reference = stringFromUTF8("XÉCbA"); + auto referenceEquivalent = stringFromUTF8("xÉcBa"); + + // Identity. + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(reference.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*reference.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(referenceEquivalent.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*referenceEquivalent.ptr())); + ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(reference.ptr())); + ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(*reference.ptr())); + ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(referenceEquivalent.ptr())); + ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(*referenceEquivalent.ptr())); + + // Proper suffixes. + auto aLower = StringImpl::createFromLiteral("a"); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(aLower.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*aLower.ptr())); + auto aUpper = StringImpl::createFromLiteral("a"); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(aUpper.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*aUpper.ptr())); + + auto abcLower = StringImpl::createFromLiteral("cba"); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcLower.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcLower.ptr())); + auto abcUpper = StringImpl::createFromLiteral("CBA"); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcUpper.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcUpper.ptr())); + + auto abcAccentLower = stringFromUTF8("Écba"); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcAccentLower.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcAccentLower.ptr())); + auto abcAccentUpper = stringFromUTF8("ÉCBA"); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcAccentUpper.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcAccentUpper.ptr())); + + // Negative cases. + auto differentLastChar = stringFromUTF8("XÉCbB"); + auto differentLastCharProperSuffix = stringFromUTF8("ÉCbb"); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(differentLastChar.ptr())); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*differentLastChar.ptr())); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(differentLastCharProperSuffix.ptr())); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*differentLastCharProperSuffix.ptr())); + + auto lowercaseAccent = stringFromUTF8("aBcéX"); + auto loweraseAccentProperSuffix = stringFromUTF8("aBcéX"); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(lowercaseAccent.ptr())); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*lowercaseAccent.ptr())); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(loweraseAccentProperSuffix.ptr())); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*loweraseAccentProperSuffix.ptr())); +} + +TEST(WTF, StringImplEndsWithIgnoringASCIICaseWithNull) +{ + auto reference = StringImpl::createFromLiteral("aBcDeFG"); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(nullptr)); + + auto empty = StringImpl::create(reinterpret_cast<const LChar*>("")); + ASSERT_FALSE(empty->endsWithIgnoringASCIICase(nullptr)); +} + +TEST(WTF, StringImplEndsWithIgnoringASCIICaseWithEmpty) +{ + auto reference = StringImpl::createFromLiteral("aBcDeFG"); + auto empty = StringImpl::create(reinterpret_cast<const LChar*>("")); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(empty.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*empty.ptr())); + ASSERT_TRUE(empty->endsWithIgnoringASCIICase(empty.ptr())); + ASSERT_TRUE(empty->endsWithIgnoringASCIICase(*empty.ptr())); + ASSERT_FALSE(empty->endsWithIgnoringASCIICase(reference.ptr())); + ASSERT_FALSE(empty->endsWithIgnoringASCIICase(*reference.ptr())); +} + +TEST(WTF, StringImplCreateNullSymbol) +{ + auto reference = SymbolImpl::createNullSymbol(); + ASSERT_TRUE(reference->isSymbol()); + ASSERT_TRUE(reference->isNullSymbol()); + ASSERT_FALSE(reference->isAtomic()); + ASSERT_EQ(0u, reference->length()); + ASSERT_TRUE(equal(reference.ptr(), "")); +} + +TEST(WTF, StringImplCreateSymbol) +{ + auto original = stringFromUTF8("original"); + auto reference = SymbolImpl::create(original); + ASSERT_TRUE(reference->isSymbol()); + ASSERT_FALSE(reference->isNullSymbol()); + ASSERT_FALSE(reference->isAtomic()); + ASSERT_FALSE(original->isSymbol()); + ASSERT_FALSE(original->isAtomic()); + ASSERT_EQ(original->length(), reference->length()); + ASSERT_TRUE(equal(reference.ptr(), "original")); + + auto empty = stringFromUTF8(""); + auto emptyReference = SymbolImpl::create(empty); + ASSERT_TRUE(emptyReference->isSymbol()); + ASSERT_FALSE(emptyReference->isNullSymbol()); + ASSERT_FALSE(emptyReference->isAtomic()); + ASSERT_FALSE(empty->isSymbol()); + ASSERT_TRUE(empty->isAtomic()); + ASSERT_EQ(empty->length(), emptyReference->length()); + ASSERT_TRUE(equal(emptyReference.ptr(), "")); +} + +TEST(WTF, StringImplSymbolToAtomicString) +{ + auto original = stringFromUTF8("original"); + auto reference = SymbolImpl::create(original); + ASSERT_TRUE(reference->isSymbol()); + ASSERT_FALSE(reference->isAtomic()); + + auto result = AtomicStringImpl::lookUp(reference.ptr()); + ASSERT_FALSE(result); + + auto atomic = AtomicStringImpl::add(reference.ptr()); + ASSERT_TRUE(atomic->isAtomic()); + ASSERT_FALSE(atomic->isSymbol()); + ASSERT_TRUE(reference->isSymbol()); + ASSERT_FALSE(reference->isAtomic()); + + auto result2 = AtomicStringImpl::lookUp(reference.ptr()); + ASSERT_TRUE(result2); +} + +TEST(WTF, StringImplNullSymbolToAtomicString) +{ + auto reference = SymbolImpl::createNullSymbol(); + ASSERT_TRUE(reference->isSymbol()); + ASSERT_FALSE(reference->isAtomic()); + + // Because the substring of the reference is the empty string which is already interned. + auto result = AtomicStringImpl::lookUp(reference.ptr()); + ASSERT_TRUE(result); + + auto atomic = AtomicStringImpl::add(reference.ptr()); + ASSERT_TRUE(atomic->isAtomic()); + ASSERT_FALSE(atomic->isSymbol()); + ASSERT_TRUE(reference->isSymbol()); + ASSERT_FALSE(reference->isAtomic()); + ASSERT_EQ(atomic.get(), StringImpl::empty()); + + auto result2 = AtomicStringImpl::lookUp(reference.ptr()); + ASSERT_TRUE(result2); +} + +static StringImpl::StaticStringImpl staticString {"Cocoa"}; + +TEST(WTF, StringImplStaticToAtomicString) +{ + StringImpl& original = staticString; + ASSERT_FALSE(original.isSymbol()); + ASSERT_FALSE(original.isAtomic()); + ASSERT_TRUE(original.isStatic()); + + auto result = AtomicStringImpl::lookUp(&original); + ASSERT_FALSE(result); + + auto atomic = AtomicStringImpl::add(&original); + ASSERT_TRUE(atomic->isAtomic()); + ASSERT_FALSE(atomic->isSymbol()); + ASSERT_FALSE(atomic->isStatic()); + ASSERT_FALSE(original.isSymbol()); + ASSERT_FALSE(original.isAtomic()); + ASSERT_TRUE(original.isStatic()); + + auto result2 = AtomicStringImpl::lookUp(&original); + ASSERT_TRUE(result2); +} + +TEST(WTF, StringImplConstexprHasher) +{ + ASSERT_EQ(stringFromUTF8("")->hash(), StringHasher::computeLiteralHashAndMaskTop8Bits("")); + ASSERT_EQ(stringFromUTF8("A")->hash(), StringHasher::computeLiteralHashAndMaskTop8Bits("A")); + ASSERT_EQ(stringFromUTF8("AA")->hash(), StringHasher::computeLiteralHashAndMaskTop8Bits("AA")); + ASSERT_EQ(stringFromUTF8("Cocoa")->hash(), StringHasher::computeLiteralHashAndMaskTop8Bits("Cocoa")); + ASSERT_EQ(stringFromUTF8("Cappuccino")->hash(), StringHasher::computeLiteralHashAndMaskTop8Bits("Cappuccino")); +} + +TEST(WTF, StringImplEmpty) +{ + ASSERT_FALSE(StringImpl::empty()->length()); +} + } // namespace TestWebKitAPI |