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.truth0.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).iteratesOverSequence("a", "b", "c");
55  }
56
57  /**
58   * All of the infrastructure of split and splitToString is identical, so we
59   * do one test of splitToString. All other cases should be covered by testing
60   * of split.
61   *
62   * <p>TODO(user): It would be good to make all the relevant tests run on
63   * both split and splitToString automatically.
64   */
65  public void testCharacterSimpleSplitToList() {
66    String simple = "a,b,c";
67    List<String> letters = COMMA_SPLITTER.splitToList(simple);
68    ASSERT.that(letters).iteratesOverSequence("a", "b", "c");
69  }
70
71  public void testToString() {
72    assertEquals("[]", Splitter.on(',').split("").toString());
73    assertEquals("[a, b, c]", Splitter.on(',').split("a,b,c").toString());
74    assertEquals("[yam, bam, jam, ham]", Splitter.on(", ").split("yam, bam, jam, ham").toString());
75  }
76
77  public void testCharacterSimpleSplitWithNoDelimiter() {
78    String simple = "a,b,c";
79    Iterable<String> letters = Splitter.on('.').split(simple);
80    ASSERT.that(letters).iteratesOverSequence("a,b,c");
81  }
82
83  public void testCharacterSplitWithDoubleDelimiter() {
84    String doubled = "a,,b,c";
85    Iterable<String> letters = COMMA_SPLITTER.split(doubled);
86    ASSERT.that(letters).iteratesOverSequence("a", "", "b", "c");
87  }
88
89  public void testCharacterSplitWithDoubleDelimiterAndSpace() {
90    String doubled = "a,, b,c";
91    Iterable<String> letters = COMMA_SPLITTER.split(doubled);
92    ASSERT.that(letters).iteratesOverSequence("a", "", " b", "c");
93  }
94
95  public void testCharacterSplitWithTrailingDelimiter() {
96    String trailing = "a,b,c,";
97    Iterable<String> letters = COMMA_SPLITTER.split(trailing);
98    ASSERT.that(letters).iteratesOverSequence("a", "b", "c", "");
99  }
100
101  public void testCharacterSplitWithLeadingDelimiter() {
102    String leading = ",a,b,c";
103    Iterable<String> letters = COMMA_SPLITTER.split(leading);
104    ASSERT.that(letters).iteratesOverSequence("", "a", "b", "c");
105  }
106
107  public void testCharacterSplitWithMulitpleLetters() {
108    Iterable<String> testCharacteringMotto = Splitter.on('-').split(
109        "Testing-rocks-Debugging-sucks");
110    ASSERT.that(testCharacteringMotto).iteratesOverSequence(
111        "Testing", "rocks", "Debugging", "sucks");
112  }
113
114  public void testCharacterSplitWithMatcherDelimiter() {
115    Iterable<String> testCharacteringMotto = Splitter
116        .on(CharMatcher.WHITESPACE)
117        .split("Testing\nrocks\tDebugging sucks");
118    ASSERT.that(testCharacteringMotto).iteratesOverSequence(
119        "Testing", "rocks", "Debugging", "sucks");
120  }
121
122  public void testCharacterSplitWithDoubleDelimiterOmitEmptyStrings() {
123    String doubled = "a..b.c";
124    Iterable<String> letters = Splitter.on('.')
125        .omitEmptyStrings().split(doubled);
126    ASSERT.that(letters).iteratesOverSequence("a", "b", "c");
127  }
128
129  public void testCharacterSplitEmptyToken() {
130    String emptyToken = "a. .c";
131    Iterable<String> letters = Splitter.on('.').trimResults()
132        .split(emptyToken);
133    ASSERT.that(letters).iteratesOverSequence("a", "", "c");
134  }
135
136  public void testCharacterSplitEmptyTokenOmitEmptyStrings() {
137    String emptyToken = "a. .c";
138    Iterable<String> letters = Splitter.on('.')
139        .omitEmptyStrings().trimResults().split(emptyToken);
140    ASSERT.that(letters).iteratesOverSequence("a", "c");
141  }
142
143  public void testCharacterSplitOnEmptyString() {
144    Iterable<String> nothing = Splitter.on('.').split("");
145    ASSERT.that(nothing).iteratesOverSequence("");
146  }
147
148  public void testCharacterSplitOnEmptyStringOmitEmptyStrings() {
149    ASSERT.that(Splitter.on('.').omitEmptyStrings().split("")).isEmpty();
150  }
151
152  public void testCharacterSplitOnOnlyDelimiter() {
153    Iterable<String> blankblank = Splitter.on('.').split(".");
154    ASSERT.that(blankblank).iteratesOverSequence("", "");
155  }
156
157  public void testCharacterSplitOnOnlyDelimitersOmitEmptyStrings() {
158    Iterable<String> empty = Splitter.on('.').omitEmptyStrings().split("...");
159    ASSERT.that(empty).isEmpty();
160  }
161
162  public void testCharacterSplitWithTrim() {
163    String jacksons = "arfo(Marlon)aorf, (Michael)orfa, afro(Jackie)orfa, "
164        + "ofar(Jemaine), aff(Tito)";
165    Iterable<String> family = COMMA_SPLITTER
166        .trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
167        .split(jacksons);
168    ASSERT.that(family).iteratesOverSequence(
169        "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
170  }
171
172  public void testStringSimpleSplit() {
173    String simple = "a,b,c";
174    Iterable<String> letters = Splitter.on(',').split(simple);
175    ASSERT.that(letters).iteratesOverSequence("a", "b", "c");
176  }
177
178  public void testStringSimpleSplitWithNoDelimiter() {
179    String simple = "a,b,c";
180    Iterable<String> letters = Splitter.on('.').split(simple);
181    ASSERT.that(letters).iteratesOverSequence("a,b,c");
182  }
183
184  public void testStringSplitWithDoubleDelimiter() {
185    String doubled = "a,,b,c";
186    Iterable<String> letters = Splitter.on(',').split(doubled);
187    ASSERT.that(letters).iteratesOverSequence("a", "", "b", "c");
188  }
189
190  public void testStringSplitWithDoubleDelimiterAndSpace() {
191    String doubled = "a,, b,c";
192    Iterable<String> letters = Splitter.on(',').split(doubled);
193    ASSERT.that(letters).iteratesOverSequence("a", "", " b", "c");
194  }
195
196  public void testStringSplitWithTrailingDelimiter() {
197    String trailing = "a,b,c,";
198    Iterable<String> letters = Splitter.on(',').split(trailing);
199    ASSERT.that(letters).iteratesOverSequence("a", "b", "c", "");
200  }
201
202  public void testStringSplitWithLeadingDelimiter() {
203    String leading = ",a,b,c";
204    Iterable<String> letters = Splitter.on(',').split(leading);
205    ASSERT.that(letters).iteratesOverSequence("", "a", "b", "c");
206  }
207
208  public void testStringSplitWithMultipleLetters() {
209    Iterable<String> testStringingMotto = Splitter.on('-').split(
210        "Testing-rocks-Debugging-sucks");
211    ASSERT.that(testStringingMotto).iteratesOverSequence(
212        "Testing", "rocks", "Debugging", "sucks");
213  }
214
215  public void testStringSplitWithDoubleDelimiterOmitEmptyStrings() {
216    String doubled = "a..b.c";
217    Iterable<String> letters = Splitter.on('.')
218        .omitEmptyStrings().split(doubled);
219    ASSERT.that(letters).iteratesOverSequence("a", "b", "c");
220  }
221
222  public void testStringSplitEmptyToken() {
223    String emptyToken = "a. .c";
224    Iterable<String> letters = Splitter.on('.').trimResults()
225        .split(emptyToken);
226    ASSERT.that(letters).iteratesOverSequence("a", "", "c");
227  }
228
229  public void testStringSplitEmptyTokenOmitEmptyStrings() {
230    String emptyToken = "a. .c";
231    Iterable<String> letters = Splitter.on('.')
232        .omitEmptyStrings().trimResults().split(emptyToken);
233    ASSERT.that(letters).iteratesOverSequence("a", "c");
234  }
235
236  public void testStringSplitWithLongDelimiter() {
237    String longDelimiter = "a, b, c";
238    Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
239    ASSERT.that(letters).iteratesOverSequence("a", "b", "c");
240  }
241
242  public void testStringSplitWithLongLeadingDelimiter() {
243    String longDelimiter = ", a, b, c";
244    Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
245    ASSERT.that(letters).iteratesOverSequence("", "a", "b", "c");
246  }
247
248  public void testStringSplitWithLongTrailingDelimiter() {
249    String longDelimiter = "a, b, c, ";
250    Iterable<String> letters = Splitter.on(", ").split(longDelimiter);
251    ASSERT.that(letters).iteratesOverSequence("a", "b", "c", "");
252  }
253
254  public void testStringSplitWithDelimiterSubstringInValue() {
255    String fourCommasAndFourSpaces = ",,,,    ";
256    Iterable<String> threeCommasThenThreeSpaces = Splitter.on(", ").split(
257        fourCommasAndFourSpaces);
258    ASSERT.that(threeCommasThenThreeSpaces).iteratesOverSequence(",,,", "   ");
259  }
260
261  public void testStringSplitWithEmptyString() {
262    try {
263      Splitter.on("");
264      fail();
265    } catch (IllegalArgumentException expected) {
266    }
267  }
268
269  public void testStringSplitOnEmptyString() {
270    Iterable<String> notMuch = Splitter.on('.').split("");
271    ASSERT.that(notMuch).iteratesOverSequence("");
272  }
273
274  public void testStringSplitOnEmptyStringOmitEmptyString() {
275    ASSERT.that(Splitter.on('.').omitEmptyStrings().split("")).isEmpty();
276  }
277
278  public void testStringSplitOnOnlyDelimiter() {
279    Iterable<String> blankblank = Splitter.on('.').split(".");
280    ASSERT.that(blankblank).iteratesOverSequence("", "");
281  }
282
283  public void testStringSplitOnOnlyDelimitersOmitEmptyStrings() {
284    Iterable<String> empty = Splitter.on('.').omitEmptyStrings().split("...");
285    ASSERT.that(empty).isEmpty();
286  }
287
288  public void testStringSplitWithTrim() {
289    String jacksons = "arfo(Marlon)aorf, (Michael)orfa, afro(Jackie)orfa, "
290        + "ofar(Jemaine), aff(Tito)";
291    Iterable<String> family = Splitter.on(',')
292        .trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
293        .split(jacksons);
294    ASSERT.that(family).iteratesOverSequence(
295        "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
296  }
297
298  @GwtIncompatible("Splitter.onPattern")
299  public void testPatternSimpleSplit() {
300    String simple = "a,b,c";
301    Iterable<String> letters = Splitter.onPattern(",").split(simple);
302    ASSERT.that(letters).iteratesOverSequence("a", "b", "c");
303  }
304
305  @GwtIncompatible("Splitter.onPattern")
306  public void testPatternSimpleSplitWithNoDelimiter() {
307    String simple = "a,b,c";
308    Iterable<String> letters = Splitter.onPattern("foo").split(simple);
309    ASSERT.that(letters).iteratesOverSequence("a,b,c");
310  }
311
312  @GwtIncompatible("Splitter.onPattern")
313  public void testPatternSplitWithDoubleDelimiter() {
314    String doubled = "a,,b,c";
315    Iterable<String> letters = Splitter.onPattern(",").split(doubled);
316    ASSERT.that(letters).iteratesOverSequence("a", "", "b", "c");
317  }
318
319  @GwtIncompatible("Splitter.onPattern")
320  public void testPatternSplitWithDoubleDelimiterAndSpace() {
321    String doubled = "a,, b,c";
322    Iterable<String> letters = Splitter.onPattern(",").split(doubled);
323    ASSERT.that(letters).iteratesOverSequence("a", "", " b", "c");
324  }
325
326  @GwtIncompatible("Splitter.onPattern")
327  public void testPatternSplitWithTrailingDelimiter() {
328    String trailing = "a,b,c,";
329    Iterable<String> letters = Splitter.onPattern(",").split(trailing);
330    ASSERT.that(letters).iteratesOverSequence("a", "b", "c", "");
331  }
332
333  @GwtIncompatible("Splitter.onPattern")
334  public void testPatternSplitWithLeadingDelimiter() {
335    String leading = ",a,b,c";
336    Iterable<String> letters = Splitter.onPattern(",").split(leading);
337    ASSERT.that(letters).iteratesOverSequence("", "a", "b", "c");
338  }
339
340  // TODO(kevinb): the name of this method suggests it might not actually be testing what it
341  // intends to be testing?
342  @GwtIncompatible("Splitter.onPattern")
343  public void testPatternSplitWithMultipleLetters() {
344    Iterable<String> testPatterningMotto = Splitter.onPattern("-").split(
345        "Testing-rocks-Debugging-sucks");
346    ASSERT.that(testPatterningMotto).iteratesOverSequence("Testing", "rocks", "Debugging", "sucks");
347  }
348
349  @GwtIncompatible("java.util.regex.Pattern")
350  private static Pattern literalDotPattern() {
351    return Pattern.compile("\\.");
352  }
353
354  @GwtIncompatible("java.util.regex.Pattern")
355  public void testPatternSplitWithDoubleDelimiterOmitEmptyStrings() {
356    String doubled = "a..b.c";
357    Iterable<String> letters = Splitter.on(literalDotPattern())
358        .omitEmptyStrings().split(doubled);
359    ASSERT.that(letters).iteratesOverSequence("a", "b", "c");
360  }
361
362  @GwtIncompatible("java.util.regex.Pattern")
363  public void testPatternSplitLookBehind() {
364    String toSplit = ":foo::barbaz:";
365    String regexPattern = "(?<=:)";
366    Iterable<String> split = Splitter.onPattern(regexPattern).split(toSplit);
367    ASSERT.that(split).iteratesOverSequence(":", "foo:", ":", "barbaz:");
368    // splits into chunks ending in :
369  }
370
371  @GwtIncompatible("java.util.regex.Pattern")
372  public void testPatternSplitWordBoundary() {
373    String string = "foo<bar>bletch";
374    Iterable<String> words = Splitter.on(Pattern.compile("\\b")).split(string);
375    ASSERT.that(words).iteratesOverSequence("foo", "<", "bar", ">", "bletch");
376  }
377
378  @GwtIncompatible("java.util.regex.Pattern")
379  public void testPatternSplitEmptyToken() {
380    String emptyToken = "a. .c";
381    Iterable<String> letters = Splitter.on(literalDotPattern()).trimResults().split(emptyToken);
382    ASSERT.that(letters).iteratesOverSequence("a", "", "c");
383  }
384
385  @GwtIncompatible("java.util.regex.Pattern")
386  public void testPatternSplitEmptyTokenOmitEmptyStrings() {
387    String emptyToken = "a. .c";
388    Iterable<String> letters = Splitter.on(literalDotPattern())
389        .omitEmptyStrings().trimResults().split(emptyToken);
390    ASSERT.that(letters).iteratesOverSequence("a", "c");
391  }
392
393  @GwtIncompatible("java.util.regex.Pattern")
394  public void testPatternSplitOnOnlyDelimiter() {
395    Iterable<String> blankblank = Splitter.on(literalDotPattern()).split(".");
396
397    ASSERT.that(blankblank).iteratesOverSequence("", "");
398  }
399
400  @GwtIncompatible("java.util.regex.Pattern")
401  public void testPatternSplitOnOnlyDelimitersOmitEmptyStrings() {
402    Iterable<String> empty = Splitter.on(literalDotPattern()).omitEmptyStrings()
403        .split("...");
404    ASSERT.that(empty).isEmpty();
405  }
406
407  @GwtIncompatible("java.util.regex.Pattern")
408  public void testPatternSplitMatchingIsGreedy() {
409    String longDelimiter = "a, b,   c";
410    Iterable<String> letters = Splitter.on(Pattern.compile(",\\s*"))
411        .split(longDelimiter);
412    ASSERT.that(letters).iteratesOverSequence("a", "b", "c");
413  }
414
415  @GwtIncompatible("java.util.regex.Pattern")
416  public void testPatternSplitWithLongLeadingDelimiter() {
417    String longDelimiter = ", a, b, c";
418    Iterable<String> letters = Splitter.on(Pattern.compile(", "))
419        .split(longDelimiter);
420    ASSERT.that(letters).iteratesOverSequence("", "a", "b", "c");
421  }
422
423  @GwtIncompatible("java.util.regex.Pattern")
424  public void testPatternSplitWithLongTrailingDelimiter() {
425    String longDelimiter = "a, b, c/ ";
426    Iterable<String> letters = Splitter.on(Pattern.compile("[,/]\\s"))
427        .split(longDelimiter);
428    ASSERT.that(letters).iteratesOverSequence("a", "b", "c", "");
429  }
430
431  @GwtIncompatible("java.util.regex.Pattern")
432  public void testPatternSplitInvalidPattern() {
433    try {
434      Splitter.on(Pattern.compile("a*"));
435      fail();
436    } catch (IllegalArgumentException expected) {
437    }
438  }
439
440  @GwtIncompatible("java.util.regex.Pattern")
441  public void testPatternSplitWithTrim() {
442    String jacksons = "arfo(Marlon)aorf, (Michael)orfa, afro(Jackie)orfa, "
443        + "ofar(Jemaine), aff(Tito)";
444    Iterable<String> family = Splitter.on(Pattern.compile(","))
445        .trimResults(CharMatcher.anyOf("afro").or(CharMatcher.WHITESPACE))
446        .split(jacksons);
447    ASSERT.that(family).iteratesOverSequence(
448        "(Marlon)", "(Michael)", "(Jackie)", "(Jemaine)", "(Tito)");
449  }
450
451  public void testSplitterIterableIsUnmodifiable_char() {
452    assertIteratorIsUnmodifiable(COMMA_SPLITTER.split("a,b").iterator());
453  }
454
455  public void testSplitterIterableIsUnmodifiable_string() {
456    assertIteratorIsUnmodifiable(Splitter.on(',').split("a,b").iterator());
457  }
458
459  @GwtIncompatible("java.util.regex.Pattern")
460  public void testSplitterIterableIsUnmodifiable_pattern() {
461    assertIteratorIsUnmodifiable(
462        Splitter.on(Pattern.compile(",")).split("a,b").iterator());
463  }
464
465  private void assertIteratorIsUnmodifiable(Iterator<?> iterator) {
466    iterator.next();
467    try {
468      iterator.remove();
469      fail();
470    } catch (UnsupportedOperationException expected) {
471    }
472  }
473
474  public void testSplitterIterableIsLazy_char() {
475    assertSplitterIterableIsLazy(COMMA_SPLITTER);
476  }
477
478  public void testSplitterIterableIsLazy_string() {
479    assertSplitterIterableIsLazy(Splitter.on(','));
480  }
481
482  @GwtIncompatible("java.util.regex.Pattern")
483  public void testSplitterIterableIsLazy_pattern() {
484    assertSplitterIterableIsLazy(Splitter.onPattern(","));
485  }
486
487  /**
488   * This test really pushes the boundaries of what we support. In general the
489   * splitter's behaviour is not well defined if the char sequence it's
490   * splitting is mutated during iteration.
491   */
492  private void assertSplitterIterableIsLazy(Splitter splitter) {
493    StringBuilder builder = new StringBuilder();
494    Iterator<String> iterator = splitter.split(builder).iterator();
495
496    builder.append("A,");
497    assertEquals("A", iterator.next());
498    builder.append("B,");
499    assertEquals("B", iterator.next());
500    builder.append("C");
501    assertEquals("C", iterator.next());
502    assertFalse(iterator.hasNext());
503  }
504
505  public void testFixedLengthSimpleSplit() {
506    String simple = "abcde";
507    Iterable<String> letters = Splitter.fixedLength(2).split(simple);
508    ASSERT.that(letters).iteratesOverSequence("ab", "cd", "e");
509  }
510
511  public void testFixedLengthSplitEqualChunkLength() {
512    String simple = "abcdef";
513    Iterable<String> letters = Splitter.fixedLength(2).split(simple);
514    ASSERT.that(letters).iteratesOverSequence("ab", "cd", "ef");
515  }
516
517  public void testFixedLengthSplitOnlyOneChunk() {
518    String simple = "abc";
519    Iterable<String> letters = Splitter.fixedLength(3).split(simple);
520    ASSERT.that(letters).iteratesOverSequence("abc");
521  }
522
523  public void testFixedLengthSplitSmallerString() {
524    String simple = "ab";
525    Iterable<String> letters = Splitter.fixedLength(3).split(simple);
526    ASSERT.that(letters).iteratesOverSequence("ab");
527  }
528
529  public void testFixedLengthSplitEmptyString() {
530    String simple = "";
531    Iterable<String> letters = Splitter.fixedLength(3).split(simple);
532    ASSERT.that(letters).iteratesOverSequence("");
533  }
534
535  public void testFixedLengthSplitEmptyStringWithOmitEmptyStrings() {
536    ASSERT.that(Splitter.fixedLength(3).omitEmptyStrings().split("")).isEmpty();
537  }
538
539  public void testFixedLengthSplitIntoChars() {
540    String simple = "abcd";
541    Iterable<String> letters = Splitter.fixedLength(1).split(simple);
542    ASSERT.that(letters).iteratesOverSequence("a", "b", "c", "d");
543  }
544
545  public void testFixedLengthSplitZeroChunkLen() {
546    try {
547      Splitter.fixedLength(0);
548      fail();
549    } catch (IllegalArgumentException expected) {
550    }
551  }
552
553  public void testFixedLengthSplitNegativeChunkLen() {
554    try {
555      Splitter.fixedLength(-1);
556      fail();
557    } catch (IllegalArgumentException expected) {
558    }
559  }
560
561  public void testLimitLarge() {
562    String simple = "abcd";
563    Iterable<String> letters = Splitter.fixedLength(1).limit(100).split(simple);
564    ASSERT.that(letters).iteratesOverSequence("a", "b", "c", "d");
565  }
566
567  public void testLimitOne() {
568    String simple = "abcd";
569    Iterable<String> letters = Splitter.fixedLength(1).limit(1).split(simple);
570    ASSERT.that(letters).iteratesOverSequence("abcd");
571  }
572
573  public void testLimitFixedLength() {
574    String simple = "abcd";
575    Iterable<String> letters = Splitter.fixedLength(1).limit(2).split(simple);
576    ASSERT.that(letters).iteratesOverSequence("a", "bcd");
577  }
578
579  public void testLimitSeparator() {
580    String simple = "a,b,c,d";
581    Iterable<String> items = COMMA_SPLITTER.limit(2).split(simple);
582    ASSERT.that(items).iteratesOverSequence("a", "b,c,d");
583  }
584
585  public void testLimitExtraSeparators() {
586    String text = "a,,,b,,c,d";
587    Iterable<String> items = COMMA_SPLITTER.limit(2).split(text);
588    ASSERT.that(items).iteratesOverSequence("a", ",,b,,c,d");
589  }
590
591  public void testLimitExtraSeparatorsOmitEmpty() {
592    String text = "a,,,b,,c,d";
593    Iterable<String> items = COMMA_SPLITTER.limit(2).omitEmptyStrings().split(text);
594    ASSERT.that(items).iteratesOverSequence("a", "b,,c,d");
595  }
596
597  public void testLimitExtraSeparatorsOmitEmpty3() {
598    String text = "a,,,b,,c,d";
599    Iterable<String> items = COMMA_SPLITTER.limit(3).omitEmptyStrings().split(text);
600    ASSERT.that(items).iteratesOverSequence("a", "b", "c,d");
601  }
602
603  public void testLimitExtraSeparatorsTrim() {
604    String text = ",,a,,  , b ,, c,d ";
605    Iterable<String> items = COMMA_SPLITTER.limit(2).omitEmptyStrings().trimResults().split(text);
606    ASSERT.that(items).iteratesOverSequence("a", "b ,, c,d");
607  }
608
609  public void testLimitExtraSeparatorsTrim3() {
610    String text = ",,a,,  , b ,, c,d ";
611    Iterable<String> items = COMMA_SPLITTER.limit(3).omitEmptyStrings().trimResults().split(text);
612    ASSERT.that(items).iteratesOverSequence("a", "b", "c,d");
613  }
614
615  public void testLimitExtraSeparatorsTrim1() {
616    String text = ",,a,,  , b ,, c,d ";
617    Iterable<String> items = COMMA_SPLITTER.limit(1).omitEmptyStrings().trimResults().split(text);
618    ASSERT.that(items).iteratesOverSequence("a,,  , b ,, c,d");
619  }
620
621  public void testLimitExtraSeparatorsTrim1NoOmit() {
622    String text = ",,a,,  , b ,, c,d ";
623    Iterable<String> items = COMMA_SPLITTER.limit(1).trimResults().split(text);
624    ASSERT.that(items).iteratesOverSequence(",,a,,  , b ,, c,d");
625  }
626
627  public void testLimitExtraSeparatorsTrim1Empty() {
628    String text = "";
629    Iterable<String> items = COMMA_SPLITTER.limit(1).split(text);
630    ASSERT.that(items).iteratesOverSequence("");
631  }
632
633  public void testLimitExtraSeparatorsTrim1EmptyOmit() {
634    String text = "";
635    Iterable<String> items = COMMA_SPLITTER.omitEmptyStrings().limit(1).split(text);
636    ASSERT.that(items).isEmpty();
637  }
638
639  @SuppressWarnings("ReturnValueIgnored") // testing for exception
640  public void testInvalidZeroLimit() {
641    try {
642      COMMA_SPLITTER.limit(0);
643      fail();
644    } catch (IllegalArgumentException expected) {
645    }
646  }
647
648  @GwtIncompatible("NullPointerTester")
649  public void testNullPointers() {
650    NullPointerTester tester = new NullPointerTester();
651    tester.testAllPublicStaticMethods(Splitter.class);
652    tester.testAllPublicInstanceMethods(Splitter.on(','));
653    tester.testAllPublicInstanceMethods(Splitter.on(',').trimResults());
654  }
655
656  private static <E> List<E> asList(Collection<E> collection) {
657    return ImmutableList.copyOf(collection);
658  }
659
660  public void testMapSplitter_trimmedBoth() {
661    Map<String, String> m = COMMA_SPLITTER
662        .trimResults()
663        .withKeyValueSeparator(Splitter.on(':').trimResults())
664        .split("boy  : tom , girl: tina , cat  : kitty , dog: tommy ");
665    ImmutableMap<String, String> expected =
666          ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
667    ASSERT.that(m).isEqualTo(expected);
668    ASSERT.that(asList(m.entrySet())).is(asList(expected.entrySet()));
669  }
670
671  public void testMapSplitter_trimmedEntries() {
672    Map<String, String> m = COMMA_SPLITTER
673        .trimResults()
674        .withKeyValueSeparator(":")
675        .split("boy  : tom , girl: tina , cat  : kitty , dog: tommy ");
676    ImmutableMap<String, String> expected =
677        ImmutableMap.of("boy  ", " tom", "girl", " tina", "cat  ", " kitty", "dog", " tommy");
678
679    ASSERT.that(m).isEqualTo(expected);
680    ASSERT.that(asList(m.entrySet())).is(asList(expected.entrySet()));
681  }
682
683  public void testMapSplitter_trimmedKeyValue() {
684    Map<String, String> m =
685        COMMA_SPLITTER.withKeyValueSeparator(Splitter.on(':').trimResults()).split(
686            "boy  : tom , girl: tina , cat  : kitty , dog: tommy ");
687    ImmutableMap<String, String> expected =
688        ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
689    ASSERT.that(m).isEqualTo(expected);
690    ASSERT.that(asList(m.entrySet())).is(asList(expected.entrySet()));
691  }
692
693  public void testMapSplitter_notTrimmed() {
694    Map<String, String> m = COMMA_SPLITTER.withKeyValueSeparator(":").split(
695        " boy:tom , girl: tina , cat :kitty , dog:  tommy ");
696    ImmutableMap<String, String> expected =
697        ImmutableMap.of(" boy", "tom ", " girl", " tina ", " cat ", "kitty ", " dog", "  tommy ");
698    ASSERT.that(m).isEqualTo(expected);
699    ASSERT.that(asList(m.entrySet())).is(asList(expected.entrySet()));
700  }
701
702  public void testMapSplitter_CharacterSeparator() {
703    // try different delimiters.
704    Map<String, String> m = Splitter
705        .on(",")
706        .withKeyValueSeparator(':')
707        .split("boy:tom,girl:tina,cat:kitty,dog:tommy");
708    ImmutableMap<String, String> expected =
709        ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
710
711    ASSERT.that(m).isEqualTo(expected);
712    ASSERT.that(asList(m.entrySet())).is(asList(expected.entrySet()));
713  }
714
715  public void testMapSplitter_multiCharacterSeparator() {
716    // try different delimiters.
717    Map<String, String> m = Splitter
718        .on(",")
719        .withKeyValueSeparator(":^&")
720        .split("boy:^&tom,girl:^&tina,cat:^&kitty,dog:^&tommy");
721    ImmutableMap<String, String> expected =
722        ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy");
723
724    ASSERT.that(m).isEqualTo(expected);
725    ASSERT.that(asList(m.entrySet())).is(asList(expected.entrySet()));
726  }
727
728  @SuppressWarnings("ReturnValueIgnored") // testing for exception
729  public void testMapSplitter_emptySeparator() {
730    try {
731      COMMA_SPLITTER.withKeyValueSeparator("");
732      fail();
733    } catch (IllegalArgumentException expected) {
734    }
735  }
736
737  public void testMapSplitter_malformedEntry() {
738    try {
739      COMMA_SPLITTER.withKeyValueSeparator("=").split("a=1,b,c=2");
740      fail();
741    } catch (IllegalArgumentException expected) {
742    }
743  }
744
745  public void testMapSplitter_orderedResults() {
746    Map<String, String> m = Splitter.on(',')
747        .withKeyValueSeparator(":")
748        .split("boy:tom,girl:tina,cat:kitty,dog:tommy");
749
750    ASSERT.that(m.keySet()).iteratesOverSequence("boy", "girl", "cat", "dog");
751    ASSERT.that(m).isEqualTo(
752        ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy"));
753
754    // try in a different order
755    m = Splitter.on(',')
756        .withKeyValueSeparator(":")
757        .split("girl:tina,boy:tom,dog:tommy,cat:kitty");
758
759    ASSERT.that(m.keySet()).iteratesOverSequence("girl", "boy", "dog", "cat");
760    ASSERT.that(m).isEqualTo(
761        ImmutableMap.of("boy", "tom", "girl", "tina", "cat", "kitty", "dog", "tommy"));
762  }
763
764  public void testMapSplitter_duplicateKeys() {
765    try {
766      Splitter.on(',').withKeyValueSeparator(":").split("a:1,b:2,a:3");
767      fail();
768    } catch (IllegalArgumentException expected) {
769    }
770  }
771}
772