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