1/*
2 * Copyright (C) 2009 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.base;
18
19import static org.junit.contrib.truth.Truth.ASSERT;
20
21import com.google.common.annotations.GwtCompatible;
22import com.google.common.annotations.GwtIncompatible;
23import com.google.common.collect.ImmutableList;
24import com.google.common.collect.ImmutableMap;
25import com.google.common.testing.NullPointerTester;
26
27import junit.framework.TestCase;
28
29import java.util.Collection;
30import java.util.Iterator;
31import java.util.List;
32import java.util.Map;
33import java.util.regex.Pattern;
34
35/**
36 * @author Julien Silland
37 */
38@GwtCompatible(emulated = true)
39public class SplitterTest extends TestCase {
40
41  private static final Splitter COMMA_SPLITTER = Splitter.on(',');
42
43  public void testSplitNullString() {
44    try {
45      COMMA_SPLITTER.split(null);
46      fail();
47    } catch (NullPointerException expected) {
48    }
49  }
50
51  public void testCharacterSimpleSplit() {
52    String simple = "a,b,c";
53    Iterable<String> letters = COMMA_SPLITTER.split(simple);
54    ASSERT.that(letters).hasContentsInOrder("a", "b", "c");
55  }
56
57  public void testCharacterSimpleSplitWithNoDelimiter() {
58    String simple = "a,b,c";
59    Iterable<String> letters = Splitter.on('.').split(simple);
60    ASSERT.that(letters).hasContentsInOrder("a,b,c");
61  }
62
63  public void testCharacterSplitWithDoubleDelimiter() {
64    String doubled = "a,,b,c";
65    Iterable<String> letters = COMMA_SPLITTER.split(doubled);
66    ASSERT.that(letters).hasContentsInOrder("a", "", "b", "c");
67  }
68
69  public void testCharacterSplitWithDoubleDelimiterAndSpace() {
70    String doubled = "a,, b,c";
71    Iterable<String> letters = COMMA_SPLITTER.split(doubled);
72    ASSERT.that(letters).hasContentsInOrder("a", "", " b", "c");
73  }
74
75  public void testCharacterSplitWithTrailingDelimiter() {
76    String trailing = "a,b,c,";
77    Iterable<String> letters = COMMA_SPLITTER.split(trailing);
78    ASSERT.that(letters).hasContentsInOrder("a", "b", "c", "");
79  }
80
81  public void testCharacterSplitWithLeadingDelimiter() {
82    String leading = ",a,b,c";
83    Iterable<String> letters = COMMA_SPLITTER.split(leading);
84    ASSERT.that(letters).hasContentsInOrder("", "a", "b", "c");
85  }
86
87  public void testCharacterSplitWithMulitpleLetters() {
88    Iterable<String> testCharacteringMotto = Splitter.on('-').split(
89        "Testing-rocks-Debugging-sucks");
90    ASSERT.that(testCharacteringMotto).hasContentsInOrder(
91        "Testing", "rocks", "Debugging", "sucks");
92  }
93
94  public void testCharacterSplitWithMatcherDelimiter() {
95    Iterable<String> testCharacteringMotto = Splitter
96        .on(CharMatcher.WHITESPACE)
97        .split("Testing\nrocks\tDebugging sucks");
98    ASSERT.that(testCharacteringMotto).hasContentsInOrder(
99        "Testing", "rocks", "Debugging", "sucks");
100  }
101
102  public void testCharacterSplitWithDoubleDelimiterOmitEmptyStrings() {
103    String doubled = "a..b.c";
104    Iterable<String> letters = Splitter.on('.')
105        .omitEmptyStrings().split(doubled);
106    ASSERT.that(letters).hasContentsInOrder("a", "b", "c");
107  }
108
109  public void testCharacterSplitEmptyToken() {
110    String emptyToken = "a. .c";
111    Iterable<String> letters = Splitter.on('.').trimResults()
112        .split(emptyToken);
113    ASSERT.that(letters).hasContentsInOrder("a", "", "c");
114  }
115
116  public void testCharacterSplitEmptyTokenOmitEmptyStrings() {
117    String emptyToken = "a. .c";
118    Iterable<String> letters = Splitter.on('.')
119        .omitEmptyStrings().trimResults().split(emptyToken);
120    ASSERT.that(letters).hasContentsInOrder("a", "c");
121  }
122
123  public void testCharacterSplitOnEmptyString() {
124    Iterable<String> nothing = Splitter.on('.').split("");
125    ASSERT.that(nothing).hasContentsInOrder("");
126  }
127
128  public void testCharacterSplitOnEmptyStringOmitEmptyStrings() {
129    ASSERT.that(Splitter.on('.').omitEmptyStrings().split("")).isEmpty();
130  }
131
132  public void testCharacterSplitOnOnlyDelimiter() {
133    Iterable<String> blankblank = Splitter.on('.').split(".");
134    ASSERT.that(blankblank).hasContentsInOrder("", "");
135  }
136
137  public void testCharacterSplitOnOnlyDelimitersOmitEmptyStrings() {
138    Iterable<String> empty = Splitter.on('.').omitEmptyStrings().split("...");
139    ASSERT.that(empty);
140  }
141
142  public void testCharacterSplitWithTrim() {
143    String jacksons = "arfo(Marlon)aorf, (Michael)orfa, afro(Jackie)orfa, "
144        + "ofar(Jemaine), aff(Tito)";
145    Iterable<String> family = COMMA_SPLITTER
146        .trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
147        .split(jacksons);
148    ASSERT.that(family).hasContentsInOrder(
149        "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
150  }
151
152  public void testStringSimpleSplit() {
153    String simple = "a,b,c";
154    Iterable<String> letters = Splitter.on(",").split(simple);
155    ASSERT.that(letters).hasContentsInOrder("a", "b", "c");
156  }
157
158  public void testStringSimpleSplitWithNoDelimiter() {
159    String simple = "a,b,c";
160    Iterable<String> letters = Splitter.on(".").split(simple);
161    ASSERT.that(letters).hasContentsInOrder("a,b,c");
162  }
163
164  public void testStringSplitWithDoubleDelimiter() {
165    String doubled = "a,,b,c";
166    Iterable<String> letters = Splitter.on(",").split(doubled);
167    ASSERT.that(letters).hasContentsInOrder("a", "", "b", "c");
168  }
169
170  public void testStringSplitWithDoubleDelimiterAndSpace() {
171    String doubled = "a,, b,c";
172    Iterable<String> letters = Splitter.on(",").split(doubled);
173    ASSERT.that(letters).hasContentsInOrder("a", "", " b", "c");
174  }
175
176  public void testStringSplitWithTrailingDelimiter() {
177    String trailing = "a,b,c,";
178    Iterable<String> letters = Splitter.on(",").split(trailing);
179    ASSERT.that(letters).hasContentsInOrder("a", "b", "c", "");
180  }
181
182  public void testStringSplitWithLeadingDelimiter() {
183    String leading = ",a,b,c";
184    Iterable<String> letters = Splitter.on(",").split(leading);
185    ASSERT.that(letters).hasContentsInOrder("", "a", "b", "c");
186  }
187
188  public void testStringSplitWithMultipleLetters() {
189    Iterable<String> testStringingMotto = Splitter.on("-").split(
190        "Testing-rocks-Debugging-sucks");
191    ASSERT.that(testStringingMotto).hasContentsInOrder(
192        "Testing", "rocks", "Debugging", "sucks");
193  }
194
195  public void testStringSplitWithDoubleDelimiterOmitEmptyStrings() {
196    String doubled = "a..b.c";
197    Iterable<String> letters = Splitter.on(".")
198        .omitEmptyStrings().split(doubled);
199    ASSERT.that(letters).hasContentsInOrder("a", "b", "c");
200  }
201
202  public void testStringSplitEmptyToken() {
203    String emptyToken = "a. .c";
204    Iterable<String> letters = Splitter.on(".").trimResults()
205        .split(emptyToken);
206    ASSERT.that(letters).hasContentsInOrder("a", "", "c");
207  }
208
209  public void testStringSplitEmptyTokenOmitEmptyStrings() {
210    String emptyToken = "a. .c";
211    Iterable<String> letters = Splitter.on(".")
212        .omitEmptyStrings().trimResults().split(emptyToken);
213    ASSERT.that(letters).hasContentsInOrder("a", "c");
214  }
215
216  public void testStringSplitWithLongDelimiter() {
217    String longDelimiter = "a, b, c";
218    Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
219    ASSERT.that(letters).hasContentsInOrder("a", "b", "c");
220  }
221
222  public void testStringSplitWithLongLeadingDelimiter() {
223    String longDelimiter = ", a, b, c";
224    Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
225    ASSERT.that(letters).hasContentsInOrder("", "a", "b", "c");
226  }
227
228  public void testStringSplitWithLongTrailingDelimiter() {
229    String longDelimiter = "a, b, c, ";
230    Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
231    ASSERT.that(letters).hasContentsInOrder("a", "b", "c", "");
232  }
233
234  public void testStringSplitWithDelimiterSubstringInValue() {
235    String fourCommasAndFourSpaces = ",,,,    ";
236    Iterable<String> threeCommasThenThreeSpaces = Splitter.on(", ").split(
237        fourCommasAndFourSpaces);
238    ASSERT.that(threeCommasThenThreeSpaces).hasContentsInOrder(",,,", "   ");
239  }
240
241  public void testStringSplitWithEmptyString() {
242    try {
243      Splitter.on("");
244      fail();
245    } catch (IllegalArgumentException expected) {
246    }
247  }
248
249  public void testStringSplitOnEmptyString() {
250    Iterable<String> notMuch = Splitter.on(".").split("");
251    ASSERT.that(notMuch).hasContentsInOrder("");
252  }
253
254  public void testStringSplitOnEmptyStringOmitEmptyString() {
255    ASSERT.that(Splitter.on(".").omitEmptyStrings().split("")).isEmpty();
256  }
257
258  public void testStringSplitOnOnlyDelimiter() {
259    Iterable<String> blankblank = Splitter.on(".").split(".");
260    ASSERT.that(blankblank).hasContentsInOrder("", "");
261  }
262
263  public void testStringSplitOnOnlyDelimitersOmitEmptyStrings() {
264    Iterable<String> empty = Splitter.on(".").omitEmptyStrings().split("...");
265    ASSERT.that(empty).isEmpty();
266  }
267
268  public void testStringSplitWithTrim() {
269    String jacksons = "arfo(Marlon)aorf, (Michael)orfa, afro(Jackie)orfa, "
270        + "ofar(Jemaine), aff(Tito)";
271    Iterable<String> family = Splitter.on(",")
272        .trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
273        .split(jacksons);
274    ASSERT.that(family).hasContentsInOrder(
275        "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
276  }
277
278  @GwtIncompatible("Splitter.onPattern")
279  public void testPatternSimpleSplit() {
280    String simple = "a,b,c";
281    Iterable<String> letters = Splitter.onPattern(",").split(simple);
282    ASSERT.that(letters).hasContentsInOrder("a", "b", "c");
283  }
284
285  @GwtIncompatible("Splitter.onPattern")
286  public void testPatternSimpleSplitWithNoDelimiter() {
287    String simple = "a,b,c";
288    Iterable<String> letters = Splitter.onPattern("foo").split(simple);
289    ASSERT.that(letters).hasContentsInOrder("a,b,c");
290  }
291
292  @GwtIncompatible("Splitter.onPattern")
293  public void testPatternSplitWithDoubleDelimiter() {
294    String doubled = "a,,b,c";
295    Iterable<String> letters = Splitter.onPattern(",").split(doubled);
296    ASSERT.that(letters).hasContentsInOrder("a", "", "b", "c");
297  }
298
299  @GwtIncompatible("Splitter.onPattern")
300  public void testPatternSplitWithDoubleDelimiterAndSpace() {
301    String doubled = "a,, b,c";
302    Iterable<String> letters = Splitter.onPattern(",").split(doubled);
303    ASSERT.that(letters).hasContentsInOrder("a", "", " b", "c");
304  }
305
306  @GwtIncompatible("Splitter.onPattern")
307  public void testPatternSplitWithTrailingDelimiter() {
308    String trailing = "a,b,c,";
309    Iterable<String> letters = Splitter.onPattern(",").split(trailing);
310    ASSERT.that(letters).hasContentsInOrder("a", "b", "c", "");
311  }
312
313  @GwtIncompatible("Splitter.onPattern")
314  public void testPatternSplitWithLeadingDelimiter() {
315    String leading = ",a,b,c";
316    Iterable<String> letters = Splitter.onPattern(",").split(leading);
317    ASSERT.that(letters).hasContentsInOrder("", "a", "b", "c");
318  }
319
320  // TODO(kevinb): the name of this method suggests it might not actually be testing what it
321  // intends to be testing?
322  @GwtIncompatible("Splitter.onPattern")
323  public void testPatternSplitWithMultipleLetters() {
324    Iterable<String> testPatterningMotto = Splitter.onPattern("-").split(
325        "Testing-rocks-Debugging-sucks");
326    ASSERT.that(testPatterningMotto).hasContentsInOrder("Testing", "rocks", "Debugging", "sucks");
327  }
328
329  @GwtIncompatible("java.util.regex.Pattern")
330  private static Pattern literalDotPattern() {
331    return Pattern.compile("\\.");
332  }
333
334  @GwtIncompatible("java.util.regex.Pattern")
335  public void testPatternSplitWithDoubleDelimiterOmitEmptyStrings() {
336    String doubled = "a..b.c";
337    Iterable<String> letters = Splitter.on(literalDotPattern())
338        .omitEmptyStrings().split(doubled);
339    ASSERT.that(letters).hasContentsInOrder("a", "b", "c");
340  }
341
342  @GwtIncompatible("java.util.regex.Pattern")
343  public void testPatternSplitEmptyToken() {
344    String emptyToken = "a. .c";
345    Iterable<String> letters = Splitter.on(literalDotPattern()).trimResults().split(emptyToken);
346    ASSERT.that(letters).hasContentsInOrder("a", "", "c");
347  }
348
349  @GwtIncompatible("java.util.regex.Pattern")
350  public void testPatternSplitEmptyTokenOmitEmptyStrings() {
351    String emptyToken = "a. .c";
352    Iterable<String> letters = Splitter.on(literalDotPattern())
353        .omitEmptyStrings().trimResults().split(emptyToken);
354    ASSERT.that(letters).hasContentsInOrder("a", "c");
355  }
356
357  @GwtIncompatible("java.util.regex.Pattern")
358  public void testPatternSplitOnOnlyDelimiter() {
359    Iterable<String> blankblank = Splitter.on(literalDotPattern()).split(".");
360
361    ASSERT.that(blankblank).hasContentsInOrder("", "");
362  }
363
364  @GwtIncompatible("java.util.regex.Pattern")
365  public void testPatternSplitOnOnlyDelimitersOmitEmptyStrings() {
366    Iterable<String> empty = Splitter.on(literalDotPattern()).omitEmptyStrings()
367        .split("...");
368    ASSERT.that(empty).isEmpty();
369  }
370
371  @GwtIncompatible("java.util.regex.Pattern")
372  public void testPatternSplitMatchingIsGreedy() {
373    String longDelimiter = "a, b,   c";
374    Iterable<String> letters = Splitter.on(Pattern.compile(",\\s*"))
375        .split(longDelimiter);
376    ASSERT.that(letters).hasContentsInOrder("a", "b", "c");
377  }
378
379  @GwtIncompatible("java.util.regex.Pattern")
380  public void testPatternSplitWithLongLeadingDelimiter() {
381    String longDelimiter = ", a, b, c";
382    Iterable<String> letters = Splitter.on(Pattern.compile(", "))
383        .split(longDelimiter);
384    ASSERT.that(letters).hasContentsInOrder("", "a", "b", "c");
385  }
386
387  @GwtIncompatible("java.util.regex.Pattern")
388  public void testPatternSplitWithLongTrailingDelimiter() {
389    String longDelimiter = "a, b, c/ ";
390    Iterable<String> letters = Splitter.on(Pattern.compile("[,/]\\s"))
391        .split(longDelimiter);
392    ASSERT.that(letters).hasContentsInOrder("a", "b", "c", "");
393  }
394
395  @GwtIncompatible("java.util.regex.Pattern")
396  public void testPatternSplitInvalidPattern() {
397    try {
398      Splitter.on(Pattern.compile("a*"));
399      fail();
400    } catch (IllegalArgumentException expected) {
401    }
402  }
403
404  @GwtIncompatible("java.util.regex.Pattern")
405  public void testPatternSplitWithTrim() {
406    String jacksons = "arfo(Marlon)aorf, (Michael)orfa, afro(Jackie)orfa, "
407        + "ofar(Jemaine), aff(Tito)";
408    Iterable<String> family = Splitter.on(Pattern.compile(","))
409        .trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
410        .split(jacksons);
411    ASSERT.that(family).hasContentsInOrder(
412        "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
413  }
414
415  public void testSplitterIterableIsUnmodifiable_char() {
416    assertIteratorIsUnmodifiable(COMMA_SPLITTER.split("a,b").iterator());
417  }
418
419  public void testSplitterIterableIsUnmodifiable_string() {
420    assertIteratorIsUnmodifiable(Splitter.on(",").split("a,b").iterator());
421  }
422
423  @GwtIncompatible("java.util.regex.Pattern")
424  public void testSplitterIterableIsUnmodifiable_pattern() {
425    assertIteratorIsUnmodifiable(
426        Splitter.on(Pattern.compile(",")).split("a,b").iterator());
427  }
428
429  private void assertIteratorIsUnmodifiable(Iterator<?> iterator) {
430    iterator.next();
431    try {
432      iterator.remove();
433      fail();
434    } catch (UnsupportedOperationException expected) {
435    }
436  }
437
438  public void testSplitterIterableIsLazy_char() {
439    assertSplitterIterableIsLazy(COMMA_SPLITTER);
440  }
441
442  public void testSplitterIterableIsLazy_string() {
443    assertSplitterIterableIsLazy(Splitter.on(","));
444  }
445
446  @GwtIncompatible("java.util.regex.Pattern")
447  public void testSplitterIterableIsLazy_pattern() {
448    assertSplitterIterableIsLazy(Splitter.onPattern(","));
449  }
450
451  /**
452   * This test really pushes the boundaries of what we support. In general the
453   * splitter's behaviour is not well defined if the char sequence it's
454   * splitting is mutated during iteration.
455   */
456  private void assertSplitterIterableIsLazy(Splitter splitter) {
457    StringBuilder builder = new StringBuilder();
458    Iterator<String> iterator = splitter.split(builder).iterator();
459
460    builder.append("A,");
461    assertEquals("A", iterator.next());
462    builder.append("B,");
463    assertEquals("B", iterator.next());
464    builder.append("C");
465    assertEquals("C", iterator.next());
466    assertFalse(iterator.hasNext());
467  }
468
469  public void testAtEachSimpleSplit() {
470    String simple = "abcde";
471    Iterable<String> letters = Splitter.fixedLength(2).split(simple);
472    ASSERT.that(letters).hasContentsInOrder("ab", "cd", "e");
473  }
474
475  public void testAtEachSplitEqualChunkLength() {
476    String simple = "abcdef";
477    Iterable<String> letters = Splitter.fixedLength(2).split(simple);
478    ASSERT.that(letters).hasContentsInOrder("ab", "cd", "ef");
479  }
480
481  public void testAtEachSplitOnlyOneChunk() {
482    String simple = "abc";
483    Iterable<String> letters = Splitter.fixedLength(3).split(simple);
484    ASSERT.that(letters).hasContentsInOrder("abc");
485  }
486
487  public void testAtEachSplitSmallerString() {
488    String simple = "ab";
489    Iterable<String> letters = Splitter.fixedLength(3).split(simple);
490    ASSERT.that(letters).hasContentsInOrder("ab");
491  }
492
493  public void testAtEachSplitEmptyString() {
494    String simple = "";
495    Iterable<String> letters = Splitter.fixedLength(3).split(simple);
496    ASSERT.that(letters).hasContentsInOrder("");
497  }
498
499  public void testAtEachSplitEmptyStringWithOmitEmptyStrings() {
500    ASSERT.that(Splitter.fixedLength(3).omitEmptyStrings().split("")).isEmpty();
501  }
502
503  public void testAtEachSplitIntoChars() {
504    String simple = "abcd";
505    Iterable<String> letters = Splitter.fixedLength(1).split(simple);
506    ASSERT.that(letters).hasContentsInOrder("a", "b", "c", "d");
507  }
508
509  public void testAtEachSplitZeroChunkLen() {
510    try {
511      Splitter.fixedLength(0);
512      fail();
513    } catch (IllegalArgumentException expected) {
514    }
515  }
516
517  public void testAtEachSplitNegativeChunkLen() {
518    try {
519      Splitter.fixedLength(-1);
520      fail();
521    } catch (IllegalArgumentException expected) {
522    }
523  }
524
525  public void testLimitLarge() {
526    String simple = "abcd";
527    Iterable<String> letters = Splitter.fixedLength(1).limit(100).split(simple);
528    ASSERT.that(letters).hasContentsInOrder("a", "b", "c", "d");
529  }
530
531  public void testLimitOne() {
532    String simple = "abcd";
533    Iterable<String> letters = Splitter.fixedLength(1).limit(1).split(simple);
534    ASSERT.that(letters).hasContentsInOrder("abcd");
535  }
536
537  public void testLimitFixedLength() {
538    String simple = "abcd";
539    Iterable<String> letters = Splitter.fixedLength(1).limit(2).split(simple);
540    ASSERT.that(letters).hasContentsInOrder("a", "bcd");
541  }
542
543  public void testLimitSeparator() {
544    String simple = "a,b,c,d";
545    Iterable<String> items = COMMA_SPLITTER.limit(2).split(simple);
546    ASSERT.that(items).hasContentsInOrder("a", "b,c,d");
547  }
548
549  public void testLimitExtraSeparators() {
550    String text = "a,,,b,,c,d";
551    Iterable<String> items = COMMA_SPLITTER.limit(2).split(text);
552    ASSERT.that(items).hasContentsInOrder("a", ",,b,,c,d");
553  }
554
555  public void testLimitExtraSeparatorsOmitEmpty() {
556    String text = "a,,,b,,c,d";
557    Iterable<String> items = COMMA_SPLITTER.limit(2).omitEmptyStrings().split(text);
558    ASSERT.that(items).hasContentsInOrder("a", "b,,c,d");
559  }
560
561  public void testLimitExtraSeparatorsOmitEmpty3() {
562    String text = "a,,,b,,c,d";
563    Iterable<String> items = COMMA_SPLITTER.limit(3).omitEmptyStrings().split(text);
564    ASSERT.that(items).hasContentsInOrder("a", "b", "c,d");
565  }
566
567  public void testLimitExtraSeparatorsTrim() {
568    String text = ",,a,,  , b ,, c,d ";
569    Iterable<String> items = COMMA_SPLITTER.limit(2).omitEmptyStrings().trimResults().split(text);
570    ASSERT.that(items).hasContentsInOrder("a", "b ,, c,d");
571  }
572
573  public void testLimitExtraSeparatorsTrim3() {
574    String text = ",,a,,  , b ,, c,d ";
575    Iterable<String> items = COMMA_SPLITTER.limit(3).omitEmptyStrings().trimResults().split(text);
576    ASSERT.that(items).hasContentsInOrder("a", "b", "c,d");
577  }
578
579  public void testLimitExtraSeparatorsTrim1() {
580    String text = ",,a,,  , b ,, c,d ";
581    Iterable<String> items = COMMA_SPLITTER.limit(1).omitEmptyStrings().trimResults().split(text);
582    ASSERT.that(items).hasContentsInOrder("a,,  , b ,, c,d");
583  }
584
585  public void testLimitExtraSeparatorsTrim1NoOmit() {
586    String text = ",,a,,  , b ,, c,d ";
587    Iterable<String> items = COMMA_SPLITTER.limit(1).trimResults().split(text);
588    ASSERT.that(items).hasContentsInOrder(",,a,,  , b ,, c,d");
589  }
590
591  public void testLimitExtraSeparatorsTrim1Empty() {
592    String text = "";
593    Iterable<String> items = COMMA_SPLITTER.limit(1).split(text);
594    ASSERT.that(items).hasContentsInOrder("");
595  }
596
597  public void testLimitExtraSeparatorsTrim1EmptyOmit() {
598    String text = "";
599    Iterable<String> items = COMMA_SPLITTER.omitEmptyStrings().limit(1).split(text);
600    ASSERT.that(items).isEmpty();
601  }
602
603  public void testInvalidZeroLimit() {
604    try {
605      COMMA_SPLITTER.limit(0);
606      fail();
607    } catch (IllegalArgumentException expected) {
608    }
609  }
610
611  @GwtIncompatible("NullPointerTester")
612  public void testNullPointers() throws Exception {
613    NullPointerTester tester = new NullPointerTester();
614    tester.testAllPublicStaticMethods(Splitter.class);
615    tester.testAllPublicInstanceMethods(Splitter.on(","));
616    tester.testAllPublicInstanceMethods(Splitter.on(",").trimResults());
617  }
618
619  private static <E> List<E> asList(Collection<E> collection){
620    return ImmutableList.copyOf(collection);
621  }
622
623  public void testMapSplitter_trimmedBoth() {
624    Map<String, String> m = COMMA_SPLITTER
625        .trimResults()
626        .withKeyValueSeparator(Splitter.on(':').trimResults())
627        .split("boy  : tom , girl: tina , cat  : kitty , dog: tommy ");
628    ImmutableMap<String, String> expected =
629          ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
630    ASSERT.that(m).isEqualTo(expected);
631    ASSERT.that(asList(m.entrySet())).is(asList(expected.entrySet()));
632  }
633
634  public void testMapSplitter_trimmedEntries() {
635    Map<String, String> m = COMMA_SPLITTER
636        .trimResults()
637        .withKeyValueSeparator(":")
638        .split("boy  : tom , girl: tina , cat  : kitty , dog: tommy ");
639    ImmutableMap<String, String> expected =
640        ImmutableMap.of("boy  ", " tom", "girl", " tina", "cat  ", " kitty", "dog", " tommy");
641
642    ASSERT.that(m).isEqualTo(expected);
643    ASSERT.that(asList(m.entrySet())).is(asList(expected.entrySet()));
644  }
645
646  public void testMapSplitter_trimmedKeyValue() {
647    Map<String, String> m =
648        COMMA_SPLITTER.withKeyValueSeparator(Splitter.on(':').trimResults()).split(
649            "boy  : tom , girl: tina , cat  : kitty , dog: tommy ");
650    ImmutableMap<String, String> expected =
651        ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
652    ASSERT.that(m).isEqualTo(expected);
653    ASSERT.that(asList(m.entrySet())).is(asList(expected.entrySet()));
654  }
655
656  public void testMapSplitter_notTrimmed() {
657    Map<String, String> m = COMMA_SPLITTER.withKeyValueSeparator(":").split(
658        " boy:tom , girl: tina , cat :kitty , dog:  tommy ");
659    ImmutableMap<String, String> expected =
660        ImmutableMap.of(" boy", "tom ", " girl", " tina ", " cat ", "kitty ", " dog", "  tommy ");
661    ASSERT.that(m).isEqualTo(expected);
662    ASSERT.that(asList(m.entrySet())).is(asList(expected.entrySet()));
663  }
664
665  public void testMapSplitter_multiCharacterSeparator() {
666    // try different delimiters.
667    Map<String, String> m = Splitter
668        .on(",")
669        .withKeyValueSeparator(":^&")
670        .split("boy:^&tom,girl:^&tina,cat:^&kitty,dog:^&tommy");
671    ImmutableMap<String, String> expected =
672        ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
673
674    ASSERT.that(m).isEqualTo(expected);
675    ASSERT.that(asList(m.entrySet())).is(asList(expected.entrySet()));
676  }
677
678  public void testMapSplitter_emptySeparator() {
679    try {
680      COMMA_SPLITTER.withKeyValueSeparator("");
681      fail();
682    } catch (IllegalArgumentException expected) {
683    }
684  }
685
686  public void testMapSplitter_malformedEntry() {
687    try {
688      COMMA_SPLITTER.withKeyValueSeparator("=").split("a=1,b,c=2");
689      fail();
690    } catch(IllegalArgumentException expected) {
691    }
692  }
693
694  public void testMapSplitter_orderedResults() {
695    Map<String, String> m = Splitter.on(",")
696        .withKeyValueSeparator(":")
697        .split("boy:tom,girl:tina,cat:kitty,dog:tommy");
698
699    ASSERT.that(m.keySet()).hasContentsInOrder("boy", "girl", "cat", "dog");
700    ASSERT.that(m).isEqualTo(
701        ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy"));
702
703    // try in a different order
704    m = Splitter.on(",")
705        .withKeyValueSeparator(":")
706        .split("girl:tina,boy:tom,dog:tommy,cat:kitty");
707
708    ASSERT.that(m.keySet()).hasContentsInOrder("girl", "boy", "dog", "cat");
709    ASSERT.that(m).isEqualTo(
710        ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy"));
711  }
712
713  public void testMapSplitter_duplicateKeys() {
714    try {
715      Splitter.on(",").withKeyValueSeparator(":").split("a:1,b:2,a:3");
716      fail();
717    } catch (IllegalArgumentException expected) {
718    }
719  }
720}
721