1 | //===- llvm/unittest/ADT/StringRefTest.cpp - StringRef unit tests ---------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "llvm/ADT/StringRef.h" |
10 | #include "llvm/ADT/Hashing.h" |
11 | #include "llvm/ADT/STLExtras.h" |
12 | #include "llvm/ADT/SmallVector.h" |
13 | #include "llvm/ADT/StringExtras.h" |
14 | #include "llvm/Support/Allocator.h" |
15 | #include "llvm/Support/raw_ostream.h" |
16 | #include "gtest/gtest.h" |
17 | using namespace llvm; |
18 | |
19 | namespace llvm { |
20 | |
21 | std::ostream &operator<<(std::ostream &OS, const StringRef &S) { |
22 | OS << S.str(); |
23 | return OS; |
24 | } |
25 | |
26 | std::ostream &operator<<(std::ostream &OS, |
27 | const std::pair<StringRef, StringRef> &P) { |
28 | OS << "(" << P.first << ", " << P.second << ")" ; |
29 | return OS; |
30 | } |
31 | |
32 | } |
33 | |
34 | // Check that we can't accidentally assign a temporary std::string to a |
35 | // StringRef. (Unfortunately we can't make use of the same thing with |
36 | // constructors.) |
37 | static_assert(!std::is_assignable_v<StringRef &, std::string>, |
38 | "Assigning from prvalue std::string" ); |
39 | static_assert(!std::is_assignable_v<StringRef &, std::string &&>, |
40 | "Assigning from xvalue std::string" ); |
41 | static_assert(std::is_assignable_v<StringRef &, std::string &>, |
42 | "Assigning from lvalue std::string" ); |
43 | static_assert(std::is_assignable_v<StringRef &, const char *>, |
44 | "Assigning from prvalue C string" ); |
45 | static_assert(std::is_assignable_v<StringRef &, const char *&&>, |
46 | "Assigning from xvalue C string" ); |
47 | static_assert(std::is_assignable_v<StringRef &, const char *&>, |
48 | "Assigning from lvalue C string" ); |
49 | |
50 | namespace { |
51 | TEST(StringRefTest, Construction) { |
52 | EXPECT_EQ("" , StringRef()); |
53 | EXPECT_EQ("hello" , StringRef("hello" )); |
54 | EXPECT_EQ("hello" , StringRef("hello world" , 5)); |
55 | EXPECT_EQ("hello" , StringRef(std::string("hello" ))); |
56 | EXPECT_EQ("hello" , StringRef(std::string_view("hello" ))); |
57 | } |
58 | |
59 | TEST(StringRefTest, Conversion) { |
60 | EXPECT_EQ("hello" , std::string(StringRef("hello" ))); |
61 | EXPECT_EQ("hello" , std::string_view(StringRef("hello" ))); |
62 | static_assert(std::string_view(StringRef("hello" )) == "hello" ); |
63 | } |
64 | |
65 | TEST(StringRefTest, EmptyInitializerList) { |
66 | StringRef S = {}; |
67 | EXPECT_TRUE(S.empty()); |
68 | |
69 | S = {}; |
70 | EXPECT_TRUE(S.empty()); |
71 | } |
72 | |
73 | TEST(StringRefTest, Iteration) { |
74 | StringRef S("hello" ); |
75 | const char *p = "hello" ; |
76 | for (const char *it = S.begin(), *ie = S.end(); it != ie; ++it, ++p) |
77 | EXPECT_EQ(*it, *p); |
78 | } |
79 | |
80 | TEST(StringRefTest, StringOps) { |
81 | const char *p = "hello" ; |
82 | |
83 | EXPECT_EQ(p, StringRef(p, 0).data()); |
84 | static_assert(StringRef("hello" ).data()[0] == 'h'); |
85 | static_assert(StringRef("hello" ).data()[1] == 'e'); |
86 | static_assert(StringRef("hello" ).data()[2] == 'l'); |
87 | static_assert(StringRef("hello" ).data()[3] == 'l'); |
88 | static_assert(StringRef("hello" ).data()[4] == 'o'); |
89 | static_assert(StringRef("hello" ).data()[5] == '\0'); |
90 | |
91 | EXPECT_TRUE(StringRef().empty()); |
92 | static_assert(StringRef("" ).empty()); |
93 | static_assert(!StringRef("hello" ).empty()); |
94 | |
95 | EXPECT_EQ((size_t) 5, StringRef("hello" ).size()); |
96 | static_assert(StringRef("hello" ).size() == 5); |
97 | |
98 | EXPECT_GT( 0, StringRef("aab" ).compare("aad" )); |
99 | EXPECT_EQ( 0, StringRef("aab" ).compare("aab" )); |
100 | EXPECT_LT( 0, StringRef("aab" ).compare("aaa" )); |
101 | EXPECT_GT( 0, StringRef("aab" ).compare("aabb" )); |
102 | EXPECT_LT( 0, StringRef("aab" ).compare("aa" )); |
103 | EXPECT_LT( 0, StringRef("\xFF" ).compare("\1" )); |
104 | |
105 | EXPECT_EQ(-1, StringRef("AaB" ).compare_insensitive("aAd" )); |
106 | EXPECT_EQ( 0, StringRef("AaB" ).compare_insensitive("aab" )); |
107 | EXPECT_EQ( 1, StringRef("AaB" ).compare_insensitive("AAA" )); |
108 | EXPECT_EQ(-1, StringRef("AaB" ).compare_insensitive("aaBb" )); |
109 | EXPECT_EQ(-1, StringRef("AaB" ).compare_insensitive("bb" )); |
110 | EXPECT_EQ( 1, StringRef("aaBb" ).compare_insensitive("AaB" )); |
111 | EXPECT_EQ( 1, StringRef("bb" ).compare_insensitive("AaB" )); |
112 | EXPECT_EQ( 1, StringRef("AaB" ).compare_insensitive("aA" )); |
113 | EXPECT_EQ( 1, StringRef("\xFF" ).compare_insensitive("\1" )); |
114 | |
115 | EXPECT_EQ(-1, StringRef("aab" ).compare_numeric("aad" )); |
116 | EXPECT_EQ( 0, StringRef("aab" ).compare_numeric("aab" )); |
117 | EXPECT_EQ( 1, StringRef("aab" ).compare_numeric("aaa" )); |
118 | EXPECT_EQ(-1, StringRef("aab" ).compare_numeric("aabb" )); |
119 | EXPECT_EQ( 1, StringRef("aab" ).compare_numeric("aa" )); |
120 | EXPECT_EQ(-1, StringRef("1" ).compare_numeric("10" )); |
121 | EXPECT_EQ( 0, StringRef("10" ).compare_numeric("10" )); |
122 | EXPECT_EQ( 0, StringRef("10a" ).compare_numeric("10a" )); |
123 | EXPECT_EQ( 1, StringRef("2" ).compare_numeric("1" )); |
124 | EXPECT_EQ( 0, StringRef("llvm_v1i64_ty" ).compare_numeric("llvm_v1i64_ty" )); |
125 | EXPECT_EQ( 1, StringRef("\xFF" ).compare_numeric("\1" )); |
126 | EXPECT_EQ( 1, StringRef("V16" ).compare_numeric("V1_q0" )); |
127 | EXPECT_EQ(-1, StringRef("V1_q0" ).compare_numeric("V16" )); |
128 | EXPECT_EQ(-1, StringRef("V8_q0" ).compare_numeric("V16" )); |
129 | EXPECT_EQ( 1, StringRef("V16" ).compare_numeric("V8_q0" )); |
130 | EXPECT_EQ(-1, StringRef("V1_q0" ).compare_numeric("V8_q0" )); |
131 | EXPECT_EQ( 1, StringRef("V8_q0" ).compare_numeric("V1_q0" )); |
132 | } |
133 | |
134 | TEST(StringRefTest, Operators) { |
135 | EXPECT_EQ("" , StringRef()); |
136 | EXPECT_TRUE(StringRef("aab" ) < StringRef("aad" )); |
137 | EXPECT_FALSE(StringRef("aab" ) < StringRef("aab" )); |
138 | EXPECT_TRUE(StringRef("aab" ) <= StringRef("aab" )); |
139 | EXPECT_FALSE(StringRef("aab" ) <= StringRef("aaa" )); |
140 | EXPECT_TRUE(StringRef("aad" ) > StringRef("aab" )); |
141 | EXPECT_FALSE(StringRef("aab" ) > StringRef("aab" )); |
142 | EXPECT_TRUE(StringRef("aab" ) >= StringRef("aab" )); |
143 | EXPECT_FALSE(StringRef("aaa" ) >= StringRef("aab" )); |
144 | EXPECT_EQ(StringRef("aab" ), StringRef("aab" )); |
145 | EXPECT_FALSE(StringRef("aab" ) == StringRef("aac" )); |
146 | EXPECT_FALSE(StringRef("aab" ) != StringRef("aab" )); |
147 | EXPECT_TRUE(StringRef("aab" ) != StringRef("aac" )); |
148 | EXPECT_EQ('a', StringRef("aab" )[1]); |
149 | } |
150 | |
151 | TEST(StringRefTest, Substr) { |
152 | StringRef Str("hello" ); |
153 | EXPECT_EQ("lo" , Str.substr(3)); |
154 | EXPECT_EQ("" , Str.substr(100)); |
155 | EXPECT_EQ("hello" , Str.substr(0, 100)); |
156 | EXPECT_EQ("o" , Str.substr(4, 10)); |
157 | } |
158 | |
159 | TEST(StringRefTest, Slice) { |
160 | StringRef Str("hello" ); |
161 | EXPECT_EQ("l" , Str.slice(2, 3)); |
162 | EXPECT_EQ("ell" , Str.slice(1, 4)); |
163 | EXPECT_EQ("llo" , Str.slice(2, 100)); |
164 | EXPECT_EQ("" , Str.slice(2, 1)); |
165 | EXPECT_EQ("" , Str.slice(10, 20)); |
166 | } |
167 | |
168 | TEST(StringRefTest, Split) { |
169 | StringRef Str("hello" ); |
170 | EXPECT_EQ(std::make_pair(StringRef("hello" ), StringRef("" )), |
171 | Str.split('X')); |
172 | EXPECT_EQ(std::make_pair(StringRef("h" ), StringRef("llo" )), |
173 | Str.split('e')); |
174 | EXPECT_EQ(std::make_pair(StringRef("" ), StringRef("ello" )), |
175 | Str.split('h')); |
176 | EXPECT_EQ(std::make_pair(StringRef("he" ), StringRef("lo" )), |
177 | Str.split('l')); |
178 | EXPECT_EQ(std::make_pair(StringRef("hell" ), StringRef("" )), |
179 | Str.split('o')); |
180 | |
181 | EXPECT_EQ(std::make_pair(StringRef("hello" ), StringRef("" )), |
182 | Str.rsplit('X')); |
183 | EXPECT_EQ(std::make_pair(StringRef("h" ), StringRef("llo" )), |
184 | Str.rsplit('e')); |
185 | EXPECT_EQ(std::make_pair(StringRef("" ), StringRef("ello" )), |
186 | Str.rsplit('h')); |
187 | EXPECT_EQ(std::make_pair(StringRef("hel" ), StringRef("o" )), |
188 | Str.rsplit('l')); |
189 | EXPECT_EQ(std::make_pair(StringRef("hell" ), StringRef("" )), |
190 | Str.rsplit('o')); |
191 | |
192 | EXPECT_EQ(std::make_pair(StringRef("he" ), StringRef("o" )), |
193 | Str.rsplit("ll" )); |
194 | EXPECT_EQ(std::make_pair(StringRef("" ), StringRef("ello" )), |
195 | Str.rsplit("h" )); |
196 | EXPECT_EQ(std::make_pair(StringRef("hell" ), StringRef("" )), |
197 | Str.rsplit("o" )); |
198 | EXPECT_EQ(std::make_pair(StringRef("hello" ), StringRef("" )), |
199 | Str.rsplit("::" )); |
200 | EXPECT_EQ(std::make_pair(StringRef("hel" ), StringRef("o" )), |
201 | Str.rsplit("l" )); |
202 | } |
203 | |
204 | TEST(StringRefTest, Split2) { |
205 | SmallVector<StringRef, 5> parts; |
206 | SmallVector<StringRef, 5> expected; |
207 | |
208 | expected.push_back(Elt: "ab" ); expected.push_back(Elt: "c" ); |
209 | StringRef(",ab,,c," ).split(A&: parts, Separator: "," , MaxSplit: -1, KeepEmpty: false); |
210 | EXPECT_TRUE(parts == expected); |
211 | |
212 | expected.clear(); parts.clear(); |
213 | expected.push_back(Elt: "" ); expected.push_back(Elt: "ab" ); expected.push_back(Elt: "" ); |
214 | expected.push_back(Elt: "c" ); expected.push_back(Elt: "" ); |
215 | StringRef(",ab,,c," ).split(A&: parts, Separator: "," , MaxSplit: -1, KeepEmpty: true); |
216 | EXPECT_TRUE(parts == expected); |
217 | |
218 | expected.clear(); parts.clear(); |
219 | expected.push_back(Elt: "" ); |
220 | StringRef("" ).split(A&: parts, Separator: "," , MaxSplit: -1, KeepEmpty: true); |
221 | EXPECT_TRUE(parts == expected); |
222 | |
223 | expected.clear(); parts.clear(); |
224 | StringRef("" ).split(A&: parts, Separator: "," , MaxSplit: -1, KeepEmpty: false); |
225 | EXPECT_TRUE(parts == expected); |
226 | |
227 | expected.clear(); parts.clear(); |
228 | StringRef("," ).split(A&: parts, Separator: "," , MaxSplit: -1, KeepEmpty: false); |
229 | EXPECT_TRUE(parts == expected); |
230 | |
231 | expected.clear(); parts.clear(); |
232 | expected.push_back(Elt: "" ); expected.push_back(Elt: "" ); |
233 | StringRef("," ).split(A&: parts, Separator: "," , MaxSplit: -1, KeepEmpty: true); |
234 | EXPECT_TRUE(parts == expected); |
235 | |
236 | expected.clear(); parts.clear(); |
237 | expected.push_back(Elt: "a" ); expected.push_back(Elt: "b" ); |
238 | StringRef("a,b" ).split(A&: parts, Separator: "," , MaxSplit: -1, KeepEmpty: true); |
239 | EXPECT_TRUE(parts == expected); |
240 | |
241 | // Test MaxSplit |
242 | expected.clear(); parts.clear(); |
243 | expected.push_back(Elt: "a,,b,c" ); |
244 | StringRef("a,,b,c" ).split(A&: parts, Separator: "," , MaxSplit: 0, KeepEmpty: true); |
245 | EXPECT_TRUE(parts == expected); |
246 | |
247 | expected.clear(); parts.clear(); |
248 | expected.push_back(Elt: "a,,b,c" ); |
249 | StringRef("a,,b,c" ).split(A&: parts, Separator: "," , MaxSplit: 0, KeepEmpty: false); |
250 | EXPECT_TRUE(parts == expected); |
251 | |
252 | expected.clear(); parts.clear(); |
253 | expected.push_back(Elt: "a" ); expected.push_back(Elt: ",b,c" ); |
254 | StringRef("a,,b,c" ).split(A&: parts, Separator: "," , MaxSplit: 1, KeepEmpty: true); |
255 | EXPECT_TRUE(parts == expected); |
256 | |
257 | expected.clear(); parts.clear(); |
258 | expected.push_back(Elt: "a" ); expected.push_back(Elt: ",b,c" ); |
259 | StringRef("a,,b,c" ).split(A&: parts, Separator: "," , MaxSplit: 1, KeepEmpty: false); |
260 | EXPECT_TRUE(parts == expected); |
261 | |
262 | expected.clear(); parts.clear(); |
263 | expected.push_back(Elt: "a" ); expected.push_back(Elt: "" ); expected.push_back(Elt: "b,c" ); |
264 | StringRef("a,,b,c" ).split(A&: parts, Separator: "," , MaxSplit: 2, KeepEmpty: true); |
265 | EXPECT_TRUE(parts == expected); |
266 | |
267 | expected.clear(); parts.clear(); |
268 | expected.push_back(Elt: "a" ); expected.push_back(Elt: "b,c" ); |
269 | StringRef("a,,b,c" ).split(A&: parts, Separator: "," , MaxSplit: 2, KeepEmpty: false); |
270 | EXPECT_TRUE(parts == expected); |
271 | |
272 | expected.clear(); parts.clear(); |
273 | expected.push_back(Elt: "a" ); expected.push_back(Elt: "" ); expected.push_back(Elt: "b" ); |
274 | expected.push_back(Elt: "c" ); |
275 | StringRef("a,,b,c" ).split(A&: parts, Separator: "," , MaxSplit: 3, KeepEmpty: true); |
276 | EXPECT_TRUE(parts == expected); |
277 | |
278 | expected.clear(); parts.clear(); |
279 | expected.push_back(Elt: "a" ); expected.push_back(Elt: "b" ); expected.push_back(Elt: "c" ); |
280 | StringRef("a,,b,c" ).split(A&: parts, Separator: "," , MaxSplit: 3, KeepEmpty: false); |
281 | EXPECT_TRUE(parts == expected); |
282 | |
283 | expected.clear(); parts.clear(); |
284 | expected.push_back(Elt: "a" ); expected.push_back(Elt: "b" ); expected.push_back(Elt: "c" ); |
285 | StringRef("a,,b,c" ).split(A&: parts, Separator: ',', MaxSplit: 3, KeepEmpty: false); |
286 | EXPECT_TRUE(parts == expected); |
287 | |
288 | expected.clear(); parts.clear(); |
289 | expected.push_back(Elt: "" ); |
290 | StringRef().split(A&: parts, Separator: "," , MaxSplit: 0, KeepEmpty: true); |
291 | EXPECT_TRUE(parts == expected); |
292 | |
293 | expected.clear(); parts.clear(); |
294 | expected.push_back(Elt: StringRef()); |
295 | StringRef("" ).split(A&: parts, Separator: "," , MaxSplit: 0, KeepEmpty: true); |
296 | EXPECT_TRUE(parts == expected); |
297 | |
298 | expected.clear(); parts.clear(); |
299 | StringRef("" ).split(A&: parts, Separator: "," , MaxSplit: 0, KeepEmpty: false); |
300 | EXPECT_TRUE(parts == expected); |
301 | StringRef().split(A&: parts, Separator: "," , MaxSplit: 0, KeepEmpty: false); |
302 | EXPECT_TRUE(parts == expected); |
303 | |
304 | expected.clear(); parts.clear(); |
305 | expected.push_back(Elt: "a" ); |
306 | expected.push_back(Elt: "" ); |
307 | expected.push_back(Elt: "b" ); |
308 | expected.push_back(Elt: "c,d" ); |
309 | StringRef("a,,b,c,d" ).split(A&: parts, Separator: "," , MaxSplit: 3, KeepEmpty: true); |
310 | EXPECT_TRUE(parts == expected); |
311 | |
312 | expected.clear(); parts.clear(); |
313 | expected.push_back(Elt: "" ); |
314 | StringRef().split(A&: parts, Separator: ',', MaxSplit: 0, KeepEmpty: true); |
315 | EXPECT_TRUE(parts == expected); |
316 | |
317 | expected.clear(); parts.clear(); |
318 | expected.push_back(Elt: StringRef()); |
319 | StringRef("" ).split(A&: parts, Separator: ',', MaxSplit: 0, KeepEmpty: true); |
320 | EXPECT_TRUE(parts == expected); |
321 | |
322 | expected.clear(); parts.clear(); |
323 | StringRef("" ).split(A&: parts, Separator: ',', MaxSplit: 0, KeepEmpty: false); |
324 | EXPECT_TRUE(parts == expected); |
325 | StringRef().split(A&: parts, Separator: ',', MaxSplit: 0, KeepEmpty: false); |
326 | EXPECT_TRUE(parts == expected); |
327 | |
328 | expected.clear(); parts.clear(); |
329 | expected.push_back(Elt: "a" ); |
330 | expected.push_back(Elt: "" ); |
331 | expected.push_back(Elt: "b" ); |
332 | expected.push_back(Elt: "c,d" ); |
333 | StringRef("a,,b,c,d" ).split(A&: parts, Separator: ',', MaxSplit: 3, KeepEmpty: true); |
334 | EXPECT_TRUE(parts == expected); |
335 | } |
336 | |
337 | TEST(StringRefTest, Trim) { |
338 | StringRef Str0("hello" ); |
339 | StringRef Str1(" hello " ); |
340 | StringRef Str2(" hello " ); |
341 | StringRef Str3("\t\n\v\f\r hello \t\n\v\f\r" ); |
342 | |
343 | EXPECT_EQ(StringRef("hello" ), Str0.rtrim()); |
344 | EXPECT_EQ(StringRef(" hello" ), Str1.rtrim()); |
345 | EXPECT_EQ(StringRef(" hello" ), Str2.rtrim()); |
346 | EXPECT_EQ(StringRef("\t\n\v\f\r hello" ), Str3.rtrim()); |
347 | EXPECT_EQ(StringRef("hello" ), Str0.ltrim()); |
348 | EXPECT_EQ(StringRef("hello " ), Str1.ltrim()); |
349 | EXPECT_EQ(StringRef("hello " ), Str2.ltrim()); |
350 | EXPECT_EQ(StringRef("hello \t\n\v\f\r" ), Str3.ltrim()); |
351 | EXPECT_EQ(StringRef("hello" ), Str0.trim()); |
352 | EXPECT_EQ(StringRef("hello" ), Str1.trim()); |
353 | EXPECT_EQ(StringRef("hello" ), Str2.trim()); |
354 | EXPECT_EQ(StringRef("hello" ), Str3.trim()); |
355 | |
356 | EXPECT_EQ(StringRef("ello" ), Str0.trim("hhhhhhhhhhh" )); |
357 | |
358 | EXPECT_EQ(StringRef("" ), StringRef("" ).trim()); |
359 | EXPECT_EQ(StringRef("" ), StringRef(" " ).trim()); |
360 | EXPECT_EQ(StringRef("\0" , 1), StringRef(" \0 " , 3).trim()); |
361 | EXPECT_EQ(StringRef("\0\0" , 2), StringRef("\0\0" , 2).trim()); |
362 | EXPECT_EQ(StringRef("x" ), StringRef("\0\0x\0\0" , 5).trim('\0')); |
363 | } |
364 | |
365 | TEST(StringRefTest, StartsWith) { |
366 | StringRef Str("hello" ); |
367 | EXPECT_TRUE(Str.starts_with("" )); |
368 | EXPECT_TRUE(Str.starts_with("he" )); |
369 | EXPECT_FALSE(Str.starts_with("helloworld" )); |
370 | EXPECT_FALSE(Str.starts_with("hi" )); |
371 | } |
372 | |
373 | TEST(StringRefTest, StartsWithInsensitive) { |
374 | StringRef Str("heLLo" ); |
375 | EXPECT_TRUE(Str.starts_with_insensitive("" )); |
376 | EXPECT_TRUE(Str.starts_with_insensitive("he" )); |
377 | EXPECT_TRUE(Str.starts_with_insensitive("hell" )); |
378 | EXPECT_TRUE(Str.starts_with_insensitive("HELlo" )); |
379 | EXPECT_FALSE(Str.starts_with_insensitive("helloworld" )); |
380 | EXPECT_FALSE(Str.starts_with_insensitive("hi" )); |
381 | } |
382 | |
383 | TEST(StringRefTest, ConsumeFront) { |
384 | StringRef Str("hello" ); |
385 | EXPECT_TRUE(Str.consume_front("" )); |
386 | EXPECT_EQ("hello" , Str); |
387 | EXPECT_TRUE(Str.consume_front("he" )); |
388 | EXPECT_EQ("llo" , Str); |
389 | EXPECT_FALSE(Str.consume_front("lloworld" )); |
390 | EXPECT_EQ("llo" , Str); |
391 | EXPECT_FALSE(Str.consume_front("lol" )); |
392 | EXPECT_EQ("llo" , Str); |
393 | EXPECT_TRUE(Str.consume_front("llo" )); |
394 | EXPECT_EQ("" , Str); |
395 | EXPECT_FALSE(Str.consume_front("o" )); |
396 | EXPECT_TRUE(Str.consume_front("" )); |
397 | } |
398 | |
399 | TEST(StringRefTest, ConsumeFrontInsensitive) { |
400 | StringRef Str("heLLo" ); |
401 | EXPECT_TRUE(Str.consume_front_insensitive("" )); |
402 | EXPECT_EQ("heLLo" , Str); |
403 | EXPECT_FALSE(Str.consume_front("HEl" )); |
404 | EXPECT_EQ("heLLo" , Str); |
405 | EXPECT_TRUE(Str.consume_front_insensitive("HEl" )); |
406 | EXPECT_EQ("Lo" , Str); |
407 | EXPECT_FALSE(Str.consume_front_insensitive("loworld" )); |
408 | EXPECT_EQ("Lo" , Str); |
409 | EXPECT_FALSE(Str.consume_front_insensitive("ol" )); |
410 | EXPECT_EQ("Lo" , Str); |
411 | EXPECT_TRUE(Str.consume_front_insensitive("lo" )); |
412 | EXPECT_EQ("" , Str); |
413 | EXPECT_FALSE(Str.consume_front_insensitive("o" )); |
414 | EXPECT_TRUE(Str.consume_front_insensitive("" )); |
415 | } |
416 | |
417 | TEST(StringRefTest, EndsWith) { |
418 | StringRef Str("hello" ); |
419 | EXPECT_TRUE(Str.ends_with("" )); |
420 | EXPECT_TRUE(Str.ends_with("lo" )); |
421 | EXPECT_FALSE(Str.ends_with("helloworld" )); |
422 | EXPECT_FALSE(Str.ends_with("worldhello" )); |
423 | EXPECT_FALSE(Str.ends_with("so" )); |
424 | } |
425 | |
426 | TEST(StringRefTest, EndsWithInsensitive) { |
427 | StringRef Str("heLLo" ); |
428 | EXPECT_TRUE(Str.ends_with_insensitive("" )); |
429 | EXPECT_TRUE(Str.ends_with_insensitive("lo" )); |
430 | EXPECT_TRUE(Str.ends_with_insensitive("LO" )); |
431 | EXPECT_TRUE(Str.ends_with_insensitive("ELlo" )); |
432 | EXPECT_FALSE(Str.ends_with_insensitive("helloworld" )); |
433 | EXPECT_FALSE(Str.ends_with_insensitive("hi" )); |
434 | } |
435 | |
436 | TEST(StringRefTest, ConsumeBack) { |
437 | StringRef Str("hello" ); |
438 | EXPECT_TRUE(Str.consume_back("" )); |
439 | EXPECT_EQ("hello" , Str); |
440 | EXPECT_TRUE(Str.consume_back("lo" )); |
441 | EXPECT_EQ("hel" , Str); |
442 | EXPECT_FALSE(Str.consume_back("helhel" )); |
443 | EXPECT_EQ("hel" , Str); |
444 | EXPECT_FALSE(Str.consume_back("hle" )); |
445 | EXPECT_EQ("hel" , Str); |
446 | EXPECT_TRUE(Str.consume_back("hel" )); |
447 | EXPECT_EQ("" , Str); |
448 | EXPECT_FALSE(Str.consume_back("h" )); |
449 | EXPECT_TRUE(Str.consume_back("" )); |
450 | } |
451 | |
452 | TEST(StringRefTest, ConsumeBackInsensitive) { |
453 | StringRef Str("heLLo" ); |
454 | EXPECT_TRUE(Str.consume_back_insensitive("" )); |
455 | EXPECT_EQ("heLLo" , Str); |
456 | EXPECT_FALSE(Str.consume_back("lO" )); |
457 | EXPECT_EQ("heLLo" , Str); |
458 | EXPECT_TRUE(Str.consume_back_insensitive("lO" )); |
459 | EXPECT_EQ("heL" , Str); |
460 | EXPECT_FALSE(Str.consume_back_insensitive("helhel" )); |
461 | EXPECT_EQ("heL" , Str); |
462 | EXPECT_FALSE(Str.consume_back_insensitive("hle" )); |
463 | EXPECT_EQ("heL" , Str); |
464 | EXPECT_TRUE(Str.consume_back_insensitive("hEl" )); |
465 | EXPECT_EQ("" , Str); |
466 | EXPECT_FALSE(Str.consume_back_insensitive("h" )); |
467 | EXPECT_TRUE(Str.consume_back_insensitive("" )); |
468 | } |
469 | |
470 | TEST(StringRefTest, Find) { |
471 | StringRef Str("helloHELLO" ); |
472 | StringRef LongStr("hellx xello hell ello world foo bar hello HELLO" ); |
473 | |
474 | struct { |
475 | StringRef Str; |
476 | char C; |
477 | std::size_t From; |
478 | std::size_t Pos; |
479 | std::size_t InsensitivePos; |
480 | } CharExpectations[] = { |
481 | {.Str: Str, .C: 'h', .From: 0U, .Pos: 0U, .InsensitivePos: 0U}, |
482 | {.Str: Str, .C: 'e', .From: 0U, .Pos: 1U, .InsensitivePos: 1U}, |
483 | {.Str: Str, .C: 'l', .From: 0U, .Pos: 2U, .InsensitivePos: 2U}, |
484 | {.Str: Str, .C: 'l', .From: 3U, .Pos: 3U, .InsensitivePos: 3U}, |
485 | {.Str: Str, .C: 'o', .From: 0U, .Pos: 4U, .InsensitivePos: 4U}, |
486 | {.Str: Str, .C: 'L', .From: 0U, .Pos: 7U, .InsensitivePos: 2U}, |
487 | {.Str: Str, .C: 'z', .From: 0U, .Pos: StringRef::npos, .InsensitivePos: StringRef::npos}, |
488 | }; |
489 | |
490 | struct { |
491 | StringRef Str; |
492 | llvm::StringRef S; |
493 | std::size_t From; |
494 | std::size_t Pos; |
495 | std::size_t InsensitivePos; |
496 | } StrExpectations[] = { |
497 | {.Str: Str, .S: "helloword" , .From: 0, .Pos: StringRef::npos, .InsensitivePos: StringRef::npos}, |
498 | {.Str: Str, .S: "hello" , .From: 0, .Pos: 0U, .InsensitivePos: 0U}, |
499 | {.Str: Str, .S: "ello" , .From: 0, .Pos: 1U, .InsensitivePos: 1U}, |
500 | {.Str: Str, .S: "zz" , .From: 0, .Pos: StringRef::npos, .InsensitivePos: StringRef::npos}, |
501 | {.Str: Str, .S: "ll" , .From: 2U, .Pos: 2U, .InsensitivePos: 2U}, |
502 | {.Str: Str, .S: "ll" , .From: 3U, .Pos: StringRef::npos, .InsensitivePos: 7U}, |
503 | {.Str: Str, .S: "LL" , .From: 2U, .Pos: 7U, .InsensitivePos: 2U}, |
504 | {.Str: Str, .S: "LL" , .From: 3U, .Pos: 7U, .InsensitivePos: 7U}, |
505 | {.Str: Str, .S: "" , .From: 0U, .Pos: 0U, .InsensitivePos: 0U}, |
506 | {.Str: LongStr, .S: "hello" , .From: 0U, .Pos: 36U, .InsensitivePos: 36U}, |
507 | {.Str: LongStr, .S: "foo" , .From: 0U, .Pos: 28U, .InsensitivePos: 28U}, |
508 | {.Str: LongStr, .S: "hell" , .From: 2U, .Pos: 12U, .InsensitivePos: 12U}, |
509 | {.Str: LongStr, .S: "HELL" , .From: 2U, .Pos: 42U, .InsensitivePos: 12U}, |
510 | {.Str: LongStr, .S: "" , .From: 0U, .Pos: 0U, .InsensitivePos: 0U}}; |
511 | |
512 | for (auto &E : CharExpectations) { |
513 | EXPECT_EQ(E.Pos, E.Str.find(E.C, E.From)); |
514 | EXPECT_EQ(E.InsensitivePos, E.Str.find_insensitive(E.C, E.From)); |
515 | EXPECT_EQ(E.InsensitivePos, E.Str.find_insensitive(toupper(E.C), E.From)); |
516 | } |
517 | |
518 | for (auto &E : StrExpectations) { |
519 | EXPECT_EQ(E.Pos, E.Str.find(E.S, E.From)); |
520 | EXPECT_EQ(E.InsensitivePos, E.Str.find_insensitive(E.S, E.From)); |
521 | EXPECT_EQ(E.InsensitivePos, E.Str.find_insensitive(E.S.upper(), E.From)); |
522 | } |
523 | |
524 | EXPECT_EQ(3U, Str.rfind('l')); |
525 | EXPECT_EQ(StringRef::npos, Str.rfind('z')); |
526 | EXPECT_EQ(StringRef::npos, Str.rfind("helloworld" )); |
527 | EXPECT_EQ(0U, Str.rfind("hello" )); |
528 | EXPECT_EQ(1U, Str.rfind("ello" )); |
529 | EXPECT_EQ(StringRef::npos, Str.rfind("zz" )); |
530 | |
531 | EXPECT_EQ(8U, Str.rfind_insensitive('l')); |
532 | EXPECT_EQ(8U, Str.rfind_insensitive('L')); |
533 | EXPECT_EQ(StringRef::npos, Str.rfind_insensitive('z')); |
534 | EXPECT_EQ(StringRef::npos, Str.rfind_insensitive("HELLOWORLD" )); |
535 | EXPECT_EQ(5U, Str.rfind("HELLO" )); |
536 | EXPECT_EQ(6U, Str.rfind("ELLO" )); |
537 | EXPECT_EQ(StringRef::npos, Str.rfind("ZZ" )); |
538 | |
539 | EXPECT_EQ(2U, Str.find_first_of('l')); |
540 | EXPECT_EQ(1U, Str.find_first_of("el" )); |
541 | EXPECT_EQ(StringRef::npos, Str.find_first_of("xyz" )); |
542 | |
543 | Str = "hello" ; |
544 | EXPECT_EQ(1U, Str.find_first_not_of('h')); |
545 | EXPECT_EQ(4U, Str.find_first_not_of("hel" )); |
546 | EXPECT_EQ(StringRef::npos, Str.find_first_not_of("hello" )); |
547 | |
548 | EXPECT_EQ(3U, Str.find_last_not_of('o')); |
549 | EXPECT_EQ(1U, Str.find_last_not_of("lo" )); |
550 | EXPECT_EQ(StringRef::npos, Str.find_last_not_of("helo" )); |
551 | } |
552 | |
553 | TEST(StringRefTest, Count) { |
554 | StringRef Str("hello" ); |
555 | EXPECT_EQ(2U, Str.count('l')); |
556 | EXPECT_EQ(1U, Str.count('o')); |
557 | EXPECT_EQ(0U, Str.count('z')); |
558 | EXPECT_EQ(0U, Str.count("helloworld" )); |
559 | EXPECT_EQ(1U, Str.count("hello" )); |
560 | EXPECT_EQ(1U, Str.count("ello" )); |
561 | EXPECT_EQ(0U, Str.count("zz" )); |
562 | EXPECT_EQ(0U, Str.count("" )); |
563 | |
564 | StringRef OverlappingAbba("abbabba" ); |
565 | EXPECT_EQ(1U, OverlappingAbba.count("abba" )); |
566 | StringRef NonOverlappingAbba("abbaabba" ); |
567 | EXPECT_EQ(2U, NonOverlappingAbba.count("abba" )); |
568 | StringRef ComplexAbba("abbabbaxyzabbaxyz" ); |
569 | EXPECT_EQ(2U, ComplexAbba.count("abba" )); |
570 | } |
571 | |
572 | TEST(StringRefTest, EditDistance) { |
573 | StringRef Hello("hello" ); |
574 | EXPECT_EQ(2U, Hello.edit_distance("hill" )); |
575 | |
576 | StringRef Industry("industry" ); |
577 | EXPECT_EQ(6U, Industry.edit_distance("interest" )); |
578 | |
579 | StringRef Soylent("soylent green is people" ); |
580 | EXPECT_EQ(19U, Soylent.edit_distance("people soiled our green" )); |
581 | EXPECT_EQ(26U, Soylent.edit_distance("people soiled our green" , |
582 | /* allow replacements = */ false)); |
583 | EXPECT_EQ(9U, Soylent.edit_distance("people soiled our green" , |
584 | /* allow replacements = */ true, |
585 | /* max edit distance = */ 8)); |
586 | EXPECT_EQ(53U, Soylent.edit_distance("people soiled our green " |
587 | "people soiled our green " |
588 | "people soiled our green " )); |
589 | } |
590 | |
591 | TEST(StringRefTest, EditDistanceInsensitive) { |
592 | StringRef Hello("HELLO" ); |
593 | EXPECT_EQ(2U, Hello.edit_distance_insensitive("hill" )); |
594 | EXPECT_EQ(0U, Hello.edit_distance_insensitive("hello" )); |
595 | |
596 | StringRef Industry("InDuStRy" ); |
597 | EXPECT_EQ(6U, Industry.edit_distance_insensitive("iNtErEsT" )); |
598 | } |
599 | |
600 | TEST(StringRefTest, Misc) { |
601 | std::string Storage; |
602 | raw_string_ostream OS(Storage); |
603 | OS << StringRef("hello" ); |
604 | EXPECT_EQ("hello" , OS.str()); |
605 | } |
606 | |
607 | TEST(StringRefTest, Hashing) { |
608 | EXPECT_EQ(hash_value(std::string()), hash_value(StringRef())); |
609 | EXPECT_EQ(hash_value(std::string()), hash_value(StringRef("" ))); |
610 | std::string S = "hello world" ; |
611 | hash_code H = hash_value(arg: S); |
612 | EXPECT_EQ(H, hash_value(StringRef("hello world" ))); |
613 | EXPECT_EQ(H, hash_value(StringRef(S))); |
614 | EXPECT_NE(H, hash_value(StringRef("hello worl" ))); |
615 | EXPECT_EQ(hash_value(std::string("hello worl" )), |
616 | hash_value(StringRef("hello worl" ))); |
617 | EXPECT_NE(H, hash_value(StringRef("hello world " ))); |
618 | EXPECT_EQ(hash_value(std::string("hello world " )), |
619 | hash_value(StringRef("hello world " ))); |
620 | EXPECT_EQ(H, hash_value(StringRef("hello world\0" ))); |
621 | EXPECT_NE(hash_value(std::string("ello worl" )), |
622 | hash_value(StringRef("hello world" ).slice(1, -1))); |
623 | } |
624 | |
625 | struct UnsignedPair { |
626 | const char *Str; |
627 | uint64_t Expected; |
628 | } Unsigned[] = |
629 | { {.Str: "0" , .Expected: 0} |
630 | , {.Str: "255" , .Expected: 255} |
631 | , {.Str: "256" , .Expected: 256} |
632 | , {.Str: "65535" , .Expected: 65535} |
633 | , {.Str: "65536" , .Expected: 65536} |
634 | , {.Str: "4294967295" , .Expected: 4294967295ULL} |
635 | , {.Str: "4294967296" , .Expected: 4294967296ULL} |
636 | , {.Str: "18446744073709551615" , .Expected: 18446744073709551615ULL} |
637 | , {.Str: "042" , .Expected: 34} |
638 | , {.Str: "0x42" , .Expected: 66} |
639 | , {.Str: "0b101010" , .Expected: 42} |
640 | }; |
641 | |
642 | struct SignedPair { |
643 | const char *Str; |
644 | int64_t Expected; |
645 | } Signed[] = |
646 | { {.Str: "0" , .Expected: 0} |
647 | , {.Str: "-0" , .Expected: 0} |
648 | , {.Str: "127" , .Expected: 127} |
649 | , {.Str: "128" , .Expected: 128} |
650 | , {.Str: "-128" , .Expected: -128} |
651 | , {.Str: "-129" , .Expected: -129} |
652 | , {.Str: "32767" , .Expected: 32767} |
653 | , {.Str: "32768" , .Expected: 32768} |
654 | , {.Str: "-32768" , .Expected: -32768} |
655 | , {.Str: "-32769" , .Expected: -32769} |
656 | , {.Str: "2147483647" , .Expected: 2147483647LL} |
657 | , {.Str: "2147483648" , .Expected: 2147483648LL} |
658 | , {.Str: "-2147483648" , .Expected: -2147483648LL} |
659 | , {.Str: "-2147483649" , .Expected: -2147483649LL} |
660 | , {.Str: "-9223372036854775808" , .Expected: -(9223372036854775807LL) - 1} |
661 | , {.Str: "042" , .Expected: 34} |
662 | , {.Str: "0x42" , .Expected: 66} |
663 | , {.Str: "0b101010" , .Expected: 42} |
664 | , {.Str: "-042" , .Expected: -34} |
665 | , {.Str: "-0x42" , .Expected: -66} |
666 | , {.Str: "-0b101010" , .Expected: -42} |
667 | }; |
668 | |
669 | TEST(StringRefTest, getAsInteger) { |
670 | uint8_t U8; |
671 | uint16_t U16; |
672 | uint32_t U32; |
673 | uint64_t U64; |
674 | |
675 | for (size_t i = 0; i < std::size(Unsigned); ++i) { |
676 | bool U8Success = StringRef(Unsigned[i].Str).getAsInteger(Radix: 0, Result&: U8); |
677 | if (static_cast<uint8_t>(Unsigned[i].Expected) == Unsigned[i].Expected) { |
678 | ASSERT_FALSE(U8Success); |
679 | EXPECT_EQ(U8, Unsigned[i].Expected); |
680 | } else { |
681 | ASSERT_TRUE(U8Success); |
682 | } |
683 | bool U16Success = StringRef(Unsigned[i].Str).getAsInteger(Radix: 0, Result&: U16); |
684 | if (static_cast<uint16_t>(Unsigned[i].Expected) == Unsigned[i].Expected) { |
685 | ASSERT_FALSE(U16Success); |
686 | EXPECT_EQ(U16, Unsigned[i].Expected); |
687 | } else { |
688 | ASSERT_TRUE(U16Success); |
689 | } |
690 | bool U32Success = StringRef(Unsigned[i].Str).getAsInteger(Radix: 0, Result&: U32); |
691 | if (static_cast<uint32_t>(Unsigned[i].Expected) == Unsigned[i].Expected) { |
692 | ASSERT_FALSE(U32Success); |
693 | EXPECT_EQ(U32, Unsigned[i].Expected); |
694 | } else { |
695 | ASSERT_TRUE(U32Success); |
696 | } |
697 | bool U64Success = StringRef(Unsigned[i].Str).getAsInteger(Radix: 0, Result&: U64); |
698 | ASSERT_FALSE(U64Success); |
699 | EXPECT_EQ(U64, Unsigned[i].Expected); |
700 | } |
701 | |
702 | int8_t S8; |
703 | int16_t S16; |
704 | int32_t S32; |
705 | int64_t S64; |
706 | |
707 | for (size_t i = 0; i < std::size(Signed); ++i) { |
708 | bool S8Success = StringRef(Signed[i].Str).getAsInteger(Radix: 0, Result&: S8); |
709 | if (static_cast<int8_t>(Signed[i].Expected) == Signed[i].Expected) { |
710 | ASSERT_FALSE(S8Success); |
711 | EXPECT_EQ(S8, Signed[i].Expected); |
712 | } else { |
713 | ASSERT_TRUE(S8Success); |
714 | } |
715 | bool S16Success = StringRef(Signed[i].Str).getAsInteger(Radix: 0, Result&: S16); |
716 | if (static_cast<int16_t>(Signed[i].Expected) == Signed[i].Expected) { |
717 | ASSERT_FALSE(S16Success); |
718 | EXPECT_EQ(S16, Signed[i].Expected); |
719 | } else { |
720 | ASSERT_TRUE(S16Success); |
721 | } |
722 | bool S32Success = StringRef(Signed[i].Str).getAsInteger(Radix: 0, Result&: S32); |
723 | if (static_cast<int32_t>(Signed[i].Expected) == Signed[i].Expected) { |
724 | ASSERT_FALSE(S32Success); |
725 | EXPECT_EQ(S32, Signed[i].Expected); |
726 | } else { |
727 | ASSERT_TRUE(S32Success); |
728 | } |
729 | bool S64Success = StringRef(Signed[i].Str).getAsInteger(Radix: 0, Result&: S64); |
730 | ASSERT_FALSE(S64Success); |
731 | EXPECT_EQ(S64, Signed[i].Expected); |
732 | } |
733 | } |
734 | |
735 | |
736 | static const char* BadStrings[] = { |
737 | "" // empty string |
738 | , "18446744073709551617" // value just over max |
739 | , "123456789012345678901" // value way too large |
740 | , "4t23v" // illegal decimal characters |
741 | , "0x123W56" // illegal hex characters |
742 | , "0b2" // illegal bin characters |
743 | , "08" // illegal oct characters |
744 | , "0o8" // illegal oct characters |
745 | , "-123" // negative unsigned value |
746 | , "0x" |
747 | , "0b" |
748 | }; |
749 | |
750 | |
751 | TEST(StringRefTest, getAsUnsignedIntegerBadStrings) { |
752 | unsigned long long U64; |
753 | for (size_t i = 0; i < std::size(BadStrings); ++i) { |
754 | bool IsBadNumber = StringRef(BadStrings[i]).getAsInteger(Radix: 0, Result&: U64); |
755 | ASSERT_TRUE(IsBadNumber); |
756 | } |
757 | } |
758 | |
759 | struct ConsumeUnsignedPair { |
760 | const char *Str; |
761 | uint64_t Expected; |
762 | const char *Leftover; |
763 | } ConsumeUnsigned[] = { |
764 | {.Str: "0" , .Expected: 0, .Leftover: "" }, |
765 | {.Str: "255" , .Expected: 255, .Leftover: "" }, |
766 | {.Str: "256" , .Expected: 256, .Leftover: "" }, |
767 | {.Str: "65535" , .Expected: 65535, .Leftover: "" }, |
768 | {.Str: "65536" , .Expected: 65536, .Leftover: "" }, |
769 | {.Str: "4294967295" , .Expected: 4294967295ULL, .Leftover: "" }, |
770 | {.Str: "4294967296" , .Expected: 4294967296ULL, .Leftover: "" }, |
771 | {.Str: "255A376" , .Expected: 255, .Leftover: "A376" }, |
772 | {.Str: "18446744073709551615" , .Expected: 18446744073709551615ULL, .Leftover: "" }, |
773 | {.Str: "18446744073709551615ABC" , .Expected: 18446744073709551615ULL, .Leftover: "ABC" }, |
774 | {.Str: "042" , .Expected: 34, .Leftover: "" }, |
775 | {.Str: "0x42" , .Expected: 66, .Leftover: "" }, |
776 | {.Str: "0x42-0x34" , .Expected: 66, .Leftover: "-0x34" }, |
777 | {.Str: "0b101010" , .Expected: 42, .Leftover: "" }, |
778 | {.Str: "0429F" , .Expected: 042, .Leftover: "9F" }, // Auto-sensed octal radix, invalid digit |
779 | {.Str: "0x42G12" , .Expected: 0x42, .Leftover: "G12" }, // Auto-sensed hex radix, invalid digit |
780 | {.Str: "0b10101020101" , .Expected: 42, .Leftover: "20101" }}; // Auto-sensed binary radix, invalid digit. |
781 | |
782 | struct ConsumeSignedPair { |
783 | const char *Str; |
784 | int64_t Expected; |
785 | const char *Leftover; |
786 | } ConsumeSigned[] = { |
787 | {.Str: "0" , .Expected: 0, .Leftover: "" }, |
788 | {.Str: "-0" , .Expected: 0, .Leftover: "" }, |
789 | {.Str: "0-1" , .Expected: 0, .Leftover: "-1" }, |
790 | {.Str: "-0-1" , .Expected: 0, .Leftover: "-1" }, |
791 | {.Str: "127" , .Expected: 127, .Leftover: "" }, |
792 | {.Str: "128" , .Expected: 128, .Leftover: "" }, |
793 | {.Str: "127-1" , .Expected: 127, .Leftover: "-1" }, |
794 | {.Str: "128-1" , .Expected: 128, .Leftover: "-1" }, |
795 | {.Str: "-128" , .Expected: -128, .Leftover: "" }, |
796 | {.Str: "-129" , .Expected: -129, .Leftover: "" }, |
797 | {.Str: "-128-1" , .Expected: -128, .Leftover: "-1" }, |
798 | {.Str: "-129-1" , .Expected: -129, .Leftover: "-1" }, |
799 | {.Str: "32767" , .Expected: 32767, .Leftover: "" }, |
800 | {.Str: "32768" , .Expected: 32768, .Leftover: "" }, |
801 | {.Str: "32767-1" , .Expected: 32767, .Leftover: "-1" }, |
802 | {.Str: "32768-1" , .Expected: 32768, .Leftover: "-1" }, |
803 | {.Str: "-32768" , .Expected: -32768, .Leftover: "" }, |
804 | {.Str: "-32769" , .Expected: -32769, .Leftover: "" }, |
805 | {.Str: "-32768-1" , .Expected: -32768, .Leftover: "-1" }, |
806 | {.Str: "-32769-1" , .Expected: -32769, .Leftover: "-1" }, |
807 | {.Str: "2147483647" , .Expected: 2147483647LL, .Leftover: "" }, |
808 | {.Str: "2147483648" , .Expected: 2147483648LL, .Leftover: "" }, |
809 | {.Str: "2147483647-1" , .Expected: 2147483647LL, .Leftover: "-1" }, |
810 | {.Str: "2147483648-1" , .Expected: 2147483648LL, .Leftover: "-1" }, |
811 | {.Str: "-2147483648" , .Expected: -2147483648LL, .Leftover: "" }, |
812 | {.Str: "-2147483649" , .Expected: -2147483649LL, .Leftover: "" }, |
813 | {.Str: "-2147483648-1" , .Expected: -2147483648LL, .Leftover: "-1" }, |
814 | {.Str: "-2147483649-1" , .Expected: -2147483649LL, .Leftover: "-1" }, |
815 | {.Str: "-9223372036854775808" , .Expected: -(9223372036854775807LL) - 1, .Leftover: "" }, |
816 | {.Str: "-9223372036854775808-1" , .Expected: -(9223372036854775807LL) - 1, .Leftover: "-1" }, |
817 | {.Str: "042" , .Expected: 34, .Leftover: "" }, |
818 | {.Str: "042-1" , .Expected: 34, .Leftover: "-1" }, |
819 | {.Str: "0x42" , .Expected: 66, .Leftover: "" }, |
820 | {.Str: "0x42-1" , .Expected: 66, .Leftover: "-1" }, |
821 | {.Str: "0b101010" , .Expected: 42, .Leftover: "" }, |
822 | {.Str: "0b101010-1" , .Expected: 42, .Leftover: "-1" }, |
823 | {.Str: "-042" , .Expected: -34, .Leftover: "" }, |
824 | {.Str: "-042-1" , .Expected: -34, .Leftover: "-1" }, |
825 | {.Str: "-0x42" , .Expected: -66, .Leftover: "" }, |
826 | {.Str: "-0x42-1" , .Expected: -66, .Leftover: "-1" }, |
827 | {.Str: "-0b101010" , .Expected: -42, .Leftover: "" }, |
828 | {.Str: "-0b101010-1" , .Expected: -42, .Leftover: "-1" }}; |
829 | |
830 | TEST(StringRefTest, consumeIntegerUnsigned) { |
831 | uint8_t U8; |
832 | uint16_t U16; |
833 | uint32_t U32; |
834 | uint64_t U64; |
835 | APInt U; |
836 | |
837 | for (size_t i = 0; i < std::size(ConsumeUnsigned); ++i) { |
838 | StringRef Str = ConsumeUnsigned[i].Str; |
839 | bool U8Success = Str.consumeInteger(Radix: 0, Result&: U8); |
840 | if (static_cast<uint8_t>(ConsumeUnsigned[i].Expected) == |
841 | ConsumeUnsigned[i].Expected) { |
842 | ASSERT_FALSE(U8Success); |
843 | EXPECT_EQ(U8, ConsumeUnsigned[i].Expected); |
844 | EXPECT_EQ(Str, ConsumeUnsigned[i].Leftover); |
845 | } else { |
846 | ASSERT_TRUE(U8Success); |
847 | } |
848 | |
849 | Str = ConsumeUnsigned[i].Str; |
850 | bool U16Success = Str.consumeInteger(Radix: 0, Result&: U16); |
851 | if (static_cast<uint16_t>(ConsumeUnsigned[i].Expected) == |
852 | ConsumeUnsigned[i].Expected) { |
853 | ASSERT_FALSE(U16Success); |
854 | EXPECT_EQ(U16, ConsumeUnsigned[i].Expected); |
855 | EXPECT_EQ(Str, ConsumeUnsigned[i].Leftover); |
856 | } else { |
857 | ASSERT_TRUE(U16Success); |
858 | } |
859 | |
860 | Str = ConsumeUnsigned[i].Str; |
861 | bool U32Success = Str.consumeInteger(Radix: 0, Result&: U32); |
862 | if (static_cast<uint32_t>(ConsumeUnsigned[i].Expected) == |
863 | ConsumeUnsigned[i].Expected) { |
864 | ASSERT_FALSE(U32Success); |
865 | EXPECT_EQ(U32, ConsumeUnsigned[i].Expected); |
866 | EXPECT_EQ(Str, ConsumeUnsigned[i].Leftover); |
867 | } else { |
868 | ASSERT_TRUE(U32Success); |
869 | } |
870 | |
871 | Str = ConsumeUnsigned[i].Str; |
872 | bool U64Success = Str.consumeInteger(Radix: 0, Result&: U64); |
873 | ASSERT_FALSE(U64Success); |
874 | EXPECT_EQ(U64, ConsumeUnsigned[i].Expected); |
875 | EXPECT_EQ(Str, ConsumeUnsigned[i].Leftover); |
876 | |
877 | Str = ConsumeUnsigned[i].Str; |
878 | U64Success = Str.consumeInteger(Radix: 0, Result&: U); |
879 | ASSERT_FALSE(U64Success); |
880 | EXPECT_EQ(U.getZExtValue(), ConsumeUnsigned[i].Expected); |
881 | EXPECT_EQ(Str, ConsumeUnsigned[i].Leftover); |
882 | } |
883 | } |
884 | |
885 | TEST(StringRefTest, consumeIntegerSigned) { |
886 | int8_t S8; |
887 | int16_t S16; |
888 | int32_t S32; |
889 | int64_t S64; |
890 | |
891 | for (size_t i = 0; i < std::size(ConsumeSigned); ++i) { |
892 | StringRef Str = ConsumeSigned[i].Str; |
893 | bool S8Success = Str.consumeInteger(Radix: 0, Result&: S8); |
894 | if (static_cast<int8_t>(ConsumeSigned[i].Expected) == |
895 | ConsumeSigned[i].Expected) { |
896 | ASSERT_FALSE(S8Success); |
897 | EXPECT_EQ(S8, ConsumeSigned[i].Expected); |
898 | EXPECT_EQ(Str, ConsumeSigned[i].Leftover); |
899 | } else { |
900 | ASSERT_TRUE(S8Success); |
901 | } |
902 | |
903 | Str = ConsumeSigned[i].Str; |
904 | bool S16Success = Str.consumeInteger(Radix: 0, Result&: S16); |
905 | if (static_cast<int16_t>(ConsumeSigned[i].Expected) == |
906 | ConsumeSigned[i].Expected) { |
907 | ASSERT_FALSE(S16Success); |
908 | EXPECT_EQ(S16, ConsumeSigned[i].Expected); |
909 | EXPECT_EQ(Str, ConsumeSigned[i].Leftover); |
910 | } else { |
911 | ASSERT_TRUE(S16Success); |
912 | } |
913 | |
914 | Str = ConsumeSigned[i].Str; |
915 | bool S32Success = Str.consumeInteger(Radix: 0, Result&: S32); |
916 | if (static_cast<int32_t>(ConsumeSigned[i].Expected) == |
917 | ConsumeSigned[i].Expected) { |
918 | ASSERT_FALSE(S32Success); |
919 | EXPECT_EQ(S32, ConsumeSigned[i].Expected); |
920 | EXPECT_EQ(Str, ConsumeSigned[i].Leftover); |
921 | } else { |
922 | ASSERT_TRUE(S32Success); |
923 | } |
924 | |
925 | Str = ConsumeSigned[i].Str; |
926 | bool S64Success = Str.consumeInteger(Radix: 0, Result&: S64); |
927 | ASSERT_FALSE(S64Success); |
928 | EXPECT_EQ(S64, ConsumeSigned[i].Expected); |
929 | EXPECT_EQ(Str, ConsumeSigned[i].Leftover); |
930 | } |
931 | } |
932 | |
933 | struct GetDoubleStrings { |
934 | const char *Str; |
935 | bool AllowInexact; |
936 | bool ShouldFail; |
937 | double D; |
938 | } DoubleStrings[] = {{.Str: "0" , .AllowInexact: false, .ShouldFail: false, .D: 0.0}, |
939 | {.Str: "0.0" , .AllowInexact: false, .ShouldFail: false, .D: 0.0}, |
940 | {.Str: "-0.0" , .AllowInexact: false, .ShouldFail: false, .D: -0.0}, |
941 | {.Str: "123.45" , .AllowInexact: false, .ShouldFail: true, .D: 123.45}, |
942 | {.Str: "123.45" , .AllowInexact: true, .ShouldFail: false, .D: 123.45}, |
943 | {.Str: "1.8e308" , .AllowInexact: true, .ShouldFail: false, .D: std::numeric_limits<double>::infinity()}, |
944 | {.Str: "1.8e308" , .AllowInexact: false, .ShouldFail: true, .D: std::numeric_limits<double>::infinity()}, |
945 | {.Str: "0x0.0000000000001P-1023" , .AllowInexact: false, .ShouldFail: true, .D: 0.0}, |
946 | {.Str: "0x0.0000000000001P-1023" , .AllowInexact: true, .ShouldFail: false, .D: 0.0}, |
947 | }; |
948 | |
949 | TEST(StringRefTest, getAsDouble) { |
950 | for (const auto &Entry : DoubleStrings) { |
951 | double Result; |
952 | StringRef S(Entry.Str); |
953 | EXPECT_EQ(Entry.ShouldFail, S.getAsDouble(Result, Entry.AllowInexact)); |
954 | if (!Entry.ShouldFail) { |
955 | EXPECT_EQ(Result, Entry.D); |
956 | } |
957 | } |
958 | } |
959 | |
960 | static const char *join_input[] = { "a" , "b" , "c" }; |
961 | static const char join_result1[] = "a" ; |
962 | static const char join_result2[] = "a:b:c" ; |
963 | static const char join_result3[] = "a::b::c" ; |
964 | |
965 | TEST(StringRefTest, joinStrings) { |
966 | std::vector<StringRef> v1; |
967 | std::vector<std::string> v2; |
968 | for (size_t i = 0; i < std::size(join_input); ++i) { |
969 | v1.push_back(x: join_input[i]); |
970 | v2.push_back(x: join_input[i]); |
971 | } |
972 | |
973 | bool v1_join1 = join(Begin: v1.begin(), End: v1.begin() + 1, Separator: ":" ) == join_result1; |
974 | EXPECT_TRUE(v1_join1); |
975 | bool v1_join2 = join(Begin: v1.begin(), End: v1.end(), Separator: ":" ) == join_result2; |
976 | EXPECT_TRUE(v1_join2); |
977 | bool v1_join3 = join(Begin: v1.begin(), End: v1.end(), Separator: "::" ) == join_result3; |
978 | EXPECT_TRUE(v1_join3); |
979 | |
980 | bool v2_join1 = join(Begin: v2.begin(), End: v2.begin() + 1, Separator: ":" ) == join_result1; |
981 | EXPECT_TRUE(v2_join1); |
982 | bool v2_join2 = join(Begin: v2.begin(), End: v2.end(), Separator: ":" ) == join_result2; |
983 | EXPECT_TRUE(v2_join2); |
984 | bool v2_join3 = join(Begin: v2.begin(), End: v2.end(), Separator: "::" ) == join_result3; |
985 | EXPECT_TRUE(v2_join3); |
986 | v2_join3 = join(R&: v2, Separator: "::" ) == join_result3; |
987 | EXPECT_TRUE(v2_join3); |
988 | } |
989 | |
990 | |
991 | TEST(StringRefTest, AllocatorCopy) { |
992 | BumpPtrAllocator Alloc; |
993 | // First test empty strings. We don't want these to allocate anything on the |
994 | // allocator. |
995 | StringRef StrEmpty = "" ; |
996 | StringRef StrEmptyc = StrEmpty.copy(A&: Alloc); |
997 | EXPECT_TRUE(StrEmpty.equals(StrEmptyc)); |
998 | EXPECT_EQ(StrEmptyc.data(), nullptr); |
999 | EXPECT_EQ(StrEmptyc.size(), 0u); |
1000 | EXPECT_EQ(Alloc.getTotalMemory(), 0u); |
1001 | |
1002 | StringRef Str1 = "hello" ; |
1003 | StringRef Str2 = "bye" ; |
1004 | StringRef Str1c = Str1.copy(A&: Alloc); |
1005 | StringRef Str2c = Str2.copy(A&: Alloc); |
1006 | EXPECT_TRUE(Str1.equals(Str1c)); |
1007 | EXPECT_NE(Str1.data(), Str1c.data()); |
1008 | EXPECT_TRUE(Str2.equals(Str2c)); |
1009 | EXPECT_NE(Str2.data(), Str2c.data()); |
1010 | } |
1011 | |
1012 | TEST(StringRefTest, Drop) { |
1013 | StringRef Test("StringRefTest::Drop" ); |
1014 | |
1015 | StringRef Dropped = Test.drop_front(N: 5); |
1016 | EXPECT_EQ(Dropped, "gRefTest::Drop" ); |
1017 | |
1018 | Dropped = Test.drop_back(N: 5); |
1019 | EXPECT_EQ(Dropped, "StringRefTest:" ); |
1020 | |
1021 | Dropped = Test.drop_front(N: 0); |
1022 | EXPECT_EQ(Dropped, Test); |
1023 | |
1024 | Dropped = Test.drop_back(N: 0); |
1025 | EXPECT_EQ(Dropped, Test); |
1026 | |
1027 | Dropped = Test.drop_front(N: Test.size()); |
1028 | EXPECT_TRUE(Dropped.empty()); |
1029 | |
1030 | Dropped = Test.drop_back(N: Test.size()); |
1031 | EXPECT_TRUE(Dropped.empty()); |
1032 | } |
1033 | |
1034 | TEST(StringRefTest, Take) { |
1035 | StringRef Test("StringRefTest::Take" ); |
1036 | |
1037 | StringRef Taken = Test.take_front(N: 5); |
1038 | EXPECT_EQ(Taken, "Strin" ); |
1039 | |
1040 | Taken = Test.take_back(N: 5); |
1041 | EXPECT_EQ(Taken, ":Take" ); |
1042 | |
1043 | Taken = Test.take_front(N: Test.size()); |
1044 | EXPECT_EQ(Taken, Test); |
1045 | |
1046 | Taken = Test.take_back(N: Test.size()); |
1047 | EXPECT_EQ(Taken, Test); |
1048 | |
1049 | Taken = Test.take_front(N: 0); |
1050 | EXPECT_TRUE(Taken.empty()); |
1051 | |
1052 | Taken = Test.take_back(N: 0); |
1053 | EXPECT_TRUE(Taken.empty()); |
1054 | } |
1055 | |
1056 | TEST(StringRefTest, FindIf) { |
1057 | StringRef Punct("Test.String" ); |
1058 | StringRef NoPunct("ABCDEFG" ); |
1059 | StringRef Empty; |
1060 | |
1061 | auto IsPunct = [](char c) { return ::ispunct(c); }; |
1062 | auto IsAlpha = [](char c) { return ::isalpha(c); }; |
1063 | EXPECT_EQ(4U, Punct.find_if(IsPunct)); |
1064 | EXPECT_EQ(StringRef::npos, NoPunct.find_if(IsPunct)); |
1065 | EXPECT_EQ(StringRef::npos, Empty.find_if(IsPunct)); |
1066 | |
1067 | EXPECT_EQ(4U, Punct.find_if_not(IsAlpha)); |
1068 | EXPECT_EQ(StringRef::npos, NoPunct.find_if_not(IsAlpha)); |
1069 | EXPECT_EQ(StringRef::npos, Empty.find_if_not(IsAlpha)); |
1070 | } |
1071 | |
1072 | TEST(StringRefTest, TakeWhileUntil) { |
1073 | StringRef Test("String With 1 Number" ); |
1074 | |
1075 | StringRef Taken = Test.take_while(F: [](char c) { return ::isdigit(c); }); |
1076 | EXPECT_EQ("" , Taken); |
1077 | |
1078 | Taken = Test.take_until(F: [](char c) { return ::isdigit(c); }); |
1079 | EXPECT_EQ("String With " , Taken); |
1080 | |
1081 | Taken = Test.take_while(F: [](char c) { return true; }); |
1082 | EXPECT_EQ(Test, Taken); |
1083 | |
1084 | Taken = Test.take_until(F: [](char c) { return true; }); |
1085 | EXPECT_EQ("" , Taken); |
1086 | |
1087 | Test = "" ; |
1088 | Taken = Test.take_while(F: [](char c) { return true; }); |
1089 | EXPECT_EQ("" , Taken); |
1090 | } |
1091 | |
1092 | TEST(StringRefTest, DropWhileUntil) { |
1093 | StringRef Test("String With 1 Number" ); |
1094 | |
1095 | StringRef Taken = Test.drop_while(F: [](char c) { return ::isdigit(c); }); |
1096 | EXPECT_EQ(Test, Taken); |
1097 | |
1098 | Taken = Test.drop_until(F: [](char c) { return ::isdigit(c); }); |
1099 | EXPECT_EQ("1 Number" , Taken); |
1100 | |
1101 | Taken = Test.drop_while(F: [](char c) { return true; }); |
1102 | EXPECT_EQ("" , Taken); |
1103 | |
1104 | Taken = Test.drop_until(F: [](char c) { return true; }); |
1105 | EXPECT_EQ(Test, Taken); |
1106 | |
1107 | StringRef EmptyString = "" ; |
1108 | Taken = EmptyString.drop_while(F: [](char c) { return true; }); |
1109 | EXPECT_EQ("" , Taken); |
1110 | } |
1111 | |
1112 | TEST(StringRefTest, StringLiteral) { |
1113 | constexpr StringRef StringRefs[] = {"Foo" , "Bar" }; |
1114 | EXPECT_EQ(StringRef("Foo" ), StringRefs[0]); |
1115 | EXPECT_EQ(3u, (std::integral_constant<size_t, StringRefs[0].size()>::value)); |
1116 | EXPECT_EQ(false, (std::integral_constant<bool, StringRefs[0].empty()>::value)); |
1117 | EXPECT_EQ(StringRef("Bar" ), StringRefs[1]); |
1118 | |
1119 | constexpr StringLiteral Strings[] = {"Foo" , "Bar" }; |
1120 | EXPECT_EQ(StringRef("Foo" ), Strings[0]); |
1121 | EXPECT_EQ(3u, (std::integral_constant<size_t, Strings[0].size()>::value)); |
1122 | EXPECT_EQ(false, (std::integral_constant<bool, Strings[0].empty()>::value)); |
1123 | EXPECT_EQ(StringRef("Bar" ), Strings[1]); |
1124 | } |
1125 | |
1126 | // Check gtest prints StringRef as a string instead of a container of chars. |
1127 | // The code is in utils/unittest/googletest/internal/custom/gtest-printers.h |
1128 | TEST(StringRefTest, GTestPrinter) { |
1129 | EXPECT_EQ(R"("foo")" , ::testing::PrintToString(StringRef("foo" ))); |
1130 | } |
1131 | |
1132 | TEST(StringRefTest, LFLineEnding) { |
1133 | constexpr StringRef Cases[] = {"\nDoggo\nPupper" , "Floofer\n" , "Woofer" }; |
1134 | EXPECT_EQ(StringRef("\n" ), Cases[0].detectEOL()); |
1135 | EXPECT_EQ(StringRef("\n" ), Cases[1].detectEOL()); |
1136 | EXPECT_EQ(StringRef("\n" ), Cases[2].detectEOL()); |
1137 | } |
1138 | |
1139 | TEST(StringRefTest, CRLineEnding) { |
1140 | constexpr StringRef Cases[] = {"\rDoggo\rPupper" , "Floofer\r" , "Woo\rfer\n" }; |
1141 | EXPECT_EQ(StringRef("\r" ), Cases[0].detectEOL()); |
1142 | EXPECT_EQ(StringRef("\r" ), Cases[1].detectEOL()); |
1143 | EXPECT_EQ(StringRef("\r" ), Cases[2].detectEOL()); |
1144 | } |
1145 | |
1146 | TEST(StringRefTest, CRLFLineEnding) { |
1147 | constexpr StringRef Cases[] = {"\r\nDoggo\r\nPupper" , "Floofer\r\n" , |
1148 | "Woofer\r\nSubWoofer\n" }; |
1149 | EXPECT_EQ(StringRef("\r\n" ), Cases[0].detectEOL()); |
1150 | EXPECT_EQ(StringRef("\r\n" ), Cases[1].detectEOL()); |
1151 | EXPECT_EQ(StringRef("\r\n" ), Cases[2].detectEOL()); |
1152 | } |
1153 | |
1154 | TEST(StringRefTest, LFCRLineEnding) { |
1155 | constexpr StringRef Cases[] = {"\n\rDoggo\n\rPupper" , "Floofer\n\r" , |
1156 | "Woofer\n\rSubWoofer\n" }; |
1157 | EXPECT_EQ(StringRef("\n\r" ), Cases[0].detectEOL()); |
1158 | EXPECT_EQ(StringRef("\n\r" ), Cases[1].detectEOL()); |
1159 | EXPECT_EQ(StringRef("\n\r" ), Cases[2].detectEOL()); |
1160 | } |
1161 | |
1162 | static_assert(std::is_trivially_copyable_v<StringRef>, "trivially copyable" ); |
1163 | |
1164 | } // end anonymous namespace |
1165 | |