1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
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 "base/strings/utf_string_conversions.h"
8#include "testing/gmock/include/gmock/gmock.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
11using ::testing::ElementsAre;
12
13namespace base {
14
15namespace {
16
17#if !defined(WCHAR_T_IS_UTF16)
18// Overload SplitString with a wide-char version to make it easier to
19// test the string16 version with wide character literals.
20void SplitString(const std::wstring& str,
21                 wchar_t c,
22                 std::vector<std::wstring>* result) {
23  std::vector<string16> result16;
24  SplitString(WideToUTF16(str), c, &result16);
25  for (size_t i = 0; i < result16.size(); ++i)
26    result->push_back(UTF16ToWide(result16[i]));
27}
28#endif
29
30}  // anonymous namespace
31
32class SplitStringIntoKeyValuePairsTest : public testing::Test {
33 protected:
34  base::StringPairs kv_pairs;
35};
36
37TEST_F(SplitStringIntoKeyValuePairsTest, EmptyString) {
38  EXPECT_TRUE(SplitStringIntoKeyValuePairs(std::string(),
39                                           ':',  // Key-value delimiter
40                                           ',',  // Key-value pair delimiter
41                                           &kv_pairs));
42  EXPECT_TRUE(kv_pairs.empty());
43}
44
45TEST_F(SplitStringIntoKeyValuePairsTest, MissingKeyValueDelimiter) {
46  EXPECT_FALSE(SplitStringIntoKeyValuePairs("key1,key2:value2",
47                                            ':',  // Key-value delimiter
48                                            ',',  // Key-value pair delimiter
49                                            &kv_pairs));
50  ASSERT_EQ(2U, kv_pairs.size());
51  EXPECT_TRUE(kv_pairs[0].first.empty());
52  EXPECT_TRUE(kv_pairs[0].second.empty());
53  EXPECT_EQ("key2", kv_pairs[1].first);
54  EXPECT_EQ("value2", kv_pairs[1].second);
55}
56
57TEST_F(SplitStringIntoKeyValuePairsTest, EmptyKeyWithKeyValueDelimiter) {
58  EXPECT_TRUE(SplitStringIntoKeyValuePairs(":value1,key2:value2",
59                                           ':',  // Key-value delimiter
60                                           ',',  // Key-value pair delimiter
61                                           &kv_pairs));
62  ASSERT_EQ(2U, kv_pairs.size());
63  EXPECT_TRUE(kv_pairs[0].first.empty());
64  EXPECT_EQ("value1", kv_pairs[0].second);
65  EXPECT_EQ("key2", kv_pairs[1].first);
66  EXPECT_EQ("value2", kv_pairs[1].second);
67}
68
69TEST_F(SplitStringIntoKeyValuePairsTest, TrailingAndLeadingPairDelimiter) {
70  EXPECT_TRUE(SplitStringIntoKeyValuePairs(",key1:value1,key2:value2,",
71                                           ':',   // Key-value delimiter
72                                           ',',   // Key-value pair delimiter
73                                           &kv_pairs));
74  ASSERT_EQ(2U, kv_pairs.size());
75  EXPECT_EQ("key1", kv_pairs[0].first);
76  EXPECT_EQ("value1", kv_pairs[0].second);
77  EXPECT_EQ("key2", kv_pairs[1].first);
78  EXPECT_EQ("value2", kv_pairs[1].second);
79}
80
81TEST_F(SplitStringIntoKeyValuePairsTest, EmptyPair) {
82  EXPECT_TRUE(SplitStringIntoKeyValuePairs("key1:value1,,key3:value3",
83                                           ':',   // Key-value delimiter
84                                           ',',   // Key-value pair delimiter
85                                           &kv_pairs));
86  ASSERT_EQ(2U, kv_pairs.size());
87  EXPECT_EQ("key1", kv_pairs[0].first);
88  EXPECT_EQ("value1", kv_pairs[0].second);
89  EXPECT_EQ("key3", kv_pairs[1].first);
90  EXPECT_EQ("value3", kv_pairs[1].second);
91}
92
93TEST_F(SplitStringIntoKeyValuePairsTest, EmptyValue) {
94  EXPECT_FALSE(SplitStringIntoKeyValuePairs("key1:,key2:value2",
95                                            ':',   // Key-value delimiter
96                                            ',',   // Key-value pair delimiter
97                                            &kv_pairs));
98  ASSERT_EQ(2U, kv_pairs.size());
99  EXPECT_EQ("key1", kv_pairs[0].first);
100  EXPECT_EQ("", kv_pairs[0].second);
101  EXPECT_EQ("key2", kv_pairs[1].first);
102  EXPECT_EQ("value2", kv_pairs[1].second);
103}
104
105TEST_F(SplitStringIntoKeyValuePairsTest, UntrimmedWhitespace) {
106  EXPECT_TRUE(SplitStringIntoKeyValuePairs("key1 : value1",
107                                           ':',  // Key-value delimiter
108                                           ',',  // Key-value pair delimiter
109                                           &kv_pairs));
110  ASSERT_EQ(1U, kv_pairs.size());
111  EXPECT_EQ("key1 ", kv_pairs[0].first);
112  EXPECT_EQ(" value1", kv_pairs[0].second);
113}
114
115TEST_F(SplitStringIntoKeyValuePairsTest, TrimmedWhitespace) {
116  EXPECT_TRUE(SplitStringIntoKeyValuePairs("key1:value1 , key2:value2",
117                                           ':',   // Key-value delimiter
118                                           ',',   // Key-value pair delimiter
119                                           &kv_pairs));
120  ASSERT_EQ(2U, kv_pairs.size());
121  EXPECT_EQ("key1", kv_pairs[0].first);
122  EXPECT_EQ("value1", kv_pairs[0].second);
123  EXPECT_EQ("key2", kv_pairs[1].first);
124  EXPECT_EQ("value2", kv_pairs[1].second);
125}
126
127TEST_F(SplitStringIntoKeyValuePairsTest, MultipleKeyValueDelimiters) {
128  EXPECT_TRUE(SplitStringIntoKeyValuePairs("key1:::value1,key2:value2",
129                                           ':',   // Key-value delimiter
130                                           ',',   // Key-value pair delimiter
131                                           &kv_pairs));
132  ASSERT_EQ(2U, kv_pairs.size());
133  EXPECT_EQ("key1", kv_pairs[0].first);
134  EXPECT_EQ("value1", kv_pairs[0].second);
135  EXPECT_EQ("key2", kv_pairs[1].first);
136  EXPECT_EQ("value2", kv_pairs[1].second);
137}
138
139TEST_F(SplitStringIntoKeyValuePairsTest, OnlySplitAtGivenSeparator) {
140  std::string a("a ?!@#$%^&*()_+:/{}\\\t\nb");
141  EXPECT_TRUE(SplitStringIntoKeyValuePairs(a + "X" + a + "Y" + a + "X" + a,
142                                           'X',  // Key-value delimiter
143                                           'Y',  // Key-value pair delimiter
144                                           &kv_pairs));
145  ASSERT_EQ(2U, kv_pairs.size());
146  EXPECT_EQ(a, kv_pairs[0].first);
147  EXPECT_EQ(a, kv_pairs[0].second);
148  EXPECT_EQ(a, kv_pairs[1].first);
149  EXPECT_EQ(a, kv_pairs[1].second);
150}
151
152
153TEST_F(SplitStringIntoKeyValuePairsTest, DelimiterInValue) {
154  EXPECT_TRUE(SplitStringIntoKeyValuePairs("key1:va:ue1,key2:value2",
155                                           ':',   // Key-value delimiter
156                                           ',',   // Key-value pair delimiter
157                                           &kv_pairs));
158  ASSERT_EQ(2U, kv_pairs.size());
159  EXPECT_EQ("key1", kv_pairs[0].first);
160  EXPECT_EQ("va:ue1", kv_pairs[0].second);
161  EXPECT_EQ("key2", kv_pairs[1].first);
162  EXPECT_EQ("value2", kv_pairs[1].second);
163}
164
165TEST(SplitStringUsingSubstrTest, EmptyString) {
166  std::vector<std::string> results;
167  SplitStringUsingSubstr(std::string(), "DELIMITER", &results);
168  ASSERT_EQ(1u, results.size());
169  EXPECT_THAT(results, ElementsAre(""));
170}
171
172TEST(StringUtilTest, SplitString) {
173  std::vector<std::wstring> r;
174
175  SplitString(std::wstring(), L',', &r);
176  EXPECT_EQ(0U, r.size());
177  r.clear();
178
179  SplitString(L"a,b,c", L',', &r);
180  ASSERT_EQ(3U, r.size());
181  EXPECT_EQ(r[0], L"a");
182  EXPECT_EQ(r[1], L"b");
183  EXPECT_EQ(r[2], L"c");
184  r.clear();
185
186  SplitString(L"a, b, c", L',', &r);
187  ASSERT_EQ(3U, r.size());
188  EXPECT_EQ(r[0], L"a");
189  EXPECT_EQ(r[1], L"b");
190  EXPECT_EQ(r[2], L"c");
191  r.clear();
192
193  SplitString(L"a,,c", L',', &r);
194  ASSERT_EQ(3U, r.size());
195  EXPECT_EQ(r[0], L"a");
196  EXPECT_EQ(r[1], L"");
197  EXPECT_EQ(r[2], L"c");
198  r.clear();
199
200  SplitString(L"   ", L'*', &r);
201  EXPECT_EQ(0U, r.size());
202  r.clear();
203
204  SplitString(L"foo", L'*', &r);
205  ASSERT_EQ(1U, r.size());
206  EXPECT_EQ(r[0], L"foo");
207  r.clear();
208
209  SplitString(L"foo ,", L',', &r);
210  ASSERT_EQ(2U, r.size());
211  EXPECT_EQ(r[0], L"foo");
212  EXPECT_EQ(r[1], L"");
213  r.clear();
214
215  SplitString(L",", L',', &r);
216  ASSERT_EQ(2U, r.size());
217  EXPECT_EQ(r[0], L"");
218  EXPECT_EQ(r[1], L"");
219  r.clear();
220
221  SplitString(L"\t\ta\t", L'\t', &r);
222  ASSERT_EQ(4U, r.size());
223  EXPECT_EQ(r[0], L"");
224  EXPECT_EQ(r[1], L"");
225  EXPECT_EQ(r[2], L"a");
226  EXPECT_EQ(r[3], L"");
227  r.clear();
228
229  SplitString(L"\ta\t\nb\tcc", L'\n', &r);
230  ASSERT_EQ(2U, r.size());
231  EXPECT_EQ(r[0], L"a");
232  EXPECT_EQ(r[1], L"b\tcc");
233  r.clear();
234}
235
236TEST(SplitStringUsingSubstrTest, StringWithNoDelimiter) {
237  std::vector<std::string> results;
238  SplitStringUsingSubstr("alongwordwithnodelimiter", "DELIMITER", &results);
239  ASSERT_EQ(1u, results.size());
240  EXPECT_THAT(results, ElementsAre("alongwordwithnodelimiter"));
241}
242
243TEST(SplitStringUsingSubstrTest, LeadingDelimitersSkipped) {
244  std::vector<std::string> results;
245  SplitStringUsingSubstr(
246      "DELIMITERDELIMITERDELIMITERoneDELIMITERtwoDELIMITERthree",
247      "DELIMITER",
248      &results);
249  ASSERT_EQ(6u, results.size());
250  EXPECT_THAT(results, ElementsAre("", "", "", "one", "two", "three"));
251}
252
253TEST(SplitStringUsingSubstrTest, ConsecutiveDelimitersSkipped) {
254  std::vector<std::string> results;
255  SplitStringUsingSubstr(
256      "unoDELIMITERDELIMITERDELIMITERdosDELIMITERtresDELIMITERDELIMITERcuatro",
257      "DELIMITER",
258      &results);
259  ASSERT_EQ(7u, results.size());
260  EXPECT_THAT(results, ElementsAre("uno", "", "", "dos", "tres", "", "cuatro"));
261}
262
263TEST(SplitStringUsingSubstrTest, TrailingDelimitersSkipped) {
264  std::vector<std::string> results;
265  SplitStringUsingSubstr(
266      "unDELIMITERdeuxDELIMITERtroisDELIMITERquatreDELIMITERDELIMITERDELIMITER",
267      "DELIMITER",
268      &results);
269  ASSERT_EQ(7u, results.size());
270  EXPECT_THAT(
271      results, ElementsAre("un", "deux", "trois", "quatre", "", "", ""));
272}
273
274TEST(StringSplitTest, StringSplitDontTrim) {
275  std::vector<std::string> r;
276
277  SplitStringDontTrim("   ", '*', &r);
278  ASSERT_EQ(1U, r.size());
279  EXPECT_EQ(r[0], "   ");
280
281  SplitStringDontTrim("\t  \ta\t ", '\t', &r);
282  ASSERT_EQ(4U, r.size());
283  EXPECT_EQ(r[0], "");
284  EXPECT_EQ(r[1], "  ");
285  EXPECT_EQ(r[2], "a");
286  EXPECT_EQ(r[3], " ");
287
288  SplitStringDontTrim("\ta\t\nb\tcc", '\n', &r);
289  ASSERT_EQ(2U, r.size());
290  EXPECT_EQ(r[0], "\ta\t");
291  EXPECT_EQ(r[1], "b\tcc");
292}
293
294TEST(StringSplitTest, SplitStringAlongWhitespace) {
295  struct TestData {
296    const char* input;
297    const size_t expected_result_count;
298    const char* output1;
299    const char* output2;
300  } data[] = {
301    { "a",       1, "a",  ""   },
302    { " ",       0, "",   ""   },
303    { " a",      1, "a",  ""   },
304    { " ab ",    1, "ab", ""   },
305    { " ab c",   2, "ab", "c"  },
306    { " ab c ",  2, "ab", "c"  },
307    { " ab cd",  2, "ab", "cd" },
308    { " ab cd ", 2, "ab", "cd" },
309    { " \ta\t",  1, "a",  ""   },
310    { " b\ta\t", 2, "b",  "a"  },
311    { " b\tat",  2, "b",  "at" },
312    { "b\tat",   2, "b",  "at" },
313    { "b\t at",  2, "b",  "at" },
314  };
315  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
316    std::vector<std::string> results;
317    SplitStringAlongWhitespace(data[i].input, &results);
318    ASSERT_EQ(data[i].expected_result_count, results.size());
319    if (data[i].expected_result_count > 0)
320      ASSERT_EQ(data[i].output1, results[0]);
321    if (data[i].expected_result_count > 1)
322      ASSERT_EQ(data[i].output2, results[1]);
323  }
324}
325
326}  // namespace base
327