blob: 92119624c91b3d2a8a5f2b6a158d3a736dabe294 [file] [log] [blame] [edit]
/*
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <wtf/text/StringBuilder.h>
#include <wtf/text/StringView.h>
namespace TestWebKitAPI {
StringView stringViewFromLiteral(const char* characters)
{
return StringView::fromLatin1(characters);
}
StringView stringViewFromUTF8(String& ref, const char* characters)
{
ref = String::fromUTF8(characters);
return ref;
}
TEST(WTF, StringViewStartsWithEmptyVsNull)
{
StringView nullView;
StringView emptyView = emptyStringView();
String stringWithCharacters("hello"_s);
StringView viewWithCharacters(stringWithCharacters);
EXPECT_TRUE(viewWithCharacters.startsWith(nullView));
EXPECT_TRUE(viewWithCharacters.startsWith(emptyView));
}
TEST(WTF, StringViewEmptyVsNull)
{
StringView nullView;
EXPECT_TRUE(nullView.isNull());
EXPECT_TRUE(nullView.isEmpty());
// Test in a boolean context to test operator bool().
if (nullView)
FAIL();
else
SUCCEED();
if (!nullView)
SUCCEED();
else
FAIL();
StringView emptyView = emptyStringView();
EXPECT_FALSE(emptyView.isNull());
EXPECT_TRUE(emptyView.isEmpty());
// Test in a boolean context to test operator bool().
if (emptyView)
SUCCEED();
else
FAIL();
if (!emptyView)
FAIL();
else
SUCCEED();
String string { "hello"_s };
StringView viewWithCharacters(string);
EXPECT_FALSE(viewWithCharacters.isNull());
EXPECT_FALSE(viewWithCharacters.isEmpty());
// Test in a boolean context to test operator bool().
if (viewWithCharacters)
SUCCEED();
else
FAIL();
if (!viewWithCharacters)
FAIL();
else
SUCCEED();
}
bool compareLoopIterations(StringView::GraphemeClusters graphemeClusters, std::vector<StringView> expected)
{
std::vector<StringView> actual;
for (auto graphemeCluster : graphemeClusters)
actual.push_back(graphemeCluster);
return actual == expected;
}
bool compareLoopIterations(StringView::CodePoints codePoints, std::vector<char32_t> expected)
{
std::vector<char32_t> actual;
for (auto codePoint : codePoints)
actual.push_back(codePoint);
return actual == expected;
}
static bool compareLoopIterations(StringView::CodeUnits codeUnits, std::vector<char16_t> expected)
{
std::vector<char16_t> actual;
for (auto codeUnit : codeUnits)
actual.push_back(codeUnit);
return actual == expected;
}
static void build(StringBuilder& builder, std::vector<char16_t> input)
{
builder.clear();
for (auto codeUnit : input)
builder.append(codeUnit);
}
TEST(WTF, StringViewIterators)
{
EXPECT_TRUE(compareLoopIterations(StringView().codePoints(), { }));
EXPECT_TRUE(compareLoopIterations(StringView().codeUnits(), { }));
EXPECT_TRUE(compareLoopIterations(StringView().graphemeClusters(), { }));
EXPECT_TRUE(compareLoopIterations(emptyStringView().codePoints(), { }));
EXPECT_TRUE(compareLoopIterations(emptyStringView().codeUnits(), { }));
EXPECT_TRUE(compareLoopIterations(emptyStringView().graphemeClusters(), { }));
String helo("helo"_s);
StringView heloView(helo);
auto codePoints = heloView.codePoints();
auto codePointsIterator = codePoints.begin();
EXPECT_EQ(*codePointsIterator, U'h');
++codePointsIterator;
++codePointsIterator;
EXPECT_EQ(*codePointsIterator, U'l');
auto savedIterator = codePointsIterator;
codePointsIterator = codePoints.begin();
EXPECT_EQ(*codePointsIterator, U'h');
codePointsIterator = savedIterator;
EXPECT_EQ(*codePointsIterator, U'l');
String webkit("webkit"_s);
auto webkitCodePoints = StringView(webkit).codePoints();
codePointsIterator = webkitCodePoints.begin();
++codePointsIterator;
++codePointsIterator;
EXPECT_EQ(*codePointsIterator, U'b');
while (codePointsIterator != webkitCodePoints.end())
++codePointsIterator;
EXPECT_TRUE(compareLoopIterations(heloView.codePoints(), {'h', 'e', 'l', 'o'}));
EXPECT_TRUE(compareLoopIterations(heloView.codeUnits(), {'h', 'e', 'l', 'o'}));
EXPECT_TRUE(compareLoopIterations(heloView.graphemeClusters(), {
StringView(heloView.span8().subspan(0, 1)),
StringView(heloView.span8().subspan(1, 1)),
StringView(heloView.span8().subspan(2, 1)),
StringView(heloView.span8().subspan(3, 1)) }));
StringBuilder b;
build(b, {0xD800, 0xDD55}); // Surrogates for unicode code point U+10155
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0x10155}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xD800, 0xDD55}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.toString())}));
build(b, {0xD800}); // Leading surrogate only
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0xD800}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xD800}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.toString())}));
build(b, {0xD800, 0xD801}); // Two leading surrogates
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0xD800, 0xD801}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xD800, 0xD801}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), { StringView(b.span<char16_t>().subspan(0, 1)), StringView(b.span<char16_t>().subspan(1, 1)) }));
build(b, {0xDD55}); // Trailing surrogate only
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0xDD55}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xDD55}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), { StringView(b.toString()) }));
build(b, {0xD800, 'h'}); // Leading surrogate followed by non-surrogate
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0xD800, 'h'}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xD800, 'h'}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), { StringView(b.span<char16_t>().subspan(0, 1)), StringView(b.span<char16_t>().subspan(1, 1)) }));
build(b, {0x0306}); // "COMBINING BREVE"
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0x0306}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0x0306}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), { StringView(b.toString()) }));
build(b, {0x0306, 0xD800, 0xDD55, 'h', 'e', 'l', 'o'}); // Mix of single code unit and multi code unit code points
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0x0306, 0x10155, 'h', 'e', 'l', 'o'}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0x0306, 0xD800, 0xDD55, 'h', 'e', 'l', 'o'}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {
StringView(b.span<char16_t>().subspan(0, 1)),
StringView(b.span<char16_t>().subspan(1, 2)),
StringView(b.span<char16_t>().subspan(3, 1)),
StringView(b.span<char16_t>().subspan(4, 1)),
StringView(b.span<char16_t>().subspan(5, 1)),
StringView(b.span<char16_t>().subspan(6, 1)) }));
build(b, {'e', 0x0301}); // "COMBINING ACUTE"
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {'e', 0x0301}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {'e', 0x0301}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.toString())}));
build(b, {'e', 0x0301, 0x0306, 'a'}); // "COMBINING ACUTE" "COMBINING BREVE"
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {'e', 0x0301, 0x0306, 'a'}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {'e', 0x0301, 0x0306, 'a'}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {
StringView(b.span<char16_t>().subspan(0, 3)),
StringView(b.span<char16_t>().subspan(3, 1)),
}));
build(b, {0x1112, 0x116f, 0x11b6, 0x1107, 0x1161, 0x11B8}); // Korean combining Jamo
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0x1112, 0x116f, 0x11b6, 0x1107, 0x1161, 0x11B8}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0x1112, 0x116f, 0x11b6, 0x1107, 0x1161, 0x11B8}));
EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {
StringView(b.span<char16_t>().subspan(0, 3)),
StringView(b.span<char16_t>().subspan(3, 3)) }));
}
static Vector<String> vectorFromSplitResult(const StringView::SplitResult& substrings)
{
Vector<String> result;
for (StringView substring : substrings)
result.append(substring.toString());
return result;
}
TEST(WTF, StringViewSplitEmptyAndNullStrings)
{
StringView a = emptyString();
auto splitResult = a.split('b');
EXPECT_TRUE(splitResult.begin() == splitResult.end());
a = { String { } };
splitResult = a.split('b');
EXPECT_TRUE(splitResult.begin() == splitResult.end());
a = { };
splitResult = a.split('b');
EXPECT_TRUE(splitResult.begin() == splitResult.end());
}
TEST(WTF, StringViewSplitBasic)
{
String referenceHolder;
StringView a = stringViewFromUTF8(referenceHolder, "This is a sentence.");
// Simple
Vector<String> actual = vectorFromSplitResult(a.split('T'));
Vector<String> expected({ "his is a sentence."_s });
ASSERT_EQ(expected.size(), actual.size());
for (size_t i = 0; i < actual.size(); ++i)
EXPECT_STREQ(expected[i].utf8().data(), actual[i].utf8().data()) << "Vectors differ at index " << i;
actual = vectorFromSplitResult(a.split('.'));
expected = { "This is a sentence"_s };
ASSERT_EQ(expected.size(), actual.size());
for (size_t i = 0; i < actual.size(); ++i)
EXPECT_STREQ(expected[i].utf8().data(), actual[i].utf8().data()) << "Vectors differ at index " << i;
actual = vectorFromSplitResult(a.split('a'));
expected = { "This is "_s, " sentence."_s };
ASSERT_EQ(expected.size(), actual.size());
for (size_t i = 0; i < actual.size(); ++i)
EXPECT_STREQ(expected[i].utf8().data(), actual[i].utf8().data()) << "Vectors differ at index " << i;
actual = vectorFromSplitResult(a.split(' '));
expected = { "This"_s, "is"_s, "a"_s, "sentence."_s };
ASSERT_EQ(expected.size(), actual.size());
for (size_t i = 0; i < actual.size(); ++i)
EXPECT_STREQ(expected[i].utf8().data(), actual[i].utf8().data()) << "Vectors differ at index " << i;
// Non-existent separator
actual = vectorFromSplitResult(a.split('z'));
expected = { "This is a sentence."_s };
ASSERT_EQ(expected.size(), actual.size());
for (size_t i = 0; i < actual.size(); ++i)
EXPECT_STREQ(expected[i].utf8().data(), actual[i].utf8().data()) << "Vectors differ at index " << i;
}
TEST(WTF, StringViewSplitWithConsecutiveSeparators)
{
String referenceHolder;
StringView a = stringViewFromUTF8(referenceHolder, " This is a sentence. ");
Vector<String> actual = vectorFromSplitResult(a.split(' '));
Vector<String> expected({ "This"_s, "is"_s, "a"_s, "sentence."_s });
ASSERT_EQ(expected.size(), actual.size());
for (size_t i = 0; i < actual.size(); ++i)
EXPECT_STREQ(expected[i].utf8().data(), actual[i].utf8().data()) << "Vectors differ at index " << i;
actual = vectorFromSplitResult(a.splitAllowingEmptyEntries(' '));
expected = { ""_s, "This"_s, ""_s, ""_s, ""_s, ""_s, "is"_s, ""_s, "a"_s, ""_s, ""_s, ""_s, ""_s, ""_s, ""_s, "sentence."_s, ""_s };
ASSERT_EQ(expected.size(), actual.size());
for (size_t i = 0; i < actual.size(); ++i)
EXPECT_STREQ(expected[i].utf8().data(), actual[i].utf8().data()) << "Vectors differ at index " << i;
}
TEST(WTF, StringViewEqualBasic)
{
String referenceHolder;
StringView a = stringViewFromUTF8(referenceHolder, "Hello World!");
EXPECT_TRUE(a == "Hello World!"_s);
EXPECT_FALSE(a == "Hello World"_s);
EXPECT_FALSE(a == "Hello World!!"_s);
auto test = "Hell\0";
a = StringView { std::span { (const Latin1Character*)test, 5 } };
EXPECT_FALSE(a == "Hell\0"_s);
EXPECT_FALSE(a == "Hell"_s);
StringView test3 = "Hello"_s;
EXPECT_TRUE(test3 == "Hello\0"_s);
EXPECT_TRUE(test3 == "Hello"_s);
}
TEST(WTF, StringViewEqualIgnoringASCIICaseBasic)
{
RefPtr<StringImpl> a = StringImpl::create("aBcDeFG"_s);
RefPtr<StringImpl> b = StringImpl::create("ABCDEFG"_s);
RefPtr<StringImpl> c = StringImpl::create("abcdefg"_s);
constexpr auto d = "aBcDeFG"_s;
RefPtr<StringImpl> empty = StringImpl::create(""_span);
RefPtr<StringImpl> shorter = StringImpl::create("abcdef"_s);
RefPtr<StringImpl> different = StringImpl::create("abcrefg"_s);
StringView stringViewA(*a.get());
StringView stringViewB(*b.get());
StringView stringViewC(*c.get());
StringView emptyStringView(*empty.get());
StringView shorterStringView(*shorter.get());
StringView differentStringView(*different.get());
ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewB));
ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewC));
ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewC));
ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, d));
ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, d));
ASSERT_TRUE(equalIgnoringASCIICase(stringViewC, d));
// Identity.
ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewA));
ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewB));
ASSERT_TRUE(equalIgnoringASCIICase(stringViewC, stringViewC));
// Transitivity.
ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewB));
ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewC));
ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewC));
// Negative cases.
ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, emptyStringView));
ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, emptyStringView));
ASSERT_FALSE(equalIgnoringASCIICase(stringViewC, emptyStringView));
ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, shorterStringView));
ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, shorterStringView));
ASSERT_FALSE(equalIgnoringASCIICase(stringViewC, shorterStringView));
ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, differentStringView));
ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, differentStringView));
ASSERT_FALSE(equalIgnoringASCIICase(stringViewC, differentStringView));
ASSERT_FALSE(equalIgnoringASCIICase(emptyStringView, d));
ASSERT_FALSE(equalIgnoringASCIICase(shorterStringView, d));
ASSERT_FALSE(equalIgnoringASCIICase(differentStringView, d));
}
TEST(WTF, StringViewEqualIgnoringASCIICaseWithEmpty)
{
RefPtr<StringImpl> a = StringImpl::create(""_span);
RefPtr<StringImpl> b = StringImpl::create(""_span);
StringView stringViewA(*a.get());
StringView stringViewB(*b.get());
ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewB));
ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewA));
}
TEST(WTF, StringViewEqualIgnoringASCIICaseWithLatin1Characters)
{
RefPtr<StringImpl> a = StringImpl::create(byteCast<Latin1Character>(std::span { "aBcéeFG", 7 }));
RefPtr<StringImpl> b = StringImpl::create(byteCast<Latin1Character>(std::span { "ABCÉEFG", 7 }));
RefPtr<StringImpl> c = StringImpl::create(byteCast<Latin1Character>(std::span { "ABCéEFG", 7 }));
RefPtr<StringImpl> d = StringImpl::create(byteCast<Latin1Character>(std::span { "abcéefg", 7 }));
StringView stringViewA(*a.get());
StringView stringViewB(*b.get());
StringView stringViewC(*c.get());
StringView stringViewD(*d.get());
// Identity.
ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewA));
ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewB));
ASSERT_TRUE(equalIgnoringASCIICase(stringViewC, stringViewC));
ASSERT_TRUE(equalIgnoringASCIICase(stringViewD, stringViewD));
// All combination.
ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, stringViewB));
ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewC));
ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewD));
ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, stringViewC));
ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, stringViewD));
ASSERT_TRUE(equalIgnoringASCIICase(stringViewC, stringViewD));
}
TEST(WTF, StringViewFindIgnoringASCIICaseBasic)
{
String referenceAHolder;
StringView referenceA = stringViewFromUTF8(referenceAHolder, "aBcéeFG");
String referenceBHolder;
StringView referenceB = stringViewFromUTF8(referenceBHolder, "ABCÉEFG");
// Search the exact string.
EXPECT_EQ(static_cast<size_t>(0), referenceA.findIgnoringASCIICase(referenceA));
EXPECT_EQ(static_cast<size_t>(0), referenceB.findIgnoringASCIICase(referenceB));
// A and B are distinct by the non-ascii character é/É.
EXPECT_EQ(static_cast<size_t>(notFound), referenceA.findIgnoringASCIICase(referenceB));
EXPECT_EQ(static_cast<size_t>(notFound), referenceB.findIgnoringASCIICase(referenceA));
String tempStringHolder;
// Find the prefix.
EXPECT_EQ(static_cast<size_t>(0), referenceA.findIgnoringASCIICase(stringViewFromLiteral("a")));
EXPECT_EQ(static_cast<size_t>(0), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "abcé")));
EXPECT_EQ(static_cast<size_t>(0), referenceA.findIgnoringASCIICase(stringViewFromLiteral("A")));
EXPECT_EQ(static_cast<size_t>(0), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCé")));
EXPECT_EQ(static_cast<size_t>(0), referenceB.findIgnoringASCIICase(stringViewFromLiteral("a")));
EXPECT_EQ(static_cast<size_t>(0), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "abcÉ")));
EXPECT_EQ(static_cast<size_t>(0), referenceB.findIgnoringASCIICase(stringViewFromLiteral("A")));
EXPECT_EQ(static_cast<size_t>(0), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ")));
// Not a prefix.
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromLiteral("x")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "accé")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "abcÉ")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromLiteral("X")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABDé")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromLiteral("y")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "accÉ")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "abcé")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromLiteral("Y")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABdÉ")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCé")));
// Find the infix.
EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cée")));
EXPECT_EQ(static_cast<size_t>(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ée")));
EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cé")));
EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "c")));
EXPECT_EQ(static_cast<size_t>(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "é")));
EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Cée")));
EXPECT_EQ(static_cast<size_t>(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éE")));
EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Cé")));
EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "C")));
EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cÉe")));
EXPECT_EQ(static_cast<size_t>(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Ée")));
EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cÉ")));
EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "c")));
EXPECT_EQ(static_cast<size_t>(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "É")));
EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "CÉe")));
EXPECT_EQ(static_cast<size_t>(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ÉE")));
EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "CÉ")));
EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "C")));
// Not an infix.
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "céd")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Ée")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "bé")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "x")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "É")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "CÉe")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éd")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "CÉ")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Y")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cée")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Éc")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cé")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "W")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "é")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "bÉe")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éE")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "BÉ")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "z")));
// Find the suffix.
EXPECT_EQ(static_cast<size_t>(6), referenceA.findIgnoringASCIICase(stringViewFromLiteral("g")));
EXPECT_EQ(static_cast<size_t>(4), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "efg")));
EXPECT_EQ(static_cast<size_t>(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éefg")));
EXPECT_EQ(static_cast<size_t>(6), referenceA.findIgnoringASCIICase(stringViewFromLiteral("G")));
EXPECT_EQ(static_cast<size_t>(4), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "EFG")));
EXPECT_EQ(static_cast<size_t>(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éEFG")));
EXPECT_EQ(static_cast<size_t>(6), referenceB.findIgnoringASCIICase(stringViewFromLiteral("g")));
EXPECT_EQ(static_cast<size_t>(4), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "efg")));
EXPECT_EQ(static_cast<size_t>(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Éefg")));
EXPECT_EQ(static_cast<size_t>(6), referenceB.findIgnoringASCIICase(stringViewFromLiteral("G")));
EXPECT_EQ(static_cast<size_t>(4), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "EFG")));
EXPECT_EQ(static_cast<size_t>(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ÉEFG")));
// Not a suffix.
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromLiteral("X")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "edg")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Éefg")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromLiteral("w")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "dFG")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ÉEFG")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromLiteral("Z")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ffg")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éefg")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromLiteral("r")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "EgG")));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éEFG")));
}
TEST(WTF, StringViewFindIgnoringASCIICaseWithValidOffset)
{
String referenceHolder;
StringView reference = stringViewFromUTF8(referenceHolder, "ABCÉEFGaBcéeFG");
String tempStringHolder;
EXPECT_EQ(static_cast<size_t>(0), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABC"), 0));
EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABC"), 1));
EXPECT_EQ(static_cast<size_t>(0), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), 0));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), 1));
EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCé"), 0));
EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCé"), 1));
}
TEST(WTF, StringViewFindIgnoringASCIICaseWithInvalidOffset)
{
String referenceHolder;
StringView reference = stringViewFromUTF8(referenceHolder, "ABCÉEFGaBcéeFG");
String tempStringHolder;
EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABC"), 15));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABC"), 16));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), 17));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), 42));
EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), std::numeric_limits<unsigned>::max()));
}
TEST(WTF, StringViewFindIgnoringASCIICaseOnEmpty)
{
String referenceHolder;
StringView reference = stringViewFromUTF8(referenceHolder, "ABCÉEFG");
StringView empty = stringViewFromLiteral("");
EXPECT_EQ(static_cast<size_t>(0), reference.findIgnoringASCIICase(empty));
EXPECT_EQ(static_cast<size_t>(0), reference.findIgnoringASCIICase(empty, 0));
EXPECT_EQ(static_cast<size_t>(3), reference.findIgnoringASCIICase(empty, 3));
EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(empty, 7));
EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(empty, 8));
EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(empty, 42));
EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(empty, std::numeric_limits<unsigned>::max()));
}
TEST(WTF, StringViewFindIgnoringASCIICaseWithPatternLongerThanReference)
{
String referenceHolder;
StringView reference = stringViewFromUTF8(referenceHolder, "ABCÉEFG");
String patternHolder;
StringView pattern = stringViewFromUTF8(patternHolder, "ABCÉEFGA");
EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(pattern));
EXPECT_EQ(static_cast<size_t>(0), pattern.findIgnoringASCIICase(reference));
}
TEST(WTF, StringViewStartsWithBasic)
{
StringView reference = stringViewFromLiteral("abcdefg");
String referenceUTF8Ref;
StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "àîûèô");
StringView oneLetterPrefix = stringViewFromLiteral("a");
StringView shortPrefix = stringViewFromLiteral("abc");
StringView longPrefix = stringViewFromLiteral("abcdef");
StringView upperCasePrefix = stringViewFromLiteral("ABC");
StringView empty = stringViewFromLiteral("");
StringView notPrefix = stringViewFromLiteral("bc");
String oneLetterPrefixUTF8Ref;
StringView oneLetterPrefixUTF8 = stringViewFromUTF8(oneLetterPrefixUTF8Ref, "à");
String shortPrefixUTF8Ref;
StringView shortPrefixUTF8 = stringViewFromUTF8(shortPrefixUTF8Ref, "àî");
String longPrefixUTF8Ref;
StringView longPrefixUTF8 = stringViewFromUTF8(longPrefixUTF8Ref, "àîûè");
String upperCasePrefixUTF8Ref;
StringView upperCasePrefixUTF8 = stringViewFromUTF8(upperCasePrefixUTF8Ref, "ÀÎ");
String notPrefixUTF8Ref;
StringView notPrefixUTF8 = stringViewFromUTF8(notPrefixUTF8Ref, "îû");
EXPECT_TRUE(reference.startsWith(reference));
EXPECT_TRUE(reference.startsWith(oneLetterPrefix));
EXPECT_TRUE(reference.startsWith(shortPrefix));
EXPECT_TRUE(reference.startsWith(longPrefix));
EXPECT_TRUE(reference.startsWith(empty));
EXPECT_TRUE(referenceUTF8.startsWith(referenceUTF8));
EXPECT_TRUE(referenceUTF8.startsWith(oneLetterPrefixUTF8));
EXPECT_TRUE(referenceUTF8.startsWith(shortPrefixUTF8));
EXPECT_TRUE(referenceUTF8.startsWith(longPrefixUTF8));
EXPECT_TRUE(referenceUTF8.startsWith(empty));
EXPECT_FALSE(reference.startsWith(notPrefix));
EXPECT_FALSE(reference.startsWith(upperCasePrefix));
EXPECT_FALSE(reference.startsWith(notPrefixUTF8));
EXPECT_FALSE(reference.startsWith(upperCasePrefixUTF8));
EXPECT_FALSE(referenceUTF8.startsWith(notPrefix));
EXPECT_FALSE(referenceUTF8.startsWith(upperCasePrefix));
EXPECT_FALSE(referenceUTF8.startsWith(notPrefixUTF8));
EXPECT_FALSE(referenceUTF8.startsWith(upperCasePrefixUTF8));
}
TEST(WTF, StringViewStartsWithEmpty)
{
StringView a = stringViewFromLiteral("");
String refB;
StringView b = stringViewFromUTF8(refB, "");
EXPECT_TRUE(a.startsWith(a));
EXPECT_TRUE(a.startsWith(b));
EXPECT_TRUE(b.startsWith(a));
EXPECT_TRUE(b.startsWith(b));
}
TEST(WTF, StringViewStartsWithIgnoringASCIICaseBasic)
{
StringView reference = stringViewFromLiteral("abcdefg");
String referenceUTF8Ref;
StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "àîûèô");
StringView oneLetterPrefix = stringViewFromLiteral("a");
StringView shortPrefix = stringViewFromLiteral("abc");
StringView longPrefix = stringViewFromLiteral("abcdef");
StringView upperCasePrefix = stringViewFromLiteral("ABC");
StringView mixedCasePrefix = stringViewFromLiteral("aBcDe");
StringView empty = stringViewFromLiteral("");
StringView notPrefix = stringViewFromLiteral("bc");
String oneLetterPrefixUTF8Ref;
StringView oneLetterPrefixUTF8 = stringViewFromUTF8(oneLetterPrefixUTF8Ref, "à");
String shortPrefixUTF8Ref;
StringView shortPrefixUTF8 = stringViewFromUTF8(shortPrefixUTF8Ref, "àî");
String longPrefixUTF8Ref;
StringView longPrefixUTF8 = stringViewFromUTF8(longPrefixUTF8Ref, "àîûè");
String upperCasePrefixUTF8Ref;
StringView upperCasePrefixUTF8 = stringViewFromUTF8(upperCasePrefixUTF8Ref, "ÀÎ");
String notPrefixUTF8Ref;
StringView notPrefixUTF8 = stringViewFromUTF8(notPrefixUTF8Ref, "îû");
EXPECT_TRUE(reference.startsWithIgnoringASCIICase(reference));
EXPECT_TRUE(reference.startsWithIgnoringASCIICase(oneLetterPrefix));
EXPECT_TRUE(reference.startsWithIgnoringASCIICase(shortPrefix));
EXPECT_TRUE(reference.startsWithIgnoringASCIICase(longPrefix));
EXPECT_TRUE(reference.startsWithIgnoringASCIICase(empty));
EXPECT_TRUE(reference.startsWithIgnoringASCIICase(upperCasePrefix));
EXPECT_TRUE(reference.startsWithIgnoringASCIICase(mixedCasePrefix));
EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(referenceUTF8));
EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(oneLetterPrefixUTF8));
EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(shortPrefixUTF8));
EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(longPrefixUTF8));
EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(empty));
EXPECT_FALSE(reference.startsWithIgnoringASCIICase(notPrefix));
EXPECT_FALSE(reference.startsWithIgnoringASCIICase(notPrefixUTF8));
EXPECT_FALSE(reference.startsWithIgnoringASCIICase(upperCasePrefixUTF8));
EXPECT_FALSE(referenceUTF8.startsWithIgnoringASCIICase(notPrefix));
EXPECT_FALSE(referenceUTF8.startsWithIgnoringASCIICase(notPrefixUTF8));
EXPECT_FALSE(referenceUTF8.startsWithIgnoringASCIICase(upperCasePrefix));
EXPECT_FALSE(referenceUTF8.startsWithIgnoringASCIICase(upperCasePrefixUTF8));
}
TEST(WTF, StringViewStartsWithIgnoringASCIICaseEmpty)
{
StringView a = stringViewFromLiteral("");
String refB;
StringView b = stringViewFromUTF8(refB, "");
EXPECT_TRUE(a.startsWithIgnoringASCIICase(a));
EXPECT_TRUE(a.startsWithIgnoringASCIICase(b));
EXPECT_TRUE(b.startsWithIgnoringASCIICase(a));
EXPECT_TRUE(b.startsWithIgnoringASCIICase(b));
}
TEST(WTF, StringViewStartsWithIgnoringASCIICaseWithLatin1Characters)
{
StringView reference = stringViewFromLiteral("aBcéeFG");
String referenceUTF8Ref;
StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "aBcéeFG");
StringView a = stringViewFromLiteral("aBcéeF");
StringView b = stringViewFromLiteral("ABCéEF");
StringView c = stringViewFromLiteral("abcéef");
StringView d = stringViewFromLiteral("Abcéef");
String refE;
StringView e = stringViewFromUTF8(refE, "aBcéeF");
String refF;
StringView f = stringViewFromUTF8(refF, "ABCéEF");
String refG;
StringView g = stringViewFromUTF8(refG, "abcéef");
String refH;
StringView h = stringViewFromUTF8(refH, "Abcéef");
EXPECT_TRUE(reference.startsWithIgnoringASCIICase(a));
EXPECT_TRUE(reference.startsWithIgnoringASCIICase(b));
EXPECT_TRUE(reference.startsWithIgnoringASCIICase(c));
EXPECT_TRUE(reference.startsWithIgnoringASCIICase(d));
EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(e));
EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(f));
EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(g));
EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(h));
EXPECT_FALSE(reference.endsWithIgnoringASCIICase(referenceUTF8));
EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(reference));
}
TEST(WTF, StringViewEndsWithBasic)
{
StringView reference = stringViewFromLiteral("abcdefg");
String referenceUTF8Ref;
StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "àîûèô");
StringView oneLetterSuffix = stringViewFromLiteral("g");
StringView shortSuffix = stringViewFromLiteral("efg");
StringView longSuffix = stringViewFromLiteral("cdefg");
StringView upperCaseSuffix = stringViewFromLiteral("EFG");
StringView empty = stringViewFromLiteral("");
StringView notSuffix = stringViewFromLiteral("bc");
String oneLetterSuffixUTF8Ref;
StringView oneLetterSuffixUTF8 = stringViewFromUTF8(oneLetterSuffixUTF8Ref, "ô");
String shortSuffixUTF8Ref;
StringView shortSuffixUTF8 = stringViewFromUTF8(shortSuffixUTF8Ref, "èô");
String longSuffixUTF8Ref;
StringView longSuffixUTF8 = stringViewFromUTF8(longSuffixUTF8Ref, "îûèô");
String upperCaseSuffixUTF8Ref;
StringView upperCaseSuffixUTF8 = stringViewFromUTF8(upperCaseSuffixUTF8Ref, "ÈÔ");
String notSuffixUTF8Ref;
StringView notSuffixUTF8 = stringViewFromUTF8(notSuffixUTF8Ref, "îû");
EXPECT_TRUE(reference.endsWith(reference));
EXPECT_TRUE(reference.endsWith(oneLetterSuffix));
EXPECT_TRUE(reference.endsWith(shortSuffix));
EXPECT_TRUE(reference.endsWith(longSuffix));
EXPECT_TRUE(reference.endsWith(empty));
EXPECT_TRUE(referenceUTF8.endsWith(referenceUTF8));
EXPECT_TRUE(referenceUTF8.endsWith(oneLetterSuffixUTF8));
EXPECT_TRUE(referenceUTF8.endsWith(shortSuffixUTF8));
EXPECT_TRUE(referenceUTF8.endsWith(longSuffixUTF8));
EXPECT_TRUE(referenceUTF8.endsWith(empty));
EXPECT_FALSE(reference.endsWith(notSuffix));
EXPECT_FALSE(reference.endsWith(upperCaseSuffix));
EXPECT_FALSE(reference.endsWith(notSuffixUTF8));
EXPECT_FALSE(reference.endsWith(upperCaseSuffixUTF8));
EXPECT_FALSE(referenceUTF8.endsWith(notSuffix));
EXPECT_FALSE(referenceUTF8.endsWith(upperCaseSuffix));
EXPECT_FALSE(referenceUTF8.endsWith(notSuffixUTF8));
EXPECT_FALSE(referenceUTF8.endsWith(upperCaseSuffixUTF8));
}
TEST(WTF, StringViewEndsWithEmpty)
{
StringView a = stringViewFromLiteral("");
String refB;
StringView b = stringViewFromUTF8(refB, "");
EXPECT_TRUE(a.endsWith(a));
EXPECT_TRUE(a.endsWith(b));
EXPECT_TRUE(b.endsWith(a));
EXPECT_TRUE(b.endsWith(b));
}
TEST(WTF, StringViewEndsWithIgnoringASCIICaseBasic)
{
StringView reference = stringViewFromLiteral("abcdefg");
String referenceUTF8Ref;
StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "àîûèô");
StringView oneLetterSuffix = stringViewFromLiteral("g");
StringView shortSuffix = stringViewFromLiteral("efg");
StringView longSuffix = stringViewFromLiteral("bcdefg");
StringView upperCaseSuffix = stringViewFromLiteral("EFG");
StringView mixedCaseSuffix = stringViewFromLiteral("bCdeFg");
StringView empty = stringViewFromLiteral("");
StringView notSuffix = stringViewFromLiteral("bc");
String oneLetterSuffixUTF8Ref;
StringView oneLetterSuffixUTF8 = stringViewFromUTF8(oneLetterSuffixUTF8Ref, "ô");
String shortSuffixUTF8Ref;
StringView shortSuffixUTF8 = stringViewFromUTF8(shortSuffixUTF8Ref, "èô");
String longSuffixUTF8Ref;
StringView longSuffixUTF8 = stringViewFromUTF8(longSuffixUTF8Ref, "îûèô");
String upperCaseSuffixUTF8Ref;
StringView upperCaseSuffixUTF8 = stringViewFromUTF8(upperCaseSuffixUTF8Ref, "ÈÔ");
String notSuffixUTF8Ref;
StringView notSuffixUTF8 = stringViewFromUTF8(notSuffixUTF8Ref, "îû");
EXPECT_TRUE(reference.endsWithIgnoringASCIICase(reference));
EXPECT_TRUE(reference.endsWithIgnoringASCIICase(oneLetterSuffix));
EXPECT_TRUE(reference.endsWithIgnoringASCIICase(shortSuffix));
EXPECT_TRUE(reference.endsWithIgnoringASCIICase(longSuffix));
EXPECT_TRUE(reference.endsWithIgnoringASCIICase(empty));
EXPECT_TRUE(reference.endsWithIgnoringASCIICase(upperCaseSuffix));
EXPECT_TRUE(reference.endsWithIgnoringASCIICase(mixedCaseSuffix));
EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(referenceUTF8));
EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(oneLetterSuffixUTF8));
EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(shortSuffixUTF8));
EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(longSuffixUTF8));
EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(empty));
EXPECT_FALSE(reference.endsWithIgnoringASCIICase(notSuffix));
EXPECT_FALSE(reference.endsWithIgnoringASCIICase(notSuffixUTF8));
EXPECT_FALSE(reference.endsWithIgnoringASCIICase(upperCaseSuffixUTF8));
EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(notSuffix));
EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(notSuffixUTF8));
EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(upperCaseSuffix));
EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(upperCaseSuffixUTF8));
}
TEST(WTF, StringViewEndsWithIgnoringASCIICaseEmpty)
{
StringView a = stringViewFromLiteral("");
String refB;
StringView b = stringViewFromUTF8(refB, "");
EXPECT_TRUE(a.endsWithIgnoringASCIICase(a));
EXPECT_TRUE(a.endsWithIgnoringASCIICase(b));
EXPECT_TRUE(b.endsWithIgnoringASCIICase(a));
EXPECT_TRUE(b.endsWithIgnoringASCIICase(b));
}
TEST(WTF, StringViewEndsWithIgnoringASCIICaseWithLatin1Characters)
{
StringView reference = stringViewFromLiteral("aBcéeFG");
String referenceUTF8Ref;
StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "aBcéeFG");
StringView a = stringViewFromLiteral("BcéeFG");
StringView b = stringViewFromLiteral("BCéEFG");
StringView c = stringViewFromLiteral("bcéefG");
StringView d = stringViewFromLiteral("bcéefg");
String refE;
StringView e = stringViewFromUTF8(refE, "bcéefG");
String refF;
StringView f = stringViewFromUTF8(refF, "BCéEFG");
String refG;
StringView g = stringViewFromUTF8(refG, "bcéefG");
String refH;
StringView h = stringViewFromUTF8(refH, "bcéefg");
EXPECT_TRUE(reference.endsWithIgnoringASCIICase(a));
EXPECT_TRUE(reference.endsWithIgnoringASCIICase(b));
EXPECT_TRUE(reference.endsWithIgnoringASCIICase(c));
EXPECT_TRUE(reference.endsWithIgnoringASCIICase(d));
EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(e));
EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(f));
EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(g));
EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(h));
EXPECT_FALSE(reference.endsWithIgnoringASCIICase(referenceUTF8));
EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(reference));
}
TEST(WTF, StringView8Bit)
{
EXPECT_TRUE(StringView().is8Bit());
EXPECT_TRUE(emptyStringView().is8Bit());
std::span<const Latin1Character> lcharSpan;
std::span<const char16_t> ucharSpan;
EXPECT_TRUE(StringView(lcharSpan).is8Bit());
EXPECT_FALSE(StringView(ucharSpan).is8Bit());
EXPECT_TRUE(StringView(String(lcharSpan)).is8Bit());
EXPECT_TRUE(StringView(String(ucharSpan)).is8Bit());
EXPECT_TRUE(StringView(String().impl()).is8Bit());
EXPECT_TRUE(StringView(emptyString().impl()).is8Bit());
}
TEST(WTF, StringViewRightBasic)
{
auto reference = stringViewFromLiteral("Cappuccino");
EXPECT_TRUE(reference.right(0) == stringViewFromLiteral(""));
EXPECT_TRUE(reference.right(1) == stringViewFromLiteral("o"));
EXPECT_TRUE(reference.right(2) == stringViewFromLiteral("no"));
EXPECT_TRUE(reference.right(3) == stringViewFromLiteral("ino"));
EXPECT_TRUE(reference.right(4) == stringViewFromLiteral("cino"));
EXPECT_TRUE(reference.right(5) == stringViewFromLiteral("ccino"));
EXPECT_TRUE(reference.right(6) == stringViewFromLiteral("uccino"));
EXPECT_TRUE(reference.right(7) == stringViewFromLiteral("puccino"));
EXPECT_TRUE(reference.right(8) == stringViewFromLiteral("ppuccino"));
EXPECT_TRUE(reference.right(9) == stringViewFromLiteral("appuccino"));
EXPECT_TRUE(reference.right(10) == stringViewFromLiteral("Cappuccino"));
}
TEST(WTF, StringViewLeftBasic)
{
auto reference = stringViewFromLiteral("Cappuccino");
EXPECT_TRUE(reference.left(0) == stringViewFromLiteral(""));
EXPECT_TRUE(reference.left(1) == stringViewFromLiteral("C"));
EXPECT_TRUE(reference.left(2) == stringViewFromLiteral("Ca"));
EXPECT_TRUE(reference.left(3) == stringViewFromLiteral("Cap"));
EXPECT_TRUE(reference.left(4) == stringViewFromLiteral("Capp"));
EXPECT_TRUE(reference.left(5) == stringViewFromLiteral("Cappu"));
EXPECT_TRUE(reference.left(6) == stringViewFromLiteral("Cappuc"));
EXPECT_TRUE(reference.left(7) == stringViewFromLiteral("Cappucc"));
EXPECT_TRUE(reference.left(8) == stringViewFromLiteral("Cappucci"));
EXPECT_TRUE(reference.left(9) == stringViewFromLiteral("Cappuccin"));
EXPECT_TRUE(reference.left(10) == stringViewFromLiteral("Cappuccino"));
}
TEST(WTF, StringViewReverseFindBasic)
{
auto reference = stringViewFromLiteral("Cappuccino");
EXPECT_EQ(reference.reverseFind('o'), 9U);
EXPECT_EQ(reference.reverseFind('n'), 8U);
EXPECT_EQ(reference.reverseFind('c'), 6U);
EXPECT_EQ(reference.reverseFind('p'), 3U);
EXPECT_EQ(reference.reverseFind('k'), notFound);
EXPECT_EQ(reference.reverseFind('o', 8), notFound);
EXPECT_EQ(reference.reverseFind('c', 8), 6U);
EXPECT_EQ(reference.reverseFind('c', 6), 6U);
EXPECT_EQ(reference.reverseFind('c', 5), 5U);
EXPECT_EQ(reference.reverseFind('c', 4), notFound);
}
TEST(WTF, StringViewTrim)
{
auto isA = [] (char16_t c) {
return c == 'A';
};
EXPECT_TRUE(stringViewFromLiteral("AAABBBAAA").trim(isA) == stringViewFromLiteral("BBB"));
EXPECT_TRUE(stringViewFromLiteral("AAABBBCCC").trim(isA) == stringViewFromLiteral("BBBCCC"));
EXPECT_TRUE(stringViewFromLiteral("CCCBBBAAA").trim(isA) == stringViewFromLiteral("CCCBBB"));
EXPECT_TRUE(stringViewFromLiteral("CCCBBBCCC").trim(isA) == stringViewFromLiteral("CCCBBBCCC"));
EXPECT_TRUE(stringViewFromLiteral("AAAAAACCC").trim(isA) == stringViewFromLiteral("CCC"));
EXPECT_TRUE(stringViewFromLiteral("BBBAAAAAA").trim(isA) == stringViewFromLiteral("BBB"));
EXPECT_TRUE(stringViewFromLiteral("CCCAAABBB").trim(isA) == stringViewFromLiteral("CCCAAABBB"));
EXPECT_TRUE(stringViewFromLiteral("AAAAAAAAA").trim(isA) == emptyStringView());
StringView emptyView = emptyStringView();
EXPECT_TRUE(emptyView.trim(isA) == emptyView);
StringView nullView;
EXPECT_TRUE(nullView.trim(isA) == nullView);
}
TEST(WTF, StringViewContainsOnlyASCII)
{
EXPECT_TRUE(StringView(String("Hello"_s)).containsOnlyASCII());
EXPECT_TRUE(StringView(String("Cocoa"_s)).containsOnlyASCII());
EXPECT_FALSE(StringView(String::fromLatin1("📱")).containsOnlyASCII());
EXPECT_FALSE(StringView(String::fromLatin1("\u0080")).containsOnlyASCII());
constexpr size_t zeroLength = 0;
EXPECT_TRUE(StringView(String({ reinterpret_cast<const char16_t*>(u"Hello"), zeroLength })).containsOnlyASCII());
}
TEST(WTF, StringViewUpconvert)
{
constexpr ASCIILiteral data[] = {
"Hello"_s,
"This is a relatively long string to use SIMD optimized path. We invoke our optimized copying only when the string length gets longer than 64."_s,
};
for (auto literal : data) {
StringView string(literal);
auto upconverted = string.upconvertedCharacters();
auto characters = upconverted.span();
for (unsigned index = 1; index < string.length(); ++index)
EXPECT_EQ(characters[index], string[index]) << index << " " << literal.characters();
}
}
} // namespace TestWebKitAPI