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