• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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 
17 package com.google.common.collect;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import com.google.common.annotations.GwtCompatible;
22 import com.google.common.annotations.GwtIncompatible;
23 import com.google.common.testing.SerializableTester;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.Comparator;
27 import java.util.Iterator;
28 import java.util.Map.Entry;
29 import java.util.SortedSet;
30 import junit.framework.TestCase;
31 import org.checkerframework.checker.nullness.qual.Nullable;
32 
33 /**
34  * Unit tests for {@code TreeMultimap} with explicit comparators.
35  *
36  * @author Jared Levy
37  */
38 @GwtCompatible(emulated = true)
39 @ElementTypesAreNonnullByDefault
40 public class TreeMultimapExplicitTest extends TestCase {
41 
42   /**
43    * Compare strings lengths, and if the lengths are equal compare the strings. A {@code null} is
44    * less than any non-null value.
45    */
46   private enum StringLength implements Comparator<@Nullable String> {
47     COMPARATOR;
48 
49     @Override
compare(@ullable String first, @Nullable String second)50     public int compare(@Nullable String first, @Nullable String second) {
51       if (first == second) {
52         return 0;
53       } else if (first == null) {
54         return -1;
55       } else if (second == null) {
56         return 1;
57       } else if (first.length() != second.length()) {
58         return first.length() - second.length();
59       } else {
60         return first.compareTo(second);
61       }
62     }
63   }
64 
65   /** Decreasing integer values. A {@code null} comes before any non-null value. */
66   private static final Comparator<@Nullable Integer> DECREASING_INT_COMPARATOR =
67       Ordering.<Integer>natural().reverse().<Integer>nullsFirst();
68 
create()69   private SetMultimap<String, Integer> create() {
70     return TreeMultimap.create(StringLength.COMPARATOR, DECREASING_INT_COMPARATOR);
71   }
72 
73   /** Create and populate a {@code TreeMultimap} with explicit comparators. */
createPopulate()74   private TreeMultimap<@Nullable String, @Nullable Integer> createPopulate() {
75     TreeMultimap<@Nullable String, @Nullable Integer> multimap =
76         TreeMultimap.create(StringLength.COMPARATOR, DECREASING_INT_COMPARATOR);
77     multimap.put("google", 2);
78     multimap.put("google", 6);
79     multimap.put(null, 3);
80     multimap.put(null, 1);
81     multimap.put(null, 7);
82     multimap.put("tree", 0);
83     multimap.put("tree", null);
84     return multimap;
85   }
86 
87   /** Test that a TreeMultimap created from another uses the natural ordering. */
testMultimapCreateFromTreeMultimap()88   public void testMultimapCreateFromTreeMultimap() {
89     TreeMultimap<String, Integer> tree =
90         TreeMultimap.create(StringLength.COMPARATOR, DECREASING_INT_COMPARATOR);
91     tree.put("google", 2);
92     tree.put("google", 6);
93     tree.put("tree", 0);
94     tree.put("tree", 3);
95     assertThat(tree.keySet()).containsExactly("tree", "google").inOrder();
96     assertThat(tree.get("google")).containsExactly(6, 2).inOrder();
97 
98     TreeMultimap<String, Integer> copy = TreeMultimap.create(tree);
99     assertEquals(tree, copy);
100     assertThat(copy.keySet()).containsExactly("google", "tree").inOrder();
101     assertThat(copy.get("google")).containsExactly(2, 6).inOrder();
102     assertEquals(Ordering.natural(), copy.keyComparator());
103     assertEquals(Ordering.natural(), copy.valueComparator());
104     assertEquals(Ordering.natural(), copy.get("google").comparator());
105   }
106 
testToString()107   public void testToString() {
108     Multimap<String, Integer> multimap = create();
109     multimap.put("foo", 3);
110     multimap.put("bar", 1);
111     multimap.putAll("foo", Arrays.asList(-1, 2, 4));
112     multimap.putAll("bar", Arrays.asList(2, 3));
113     multimap.put("foo", 1);
114     assertEquals("{bar=[3, 2, 1], foo=[4, 3, 2, 1, -1]}", multimap.toString());
115   }
116 
testGetComparator()117   public void testGetComparator() {
118     TreeMultimap<@Nullable String, @Nullable Integer> multimap = createPopulate();
119     assertEquals(StringLength.COMPARATOR, multimap.keyComparator());
120     assertEquals(DECREASING_INT_COMPARATOR, multimap.valueComparator());
121   }
122 
testOrderedGet()123   public void testOrderedGet() {
124     TreeMultimap<@Nullable String, @Nullable Integer> multimap = createPopulate();
125     assertThat(multimap.get(null)).containsExactly(7, 3, 1).inOrder();
126     assertThat(multimap.get("google")).containsExactly(6, 2).inOrder();
127     assertThat(multimap.get("tree")).containsExactly(null, 0).inOrder();
128   }
129 
testOrderedKeySet()130   public void testOrderedKeySet() {
131     TreeMultimap<@Nullable String, @Nullable Integer> multimap = createPopulate();
132     assertThat(multimap.keySet()).containsExactly(null, "tree", "google").inOrder();
133   }
134 
testOrderedAsMapEntries()135   public void testOrderedAsMapEntries() {
136     TreeMultimap<@Nullable String, @Nullable Integer> multimap = createPopulate();
137     Iterator<Entry<String, Collection<Integer>>> iterator = multimap.asMap().entrySet().iterator();
138     Entry<String, Collection<Integer>> entry = iterator.next();
139     assertEquals(null, entry.getKey());
140     assertThat(entry.getValue()).containsExactly(7, 3, 1);
141     entry = iterator.next();
142     assertEquals("tree", entry.getKey());
143     assertThat(entry.getValue()).containsExactly(null, 0);
144     entry = iterator.next();
145     assertEquals("google", entry.getKey());
146     assertThat(entry.getValue()).containsExactly(6, 2);
147   }
148 
testOrderedEntries()149   public void testOrderedEntries() {
150     TreeMultimap<@Nullable String, @Nullable Integer> multimap = createPopulate();
151     assertThat(multimap.entries())
152         .containsExactly(
153             Maps.<@Nullable String, Integer>immutableEntry(null, 7),
154             Maps.<@Nullable String, Integer>immutableEntry(null, 3),
155             Maps.<@Nullable String, Integer>immutableEntry(null, 1),
156             Maps.<String, @Nullable Integer>immutableEntry("tree", null),
157             Maps.immutableEntry("tree", 0),
158             Maps.immutableEntry("google", 6),
159             Maps.immutableEntry("google", 2))
160         .inOrder();
161   }
162 
testOrderedValues()163   public void testOrderedValues() {
164     TreeMultimap<@Nullable String, @Nullable Integer> multimap = createPopulate();
165     assertThat(multimap.values()).containsExactly(7, 3, 1, null, 0, 6, 2).inOrder();
166   }
167 
testComparator()168   public void testComparator() {
169     TreeMultimap<@Nullable String, @Nullable Integer> multimap = createPopulate();
170     assertEquals(DECREASING_INT_COMPARATOR, multimap.get("foo").comparator());
171     assertEquals(DECREASING_INT_COMPARATOR, multimap.get("missing").comparator());
172   }
173 
testMultimapComparators()174   public void testMultimapComparators() {
175     Multimap<String, Integer> multimap = create();
176     multimap.put("foo", 3);
177     multimap.put("bar", 1);
178     multimap.putAll("foo", Arrays.asList(-1, 2, 4));
179     multimap.putAll("bar", Arrays.asList(2, 3));
180     multimap.put("foo", 1);
181     TreeMultimap<String, Integer> copy =
182         TreeMultimap.create(StringLength.COMPARATOR, DECREASING_INT_COMPARATOR);
183     copy.putAll(multimap);
184     assertEquals(multimap, copy);
185     assertEquals(StringLength.COMPARATOR, copy.keyComparator());
186     assertEquals(DECREASING_INT_COMPARATOR, copy.valueComparator());
187   }
188 
testSortedKeySet()189   public void testSortedKeySet() {
190     TreeMultimap<@Nullable String, @Nullable Integer> multimap = createPopulate();
191     SortedSet<@Nullable String> keySet = multimap.keySet();
192 
193     assertEquals(null, keySet.first());
194     assertEquals("google", keySet.last());
195     assertEquals(StringLength.COMPARATOR, keySet.comparator());
196     assertEquals(Sets.<@Nullable String>newHashSet(null, "tree"), keySet.headSet("yahoo"));
197     assertEquals(Sets.newHashSet("google"), keySet.tailSet("yahoo"));
198     assertEquals(Sets.newHashSet("tree"), keySet.subSet("ask", "yahoo"));
199   }
200 
201   @GwtIncompatible // SerializableTester
testExplicitComparatorSerialization()202   public void testExplicitComparatorSerialization() {
203     TreeMultimap<@Nullable String, @Nullable Integer> multimap = createPopulate();
204     TreeMultimap<@Nullable String, @Nullable Integer> copy =
205         SerializableTester.reserializeAndAssert(multimap);
206     assertThat(copy.values()).containsExactly(7, 3, 1, null, 0, 6, 2).inOrder();
207     assertThat(copy.keySet()).containsExactly(null, "tree", "google").inOrder();
208     assertEquals(multimap.keyComparator(), copy.keyComparator());
209     assertEquals(multimap.valueComparator(), copy.valueComparator());
210   }
211 }
212