Leverage Substring to create new AtomicStringImpl for StaticStringImpl and SymbolImpl
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WTF / StringImpl.cpp
1 /*
2  * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #include <wtf/Hasher.h>
29 #include <wtf/text/SymbolImpl.h>
30 #include <wtf/text/WTFString.h>
31
32 namespace TestWebKitAPI {
33
34 TEST(WTF, StringImplCreationFromLiteral)
35 {
36     // Constructor using the template to determine the size.
37     auto stringWithTemplate = StringImpl::createFromLiteral("Template Literal");
38     ASSERT_EQ(strlen("Template Literal"), stringWithTemplate->length());
39     ASSERT_TRUE(equal(stringWithTemplate.get(), "Template Literal"));
40     ASSERT_TRUE(stringWithTemplate->is8Bit());
41
42     // Constructor taking the size explicitely.
43     const char* programmaticStringData = "Explicit Size Literal";
44     auto programmaticString = StringImpl::createFromLiteral(programmaticStringData, strlen(programmaticStringData));
45     ASSERT_EQ(strlen(programmaticStringData), programmaticString->length());
46     ASSERT_TRUE(equal(programmaticString.get(), programmaticStringData));
47     ASSERT_EQ(programmaticStringData, reinterpret_cast<const char*>(programmaticString->characters8()));
48     ASSERT_TRUE(programmaticString->is8Bit());
49
50     // Constructor without explicit size.
51     const char* stringWithoutLengthLiteral = "No Size Literal";
52     auto programmaticStringNoLength = StringImpl::createFromLiteral(stringWithoutLengthLiteral);
53     ASSERT_EQ(strlen(stringWithoutLengthLiteral), programmaticStringNoLength->length());
54     ASSERT_TRUE(equal(programmaticStringNoLength.get(), stringWithoutLengthLiteral));
55     ASSERT_EQ(stringWithoutLengthLiteral, reinterpret_cast<const char*>(programmaticStringNoLength->characters8()));
56     ASSERT_TRUE(programmaticStringNoLength->is8Bit());
57 }
58
59 TEST(WTF, StringImplReplaceWithLiteral)
60 {
61     auto testStringImpl = StringImpl::createFromLiteral("1224");
62     ASSERT_TRUE(testStringImpl->is8Bit());
63
64     // Cases for 8Bit source.
65     testStringImpl = testStringImpl->replace('2', "", 0);
66     ASSERT_TRUE(equal(testStringImpl.get(), "14"));
67
68     testStringImpl = StringImpl::createFromLiteral("1224");
69     ASSERT_TRUE(testStringImpl->is8Bit());
70
71     testStringImpl = testStringImpl->replace('3', "NotFound", 8);
72     ASSERT_TRUE(equal(testStringImpl.get(), "1224"));
73
74     testStringImpl = testStringImpl->replace('2', "3", 1);
75     ASSERT_TRUE(equal(testStringImpl.get(), "1334"));
76
77     testStringImpl = StringImpl::createFromLiteral("1224");
78     ASSERT_TRUE(testStringImpl->is8Bit());
79     testStringImpl = testStringImpl->replace('2', "555", 3);
80     ASSERT_TRUE(equal(testStringImpl.get(), "15555554"));
81
82     // Cases for 16Bit source.
83     String testString = String::fromUTF8("résumé");
84     ASSERT_FALSE(testString.impl()->is8Bit());
85
86     testStringImpl = testString.impl()->replace('2', "NotFound", 8);
87     ASSERT_TRUE(equal(testStringImpl.get(), String::fromUTF8("résumé").impl()));
88
89     testStringImpl = testString.impl()->replace(UChar(0x00E9 /*U+00E9 is 'é'*/), "e", 1);
90     ASSERT_TRUE(equal(testStringImpl.get(), "resume"));
91
92     testString = String::fromUTF8("résumé");
93     ASSERT_FALSE(testString.impl()->is8Bit());
94     testStringImpl = testString.impl()->replace(UChar(0x00E9 /*U+00E9 is 'é'*/), "", 0);
95     ASSERT_TRUE(equal(testStringImpl.get(), "rsum"));
96
97     testString = String::fromUTF8("résumé");
98     ASSERT_FALSE(testString.impl()->is8Bit());
99     testStringImpl = testString.impl()->replace(UChar(0x00E9 /*U+00E9 is 'é'*/), "555", 3);
100     ASSERT_TRUE(equal(testStringImpl.get(), "r555sum555"));
101 }
102
103 TEST(WTF, StringImplEqualIgnoringASCIICaseBasic)
104 {
105     auto a = StringImpl::createFromLiteral("aBcDeFG");
106     auto b = StringImpl::createFromLiteral("ABCDEFG");
107     auto c = StringImpl::createFromLiteral("abcdefg");
108     const char d[] = "aBcDeFG";
109     auto empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
110     auto shorter = StringImpl::createFromLiteral("abcdef");
111     auto different = StringImpl::createFromLiteral("abcrefg");
112
113     // Identity.
114     ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), a.ptr()));
115     ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), b.ptr()));
116     ASSERT_TRUE(equalIgnoringASCIICase(c.ptr(), c.ptr()));
117     ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), d));
118     ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), d));
119     ASSERT_TRUE(equalIgnoringASCIICase(c.ptr(), d));
120
121     // Transitivity.
122     ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), b.ptr()));
123     ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), c.ptr()));
124     ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), c.ptr()));
125
126     // Negative cases.
127     ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), empty.ptr()));
128     ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), empty.ptr()));
129     ASSERT_FALSE(equalIgnoringASCIICase(c.ptr(), empty.ptr()));
130     ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), shorter.ptr()));
131     ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), shorter.ptr()));
132     ASSERT_FALSE(equalIgnoringASCIICase(c.ptr(), shorter.ptr()));
133     ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), different.ptr()));
134     ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), different.ptr()));
135     ASSERT_FALSE(equalIgnoringASCIICase(c.ptr(), different.ptr()));
136     ASSERT_FALSE(equalIgnoringASCIICase(empty.ptr(), d));
137     ASSERT_FALSE(equalIgnoringASCIICase(shorter.ptr(), d));
138     ASSERT_FALSE(equalIgnoringASCIICase(different.ptr(), d));
139 }
140
141 TEST(WTF, StringImplEqualIgnoringASCIICaseWithNull)
142 {
143     auto reference = StringImpl::createFromLiteral("aBcDeFG");
144     StringImpl* nullStringImpl = nullptr;
145     ASSERT_FALSE(equalIgnoringASCIICase(nullStringImpl, reference.ptr()));
146     ASSERT_FALSE(equalIgnoringASCIICase(reference.ptr(), nullStringImpl));
147     ASSERT_TRUE(equalIgnoringASCIICase(nullStringImpl, nullStringImpl));
148 }
149
150 TEST(WTF, StringImplEqualIgnoringASCIICaseWithEmpty)
151 {
152     auto a = StringImpl::create(reinterpret_cast<const LChar*>(""));
153     auto b = StringImpl::create(reinterpret_cast<const LChar*>(""));
154     ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), b.ptr()));
155     ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), a.ptr()));
156 }
157
158 static Ref<StringImpl> stringFromUTF8(const char* characters)
159 {
160     return String::fromUTF8(characters).releaseImpl().releaseNonNull();
161 }
162
163 TEST(WTF, StringImplEqualIgnoringASCIICaseWithLatin1Characters)
164 {
165     auto a = stringFromUTF8("aBcéeFG");
166     auto b = stringFromUTF8("ABCÉEFG");
167     auto c = stringFromUTF8("ABCéEFG");
168     auto d = stringFromUTF8("abcéefg");
169     const char e[] = "aBcéeFG";
170
171     // Identity.
172     ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), a.ptr()));
173     ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), b.ptr()));
174     ASSERT_TRUE(equalIgnoringASCIICase(c.ptr(), c.ptr()));
175     ASSERT_TRUE(equalIgnoringASCIICase(d.ptr(), d.ptr()));
176
177     // All combination.
178     ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), b.ptr()));
179     ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), c.ptr()));
180     ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), d.ptr()));
181     ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), c.ptr()));
182     ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), d.ptr()));
183     ASSERT_TRUE(equalIgnoringASCIICase(c.ptr(), d.ptr()));
184     ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), e));
185     ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), e));
186     ASSERT_FALSE(equalIgnoringASCIICase(c.ptr(), e));
187     ASSERT_FALSE(equalIgnoringASCIICase(d.ptr(), e));
188 }
189
190 TEST(WTF, StringImplFindIgnoringASCIICaseBasic)
191 {
192     auto referenceA = stringFromUTF8("aBcéeFG");
193     auto referenceB = stringFromUTF8("ABCÉEFG");
194
195     // Search the exact string.
196     EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(referenceA.ptr()));
197     EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(referenceB.ptr()));
198
199     // A and B are distinct by the non-ascii character é/É.
200     EXPECT_EQ(static_cast<size_t>(notFound), referenceA->findIgnoringASCIICase(referenceB.ptr()));
201     EXPECT_EQ(static_cast<size_t>(notFound), referenceB->findIgnoringASCIICase(referenceA.ptr()));
202
203     // Find the prefix.
204     EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("a").ptr()));
205     EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(stringFromUTF8("abcé").ptr()));
206     EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("A").ptr()));
207     EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr()));
208     EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("a").ptr()));
209     EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(stringFromUTF8("abcÉ").ptr()));
210     EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("A").ptr()));
211     EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr()));
212
213     // Not a prefix.
214     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("x").ptr()));
215     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("accé").ptr()));
216     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("abcÉ").ptr()));
217     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("X").ptr()));
218     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ABDé").ptr()));
219     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr()));
220     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("y").ptr()));
221     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("accÉ").ptr()));
222     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("abcé").ptr()));
223     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("Y").ptr()));
224     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ABdÉ").ptr()));
225     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr()));
226
227     // Find the infix.
228     EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("cée").ptr()));
229     EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("ée").ptr()));
230     EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("cé").ptr()));
231     EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("c").ptr()));
232     EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("é").ptr()));
233     EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("Cée").ptr()));
234     EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éE").ptr()));
235     EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("Cé").ptr()));
236     EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("C").ptr()));
237
238     EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("cÉe").ptr()));
239     EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("Ée").ptr()));
240     EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("cÉ").ptr()));
241     EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("c").ptr()));
242     EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("É").ptr()));
243     EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("CÉe").ptr()));
244     EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("ÉE").ptr()));
245     EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("CÉ").ptr()));
246     EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("C").ptr()));
247
248     // Not an infix.
249     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("céd").ptr()));
250     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Ée").ptr()));
251     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("bé").ptr()));
252     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("x").ptr()));
253     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("É").ptr()));
254     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("CÉe").ptr()));
255     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("éd").ptr()));
256     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("CÉ").ptr()));
257     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Y").ptr()));
258
259     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("cée").ptr()));
260     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("Éc").ptr()));
261     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("cé").ptr()));
262     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("W").ptr()));
263     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("é").ptr()));
264     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("bÉe").ptr()));
265     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éE").ptr()));
266     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("BÉ").ptr()));
267     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("z").ptr()));
268
269     // Find the suffix.
270     EXPECT_EQ(static_cast<size_t>(6), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("g").ptr()));
271     EXPECT_EQ(static_cast<size_t>(4), referenceA->findIgnoringASCIICase(stringFromUTF8("efg").ptr()));
272     EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éefg").ptr()));
273     EXPECT_EQ(static_cast<size_t>(6), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("G").ptr()));
274     EXPECT_EQ(static_cast<size_t>(4), referenceA->findIgnoringASCIICase(stringFromUTF8("EFG").ptr()));
275     EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éEFG").ptr()));
276
277     EXPECT_EQ(static_cast<size_t>(6), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("g").ptr()));
278     EXPECT_EQ(static_cast<size_t>(4), referenceB->findIgnoringASCIICase(stringFromUTF8("efg").ptr()));
279     EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("Éefg").ptr()));
280     EXPECT_EQ(static_cast<size_t>(6), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("G").ptr()));
281     EXPECT_EQ(static_cast<size_t>(4), referenceB->findIgnoringASCIICase(stringFromUTF8("EFG").ptr()));
282     EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("ÉEFG").ptr()));
283
284     // Not a suffix.
285     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("X").ptr()));
286     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("edg").ptr()));
287     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Éefg").ptr()));
288     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("w").ptr()));
289     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("dFG").ptr()));
290     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ÉEFG").ptr()));
291
292     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("Z").ptr()));
293     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ffg").ptr()));
294     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éefg").ptr()));
295     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("r").ptr()));
296     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("EgG").ptr()));
297     EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éEFG").ptr()));
298 }
299
300 TEST(WTF, StringImplFindIgnoringASCIICaseWithValidOffset)
301 {
302     auto reference = stringFromUTF8("ABCÉEFGaBcéeFG");
303     EXPECT_EQ(static_cast<size_t>(0), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 0));
304     EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 1));
305     EXPECT_EQ(static_cast<size_t>(0), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 0));
306     EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 1));
307     EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr(), 0));
308     EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr(), 1));
309 }
310
311 TEST(WTF, StringImplFindIgnoringASCIICaseWithInvalidOffset)
312 {
313     auto reference = stringFromUTF8("ABCÉEFGaBcéeFG");
314     EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 15));
315     EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 16));
316     EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 17));
317     EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 42));
318     EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), std::numeric_limits<unsigned>::max()));
319 }
320
321 TEST(WTF, StringImplFindIgnoringASCIICaseOnNull)
322 {
323     auto reference = stringFromUTF8("ABCÉEFG");
324     EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr));
325     EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 0));
326     EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 3));
327     EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 7));
328     EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 8));
329     EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 42));
330     EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, std::numeric_limits<unsigned>::max()));
331 }
332
333 TEST(WTF, StringImplFindIgnoringASCIICaseOnEmpty)
334 {
335     auto reference = stringFromUTF8("ABCÉEFG");
336     auto empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
337     EXPECT_EQ(static_cast<size_t>(0), reference->findIgnoringASCIICase(empty.ptr()));
338     EXPECT_EQ(static_cast<size_t>(0), reference->findIgnoringASCIICase(empty.ptr(), 0));
339     EXPECT_EQ(static_cast<size_t>(3), reference->findIgnoringASCIICase(empty.ptr(), 3));
340     EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(empty.ptr(), 7));
341     EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(empty.ptr(), 8));
342     EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(empty.ptr(), 42));
343     EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(empty.ptr(), std::numeric_limits<unsigned>::max()));
344 }
345
346 TEST(WTF, StringImplFindIgnoringASCIICaseWithPatternLongerThanReference)
347 {
348     auto reference = stringFromUTF8("ABCÉEFG");
349     auto pattern = stringFromUTF8("XABCÉEFG");
350     EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(pattern.ptr()));
351     EXPECT_EQ(static_cast<size_t>(1), pattern->findIgnoringASCIICase(reference.ptr()));
352 }
353
354 TEST(WTF, StringImplStartsWithIgnoringASCIICaseBasic)
355 {
356     auto reference = stringFromUTF8("aBcéX");
357     auto referenceEquivalent = stringFromUTF8("AbCéx");
358
359     // Identity.
360     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(reference.ptr()));
361     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*reference.ptr()));
362     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(referenceEquivalent.ptr()));
363     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*referenceEquivalent.ptr()));
364     ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(reference.ptr()));
365     ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(*reference.ptr()));
366     ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(referenceEquivalent.ptr()));
367     ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(*referenceEquivalent.ptr()));
368
369     // Proper prefixes.
370     auto aLower = StringImpl::createFromLiteral("a");
371     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(aLower.ptr()));
372     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*aLower.ptr()));
373     auto aUpper = StringImpl::createFromLiteral("A");
374     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(aUpper.ptr()));
375     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*aUpper.ptr()));
376
377     auto abcLower = StringImpl::createFromLiteral("abc");
378     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcLower.ptr()));
379     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcLower.ptr()));
380     auto abcUpper = StringImpl::createFromLiteral("ABC");
381     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcUpper.ptr()));
382     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcUpper.ptr()));
383
384     auto abcAccentLower = stringFromUTF8("abcé");
385     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcAccentLower.ptr()));
386     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcAccentLower.ptr()));
387     auto abcAccentUpper = stringFromUTF8("ABCé");
388     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcAccentUpper.ptr()));
389     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcAccentUpper.ptr()));
390
391     // Negative cases.
392     auto differentFirstChar = stringFromUTF8("bBcéX");
393     auto differentFirstCharProperPrefix = stringFromUTF8("CBcé");
394     ASSERT_FALSE(reference->startsWithIgnoringASCIICase(differentFirstChar.ptr()));
395     ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*differentFirstChar.ptr()));
396     ASSERT_FALSE(reference->startsWithIgnoringASCIICase(differentFirstCharProperPrefix.ptr()));
397     ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*differentFirstCharProperPrefix.ptr()));
398
399     auto uppercaseAccent = stringFromUTF8("aBcÉX");
400     auto uppercaseAccentProperPrefix = stringFromUTF8("aBcÉX");
401     ASSERT_FALSE(reference->startsWithIgnoringASCIICase(uppercaseAccent.ptr()));
402     ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*uppercaseAccent.ptr()));
403     ASSERT_FALSE(reference->startsWithIgnoringASCIICase(uppercaseAccentProperPrefix.ptr()));
404     ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*uppercaseAccentProperPrefix.ptr()));
405 }
406
407 TEST(WTF, StringImplStartsWithIgnoringASCIICaseWithNull)
408 {
409     auto reference = StringImpl::createFromLiteral("aBcDeFG");
410     ASSERT_FALSE(reference->startsWithIgnoringASCIICase(nullptr));
411
412     auto empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
413     ASSERT_FALSE(empty->startsWithIgnoringASCIICase(nullptr));
414 }
415
416 TEST(WTF, StringImplStartsWithIgnoringASCIICaseWithEmpty)
417 {
418     auto reference = StringImpl::createFromLiteral("aBcDeFG");
419     auto empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
420     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(empty.ptr()));
421     ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*empty.ptr()));
422     ASSERT_TRUE(empty->startsWithIgnoringASCIICase(empty.ptr()));
423     ASSERT_TRUE(empty->startsWithIgnoringASCIICase(*empty.ptr()));
424     ASSERT_FALSE(empty->startsWithIgnoringASCIICase(reference.ptr()));
425     ASSERT_FALSE(empty->startsWithIgnoringASCIICase(*reference.ptr()));
426 }
427
428 TEST(WTF, StartsWithLettersIgnoringASCIICase)
429 {
430     String string("Test tEST");
431     ASSERT_TRUE(startsWithLettersIgnoringASCIICase(string, "test t"));
432     ASSERT_TRUE(startsWithLettersIgnoringASCIICase(string, "test te"));
433     ASSERT_TRUE(startsWithLettersIgnoringASCIICase(string, "test test"));
434     ASSERT_FALSE(startsWithLettersIgnoringASCIICase(string, "test tex"));
435
436     ASSERT_TRUE(startsWithLettersIgnoringASCIICase(string, ""));
437     ASSERT_TRUE(startsWithLettersIgnoringASCIICase(String(""), ""));
438
439     ASSERT_FALSE(startsWithLettersIgnoringASCIICase(String(), "t"));
440     ASSERT_FALSE(startsWithLettersIgnoringASCIICase(String(), ""));
441 }
442
443 TEST(WTF, StringImplEndsWithIgnoringASCIICaseBasic)
444 {
445     auto reference = stringFromUTF8("XÉCbA");
446     auto referenceEquivalent = stringFromUTF8("xÉcBa");
447
448     // Identity.
449     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(reference.ptr()));
450     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*reference.ptr()));
451     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(referenceEquivalent.ptr()));
452     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*referenceEquivalent.ptr()));
453     ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(reference.ptr()));
454     ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(*reference.ptr()));
455     ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(referenceEquivalent.ptr()));
456     ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(*referenceEquivalent.ptr()));
457
458     // Proper suffixes.
459     auto aLower = StringImpl::createFromLiteral("a");
460     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(aLower.ptr()));
461     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*aLower.ptr()));
462     auto aUpper = StringImpl::createFromLiteral("a");
463     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(aUpper.ptr()));
464     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*aUpper.ptr()));
465
466     auto abcLower = StringImpl::createFromLiteral("cba");
467     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcLower.ptr()));
468     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcLower.ptr()));
469     auto abcUpper = StringImpl::createFromLiteral("CBA");
470     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcUpper.ptr()));
471     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcUpper.ptr()));
472
473     auto abcAccentLower = stringFromUTF8("Écba");
474     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcAccentLower.ptr()));
475     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcAccentLower.ptr()));
476     auto abcAccentUpper = stringFromUTF8("ÉCBA");
477     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcAccentUpper.ptr()));
478     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcAccentUpper.ptr()));
479
480     // Negative cases.
481     auto differentLastChar = stringFromUTF8("XÉCbB");
482     auto differentLastCharProperSuffix = stringFromUTF8("ÉCbb");
483     ASSERT_FALSE(reference->endsWithIgnoringASCIICase(differentLastChar.ptr()));
484     ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*differentLastChar.ptr()));
485     ASSERT_FALSE(reference->endsWithIgnoringASCIICase(differentLastCharProperSuffix.ptr()));
486     ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*differentLastCharProperSuffix.ptr()));
487
488     auto lowercaseAccent = stringFromUTF8("aBcéX");
489     auto loweraseAccentProperSuffix = stringFromUTF8("aBcéX");
490     ASSERT_FALSE(reference->endsWithIgnoringASCIICase(lowercaseAccent.ptr()));
491     ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*lowercaseAccent.ptr()));
492     ASSERT_FALSE(reference->endsWithIgnoringASCIICase(loweraseAccentProperSuffix.ptr()));
493     ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*loweraseAccentProperSuffix.ptr()));
494 }
495
496 TEST(WTF, StringImplEndsWithIgnoringASCIICaseWithNull)
497 {
498     auto reference = StringImpl::createFromLiteral("aBcDeFG");
499     ASSERT_FALSE(reference->endsWithIgnoringASCIICase(nullptr));
500
501     auto empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
502     ASSERT_FALSE(empty->endsWithIgnoringASCIICase(nullptr));
503 }
504
505 TEST(WTF, StringImplEndsWithIgnoringASCIICaseWithEmpty)
506 {
507     auto reference = StringImpl::createFromLiteral("aBcDeFG");
508     auto empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
509     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(empty.ptr()));
510     ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*empty.ptr()));
511     ASSERT_TRUE(empty->endsWithIgnoringASCIICase(empty.ptr()));
512     ASSERT_TRUE(empty->endsWithIgnoringASCIICase(*empty.ptr()));
513     ASSERT_FALSE(empty->endsWithIgnoringASCIICase(reference.ptr()));
514     ASSERT_FALSE(empty->endsWithIgnoringASCIICase(*reference.ptr()));
515 }
516
517 TEST(WTF, StringImplCreateNullSymbol)
518 {
519     auto reference = SymbolImpl::createNullSymbol();
520     ASSERT_TRUE(reference->isSymbol());
521     ASSERT_TRUE(reference->isNullSymbol());
522     ASSERT_FALSE(reference->isAtomic());
523     ASSERT_EQ(0u, reference->length());
524     ASSERT_TRUE(equal(reference.ptr(), ""));
525 }
526
527 TEST(WTF, StringImplCreateSymbol)
528 {
529     auto original = stringFromUTF8("original");
530     auto reference = SymbolImpl::create(original);
531     ASSERT_TRUE(reference->isSymbol());
532     ASSERT_FALSE(reference->isNullSymbol());
533     ASSERT_FALSE(reference->isAtomic());
534     ASSERT_FALSE(original->isSymbol());
535     ASSERT_FALSE(original->isAtomic());
536     ASSERT_EQ(original->length(), reference->length());
537     ASSERT_TRUE(equal(reference.ptr(), "original"));
538
539     auto empty = stringFromUTF8("");
540     auto emptyReference = SymbolImpl::create(empty);
541     ASSERT_TRUE(emptyReference->isSymbol());
542     ASSERT_FALSE(emptyReference->isNullSymbol());
543     ASSERT_FALSE(emptyReference->isAtomic());
544     ASSERT_FALSE(empty->isSymbol());
545     ASSERT_TRUE(empty->isAtomic());
546     ASSERT_EQ(empty->length(), emptyReference->length());
547     ASSERT_TRUE(equal(emptyReference.ptr(), ""));
548 }
549
550 TEST(WTF, StringImplSymbolToAtomicString)
551 {
552     auto original = stringFromUTF8("original");
553     auto reference = SymbolImpl::create(original);
554     ASSERT_TRUE(reference->isSymbol());
555     ASSERT_FALSE(reference->isAtomic());
556
557     auto result = AtomicStringImpl::lookUp(reference.ptr());
558     ASSERT_FALSE(result);
559
560     auto atomic = AtomicStringImpl::add(reference.ptr());
561     ASSERT_TRUE(atomic->isAtomic());
562     ASSERT_FALSE(atomic->isSymbol());
563     ASSERT_TRUE(reference->isSymbol());
564     ASSERT_FALSE(reference->isAtomic());
565
566     auto result2 = AtomicStringImpl::lookUp(reference.ptr());
567     ASSERT_TRUE(result2);
568 }
569
570 TEST(WTF, StringImplNullSymbolToAtomicString)
571 {
572     auto reference = SymbolImpl::createNullSymbol();
573     ASSERT_TRUE(reference->isSymbol());
574     ASSERT_FALSE(reference->isAtomic());
575
576     // Because the substring of the reference is the empty string which is already interned.
577     auto result = AtomicStringImpl::lookUp(reference.ptr());
578     ASSERT_TRUE(result);
579
580     auto atomic = AtomicStringImpl::add(reference.ptr());
581     ASSERT_TRUE(atomic->isAtomic());
582     ASSERT_FALSE(atomic->isSymbol());
583     ASSERT_TRUE(reference->isSymbol());
584     ASSERT_FALSE(reference->isAtomic());
585     ASSERT_EQ(atomic.get(), StringImpl::empty());
586
587     auto result2 = AtomicStringImpl::lookUp(reference.ptr());
588     ASSERT_TRUE(result2);
589 }
590
591 static StringImpl::StaticStringImpl staticString {"Cocoa"};
592
593 TEST(WTF, StringImplStaticToAtomicString)
594 {
595     StringImpl& original = staticString;
596     ASSERT_FALSE(original.isSymbol());
597     ASSERT_FALSE(original.isAtomic());
598     ASSERT_TRUE(original.isStatic());
599
600     auto result = AtomicStringImpl::lookUp(&original);
601     ASSERT_FALSE(result);
602
603     auto atomic = AtomicStringImpl::add(&original);
604     ASSERT_TRUE(atomic->isAtomic());
605     ASSERT_FALSE(atomic->isSymbol());
606     ASSERT_FALSE(atomic->isStatic());
607     ASSERT_FALSE(original.isSymbol());
608     ASSERT_FALSE(original.isAtomic());
609     ASSERT_TRUE(original.isStatic());
610
611     auto result2 = AtomicStringImpl::lookUp(&original);
612     ASSERT_TRUE(result2);
613 }
614
615 TEST(WTF, StringImplConstexprHasher)
616 {
617     ASSERT_EQ(stringFromUTF8("")->hash(), StringHasher::computeLiteralHashAndMaskTop8Bits(""));
618     ASSERT_EQ(stringFromUTF8("A")->hash(), StringHasher::computeLiteralHashAndMaskTop8Bits("A"));
619     ASSERT_EQ(stringFromUTF8("AA")->hash(), StringHasher::computeLiteralHashAndMaskTop8Bits("AA"));
620     ASSERT_EQ(stringFromUTF8("Cocoa")->hash(), StringHasher::computeLiteralHashAndMaskTop8Bits("Cocoa"));
621     ASSERT_EQ(stringFromUTF8("Cappuccino")->hash(), StringHasher::computeLiteralHashAndMaskTop8Bits("Cappuccino"));
622 }
623
624 TEST(WTF, StringImplEmpty)
625 {
626     ASSERT_FALSE(StringImpl::empty()->length());
627 }
628
629 } // namespace TestWebKitAPI