OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2011 Google Inc. All rights reserved. | |
3 * Copyright (C) 2013 Apple Inc. All rights reserved. | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions are | |
7 * met: | |
8 * | |
9 * * Redistributions of source code must retain the above copyright | |
10 * notice, this list of conditions and the following disclaimer. | |
11 * * Redistributions in binary form must reproduce the above | |
12 * copyright notice, this list of conditions and the following disclaimer | |
13 * in the documentation and/or other materials provided with the | |
14 * distribution. | |
15 * * Neither the name of Google Inc. nor the names of its | |
16 * contributors may be used to endorse or promote products derived from | |
17 * this software without specific prior written permission. | |
18 * | |
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
30 */ | |
31 | |
32 #include "wtf/text/StringBuilder.h" | |
33 | |
34 #include "testing/gtest/include/gtest/gtest.h" | |
35 #include "wtf/Assertions.h" | |
36 #include "wtf/text/CString.h" | |
37 #include "wtf/text/CharacterNames.h" | |
38 #include "wtf/text/WTFString.h" | |
39 | |
40 namespace WTF { | |
41 | |
42 namespace { | |
43 | |
44 void expectBuilderContent(const String& expected, | |
45 const StringBuilder& builder) { | |
46 // Not using builder.toString() because it changes internal state of builder. | |
47 if (builder.is8Bit()) | |
48 EXPECT_EQ(expected, String(builder.characters8(), builder.length())); | |
49 else | |
50 EXPECT_EQ(expected, String(builder.characters16(), builder.length())); | |
51 } | |
52 | |
53 void expectEmpty(const StringBuilder& builder) { | |
54 EXPECT_EQ(0U, builder.length()); | |
55 EXPECT_TRUE(builder.isEmpty()); | |
56 EXPECT_EQ(0, builder.characters8()); | |
57 } | |
58 | |
59 } // namespace | |
60 | |
61 TEST(StringBuilderTest, DefaultConstructor) { | |
62 StringBuilder builder; | |
63 expectEmpty(builder); | |
64 } | |
65 | |
66 TEST(StringBuilderTest, Append) { | |
67 StringBuilder builder; | |
68 builder.append(String("0123456789")); | |
69 expectBuilderContent("0123456789", builder); | |
70 builder.append("abcd"); | |
71 expectBuilderContent("0123456789abcd", builder); | |
72 builder.append("efgh", 3); | |
73 expectBuilderContent("0123456789abcdefg", builder); | |
74 builder.append(""); | |
75 expectBuilderContent("0123456789abcdefg", builder); | |
76 builder.append('#'); | |
77 expectBuilderContent("0123456789abcdefg#", builder); | |
78 | |
79 builder.toString(); // Test after reifyString(). | |
80 StringBuilder builder1; | |
81 builder.append("", 0); | |
82 expectBuilderContent("0123456789abcdefg#", builder); | |
83 builder1.append(builder.characters8(), builder.length()); | |
84 builder1.append("XYZ"); | |
85 builder.append(builder1.characters8(), builder1.length()); | |
86 expectBuilderContent("0123456789abcdefg#0123456789abcdefg#XYZ", builder); | |
87 | |
88 StringBuilder builder2; | |
89 builder2.reserveCapacity(100); | |
90 builder2.append("xyz"); | |
91 const LChar* characters = builder2.characters8(); | |
92 builder2.append("0123456789"); | |
93 EXPECT_EQ(characters, builder2.characters8()); | |
94 | |
95 StringBuilder builder3; | |
96 builder3.append("xyz", 1, 2); | |
97 expectBuilderContent("yz", builder3); | |
98 | |
99 StringBuilder builder4; | |
100 builder4.append("abc", 5, 3); | |
101 expectEmpty(builder4); | |
102 | |
103 StringBuilder builder5; | |
104 builder5.append(StringView(StringView("def"), 1, 1)); | |
105 expectBuilderContent("e", builder5); | |
106 | |
107 // append() has special code paths for String backed StringView instead of | |
108 // just char* backed ones. | |
109 StringBuilder builder6; | |
110 builder6.append(String("ghi"), 1, 2); | |
111 expectBuilderContent("hi", builder6); | |
112 | |
113 // Test appending UChar32 characters to StringBuilder. | |
114 StringBuilder builderForUChar32Append; | |
115 UChar32 frakturAChar = 0x1D504; | |
116 // The fraktur A is not in the BMP, so it's two UTF-16 code units long. | |
117 builderForUChar32Append.append(frakturAChar); | |
118 EXPECT_FALSE(builderForUChar32Append.is8Bit()); | |
119 EXPECT_EQ(2U, builderForUChar32Append.length()); | |
120 builderForUChar32Append.append(static_cast<UChar32>('A')); | |
121 EXPECT_EQ(3U, builderForUChar32Append.length()); | |
122 const UChar resultArray[] = {U16_LEAD(frakturAChar), U16_TRAIL(frakturAChar), | |
123 'A'}; | |
124 expectBuilderContent(String(resultArray, WTF_ARRAY_LENGTH(resultArray)), | |
125 builderForUChar32Append); | |
126 } | |
127 | |
128 TEST(StringBuilderTest, AppendSharingImpl) { | |
129 String string("abc"); | |
130 StringBuilder builder1; | |
131 builder1.append(string); | |
132 EXPECT_EQ(string.impl(), builder1.toString().impl()); | |
133 EXPECT_EQ(string.impl(), builder1.toAtomicString().impl()); | |
134 | |
135 StringBuilder builder2; | |
136 builder2.append(string, 0, string.length()); | |
137 EXPECT_EQ(string.impl(), builder2.toString().impl()); | |
138 EXPECT_EQ(string.impl(), builder2.toAtomicString().impl()); | |
139 } | |
140 | |
141 TEST(StringBuilderTest, ToString) { | |
142 StringBuilder builder; | |
143 builder.append("0123456789"); | |
144 String string = builder.toString(); | |
145 EXPECT_EQ(String("0123456789"), string); | |
146 EXPECT_EQ(string.impl(), builder.toString().impl()); | |
147 | |
148 // Changing the StringBuilder should not affect the original result of | |
149 // toString(). | |
150 builder.append("abcdefghijklmnopqrstuvwxyz"); | |
151 EXPECT_EQ(String("0123456789"), string); | |
152 | |
153 // Changing the StringBuilder should not affect the original result of | |
154 // toString() in case the capacity is not changed. | |
155 builder.reserveCapacity(200); | |
156 string = builder.toString(); | |
157 EXPECT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyz"), string); | |
158 builder.append("ABC"); | |
159 EXPECT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyz"), string); | |
160 | |
161 // Changing the original result of toString() should not affect the content of | |
162 // the StringBuilder. | |
163 String string1 = builder.toString(); | |
164 EXPECT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), string1); | |
165 string1.append("DEF"); | |
166 EXPECT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), | |
167 builder.toString()); | |
168 EXPECT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABCDEF"), string1); | |
169 | |
170 // Resizing the StringBuilder should not affect the original result of | |
171 // toString(). | |
172 string1 = builder.toString(); | |
173 builder.resize(10); | |
174 builder.append("###"); | |
175 EXPECT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), string1); | |
176 } | |
177 | |
178 TEST(StringBuilderTest, Clear) { | |
179 StringBuilder builder; | |
180 builder.append("0123456789"); | |
181 builder.clear(); | |
182 expectEmpty(builder); | |
183 } | |
184 | |
185 TEST(StringBuilderTest, Array) { | |
186 StringBuilder builder; | |
187 builder.append("0123456789"); | |
188 EXPECT_EQ('0', static_cast<char>(builder[0])); | |
189 EXPECT_EQ('9', static_cast<char>(builder[9])); | |
190 builder.toString(); // Test after reifyString(). | |
191 EXPECT_EQ('0', static_cast<char>(builder[0])); | |
192 EXPECT_EQ('9', static_cast<char>(builder[9])); | |
193 } | |
194 | |
195 TEST(StringBuilderTest, Resize) { | |
196 StringBuilder builder; | |
197 builder.append("0123456789"); | |
198 builder.resize(10); | |
199 EXPECT_EQ(10U, builder.length()); | |
200 expectBuilderContent("0123456789", builder); | |
201 builder.resize(8); | |
202 EXPECT_EQ(8U, builder.length()); | |
203 expectBuilderContent("01234567", builder); | |
204 | |
205 builder.toString(); | |
206 builder.resize(7); | |
207 EXPECT_EQ(7U, builder.length()); | |
208 expectBuilderContent("0123456", builder); | |
209 builder.resize(0); | |
210 expectEmpty(builder); | |
211 } | |
212 | |
213 TEST(StringBuilderTest, Equal) { | |
214 StringBuilder builder1; | |
215 StringBuilder builder2; | |
216 EXPECT_TRUE(builder1 == builder2); | |
217 EXPECT_TRUE(equal(builder1, static_cast<LChar*>(0), 0)); | |
218 EXPECT_TRUE(builder1 == String()); | |
219 EXPECT_TRUE(String() == builder1); | |
220 EXPECT_TRUE(builder1 != String("abc")); | |
221 | |
222 builder1.append("123"); | |
223 builder1.reserveCapacity(32); | |
224 builder2.append("123"); | |
225 builder1.reserveCapacity(64); | |
226 EXPECT_TRUE(builder1 == builder2); | |
227 EXPECT_TRUE(builder1 == String("123")); | |
228 EXPECT_TRUE(String("123") == builder1); | |
229 | |
230 builder2.append("456"); | |
231 EXPECT_TRUE(builder1 != builder2); | |
232 EXPECT_TRUE(builder2 != builder1); | |
233 EXPECT_TRUE(String("123") != builder2); | |
234 EXPECT_TRUE(builder2 != String("123")); | |
235 builder2.toString(); // Test after reifyString(). | |
236 EXPECT_TRUE(builder1 != builder2); | |
237 | |
238 builder2.resize(3); | |
239 EXPECT_TRUE(builder1 == builder2); | |
240 | |
241 builder1.toString(); // Test after reifyString(). | |
242 EXPECT_TRUE(builder1 == builder2); | |
243 } | |
244 | |
245 TEST(StringBuilderTest, ToAtomicString) { | |
246 StringBuilder builder; | |
247 builder.append("123"); | |
248 AtomicString atomicString = builder.toAtomicString(); | |
249 EXPECT_EQ(String("123"), atomicString); | |
250 | |
251 builder.reserveCapacity(256); | |
252 for (int i = builder.length(); i < 128; i++) | |
253 builder.append('x'); | |
254 AtomicString atomicString1 = builder.toAtomicString(); | |
255 EXPECT_EQ(128u, atomicString1.length()); | |
256 EXPECT_EQ('x', atomicString1[127]); | |
257 | |
258 // Later change of builder should not affect the atomic string. | |
259 for (int i = builder.length(); i < 256; i++) | |
260 builder.append('x'); | |
261 EXPECT_EQ(128u, atomicString1.length()); | |
262 | |
263 String string = builder.toString(); | |
264 AtomicString atomicString2 = builder.toAtomicString(); | |
265 // They should share the same StringImpl. | |
266 EXPECT_EQ(atomicString2.impl(), string.impl()); | |
267 } | |
268 | |
269 TEST(StringBuilderTest, ToAtomicStringOnEmpty) { | |
270 { // Default constructed. | |
271 StringBuilder builder; | |
272 AtomicString atomicString = builder.toAtomicString(); | |
273 EXPECT_EQ(emptyAtom, atomicString); | |
274 } | |
275 { // With capacity. | |
276 StringBuilder builder; | |
277 builder.reserveCapacity(64); | |
278 AtomicString atomicString = builder.toAtomicString(); | |
279 EXPECT_EQ(emptyAtom, atomicString); | |
280 } | |
281 { // AtomicString constructed from a null string. | |
282 StringBuilder builder; | |
283 builder.append(String()); | |
284 AtomicString atomicString = builder.toAtomicString(); | |
285 EXPECT_EQ(emptyAtom, atomicString); | |
286 } | |
287 { // AtomicString constructed from an empty string. | |
288 StringBuilder builder; | |
289 builder.append(emptyString); | |
290 AtomicString atomicString = builder.toAtomicString(); | |
291 EXPECT_EQ(emptyAtom, atomicString); | |
292 } | |
293 { // AtomicString constructed from an empty StringBuilder. | |
294 StringBuilder builder; | |
295 StringBuilder emptyBuilder; | |
296 builder.append(emptyBuilder); | |
297 AtomicString atomicString = builder.toAtomicString(); | |
298 EXPECT_EQ(emptyAtom, atomicString); | |
299 } | |
300 { // AtomicString constructed from an empty char* string. | |
301 StringBuilder builder; | |
302 builder.append("", 0); | |
303 AtomicString atomicString = builder.toAtomicString(); | |
304 EXPECT_EQ(emptyAtom, atomicString); | |
305 } | |
306 { // Cleared StringBuilder. | |
307 StringBuilder builder; | |
308 builder.append("WebKit"); | |
309 builder.clear(); | |
310 AtomicString atomicString = builder.toAtomicString(); | |
311 EXPECT_EQ(emptyAtom, atomicString); | |
312 } | |
313 } | |
314 | |
315 TEST(StringBuilderTest, Substring) { | |
316 { // Default constructed. | |
317 StringBuilder builder; | |
318 String substring = builder.substring(0, 10); | |
319 EXPECT_EQ(emptyString, substring); | |
320 } | |
321 { // With capacity. | |
322 StringBuilder builder; | |
323 builder.reserveCapacity(64); | |
324 builder.append("abc"); | |
325 String substring = builder.substring(2, 10); | |
326 EXPECT_EQ(String("c"), substring); | |
327 } | |
328 } | |
329 | |
330 TEST(StringBuilderTest, AppendNumberDoubleUChar) { | |
331 const double someNumber = 1.2345; | |
332 StringBuilder reference; | |
333 reference.append(replacementCharacter); // Make it UTF-16. | |
334 reference.append(String::number(someNumber)); | |
335 StringBuilder test; | |
336 test.append(replacementCharacter); | |
337 test.appendNumber(someNumber); | |
338 EXPECT_EQ(reference, test); | |
339 } | |
340 | |
341 } // namespace WTF | |
OLD | NEW |