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 | |
34 | namespace TestWebKitAPI { |
35 | |
36 | TEST(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 | |
72 | TEST(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 | |
116 | TEST(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 | |
154 | TEST(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 | |
163 | TEST(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 | |
171 | static Ref<StringImpl> stringFromUTF8(const char* characters) |
172 | { |
173 | return String::fromUTF8(characters).releaseImpl().releaseNonNull(); |
174 | } |
175 | |
176 | TEST(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 | |
203 | TEST(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 | |
313 | TEST(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 | |
324 | TEST(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 | |
334 | TEST(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 | |
346 | TEST(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 | |
359 | TEST(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 | |
367 | TEST(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 | |
420 | TEST(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 | |
429 | TEST(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 | |
441 | TEST(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 | |
456 | TEST(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 | |
509 | TEST(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 | |
518 | TEST(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 | |
530 | TEST(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 | |
541 | TEST(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 | |
566 | TEST(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 | |
591 | TEST(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 | |
612 | TEST(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 | |
634 | static StringImpl::StaticStringImpl staticString {"Cocoa" }; |
635 | |
636 | TEST(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 | |
662 | TEST(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 | |
671 | TEST(WTF, StringImplEmpty) |
672 | { |
673 | ASSERT_FALSE(StringImpl::empty()->length()); |
674 | } |
675 | |
676 | static const String& neverDestroyedString() |
677 | { |
678 | static NeverDestroyed<String> str(MAKE_STATIC_STRING_IMPL("NeverDestroyedString" )); |
679 | return str; |
680 | }; |
681 | |
682 | static const String& getNeverDestroyedStringAtStackDepth(int i) |
683 | { |
684 | if (--i) |
685 | return getNeverDestroyedStringAtStackDepth(i); |
686 | return neverDestroyedString(); |
687 | }; |
688 | |
689 | TEST(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 | |
724 | static SymbolImpl::StaticSymbolImpl staticSymbol {"Cocoa" }; |
725 | static SymbolImpl::StaticSymbolImpl staticPrivateSymbol {"Cocoa" , SymbolImpl::s_flagIsPrivate }; |
726 | |
727 | TEST(WTF, StaticSymbolImpl) |
728 | { |
729 | auto& symbol = static_cast<SymbolImpl&>(staticSymbol); |
730 | ASSERT_TRUE(symbol.isSymbol()); |
731 | ASSERT_FALSE(symbol.isPrivate()); |
732 | } |
733 | |
734 | TEST(WTF, StaticPrivateSymbolImpl) |
735 | { |
736 | auto& symbol = static_cast<SymbolImpl&>(staticPrivateSymbol); |
737 | ASSERT_TRUE(symbol.isSymbol()); |
738 | ASSERT_TRUE(symbol.isPrivate()); |
739 | } |
740 | |
741 | TEST(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 | |
763 | TEST(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 | |
785 | TEST(WTF, StringImplNotExternal) |
786 | { |
787 | auto notExternal = stringFromUTF8("hello" ); |
788 | ASSERT_FALSE(notExternal->isExternal()); |
789 | } |
790 | |
791 | |
792 | TEST(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 | |
829 | TEST(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 | |