1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // string_utils_unittests:
7 // Unit tests for the string utils.
8 //
9
10 #include "string_utils.h"
11
12 #include <gmock/gmock.h>
13 #include <gtest/gtest.h>
14
15 using namespace angle;
16
17 namespace
18 {
19
20 // Basic SplitString tests
TEST(StringUtilsTest,SplitStringBasics)21 TEST(StringUtilsTest, SplitStringBasics)
22 {
23 std::vector<std::string> r;
24
25 r = SplitString(std::string(), ",:;", KEEP_WHITESPACE, SPLIT_WANT_ALL);
26 EXPECT_TRUE(r.empty());
27
28 // Empty separator list
29 r = SplitString("hello, world", "", KEEP_WHITESPACE, SPLIT_WANT_ALL);
30 ASSERT_EQ(1u, r.size());
31 EXPECT_EQ("hello, world", r[0]);
32
33 // Should split on any of the separators.
34 r = SplitString("::,,;;", ",:;", KEEP_WHITESPACE, SPLIT_WANT_ALL);
35 ASSERT_EQ(7u, r.size());
36 for (auto str : r)
37 ASSERT_TRUE(str.empty());
38
39 r = SplitString("red, green; blue:", ",:;", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
40 ASSERT_EQ(3u, r.size());
41 EXPECT_EQ("red", r[0]);
42 EXPECT_EQ("green", r[1]);
43 EXPECT_EQ("blue", r[2]);
44
45 // Want to split a string along whitespace sequences.
46 r = SplitString(" red green \tblue\n", " \t\n", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
47 ASSERT_EQ(3u, r.size());
48 EXPECT_EQ("red", r[0]);
49 EXPECT_EQ("green", r[1]);
50 EXPECT_EQ("blue", r[2]);
51
52 // Weird case of splitting on spaces but not trimming.
53 r = SplitString(" red ", " ", TRIM_WHITESPACE, SPLIT_WANT_ALL);
54 ASSERT_EQ(3u, r.size());
55 EXPECT_EQ("", r[0]); // Before the first space.
56 EXPECT_EQ("red", r[1]);
57 EXPECT_EQ("", r[2]); // After the last space.
58 }
59
60 // Check different whitespace and result types for SplitString
TEST(StringUtilsTest,SplitStringWhitespaceAndResultType)61 TEST(StringUtilsTest, SplitStringWhitespaceAndResultType)
62 {
63 std::vector<std::string> r;
64
65 // Empty input handling.
66 r = SplitString(std::string(), ",", KEEP_WHITESPACE, SPLIT_WANT_ALL);
67 EXPECT_TRUE(r.empty());
68 r = SplitString(std::string(), ",", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY);
69 EXPECT_TRUE(r.empty());
70
71 // Input string is space and we're trimming.
72 r = SplitString(" ", ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
73 ASSERT_EQ(1u, r.size());
74 EXPECT_EQ("", r[0]);
75 r = SplitString(" ", ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
76 EXPECT_TRUE(r.empty());
77
78 // Test all 4 combinations of flags on ", ,".
79 r = SplitString(", ,", ",", KEEP_WHITESPACE, SPLIT_WANT_ALL);
80 ASSERT_EQ(3u, r.size());
81 EXPECT_EQ("", r[0]);
82 EXPECT_EQ(" ", r[1]);
83 EXPECT_EQ("", r[2]);
84 r = SplitString(", ,", ",", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY);
85 ASSERT_EQ(1u, r.size());
86 ASSERT_EQ(" ", r[0]);
87 r = SplitString(", ,", ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
88 ASSERT_EQ(3u, r.size());
89 EXPECT_EQ("", r[0]);
90 EXPECT_EQ("", r[1]);
91 EXPECT_EQ("", r[2]);
92 r = SplitString(", ,", ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
93 ASSERT_TRUE(r.empty());
94 }
95
96 // Tests for SplitStringAlongWhitespace
TEST(StringUtilsTest,SplitStringAlongWhitespace)97 TEST(StringUtilsTest, SplitStringAlongWhitespace)
98 {
99 {
100 // No whitespace.
101 std::vector<std::string> r;
102 SplitStringAlongWhitespace("abcd", &r);
103 ASSERT_THAT(r, testing::ElementsAre("abcd"));
104 }
105
106 {
107 // Just whitespace.
108 std::vector<std::string> r;
109 SplitStringAlongWhitespace(" \t", &r);
110 ASSERT_THAT(r, testing::ElementsAre());
111 }
112
113 {
114 // Consecutive whitespace of same type.
115 std::vector<std::string> r;
116 SplitStringAlongWhitespace("a b", &r);
117 ASSERT_THAT(r, testing::ElementsAre("a", "b"));
118 }
119
120 {
121 // Consecutive whitespace of different types.
122 std::vector<std::string> r;
123 SplitStringAlongWhitespace("ab \tcd", &r);
124 ASSERT_THAT(r, testing::ElementsAre("ab", "cd"));
125 }
126
127 {
128 // Non-empty output std::vector.
129 std::vector<std::string> r;
130 r.push_back("z");
131 SplitStringAlongWhitespace("abc", &r);
132 ASSERT_THAT(r, testing::ElementsAre("z", "abc"));
133 }
134 }
135
136 // Tests for TrimString
TEST(StringUtilsTest,TrimString)137 TEST(StringUtilsTest, TrimString)
138 {
139 // Basic tests
140 EXPECT_EQ("a", TrimString("a", kWhitespaceASCII));
141 EXPECT_EQ("a", TrimString(" a", kWhitespaceASCII));
142 EXPECT_EQ("a", TrimString("a ", kWhitespaceASCII));
143 EXPECT_EQ("a", TrimString(" a ", kWhitespaceASCII));
144
145 // Tests with empty strings
146 EXPECT_EQ("", TrimString("", kWhitespaceASCII));
147 EXPECT_EQ("", TrimString(" \n\r\t", kWhitespaceASCII));
148 EXPECT_EQ(" foo ", TrimString(" foo ", ""));
149
150 // Tests it doesn't removes characters in the middle
151 EXPECT_EQ("foo bar", TrimString(" foo bar ", kWhitespaceASCII));
152
153 // Test with non-whitespace trimChars
154 EXPECT_EQ(" ", TrimString("foo bar", "abcdefghijklmnopqrstuvwxyz"));
155 }
156
157 // Basic functionality tests for HexStringToUInt
TEST(StringUtilsTest,HexStringToUIntBasic)158 TEST(StringUtilsTest, HexStringToUIntBasic)
159 {
160 unsigned int uintValue;
161
162 std::string emptyString;
163 ASSERT_FALSE(HexStringToUInt(emptyString, &uintValue));
164
165 std::string testStringA("0xBADF00D");
166 ASSERT_TRUE(HexStringToUInt(testStringA, &uintValue));
167 EXPECT_EQ(0xBADF00Du, uintValue);
168
169 std::string testStringB("0xBADFOOD");
170 EXPECT_FALSE(HexStringToUInt(testStringB, &uintValue));
171
172 std::string testStringC("BADF00D");
173 EXPECT_TRUE(HexStringToUInt(testStringC, &uintValue));
174 EXPECT_EQ(0xBADF00Du, uintValue);
175
176 std::string testStringD("0x BADF00D");
177 EXPECT_FALSE(HexStringToUInt(testStringD, &uintValue));
178 }
179
180 // Tests for ToCamelCase
TEST(StringUtilsTest,ToCamelCase)181 TEST(StringUtilsTest, ToCamelCase)
182 {
183 // No underscore in input; expect identical output
184 EXPECT_EQ("", ToCamelCase(""));
185 EXPECT_EQ("a", ToCamelCase("a"));
186 EXPECT_EQ("AbCdEfG", ToCamelCase("AbCdEfG"));
187 EXPECT_EQ("aBcDeFg", ToCamelCase("aBcDeFg"));
188
189 // Underscore should be removed and the next character turned upper case
190 EXPECT_EQ("", ToCamelCase("_"));
191 EXPECT_EQ("aB", ToCamelCase("a_b"));
192 EXPECT_EQ("aB", ToCamelCase("a_b"));
193 EXPECT_EQ("camelCase", ToCamelCase("camel_case"));
194 EXPECT_EQ("abCDeBEfG", ToCamelCase("abCDe_bEfG"));
195
196 // Multiple underscores
197 EXPECT_EQ("aBCDEFG", ToCamelCase("a_b_c_d_e_f_g"));
198 EXPECT_EQ("abCdEfGh", ToCamelCase("ab_cd_ef_gh"));
199 EXPECT_EQ("aShortName", ToCamelCase("a_short_name"));
200 EXPECT_EQ("someShortWords", ToCamelCase("some_short_words"));
201 EXPECT_EQ("bunchOLetters", ToCamelCase("bunch_o_letters"));
202 EXPECT_EQ("whatEndsInE", ToCamelCase("what_ends_in_e"));
203 EXPECT_EQ("adjustSrcDstRegionForBlitFramebuffer",
204 ToCamelCase("adjust_src_dst_region_for_BlitFramebuffer"));
205
206 // Uppercase after underscore
207 EXPECT_EQ("abCDEFGh", ToCamelCase("ab_CD_eF_Gh"));
208 EXPECT_EQ("IWasThere", ToCamelCase("I_was_there"));
209 EXPECT_EQ("whereDidTHATComeFrom", ToCamelCase("where_did_THAT_come_from"));
210
211 // Digits
212 EXPECT_EQ("ab123c4deF5gHi6J", ToCamelCase("ab1_2_3c_4de_f5g_hi6_j"));
213 EXPECT_EQ("maxSize16KB", ToCamelCase("max_size_16KB"));
214 EXPECT_EQ("supportRGBA8", ToCamelCase("support_RGBA8"));
215 }
216
217 // Basic functionality for NamesMatchWithWildcard.
TEST(StringUtilsTest,NamesMatchWithWildcard)218 TEST(StringUtilsTest, NamesMatchWithWildcard)
219 {
220 EXPECT_TRUE(NamesMatchWithWildcard("ASDF", "ASDF"));
221 EXPECT_TRUE(NamesMatchWithWildcard("A*", "ASDF"));
222 EXPECT_TRUE(NamesMatchWithWildcard("AS*", "ASDF"));
223 EXPECT_TRUE(NamesMatchWithWildcard("ASD*", "ASDF"));
224 EXPECT_TRUE(NamesMatchWithWildcard("ASDF*", "ASDF"));
225
226 EXPECT_TRUE(NamesMatchWithWildcard("*F", "ASDF"));
227 EXPECT_TRUE(NamesMatchWithWildcard("*DF", "ASDF"));
228 EXPECT_TRUE(NamesMatchWithWildcard("*SDF", "ASDF"));
229 EXPECT_TRUE(NamesMatchWithWildcard("*ASDF", "ASDF"));
230
231 EXPECT_TRUE(NamesMatchWithWildcard("AS**", "ASDF"));
232 EXPECT_TRUE(NamesMatchWithWildcard("AS***", "ASDF"));
233 EXPECT_TRUE(NamesMatchWithWildcard("**DF", "ASDF"));
234 EXPECT_TRUE(NamesMatchWithWildcard("***DF", "ASDF"));
235
236 EXPECT_TRUE(NamesMatchWithWildcard("A*F", "ASDF"));
237 EXPECT_TRUE(NamesMatchWithWildcard("A**F", "ASDF"));
238 EXPECT_TRUE(NamesMatchWithWildcard("*SD*", "ASDF"));
239 EXPECT_TRUE(NamesMatchWithWildcard("*S*D*", "ASDF"));
240
241 EXPECT_TRUE(NamesMatchWithWildcard("ASD*", "ASDF*"));
242 }
243
244 // Note: ReadFileToString is harder to test
245
246 class BeginsWithTest : public testing::Test
247 {
248 public:
BeginsWithTest()249 BeginsWithTest() : mMode(TestMode::CHAR_ARRAY) {}
250
251 enum class TestMode
252 {
253 CHAR_ARRAY,
254 STRING_AND_CHAR_ARRAY,
255 STRING
256 };
257
setMode(TestMode mode)258 void setMode(TestMode mode) { mMode = mode; }
259
runBeginsWith(const char * str,const char * prefix)260 bool runBeginsWith(const char *str, const char *prefix)
261 {
262 if (mMode == TestMode::CHAR_ARRAY)
263 {
264 return BeginsWith(str, prefix);
265 }
266 if (mMode == TestMode::STRING_AND_CHAR_ARRAY)
267 {
268 return BeginsWith(std::string(str), prefix);
269 }
270 return BeginsWith(std::string(str), std::string(prefix));
271 }
272
runTest()273 void runTest()
274 {
275 ASSERT_FALSE(runBeginsWith("foo", "bar"));
276 ASSERT_FALSE(runBeginsWith("", "foo"));
277 ASSERT_FALSE(runBeginsWith("foo", "foobar"));
278
279 ASSERT_TRUE(runBeginsWith("foobar", "foo"));
280 ASSERT_TRUE(runBeginsWith("foobar", ""));
281 ASSERT_TRUE(runBeginsWith("foo", "foo"));
282 ASSERT_TRUE(runBeginsWith("", ""));
283 }
284
285 private:
286 TestMode mMode;
287 };
288
289 // Test that BeginsWith works correctly for const char * arguments.
TEST_F(BeginsWithTest,CharArrays)290 TEST_F(BeginsWithTest, CharArrays)
291 {
292 setMode(TestMode::CHAR_ARRAY);
293 runTest();
294 }
295
296 // Test that BeginsWith works correctly for std::string and const char * arguments.
TEST_F(BeginsWithTest,StringAndCharArray)297 TEST_F(BeginsWithTest, StringAndCharArray)
298 {
299 setMode(TestMode::STRING_AND_CHAR_ARRAY);
300 runTest();
301 }
302
303 // Test that BeginsWith works correctly for std::string arguments.
TEST_F(BeginsWithTest,Strings)304 TEST_F(BeginsWithTest, Strings)
305 {
306 setMode(TestMode::STRING);
307 runTest();
308 }
309
310 class EndsWithTest : public testing::Test
311 {
312 public:
EndsWithTest()313 EndsWithTest() : mMode(TestMode::CHAR_ARRAY) {}
314
315 enum class TestMode
316 {
317 CHAR_ARRAY,
318 STRING_AND_CHAR_ARRAY,
319 STRING
320 };
321
setMode(TestMode mode)322 void setMode(TestMode mode) { mMode = mode; }
323
runEndsWith(const char * str,const char * suffix)324 bool runEndsWith(const char *str, const char *suffix)
325 {
326 if (mMode == TestMode::CHAR_ARRAY)
327 {
328 return EndsWith(str, suffix);
329 }
330 if (mMode == TestMode::STRING_AND_CHAR_ARRAY)
331 {
332 return EndsWith(std::string(str), suffix);
333 }
334 return EndsWith(std::string(str), std::string(suffix));
335 }
336
runTest()337 void runTest()
338 {
339 ASSERT_FALSE(EndsWith("foo", "bar"));
340 ASSERT_FALSE(EndsWith("", "bar"));
341 ASSERT_FALSE(EndsWith("foo", "foobar"));
342
343 ASSERT_TRUE(EndsWith("foobar", "bar"));
344 ASSERT_TRUE(EndsWith("foobar", ""));
345 ASSERT_TRUE(EndsWith("bar", "bar"));
346 ASSERT_TRUE(EndsWith("", ""));
347 }
348
349 private:
350 TestMode mMode;
351 };
352
353 // Test that EndsWith works correctly for const char * arguments.
TEST_F(EndsWithTest,CharArrays)354 TEST_F(EndsWithTest, CharArrays)
355 {
356 setMode(TestMode::CHAR_ARRAY);
357 runTest();
358 }
359
360 // Test that EndsWith works correctly for std::string and const char * arguments.
TEST_F(EndsWithTest,StringAndCharArray)361 TEST_F(EndsWithTest, StringAndCharArray)
362 {
363 setMode(TestMode::STRING_AND_CHAR_ARRAY);
364 runTest();
365 }
366
367 // Test that EndsWith works correctly for std::string arguments.
TEST_F(EndsWithTest,Strings)368 TEST_F(EndsWithTest, Strings)
369 {
370 setMode(TestMode::STRING);
371 runTest();
372 }
373
374 } // anonymous namespace
375