1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/strings/string_split.h"
6
7 #include <stddef.h>
8
9 #include <string>
10 #include <string_view>
11 #include <vector>
12
13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 using ::testing::ElementsAre;
19 using ::testing::Optional;
20 using ::testing::Pair;
21
22 namespace base {
23
24 class SplitStringIntoKeyValuePairsTest : public testing::Test {
25 protected:
26 base::StringPairs kv_pairs;
27 };
28
29 using SplitStringIntoKeyValuePairsUsingSubstrTest =
30 SplitStringIntoKeyValuePairsTest;
31
TEST_F(SplitStringIntoKeyValuePairsUsingSubstrTest,EmptyString)32 TEST_F(SplitStringIntoKeyValuePairsUsingSubstrTest, EmptyString) {
33 EXPECT_TRUE(
34 SplitStringIntoKeyValuePairsUsingSubstr(std::string(),
35 ':', // Key-value delimiter
36 ",", // Key-value pair delimiter
37 &kv_pairs));
38 EXPECT_TRUE(kv_pairs.empty());
39 }
40
TEST_F(SplitStringIntoKeyValuePairsUsingSubstrTest,MissingKeyValueDelimiter)41 TEST_F(SplitStringIntoKeyValuePairsUsingSubstrTest, MissingKeyValueDelimiter) {
42 EXPECT_FALSE(
43 SplitStringIntoKeyValuePairsUsingSubstr("key1,,key2:value2",
44 ':', // Key-value delimiter
45 ",,", // Key-value pair delimiter
46 &kv_pairs));
47 ASSERT_EQ(2U, kv_pairs.size());
48 EXPECT_TRUE(kv_pairs[0].first.empty());
49 EXPECT_TRUE(kv_pairs[0].second.empty());
50 EXPECT_EQ("key2", kv_pairs[1].first);
51 EXPECT_EQ("value2", kv_pairs[1].second);
52 }
53
TEST_F(SplitStringIntoKeyValuePairsUsingSubstrTest,MissingKeyValuePairDelimiter)54 TEST_F(SplitStringIntoKeyValuePairsUsingSubstrTest,
55 MissingKeyValuePairDelimiter) {
56 EXPECT_TRUE(SplitStringIntoKeyValuePairsUsingSubstr(
57 "key1:value1,,key3:value3",
58 ':', // Key-value delimiter
59 ",,,", // Key-value pair delimiter
60 &kv_pairs));
61 ASSERT_EQ(1U, kv_pairs.size());
62 EXPECT_EQ("key1", kv_pairs[0].first);
63 EXPECT_EQ("value1,,key3:value3", kv_pairs[0].second);
64 }
65
TEST_F(SplitStringIntoKeyValuePairsUsingSubstrTest,UntrimmedWhitespace)66 TEST_F(SplitStringIntoKeyValuePairsUsingSubstrTest, UntrimmedWhitespace) {
67 EXPECT_TRUE(
68 SplitStringIntoKeyValuePairsUsingSubstr("key1 : value1",
69 ':', // Key-value delimiter
70 ",", // Key-value pair delimiter
71 &kv_pairs));
72 ASSERT_EQ(1U, kv_pairs.size());
73 EXPECT_EQ("key1 ", kv_pairs[0].first);
74 EXPECT_EQ(" value1", kv_pairs[0].second);
75 }
76
TEST_F(SplitStringIntoKeyValuePairsUsingSubstrTest,OnlySplitAtGivenSeparator)77 TEST_F(SplitStringIntoKeyValuePairsUsingSubstrTest, OnlySplitAtGivenSeparator) {
78 std::string a("a ?!@#$%^&*()_+:/{}\\\t\nb");
79 EXPECT_TRUE(
80 SplitStringIntoKeyValuePairsUsingSubstr(a + "X" + a + "XY" + a + "YX" + a,
81 'X', // Key-value delimiter
82 "XY", // Key-value pair delimiter
83 &kv_pairs));
84 ASSERT_EQ(2U, kv_pairs.size());
85 EXPECT_EQ(a, kv_pairs[0].first);
86 EXPECT_EQ(a, kv_pairs[0].second);
87 EXPECT_EQ(a + 'Y', kv_pairs[1].first);
88 EXPECT_EQ(a, kv_pairs[1].second);
89 }
90
TEST_F(SplitStringIntoKeyValuePairsTest,EmptyString)91 TEST_F(SplitStringIntoKeyValuePairsTest, EmptyString) {
92 EXPECT_TRUE(SplitStringIntoKeyValuePairs(std::string(),
93 ':', // Key-value delimiter
94 ',', // Key-value pair delimiter
95 &kv_pairs));
96 EXPECT_TRUE(kv_pairs.empty());
97 }
98
TEST_F(SplitStringIntoKeyValuePairsTest,MissingKeyValueDelimiter)99 TEST_F(SplitStringIntoKeyValuePairsTest, MissingKeyValueDelimiter) {
100 EXPECT_FALSE(SplitStringIntoKeyValuePairs("key1,key2:value2",
101 ':', // Key-value delimiter
102 ',', // Key-value pair delimiter
103 &kv_pairs));
104 ASSERT_EQ(2U, kv_pairs.size());
105 EXPECT_TRUE(kv_pairs[0].first.empty());
106 EXPECT_TRUE(kv_pairs[0].second.empty());
107 EXPECT_EQ("key2", kv_pairs[1].first);
108 EXPECT_EQ("value2", kv_pairs[1].second);
109 }
110
TEST_F(SplitStringIntoKeyValuePairsTest,EmptyKeyWithKeyValueDelimiter)111 TEST_F(SplitStringIntoKeyValuePairsTest, EmptyKeyWithKeyValueDelimiter) {
112 EXPECT_TRUE(SplitStringIntoKeyValuePairs(":value1,key2:value2",
113 ':', // Key-value delimiter
114 ',', // Key-value pair delimiter
115 &kv_pairs));
116 ASSERT_EQ(2U, kv_pairs.size());
117 EXPECT_TRUE(kv_pairs[0].first.empty());
118 EXPECT_EQ("value1", kv_pairs[0].second);
119 EXPECT_EQ("key2", kv_pairs[1].first);
120 EXPECT_EQ("value2", kv_pairs[1].second);
121 }
122
TEST_F(SplitStringIntoKeyValuePairsTest,TrailingAndLeadingPairDelimiter)123 TEST_F(SplitStringIntoKeyValuePairsTest, TrailingAndLeadingPairDelimiter) {
124 EXPECT_TRUE(SplitStringIntoKeyValuePairs(",key1:value1,key2:value2,",
125 ':', // Key-value delimiter
126 ',', // Key-value pair delimiter
127 &kv_pairs));
128 ASSERT_EQ(2U, kv_pairs.size());
129 EXPECT_EQ("key1", kv_pairs[0].first);
130 EXPECT_EQ("value1", kv_pairs[0].second);
131 EXPECT_EQ("key2", kv_pairs[1].first);
132 EXPECT_EQ("value2", kv_pairs[1].second);
133 }
134
TEST_F(SplitStringIntoKeyValuePairsTest,EmptyPair)135 TEST_F(SplitStringIntoKeyValuePairsTest, EmptyPair) {
136 EXPECT_TRUE(SplitStringIntoKeyValuePairs("key1:value1,,key3:value3",
137 ':', // Key-value delimiter
138 ',', // Key-value pair delimiter
139 &kv_pairs));
140 ASSERT_EQ(2U, kv_pairs.size());
141 EXPECT_EQ("key1", kv_pairs[0].first);
142 EXPECT_EQ("value1", kv_pairs[0].second);
143 EXPECT_EQ("key3", kv_pairs[1].first);
144 EXPECT_EQ("value3", kv_pairs[1].second);
145 }
146
TEST_F(SplitStringIntoKeyValuePairsTest,EmptyValue)147 TEST_F(SplitStringIntoKeyValuePairsTest, EmptyValue) {
148 EXPECT_FALSE(SplitStringIntoKeyValuePairs("key1:,key2:value2",
149 ':', // Key-value delimiter
150 ',', // Key-value pair delimiter
151 &kv_pairs));
152 ASSERT_EQ(2U, kv_pairs.size());
153 EXPECT_EQ("key1", kv_pairs[0].first);
154 EXPECT_EQ("", kv_pairs[0].second);
155 EXPECT_EQ("key2", kv_pairs[1].first);
156 EXPECT_EQ("value2", kv_pairs[1].second);
157 }
158
TEST_F(SplitStringIntoKeyValuePairsTest,UntrimmedWhitespace)159 TEST_F(SplitStringIntoKeyValuePairsTest, UntrimmedWhitespace) {
160 EXPECT_TRUE(SplitStringIntoKeyValuePairs("key1 : value1",
161 ':', // Key-value delimiter
162 ',', // Key-value pair delimiter
163 &kv_pairs));
164 ASSERT_EQ(1U, kv_pairs.size());
165 EXPECT_EQ("key1 ", kv_pairs[0].first);
166 EXPECT_EQ(" value1", kv_pairs[0].second);
167 }
168
TEST_F(SplitStringIntoKeyValuePairsTest,TrimmedWhitespace)169 TEST_F(SplitStringIntoKeyValuePairsTest, TrimmedWhitespace) {
170 EXPECT_TRUE(SplitStringIntoKeyValuePairs("key1:value1 , key2:value2",
171 ':', // Key-value delimiter
172 ',', // Key-value pair delimiter
173 &kv_pairs));
174 ASSERT_EQ(2U, kv_pairs.size());
175 EXPECT_EQ("key1", kv_pairs[0].first);
176 EXPECT_EQ("value1", kv_pairs[0].second);
177 EXPECT_EQ("key2", kv_pairs[1].first);
178 EXPECT_EQ("value2", kv_pairs[1].second);
179 }
180
TEST_F(SplitStringIntoKeyValuePairsTest,MultipleKeyValueDelimiters)181 TEST_F(SplitStringIntoKeyValuePairsTest, MultipleKeyValueDelimiters) {
182 EXPECT_TRUE(SplitStringIntoKeyValuePairs("key1:::value1,key2:value2",
183 ':', // Key-value delimiter
184 ',', // Key-value pair delimiter
185 &kv_pairs));
186 ASSERT_EQ(2U, kv_pairs.size());
187 EXPECT_EQ("key1", kv_pairs[0].first);
188 EXPECT_EQ("value1", kv_pairs[0].second);
189 EXPECT_EQ("key2", kv_pairs[1].first);
190 EXPECT_EQ("value2", kv_pairs[1].second);
191 }
192
TEST_F(SplitStringIntoKeyValuePairsTest,OnlySplitAtGivenSeparator)193 TEST_F(SplitStringIntoKeyValuePairsTest, OnlySplitAtGivenSeparator) {
194 std::string a("a ?!@#$%^&*()_+:/{}\\\t\nb");
195 EXPECT_TRUE(SplitStringIntoKeyValuePairs(a + "X" + a + "Y" + a + "X" + a,
196 'X', // Key-value delimiter
197 'Y', // Key-value pair delimiter
198 &kv_pairs));
199 ASSERT_EQ(2U, kv_pairs.size());
200 EXPECT_EQ(a, kv_pairs[0].first);
201 EXPECT_EQ(a, kv_pairs[0].second);
202 EXPECT_EQ(a, kv_pairs[1].first);
203 EXPECT_EQ(a, kv_pairs[1].second);
204 }
205
206
TEST_F(SplitStringIntoKeyValuePairsTest,DelimiterInValue)207 TEST_F(SplitStringIntoKeyValuePairsTest, DelimiterInValue) {
208 EXPECT_TRUE(SplitStringIntoKeyValuePairs("key1:va:ue1,key2:value2",
209 ':', // Key-value delimiter
210 ',', // Key-value pair delimiter
211 &kv_pairs));
212 ASSERT_EQ(2U, kv_pairs.size());
213 EXPECT_EQ("key1", kv_pairs[0].first);
214 EXPECT_EQ("va:ue1", kv_pairs[0].second);
215 EXPECT_EQ("key2", kv_pairs[1].first);
216 EXPECT_EQ("value2", kv_pairs[1].second);
217 }
218
TEST(SplitStringUsingSubstrTest,EmptyString)219 TEST(SplitStringUsingSubstrTest, EmptyString) {
220 std::vector<std::string> results = SplitStringUsingSubstr(
221 std::string(), "DELIMITER", TRIM_WHITESPACE, SPLIT_WANT_ALL);
222 ASSERT_EQ(1u, results.size());
223 EXPECT_THAT(results, ElementsAre(""));
224 }
225
TEST(SplitStringUsingSubstrTest,EmptyDelimiter)226 TEST(SplitStringUsingSubstrTest, EmptyDelimiter) {
227 std::vector<std::string> results = SplitStringUsingSubstr(
228 "TEST", std::string(), TRIM_WHITESPACE, SPLIT_WANT_ALL);
229 ASSERT_EQ(1u, results.size());
230 EXPECT_THAT(results, ElementsAre("TEST"));
231 }
232
TEST(StringUtilTest,SplitString_Basics)233 TEST(StringUtilTest, SplitString_Basics) {
234 std::vector<std::string> r;
235
236 r = SplitString(std::string(), ",:;", KEEP_WHITESPACE, SPLIT_WANT_ALL);
237 EXPECT_TRUE(r.empty());
238
239 // Empty separator list
240 r = SplitString("hello, world", "", KEEP_WHITESPACE, SPLIT_WANT_ALL);
241 ASSERT_EQ(1u, r.size());
242 EXPECT_EQ("hello, world", r[0]);
243
244 // Should split on any of the separators.
245 r = SplitString("::,,;;", ",:;", KEEP_WHITESPACE, SPLIT_WANT_ALL);
246 ASSERT_EQ(7u, r.size());
247 for (auto str : r)
248 ASSERT_TRUE(str.empty());
249
250 r = SplitString("red, green; blue:", ",:;", TRIM_WHITESPACE,
251 SPLIT_WANT_NONEMPTY);
252 ASSERT_EQ(3u, r.size());
253 EXPECT_EQ("red", r[0]);
254 EXPECT_EQ("green", r[1]);
255 EXPECT_EQ("blue", r[2]);
256
257 // Want to split a string along whitespace sequences.
258 r = SplitString(" red green \tblue\n", " \t\n", TRIM_WHITESPACE,
259 SPLIT_WANT_NONEMPTY);
260 ASSERT_EQ(3u, r.size());
261 EXPECT_EQ("red", r[0]);
262 EXPECT_EQ("green", r[1]);
263 EXPECT_EQ("blue", r[2]);
264
265 // Weird case of splitting on spaces but not trimming.
266 r = SplitString(" red ", " ", TRIM_WHITESPACE, SPLIT_WANT_ALL);
267 ASSERT_EQ(3u, r.size());
268 EXPECT_EQ("", r[0]); // Before the first space.
269 EXPECT_EQ("red", r[1]);
270 EXPECT_EQ("", r[2]); // After the last space.
271 }
272
TEST(StringUtilTest,SplitString_WhitespaceAndResultType)273 TEST(StringUtilTest, SplitString_WhitespaceAndResultType) {
274 std::vector<std::string> r;
275
276 // Empty input handling.
277 r = SplitString(std::string(), ",", KEEP_WHITESPACE, SPLIT_WANT_ALL);
278 EXPECT_TRUE(r.empty());
279 r = SplitString(std::string(), ",", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY);
280 EXPECT_TRUE(r.empty());
281
282 // Input string is space and we're trimming.
283 r = SplitString(" ", ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
284 ASSERT_EQ(1u, r.size());
285 EXPECT_EQ("", r[0]);
286 r = SplitString(" ", ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
287 EXPECT_TRUE(r.empty());
288
289 // Test all 4 combinations of flags on ", ,".
290 r = SplitString(", ,", ",", KEEP_WHITESPACE, SPLIT_WANT_ALL);
291 ASSERT_EQ(3u, r.size());
292 EXPECT_EQ("", r[0]);
293 EXPECT_EQ(" ", r[1]);
294 EXPECT_EQ("", r[2]);
295 r = SplitString(", ,", ",", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY);
296 ASSERT_EQ(1u, r.size());
297 ASSERT_EQ(" ", r[0]);
298 r = SplitString(", ,", ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
299 ASSERT_EQ(3u, r.size());
300 EXPECT_EQ("", r[0]);
301 EXPECT_EQ("", r[1]);
302 EXPECT_EQ("", r[2]);
303 r = SplitString(", ,", ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
304 ASSERT_TRUE(r.empty());
305 }
306
TEST(SplitStringUsingSubstrTest,StringWithNoDelimiter)307 TEST(SplitStringUsingSubstrTest, StringWithNoDelimiter) {
308 std::vector<std::string> results = SplitStringUsingSubstr(
309 "alongwordwithnodelimiter", "DELIMITER", TRIM_WHITESPACE,
310 SPLIT_WANT_ALL);
311 ASSERT_EQ(1u, results.size());
312 EXPECT_THAT(results, ElementsAre("alongwordwithnodelimiter"));
313 }
314
TEST(SplitStringUsingSubstrTest,LeadingDelimitersSkipped)315 TEST(SplitStringUsingSubstrTest, LeadingDelimitersSkipped) {
316 std::vector<std::string> results = SplitStringUsingSubstr(
317 "DELIMITERDELIMITERDELIMITERoneDELIMITERtwoDELIMITERthree",
318 "DELIMITER", TRIM_WHITESPACE, SPLIT_WANT_ALL);
319 ASSERT_EQ(6u, results.size());
320 EXPECT_THAT(results, ElementsAre("", "", "", "one", "two", "three"));
321 }
322
TEST(SplitStringUsingSubstrTest,ConsecutiveDelimitersSkipped)323 TEST(SplitStringUsingSubstrTest, ConsecutiveDelimitersSkipped) {
324 std::vector<std::string> results = SplitStringUsingSubstr(
325 "unoDELIMITERDELIMITERDELIMITERdosDELIMITERtresDELIMITERDELIMITERcuatro",
326 "DELIMITER", TRIM_WHITESPACE, SPLIT_WANT_ALL);
327 ASSERT_EQ(7u, results.size());
328 EXPECT_THAT(results, ElementsAre("uno", "", "", "dos", "tres", "", "cuatro"));
329 }
330
TEST(SplitStringUsingSubstrTest,TrailingDelimitersSkipped)331 TEST(SplitStringUsingSubstrTest, TrailingDelimitersSkipped) {
332 std::vector<std::string> results = SplitStringUsingSubstr(
333 "unDELIMITERdeuxDELIMITERtroisDELIMITERquatreDELIMITERDELIMITERDELIMITER",
334 "DELIMITER", TRIM_WHITESPACE, SPLIT_WANT_ALL);
335 ASSERT_EQ(7u, results.size());
336 EXPECT_THAT(
337 results, ElementsAre("un", "deux", "trois", "quatre", "", "", ""));
338 }
339
TEST(SplitStringPieceUsingSubstrTest,StringWithNoDelimiter)340 TEST(SplitStringPieceUsingSubstrTest, StringWithNoDelimiter) {
341 std::vector<std::string_view> results =
342 SplitStringPieceUsingSubstr("alongwordwithnodelimiter", "DELIMITER",
343 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
344 ASSERT_EQ(1u, results.size());
345 EXPECT_THAT(results, ElementsAre("alongwordwithnodelimiter"));
346 }
347
TEST(SplitStringPieceUsingSubstrTest,LeadingDelimitersSkipped)348 TEST(SplitStringPieceUsingSubstrTest, LeadingDelimitersSkipped) {
349 std::vector<std::string_view> results = SplitStringPieceUsingSubstr(
350 "DELIMITERDELIMITERDELIMITERoneDELIMITERtwoDELIMITERthree", "DELIMITER",
351 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
352 ASSERT_EQ(6u, results.size());
353 EXPECT_THAT(results, ElementsAre("", "", "", "one", "two", "three"));
354 }
355
TEST(SplitStringPieceUsingSubstrTest,ConsecutiveDelimitersSkipped)356 TEST(SplitStringPieceUsingSubstrTest, ConsecutiveDelimitersSkipped) {
357 std::vector<std::string_view> results = SplitStringPieceUsingSubstr(
358 "unoDELIMITERDELIMITERDELIMITERdosDELIMITERtresDELIMITERDELIMITERcuatro",
359 "DELIMITER", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
360 ASSERT_EQ(7u, results.size());
361 EXPECT_THAT(results, ElementsAre("uno", "", "", "dos", "tres", "", "cuatro"));
362 }
363
TEST(SplitStringPieceUsingSubstrTest,TrailingDelimitersSkipped)364 TEST(SplitStringPieceUsingSubstrTest, TrailingDelimitersSkipped) {
365 std::vector<std::string_view> results = SplitStringPieceUsingSubstr(
366 "unDELIMITERdeuxDELIMITERtroisDELIMITERquatreDELIMITERDELIMITERDELIMITER",
367 "DELIMITER", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
368 ASSERT_EQ(7u, results.size());
369 EXPECT_THAT(results,
370 ElementsAre("un", "deux", "trois", "quatre", "", "", ""));
371 }
372
TEST(SplitStringPieceUsingSubstrTest,KeepWhitespace)373 TEST(SplitStringPieceUsingSubstrTest, KeepWhitespace) {
374 std::vector<std::string_view> results = SplitStringPieceUsingSubstr(
375 "un DELIMITERdeux\tDELIMITERtrois\nDELIMITERquatre", "DELIMITER",
376 base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
377 ASSERT_EQ(4u, results.size());
378 EXPECT_THAT(results, ElementsAre("un ", "deux\t", "trois\n", "quatre"));
379 }
380
TEST(SplitStringPieceUsingSubstrTest,TrimWhitespace)381 TEST(SplitStringPieceUsingSubstrTest, TrimWhitespace) {
382 std::vector<std::string_view> results = SplitStringPieceUsingSubstr(
383 "un DELIMITERdeux\tDELIMITERtrois\nDELIMITERquatre", "DELIMITER",
384 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
385 ASSERT_EQ(4u, results.size());
386 EXPECT_THAT(results, ElementsAre("un", "deux", "trois", "quatre"));
387 }
388
TEST(SplitStringPieceUsingSubstrTest,SplitWantAll)389 TEST(SplitStringPieceUsingSubstrTest, SplitWantAll) {
390 std::vector<std::string_view> results = SplitStringPieceUsingSubstr(
391 "unDELIMITERdeuxDELIMITERtroisDELIMITERDELIMITER", "DELIMITER",
392 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
393 ASSERT_EQ(5u, results.size());
394 EXPECT_THAT(results, ElementsAre("un", "deux", "trois", "", ""));
395 }
396
TEST(SplitStringPieceUsingSubstrTest,SplitWantNonEmpty)397 TEST(SplitStringPieceUsingSubstrTest, SplitWantNonEmpty) {
398 std::vector<std::string_view> results = SplitStringPieceUsingSubstr(
399 "unDELIMITERdeuxDELIMITERtroisDELIMITERDELIMITER", "DELIMITER",
400 base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
401 ASSERT_EQ(3u, results.size());
402 EXPECT_THAT(results, ElementsAre("un", "deux", "trois"));
403 }
404
TEST(StringSplitTest,SplitStringOnce)405 TEST(StringSplitTest, SplitStringOnce) {
406 // None of the separators are in the input, so should always be std::nullopt.
407 EXPECT_EQ(std::nullopt, SplitStringOnce("", ""));
408 EXPECT_EQ(std::nullopt, SplitStringOnce("a", ""));
409 EXPECT_EQ(std::nullopt, SplitStringOnce("ab", ""));
410
411 EXPECT_THAT(SplitStringOnce("a:b:c", ':'), Optional(Pair("a", "b:c")));
412 EXPECT_THAT(SplitStringOnce("a:", ':'), Optional(Pair("a", "")));
413 EXPECT_THAT(SplitStringOnce(":b", ':'), Optional(Pair("", "b")));
414
415 // Now the same using the multiple separators overload, but with only one
416 // separator specified.
417 EXPECT_THAT(SplitStringOnce("a:b:c", ":"), Optional(Pair("a", "b:c")));
418 EXPECT_THAT(SplitStringOnce("a:", ":"), Optional(Pair("a", "")));
419 EXPECT_THAT(SplitStringOnce(":b", ":"), Optional(Pair("", "b")));
420
421 // Multiple separators overload, but only the first one present.
422 EXPECT_THAT(SplitStringOnce("a:b:c", ":="), Optional(Pair("a", "b:c")));
423 EXPECT_THAT(SplitStringOnce("a:", ":="), Optional(Pair("a", "")));
424 EXPECT_THAT(SplitStringOnce(":b", ":="), Optional(Pair("", "b")));
425
426 // Multiple separators overload, but only the second one present.
427 EXPECT_THAT(SplitStringOnce("a:b:c", "=:"), Optional(Pair("a", "b:c")));
428 EXPECT_THAT(SplitStringOnce("a:", "=:"), Optional(Pair("a", "")));
429 EXPECT_THAT(SplitStringOnce(":b", "=:"), Optional(Pair("", "b")));
430
431 // Multiple separators overload, both present. The separator that comes first
432 // in the input string (not separators string) should win.
433 EXPECT_THAT(SplitStringOnce("a:b=c", ":="), Optional(Pair("a", "b=c")));
434 EXPECT_THAT(SplitStringOnce("a:b=c", "=:"), Optional(Pair("a", "b=c")));
435 EXPECT_THAT(SplitStringOnce("a=b:c", ":="), Optional(Pair("a", "b:c")));
436 EXPECT_THAT(SplitStringOnce("a=b:c", "=:"), Optional(Pair("a", "b:c")));
437 }
438
TEST(StringSplitTest,RSplitStringOnce)439 TEST(StringSplitTest, RSplitStringOnce) {
440 // None of the separators are in the input, so should always be std::nullopt.
441 EXPECT_EQ(std::nullopt, RSplitStringOnce("", ""));
442 EXPECT_EQ(std::nullopt, RSplitStringOnce("a", ""));
443 EXPECT_EQ(std::nullopt, RSplitStringOnce("ab", ""));
444
445 EXPECT_THAT(RSplitStringOnce("a:b:c", ':'), Optional(Pair("a:b", "c")));
446 EXPECT_THAT(RSplitStringOnce("a:", ':'), Optional(Pair("a", "")));
447 EXPECT_THAT(RSplitStringOnce(":b", ':'), Optional(Pair("", "b")));
448
449 // Now the same using the multiple separators overload, but with only one
450 // separator specified.
451 EXPECT_THAT(RSplitStringOnce("a:b:c", ":"), Optional(Pair("a:b", "c")));
452 EXPECT_THAT(RSplitStringOnce("a:", ":"), Optional(Pair("a", "")));
453 EXPECT_THAT(RSplitStringOnce(":b", ":"), Optional(Pair("", "b")));
454
455 // Multiple separators overload, but only the first one present.
456 EXPECT_THAT(RSplitStringOnce("a:b:c", ":="), Optional(Pair("a:b", "c")));
457 EXPECT_THAT(RSplitStringOnce("a:", ":="), Optional(Pair("a", "")));
458 EXPECT_THAT(RSplitStringOnce(":b", ":="), Optional(Pair("", "b")));
459
460 // Multiple separators overload, but only the second one present.
461 EXPECT_THAT(RSplitStringOnce("a:b:c", "=:"), Optional(Pair("a:b", "c")));
462 EXPECT_THAT(RSplitStringOnce("a:", "=:"), Optional(Pair("a", "")));
463 EXPECT_THAT(RSplitStringOnce(":b", "=:"), Optional(Pair("", "b")));
464
465 // Multiple separators overload, both present. The separator that comes first
466 // in the input string (not separators string) should win.
467 EXPECT_THAT(RSplitStringOnce("a:b=c", ":="), Optional(Pair("a:b", "c")));
468 EXPECT_THAT(RSplitStringOnce("a:b=c", "=:"), Optional(Pair("a:b", "c")));
469 EXPECT_THAT(RSplitStringOnce("a=b:c", ":="), Optional(Pair("a=b", "c")));
470 EXPECT_THAT(RSplitStringOnce("a=b:c", "=:"), Optional(Pair("a=b", "c")));
471 }
472
TEST(StringSplitTest,StringSplitKeepWhitespace)473 TEST(StringSplitTest, StringSplitKeepWhitespace) {
474 std::vector<std::string> r;
475
476 r = SplitString(" ", "*", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
477 ASSERT_EQ(1U, r.size());
478 EXPECT_EQ(r[0], " ");
479
480 r = SplitString("\t \ta\t ", "\t", base::KEEP_WHITESPACE,
481 base::SPLIT_WANT_ALL);
482 ASSERT_EQ(4U, r.size());
483 EXPECT_EQ(r[0], "");
484 EXPECT_EQ(r[1], " ");
485 EXPECT_EQ(r[2], "a");
486 EXPECT_EQ(r[3], " ");
487
488 r = SplitString("\ta\t\nb\tcc", "\n", base::KEEP_WHITESPACE,
489 base::SPLIT_WANT_ALL);
490 ASSERT_EQ(2U, r.size());
491 EXPECT_EQ(r[0], "\ta\t");
492 EXPECT_EQ(r[1], "b\tcc");
493 }
494
TEST(StringSplitTest,SplitStringAlongWhitespace)495 TEST(StringSplitTest, SplitStringAlongWhitespace) {
496 struct TestData {
497 const char* input;
498 const size_t expected_result_count;
499 const char* output1;
500 const char* output2;
501 } data[] = {
502 { "a", 1, "a", "" },
503 { " ", 0, "", "" },
504 { " a", 1, "a", "" },
505 { " ab ", 1, "ab", "" },
506 { " ab c", 2, "ab", "c" },
507 { " ab c ", 2, "ab", "c" },
508 { " ab cd", 2, "ab", "cd" },
509 { " ab cd ", 2, "ab", "cd" },
510 { " \ta\t", 1, "a", "" },
511 { " b\ta\t", 2, "b", "a" },
512 { " b\tat", 2, "b", "at" },
513 { "b\tat", 2, "b", "at" },
514 { "b\t at", 2, "b", "at" },
515 };
516 for (const TestData& i : data) {
517 std::vector<std::string> results =
518 base::SplitString(i.input, kWhitespaceASCII, base::KEEP_WHITESPACE,
519 base::SPLIT_WANT_NONEMPTY);
520 ASSERT_EQ(i.expected_result_count, results.size());
521 if (i.expected_result_count > 0)
522 ASSERT_EQ(i.output1, results[0]);
523 if (i.expected_result_count > 1)
524 ASSERT_EQ(i.output2, results[1]);
525 }
526 }
527
TEST(StringSplitTest,NullSeparatorWantNonEmpty)528 TEST(StringSplitTest, NullSeparatorWantNonEmpty) {
529 struct TestData {
530 std::string_view test_case;
531 std::vector<std::string_view> expected;
532 } data[] = {
533 {base::MakeStringViewWithNulChars("a"), {"a"}},
534 {base::MakeStringViewWithNulChars("a\0"), {"a"}},
535 {base::MakeStringViewWithNulChars("a\0a"), {"a", "a"}},
536 {base::MakeStringViewWithNulChars("\0a\0\0a\0"), {"a", "a"}},
537 };
538
539 for (const auto& i : data) {
540 std::vector<std::string_view> results = base::SplitStringPiece(
541 i.test_case, base::MakeStringViewWithNulChars("\0"),
542 base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
543 EXPECT_EQ(results, i.expected);
544 }
545 }
546
TEST(StringSplitTest,NullSeparatorWantAll)547 TEST(StringSplitTest, NullSeparatorWantAll) {
548 struct TestData {
549 std::string_view test_case;
550 std::vector<std::string_view> expected;
551 } data[] = {
552 {base::MakeStringViewWithNulChars("a"), {"a"}},
553 {base::MakeStringViewWithNulChars("a\0"), {"a", ""}},
554 {base::MakeStringViewWithNulChars("a\0a"), {"a", "a"}},
555 {base::MakeStringViewWithNulChars("\0a\0\0a\0"), {"", "a", "", "a", ""}},
556 };
557
558 for (const TestData& i : data) {
559 std::vector<std::string_view> results = base::SplitStringPiece(
560 i.test_case, base::MakeStringViewWithNulChars("\0"),
561 base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
562 EXPECT_EQ(results, i.expected);
563 }
564 }
565
566 } // namespace base
567