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