ImmutableSortedMapTest.java revision 1d580d0f6ee4f21eb309ba7b509d2c6d671c4044
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.collect;
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.base.Joiner;
24import com.google.common.collect.ImmutableSortedMap.Builder;
25import com.google.common.collect.testing.CollectionTestSuiteBuilder;
26import com.google.common.collect.testing.ReserializingTestCollectionGenerator;
27import com.google.common.collect.testing.ReserializingTestSetGenerator;
28import com.google.common.collect.testing.SetTestSuiteBuilder;
29import com.google.common.collect.testing.SortedMapInterfaceTest;
30import com.google.common.collect.testing.features.CollectionFeature;
31import com.google.common.collect.testing.features.CollectionSize;
32import com.google.common.collect.testing.google.SortedMapGenerators.ImmutableSortedMapEntrySetGenerator;
33import com.google.common.collect.testing.google.SortedMapGenerators.ImmutableSortedMapHeadMapKeySetGenerator;
34import com.google.common.collect.testing.google.SortedMapGenerators.ImmutableSortedMapKeySetGenerator;
35import com.google.common.collect.testing.google.SortedMapGenerators.ImmutableSortedMapSubMapEntryGenerator;
36import com.google.common.collect.testing.google.SortedMapGenerators.ImmutableSortedMapTailMapValuesGenerator;
37import com.google.common.collect.testing.google.SortedMapGenerators.ImmutableSortedMapValuesGenerator;
38import com.google.common.testing.NullPointerTester;
39import com.google.common.testing.SerializableTester;
40
41import junit.framework.Test;
42import junit.framework.TestCase;
43import junit.framework.TestSuite;
44
45import java.io.Serializable;
46import java.util.Collections;
47import java.util.Comparator;
48import java.util.LinkedHashMap;
49import java.util.Map;
50import java.util.Map.Entry;
51import java.util.SortedMap;
52
53/**
54 * Tests for {@link ImmutableSortedMap}.
55 *
56 * @author Kevin Bourrillion
57 * @author Jesse Wilson
58 * @author Jared Levy
59 */
60@GwtCompatible(emulated = true)
61public class ImmutableSortedMapTest extends TestCase {
62  // TODO: Avoid duplicating code in ImmutableMapTest
63
64  @GwtIncompatible("suite")
65  public static Test suite() {
66    TestSuite suite = new TestSuite();
67    suite.addTestSuite(ImmutableSortedMapTest.class);
68
69    suite.addTest(SetTestSuiteBuilder.using(
70        new ImmutableSortedMapKeySetGenerator())
71        .withFeatures(
72            CollectionSize.ANY,
73            CollectionFeature.KNOWN_ORDER,
74            CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
75            CollectionFeature.ALLOWS_NULL_QUERIES)
76        .named("ImmutableSortedMap.keySet")
77        .createTestSuite());
78
79    suite.addTest(SetTestSuiteBuilder.using(
80        new ImmutableSortedMapEntrySetGenerator())
81        .withFeatures(
82            CollectionSize.ANY,
83            CollectionFeature.KNOWN_ORDER,
84            CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
85            CollectionFeature.ALLOWS_NULL_QUERIES)
86        .named("ImmutableSortedMap.entrySet")
87        .createTestSuite());
88
89    suite.addTest(CollectionTestSuiteBuilder.using(
90        new ImmutableSortedMapValuesGenerator())
91        .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER,
92            CollectionFeature.ALLOWS_NULL_QUERIES)
93        .named("ImmutableSortedMap.values")
94        .createTestSuite());
95
96    suite.addTest(SetTestSuiteBuilder.using(
97        ReserializingTestSetGenerator.newInstance(
98            new ImmutableSortedMapKeySetGenerator()))
99        .withFeatures(
100            CollectionSize.ANY,
101            CollectionFeature.KNOWN_ORDER,
102            CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
103            CollectionFeature.ALLOWS_NULL_QUERIES)
104        .named("ImmutableSortedMap.keySet, reserialized")
105        .createTestSuite());
106
107    suite.addTest(SetTestSuiteBuilder.using(
108        ReserializingTestSetGenerator.newInstance(
109            new ImmutableSortedMapEntrySetGenerator()))
110        .withFeatures(
111            CollectionSize.ANY,
112            CollectionFeature.KNOWN_ORDER,
113            CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
114            CollectionFeature.ALLOWS_NULL_QUERIES)
115        .named("ImmutableSortedMap.entrySet, reserialized")
116        .createTestSuite());
117
118    suite.addTest(CollectionTestSuiteBuilder.using(
119        ReserializingTestCollectionGenerator.newInstance(
120            new ImmutableSortedMapValuesGenerator()))
121        .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER,
122            CollectionFeature.ALLOWS_NULL_QUERIES)
123        .named("ImmutableSortedMap.values, reserialized")
124        .createTestSuite());
125
126    suite.addTest(SetTestSuiteBuilder.using(
127        new ImmutableSortedMapHeadMapKeySetGenerator())
128        .withFeatures(
129            CollectionSize.ANY,
130            CollectionFeature.KNOWN_ORDER,
131            CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
132            CollectionFeature.ALLOWS_NULL_QUERIES)
133        .named("ImmutableSortedMap.headMap.keySet")
134        .createTestSuite());
135
136    suite.addTest(SetTestSuiteBuilder.using(
137        new ImmutableSortedMapSubMapEntryGenerator())
138        .withFeatures(
139            CollectionSize.ANY,
140            CollectionFeature.KNOWN_ORDER,
141            CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
142            CollectionFeature.ALLOWS_NULL_QUERIES)
143        .named("ImmutableSortedMap.subMap.entrySet")
144        .createTestSuite());
145
146    suite.addTest(CollectionTestSuiteBuilder.using(
147        new ImmutableSortedMapTailMapValuesGenerator())
148        .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER,
149            CollectionFeature.ALLOWS_NULL_QUERIES)
150        .named("ImmutableSortedMap.tailMap.values")
151        .createTestSuite());
152
153    return suite;
154  }
155
156  public abstract static class AbstractMapTests<K, V>
157      extends SortedMapInterfaceTest<K, V> {
158    public AbstractMapTests() {
159      super(false, false, false, false, false);
160    }
161
162    @Override protected SortedMap<K, V> makeEmptyMap() {
163      throw new UnsupportedOperationException();
164    }
165
166    private static final Joiner joiner = Joiner.on(", ");
167
168    @Override protected void assertMoreInvariants(Map<K, V> map) {
169      // TODO: can these be moved to MapInterfaceTest?
170      for (Entry<K, V> entry : map.entrySet()) {
171        assertEquals(entry.getKey() + "=" + entry.getValue(),
172            entry.toString());
173      }
174
175      assertEquals("{" + joiner.join(map.entrySet()) + "}",
176          map.toString());
177      assertEquals("[" + joiner.join(map.entrySet()) + "]",
178          map.entrySet().toString());
179      assertEquals("[" + joiner.join(map.keySet()) + "]",
180          map.keySet().toString());
181      assertEquals("[" + joiner.join(map.values()) + "]",
182          map.values().toString());
183
184      assertEquals(Sets.newHashSet(map.entrySet()), map.entrySet());
185      assertEquals(Sets.newHashSet(map.keySet()), map.keySet());
186    }
187  }
188
189  public static class MapTests extends AbstractMapTests<String, Integer> {
190    @Override protected SortedMap<String, Integer> makeEmptyMap() {
191      return ImmutableSortedMap.of();
192    }
193
194    @Override protected SortedMap<String, Integer> makePopulatedMap() {
195      return ImmutableSortedMap.of("one", 1, "two", 2, "three", 3);
196    }
197
198    @Override protected String getKeyNotInPopulatedMap() {
199      return "minus one";
200    }
201
202    @Override protected Integer getValueNotInPopulatedMap() {
203      return -1;
204    }
205  }
206
207  public static class SingletonMapTests
208      extends AbstractMapTests<String, Integer> {
209    @Override protected SortedMap<String, Integer> makePopulatedMap() {
210      return ImmutableSortedMap.of("one", 1);
211    }
212
213    @Override protected String getKeyNotInPopulatedMap() {
214      return "minus one";
215    }
216
217    @Override protected Integer getValueNotInPopulatedMap() {
218      return -1;
219    }
220  }
221
222  @GwtIncompatible("SerializableTester")
223  public static class ReserializedMapTests
224      extends AbstractMapTests<String, Integer> {
225    @Override protected SortedMap<String, Integer> makePopulatedMap() {
226      return SerializableTester.reserialize(
227          ImmutableSortedMap.of("one", 1, "two", 2, "three", 3));
228    }
229
230    @Override protected String getKeyNotInPopulatedMap() {
231      return "minus one";
232    }
233
234    @Override protected Integer getValueNotInPopulatedMap() {
235      return -1;
236    }
237  }
238
239  public static class HeadMapTests extends AbstractMapTests<String, Integer> {
240    @Override protected SortedMap<String, Integer> makePopulatedMap() {
241      return ImmutableSortedMap.of("a", 1, "b", 2, "c", 3, "d", 4, "e", 5)
242          .headMap("d");
243    }
244
245    @Override protected String getKeyNotInPopulatedMap() {
246      return "d";
247    }
248
249    @Override protected Integer getValueNotInPopulatedMap() {
250      return 4;
251    }
252  }
253
254  public static class HeadMapInclusiveTests extends AbstractMapTests<String, Integer> {
255    @Override protected SortedMap<String, Integer> makePopulatedMap() {
256      return ImmutableSortedMap.of("a", 1, "b", 2, "c", 3, "d", 4, "e", 5)
257          .headMap("c", true);
258    }
259
260    @Override protected String getKeyNotInPopulatedMap() {
261      return "d";
262    }
263
264    @Override protected Integer getValueNotInPopulatedMap() {
265      return 4;
266    }
267  }
268
269  public static class TailMapTests extends AbstractMapTests<String, Integer> {
270    @Override protected SortedMap<String, Integer> makePopulatedMap() {
271      return ImmutableSortedMap.of("a", 1, "b", 2, "c", 3, "d", 4, "e", 5)
272          .tailMap("b");
273    }
274
275    @Override protected String getKeyNotInPopulatedMap() {
276      return "a";
277    }
278
279    @Override protected Integer getValueNotInPopulatedMap() {
280      return 1;
281    }
282  }
283
284  public static class TailExclusiveMapTests extends AbstractMapTests<String, Integer> {
285    @Override protected SortedMap<String, Integer> makePopulatedMap() {
286      return ImmutableSortedMap.of("a", 1, "b", 2, "c", 3, "d", 4, "e", 5)
287          .tailMap("a", false);
288    }
289
290    @Override protected String getKeyNotInPopulatedMap() {
291      return "a";
292    }
293
294    @Override protected Integer getValueNotInPopulatedMap() {
295      return 1;
296    }
297  }
298
299  public static class SubMapTests extends AbstractMapTests<String, Integer> {
300    @Override protected SortedMap<String, Integer> makePopulatedMap() {
301      return ImmutableSortedMap.of("a", 1, "b", 2, "c", 3, "d", 4, "e", 5)
302          .subMap("b", "d");
303    }
304
305    @Override protected String getKeyNotInPopulatedMap() {
306      return "a";
307    }
308
309    @Override protected Integer getValueNotInPopulatedMap() {
310      return 4;
311    }
312  }
313
314  public static class CreationTests extends TestCase {
315    public void testEmptyBuilder() {
316      ImmutableSortedMap<String, Integer> map
317          = ImmutableSortedMap.<String, Integer>naturalOrder().build();
318      assertEquals(Collections.<String, Integer>emptyMap(), map);
319    }
320
321    public void testSingletonBuilder() {
322      ImmutableSortedMap<String, Integer> map
323          = ImmutableSortedMap.<String, Integer>naturalOrder()
324              .put("one", 1)
325              .build();
326      assertMapEquals(map, "one", 1);
327    }
328
329    public void testBuilder() {
330      ImmutableSortedMap<String, Integer> map
331          = ImmutableSortedMap.<String, Integer>naturalOrder()
332              .put("one", 1)
333              .put("two", 2)
334              .put("three", 3)
335              .put("four", 4)
336              .put("five", 5)
337              .build();
338      assertMapEquals(map,
339          "five", 5, "four", 4, "one", 1, "three", 3, "two", 2);
340    }
341
342    public void testBuilder_withImmutableEntry() {
343      ImmutableSortedMap<String, Integer> map =
344          ImmutableSortedMap.<String, Integer>naturalOrder()
345              .put(Maps.immutableEntry("one", 1))
346              .build();
347      assertMapEquals(map, "one", 1);
348    }
349
350    public void testBuilder_withImmutableEntryAndNullContents() {
351      Builder<String, Integer> builder =
352          ImmutableSortedMap.naturalOrder();
353      try {
354        builder.put(Maps.immutableEntry("one", (Integer) null));
355        fail();
356      } catch (NullPointerException expected) {
357      }
358      try {
359        builder.put(Maps.immutableEntry((String) null, 1));
360        fail();
361      } catch (NullPointerException expected) {
362      }
363    }
364
365    private static class StringHolder {
366      String string;
367    }
368
369    public void testBuilder_withMutableEntry() {
370      ImmutableSortedMap.Builder<String, Integer> builder =
371          ImmutableSortedMap.naturalOrder();
372      final StringHolder holder = new StringHolder();
373      holder.string = "one";
374      Entry<String, Integer> entry = new AbstractMapEntry<String, Integer>() {
375        @Override public String getKey() {
376          return holder.string;
377        }
378        @Override public Integer getValue() {
379          return 1;
380        }
381      };
382
383      builder.put(entry);
384      holder.string = "two";
385      assertMapEquals(builder.build(), "one", 1);
386    }
387
388    public void testBuilderPutAllWithEmptyMap() {
389      ImmutableSortedMap<String, Integer> map
390          = ImmutableSortedMap.<String, Integer>naturalOrder()
391              .putAll(Collections.<String, Integer>emptyMap())
392              .build();
393      assertEquals(Collections.<String, Integer>emptyMap(), map);
394    }
395
396    public void testBuilderPutAll() {
397      Map<String, Integer> toPut = new LinkedHashMap<String, Integer>();
398      toPut.put("one", 1);
399      toPut.put("two", 2);
400      toPut.put("three", 3);
401      Map<String, Integer> moreToPut = new LinkedHashMap<String, Integer>();
402      moreToPut.put("four", 4);
403      moreToPut.put("five", 5);
404
405      ImmutableSortedMap<String, Integer> map
406          = ImmutableSortedMap.<String, Integer>naturalOrder()
407              .putAll(toPut)
408              .putAll(moreToPut)
409              .build();
410      assertMapEquals(map,
411          "five", 5, "four", 4, "one", 1, "three", 3, "two", 2);
412    }
413
414    public void testBuilderReuse() {
415      Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
416      ImmutableSortedMap<String, Integer> mapOne = builder
417          .put("one", 1)
418          .put("two", 2)
419          .build();
420      ImmutableSortedMap<String, Integer> mapTwo = builder
421          .put("three", 3)
422          .put("four", 4)
423          .build();
424
425      assertMapEquals(mapOne, "one", 1, "two", 2);
426      assertMapEquals(mapTwo, "four", 4, "one", 1, "three", 3, "two", 2);
427    }
428
429    public void testBuilderPutNullKey() {
430      Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
431      try {
432        builder.put(null, 1);
433        fail();
434      } catch (NullPointerException expected) {
435      }
436    }
437
438    public void testBuilderPutNullValue() {
439      Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
440      try {
441        builder.put("one", null);
442        fail();
443      } catch (NullPointerException expected) {
444      }
445    }
446
447    public void testBuilderPutNullKeyViaPutAll() {
448      Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
449      try {
450        builder.putAll(Collections.<String, Integer>singletonMap(null, 1));
451        fail();
452      } catch (NullPointerException expected) {
453      }
454    }
455
456    public void testBuilderPutNullValueViaPutAll() {
457      Builder<String, Integer> builder = ImmutableSortedMap.naturalOrder();
458      try {
459        builder.putAll(Collections.<String, Integer>singletonMap("one", null));
460        fail();
461      } catch (NullPointerException expected) {
462      }
463    }
464
465    public void testPuttingTheSameKeyTwiceThrowsOnBuild() {
466      Builder<String, Integer> builder
467          = ImmutableSortedMap.<String, Integer>naturalOrder()
468              .put("one", 1)
469              .put("one", 2); // throwing on this line would be even better
470
471      try {
472        builder.build();
473        fail();
474      } catch (IllegalArgumentException expected) {
475        assertEquals("Duplicate keys in mappings one=1 and one=2",
476            expected.getMessage());
477      }
478    }
479
480    public void testOf() {
481      assertMapEquals(
482          ImmutableSortedMap.of("one", 1),
483          "one", 1);
484      assertMapEquals(
485          ImmutableSortedMap.of("one", 1, "two", 2),
486          "one", 1, "two", 2);
487      assertMapEquals(
488          ImmutableSortedMap.of("one", 1, "two", 2, "three", 3),
489          "one", 1, "three", 3, "two", 2);
490      assertMapEquals(
491          ImmutableSortedMap.of("one", 1, "two", 2, "three", 3, "four", 4),
492          "four", 4, "one", 1, "three", 3, "two", 2);
493      assertMapEquals(
494          ImmutableSortedMap.of(
495              "one", 1, "two", 2, "three", 3, "four", 4, "five", 5),
496          "five", 5, "four", 4, "one", 1, "three", 3, "two", 2);
497    }
498
499    public void testOfNullKey() {
500      Integer n = null;
501      try {
502        ImmutableSortedMap.of(n, 1);
503        fail();
504      } catch (NullPointerException expected) {
505      }
506
507      try {
508        ImmutableSortedMap.of("one", 1, null, 2);
509        fail();
510      } catch (NullPointerException expected) {
511      }
512    }
513
514    public void testOfNullValue() {
515      try {
516        ImmutableSortedMap.of("one", null);
517        fail();
518      } catch (NullPointerException expected) {
519      }
520
521      try {
522        ImmutableSortedMap.of("one", 1, "two", null);
523        fail();
524      } catch (NullPointerException expected) {
525      }
526    }
527
528    public void testOfWithDuplicateKey() {
529      try {
530        ImmutableSortedMap.of("one", 1, "one", 1);
531        fail();
532      } catch (IllegalArgumentException expected) {
533        assertEquals("Duplicate keys in mappings one=1 and one=1",
534            expected.getMessage());
535      }
536    }
537
538    public void testCopyOfEmptyMap() {
539      ImmutableSortedMap<String, Integer> copy
540          = ImmutableSortedMap.copyOf(Collections.<String, Integer>emptyMap());
541      assertEquals(Collections.<String, Integer>emptyMap(), copy);
542      assertSame(copy, ImmutableSortedMap.copyOf(copy));
543      assertSame(Ordering.natural(), copy.comparator());
544    }
545
546    public void testCopyOfSingletonMap() {
547      ImmutableSortedMap<String, Integer> copy
548          = ImmutableSortedMap.copyOf(Collections.singletonMap("one", 1));
549      assertMapEquals(copy, "one", 1);
550      assertSame(copy, ImmutableSortedMap.copyOf(copy));
551      assertSame(Ordering.natural(), copy.comparator());
552    }
553
554    public void testCopyOf() {
555      Map<String, Integer> original = new LinkedHashMap<String, Integer>();
556      original.put("one", 1);
557      original.put("two", 2);
558      original.put("three", 3);
559
560      ImmutableSortedMap<String, Integer> copy
561          = ImmutableSortedMap.copyOf(original);
562      assertMapEquals(copy, "one", 1, "three", 3, "two", 2);
563      assertSame(copy, ImmutableSortedMap.copyOf(copy));
564      assertSame(Ordering.natural(), copy.comparator());
565    }
566
567    public void testCopyOfExplicitComparator() {
568      Comparator<String> comparator = Ordering.natural().reverse();
569      Map<String, Integer> original = new LinkedHashMap<String, Integer>();
570      original.put("one", 1);
571      original.put("two", 2);
572      original.put("three", 3);
573
574      ImmutableSortedMap<String, Integer> copy
575          = ImmutableSortedMap.copyOf(original, comparator);
576      assertMapEquals(copy, "two", 2, "three", 3, "one", 1);
577      assertSame(copy, ImmutableSortedMap.copyOf(copy, comparator));
578      assertSame(comparator, copy.comparator());
579    }
580
581    public void testCopyOfImmutableSortedSetDifferentComparator() {
582      Comparator<String> comparator = Ordering.natural().reverse();
583      Map<String, Integer> original
584          = ImmutableSortedMap.of("one", 1, "two", 2, "three", 3);
585      ImmutableSortedMap<String, Integer> copy
586          = ImmutableSortedMap.copyOf(original, comparator);
587      assertMapEquals(copy, "two", 2, "three", 3, "one", 1);
588      assertSame(copy, ImmutableSortedMap.copyOf(copy, comparator));
589      assertSame(comparator, copy.comparator());
590    }
591
592    public void testCopyOfSortedNatural() {
593      SortedMap<String, Integer> original = Maps.newTreeMap();
594      original.put("one", 1);
595      original.put("two", 2);
596      original.put("three", 3);
597
598      ImmutableSortedMap<String, Integer> copy
599          = ImmutableSortedMap.copyOfSorted(original);
600      assertMapEquals(copy, "one", 1, "three", 3, "two", 2);
601      assertSame(copy, ImmutableSortedMap.copyOfSorted(copy));
602      assertSame(Ordering.natural(), copy.comparator());
603    }
604
605    public void testCopyOfSortedExplicit() {
606      Comparator<String> comparator = Ordering.natural().reverse();
607      SortedMap<String, Integer> original = Maps.newTreeMap(comparator);
608      original.put("one", 1);
609      original.put("two", 2);
610      original.put("three", 3);
611
612      ImmutableSortedMap<String, Integer> copy
613          = ImmutableSortedMap.copyOfSorted(original);
614      assertMapEquals(copy, "two", 2, "three", 3, "one", 1);
615      assertSame(copy, ImmutableSortedMap.copyOfSorted(copy));
616      assertSame(comparator, copy.comparator());
617    }
618
619    private static class IntegerDiv10 implements Comparable<IntegerDiv10> {
620      final int value;
621
622      IntegerDiv10(int value) {
623        this.value = value;
624      }
625
626      @Override
627      public int compareTo(IntegerDiv10 o) {
628        return value / 10 - o.value / 10;
629      }
630
631      @Override public String toString() {
632        return Integer.toString(value);
633      }
634    }
635
636    public void testCopyOfDuplicateKey() {
637      Map<IntegerDiv10, String> original = ImmutableMap.of(
638          new IntegerDiv10(3), "three",
639          new IntegerDiv10(20), "twenty",
640          new IntegerDiv10(11), "eleven",
641          new IntegerDiv10(35), "thirty five",
642          new IntegerDiv10(12), "twelve"
643      );
644
645      try {
646        ImmutableSortedMap.copyOf(original);
647        fail("Expected IllegalArgumentException");
648      } catch (IllegalArgumentException expected) {
649        assertEquals("Duplicate keys in mappings 11=eleven and 12=twelve",
650            expected.getMessage());
651      }
652    }
653
654    public void testImmutableMapCopyOfImmutableSortedMap() {
655      IntegerDiv10 three = new IntegerDiv10(3);
656      IntegerDiv10 eleven = new IntegerDiv10(11);
657      IntegerDiv10 twelve = new IntegerDiv10(12);
658      IntegerDiv10 twenty = new IntegerDiv10(20);
659      Map<IntegerDiv10, String> original = ImmutableSortedMap.of(
660          three, "three", eleven, "eleven", twenty, "twenty");
661      Map<IntegerDiv10, String> copy = ImmutableMap.copyOf(original);
662      assertTrue(original.containsKey(twelve));
663      assertFalse(copy.containsKey(twelve));
664    }
665
666    public void testBuilderReverseOrder() {
667      ImmutableSortedMap<String, Integer> map
668          = ImmutableSortedMap.<String, Integer>reverseOrder()
669              .put("one", 1)
670              .put("two", 2)
671              .put("three", 3)
672              .put("four", 4)
673              .put("five", 5)
674              .build();
675      assertMapEquals(map,
676          "two", 2, "three", 3, "one", 1, "four", 4, "five", 5);
677      assertEquals(Ordering.natural().reverse(), map.comparator());
678    }
679
680    public void testBuilderComparator() {
681      Comparator<String> comparator = Ordering.natural().reverse();
682      ImmutableSortedMap<String, Integer> map
683          = new ImmutableSortedMap.Builder<String, Integer>(comparator)
684              .put("one", 1)
685              .put("two", 2)
686              .put("three", 3)
687              .put("four", 4)
688              .put("five", 5)
689              .build();
690      assertMapEquals(map,
691          "two", 2, "three", 3, "one", 1, "four", 4, "five", 5);
692      assertSame(comparator, map.comparator());
693    }
694  }
695
696  public void testNullGet() {
697    ImmutableSortedMap<String, Integer> map = ImmutableSortedMap.of("one", 1);
698    assertNull(map.get(null));
699  }
700
701  @GwtIncompatible("NullPointerTester")
702  public void testNullPointers() throws Exception {
703    NullPointerTester tester = new NullPointerTester();
704    tester.testAllPublicStaticMethods(ImmutableSortedMap.class);
705    tester.testAllPublicInstanceMethods(
706        ImmutableSortedMap.<String, Integer>naturalOrder());
707    tester.testAllPublicInstanceMethods(ImmutableSortedMap.of());
708    tester.testAllPublicInstanceMethods(ImmutableSortedMap.of("one", 1));
709    tester.testAllPublicInstanceMethods(
710        ImmutableSortedMap.of("one", 1, "two", 2, "three", 3));
711  }
712
713  private static <K, V> void assertMapEquals(Map<K, V> map,
714      Object... alternatingKeysAndValues) {
715    assertEquals(map.size(), alternatingKeysAndValues.length / 2);
716    int i = 0;
717    for (Entry<K, V> entry : map.entrySet()) {
718      assertEquals(alternatingKeysAndValues[i++], entry.getKey());
719      assertEquals(alternatingKeysAndValues[i++], entry.getValue());
720    }
721  }
722
723  private static class IntHolder implements Serializable {
724    public int value;
725
726    public IntHolder(int value) {
727      this.value = value;
728    }
729
730    @Override public boolean equals(Object o) {
731      return (o instanceof IntHolder) && ((IntHolder) o).value == value;
732    }
733
734    @Override public int hashCode() {
735      return value;
736    }
737
738    private static final long serialVersionUID = 5;
739  }
740
741  public void testMutableValues() {
742    IntHolder holderA = new IntHolder(1);
743    IntHolder holderB = new IntHolder(2);
744    Map<String, IntHolder> map
745        = ImmutableSortedMap.of("a", holderA, "b", holderB);
746    holderA.value = 3;
747    assertTrue(map.entrySet().contains(
748        Maps.immutableEntry("a", new IntHolder(3))));
749    Map<String, Integer> intMap
750        = ImmutableSortedMap.of("a", 3, "b", 2);
751    assertEquals(intMap.hashCode(), map.entrySet().hashCode());
752    assertEquals(intMap.hashCode(), map.hashCode());
753  }
754
755  @GwtIncompatible("SerializableTester")
756  public void testViewSerialization() {
757    Map<String, Integer> map
758        = ImmutableSortedMap.of("one", 1, "two", 2, "three", 3);
759    SerializableTester.reserializeAndAssert(map.entrySet());
760    SerializableTester.reserializeAndAssert(map.keySet());
761    assertEquals(Lists.newArrayList(map.values()),
762        Lists.newArrayList(SerializableTester.reserialize(map.values())));
763  }
764
765  @SuppressWarnings("unchecked") // varargs
766  public void testHeadMapInclusive() {
767    Map<String, Integer> map =
768        ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).headMap("three", true);
769    ASSERT.that(map.entrySet()).hasContentsInOrder(Maps.immutableEntry("one", 1),
770        Maps.immutableEntry("three", 3));
771  }
772
773  @SuppressWarnings("unchecked") // varargs
774  public void testHeadMapExclusive() {
775    Map<String, Integer> map =
776        ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).headMap("three", false);
777    ASSERT.that(map.entrySet()).hasContentsInOrder(Maps.immutableEntry("one", 1));
778  }
779
780  @SuppressWarnings("unchecked") // varargs
781  public void testTailMapInclusive() {
782    Map<String, Integer> map =
783        ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).tailMap("three", true);
784    ASSERT.that(map.entrySet()).hasContentsInOrder(Maps.immutableEntry("three", 3),
785        Maps.immutableEntry("two", 2));
786  }
787
788  @SuppressWarnings("unchecked") // varargs
789  public void testTailMapExclusive() {
790    Map<String, Integer> map =
791        ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).tailMap("three", false);
792    ASSERT.that(map.entrySet()).hasContentsInOrder(Maps.immutableEntry("two", 2));
793  }
794
795  @SuppressWarnings("unchecked") // varargs
796  public void testSubMapExclusiveExclusive() {
797    Map<String, Integer> map =
798        ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", false, "two", false);
799    ASSERT.that(map.entrySet()).hasContentsInOrder(Maps.immutableEntry("three", 3));
800  }
801
802  @SuppressWarnings("unchecked") // varargs
803  public void testSubMapInclusiveExclusive() {
804    Map<String, Integer> map =
805        ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", true, "two", false);
806    ASSERT.that(map.entrySet()).hasContentsInOrder(Maps.immutableEntry("one", 1),
807        Maps.immutableEntry("three", 3));
808  }
809
810  @SuppressWarnings("unchecked") // varargs
811  public void testSubMapExclusiveInclusive() {
812    Map<String, Integer> map =
813        ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", false, "two", true);
814    ASSERT.that(map.entrySet()).hasContentsInOrder(Maps.immutableEntry("three", 3),
815        Maps.immutableEntry("two", 2));
816  }
817
818  @SuppressWarnings("unchecked") // varargs
819  public void testSubMapInclusiveInclusive() {
820    Map<String, Integer> map =
821        ImmutableSortedMap.of("one", 1, "two", 2, "three", 3).subMap("one", true, "two", true);
822    ASSERT.that(map.entrySet()).hasContentsInOrder(Maps.immutableEntry("one", 1),
823        Maps.immutableEntry("three", 3), Maps.immutableEntry("two", 2));
824  }
825}
826