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