• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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