• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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.collect.testing.Helpers.mapEntry;
20 import static com.google.common.testing.SerializableTester.reserialize;
21 import static com.google.common.truth.Truth.assertThat;
22 import static com.google.common.truth.Truth.assertWithMessage;
23 
24 import com.google.common.annotations.GwtCompatible;
25 import com.google.common.annotations.GwtIncompatible;
26 import com.google.common.base.Equivalence;
27 import com.google.common.collect.ImmutableMap.Builder;
28 import com.google.common.collect.testing.AnEnum;
29 import com.google.common.collect.testing.CollectionTestSuiteBuilder;
30 import com.google.common.collect.testing.ListTestSuiteBuilder;
31 import com.google.common.collect.testing.MapTestSuiteBuilder;
32 import com.google.common.collect.testing.TestStringMapGenerator;
33 import com.google.common.collect.testing.features.CollectionFeature;
34 import com.google.common.collect.testing.features.CollectionSize;
35 import com.google.common.collect.testing.features.MapFeature;
36 import com.google.common.collect.testing.google.MapGenerators.ImmutableMapCopyOfEntriesGenerator;
37 import com.google.common.collect.testing.google.MapGenerators.ImmutableMapCopyOfEnumMapGenerator;
38 import com.google.common.collect.testing.google.MapGenerators.ImmutableMapCopyOfGenerator;
39 import com.google.common.collect.testing.google.MapGenerators.ImmutableMapEntryListGenerator;
40 import com.google.common.collect.testing.google.MapGenerators.ImmutableMapGenerator;
41 import com.google.common.collect.testing.google.MapGenerators.ImmutableMapKeyListGenerator;
42 import com.google.common.collect.testing.google.MapGenerators.ImmutableMapUnhashableValuesGenerator;
43 import com.google.common.collect.testing.google.MapGenerators.ImmutableMapValueListGenerator;
44 import com.google.common.collect.testing.google.MapGenerators.ImmutableMapValuesAsSingletonSetGenerator;
45 import com.google.common.testing.CollectorTester;
46 import com.google.common.testing.EqualsTester;
47 import com.google.common.testing.NullPointerTester;
48 import java.io.ByteArrayOutputStream;
49 import java.io.ObjectOutputStream;
50 import java.io.Serializable;
51 import java.util.AbstractMap;
52 import java.util.Arrays;
53 import java.util.Collection;
54 import java.util.Collections;
55 import java.util.EnumMap;
56 import java.util.LinkedHashMap;
57 import java.util.List;
58 import java.util.Map;
59 import java.util.Map.Entry;
60 import java.util.Set;
61 import java.util.regex.Matcher;
62 import java.util.regex.Pattern;
63 import java.util.stream.Collector;
64 import java.util.stream.Stream;
65 import junit.framework.Test;
66 import junit.framework.TestCase;
67 import junit.framework.TestSuite;
68 import org.checkerframework.checker.nullness.qual.Nullable;
69 
70 /**
71  * Tests for {@link ImmutableMap}.
72  *
73  * @author Kevin Bourrillion
74  * @author Jesse Wilson
75  */
76 @GwtCompatible(emulated = true)
77 @SuppressWarnings("AlwaysThrows")
78 public class ImmutableMapTest extends TestCase {
79 
80   @GwtIncompatible // suite
suite()81   public static Test suite() {
82     TestSuite suite = new TestSuite();
83     suite.addTestSuite(ImmutableMapTest.class);
84 
85     suite.addTest(
86         MapTestSuiteBuilder.using(new ImmutableMapGenerator())
87             .withFeatures(
88                 CollectionSize.ANY,
89                 CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
90                 CollectionFeature.KNOWN_ORDER,
91                 MapFeature.REJECTS_DUPLICATES_AT_CREATION,
92                 CollectionFeature.ALLOWS_NULL_QUERIES)
93             .named("ImmutableMap")
94             .createTestSuite());
95 
96     suite.addTest(
97         MapTestSuiteBuilder.using(
98                 new TestStringMapGenerator() {
99                   @Override
100                   protected Map<String, String> create(Entry<String, String>[] entries) {
101                     ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
102                     builder.putAll(Arrays.asList(entries));
103                     return builder.buildJdkBacked();
104                   }
105                 })
106             .withFeatures(
107                 CollectionSize.ANY,
108                 CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
109                 CollectionFeature.KNOWN_ORDER,
110                 MapFeature.REJECTS_DUPLICATES_AT_CREATION,
111                 CollectionFeature.ALLOWS_NULL_QUERIES)
112             .named("ImmutableMap [JDK backed]")
113             .createTestSuite());
114 
115     suite.addTest(
116         MapTestSuiteBuilder.using(new ImmutableMapCopyOfGenerator())
117             .withFeatures(
118                 CollectionSize.ANY,
119                 CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
120                 CollectionFeature.KNOWN_ORDER,
121                 CollectionFeature.ALLOWS_NULL_QUERIES)
122             .named("ImmutableMap.copyOf[Map]")
123             .createTestSuite());
124 
125     suite.addTest(
126         MapTestSuiteBuilder.using(new ImmutableMapCopyOfEntriesGenerator())
127             .withFeatures(
128                 CollectionSize.ANY,
129                 MapFeature.REJECTS_DUPLICATES_AT_CREATION,
130                 CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
131                 CollectionFeature.KNOWN_ORDER,
132                 CollectionFeature.ALLOWS_NULL_QUERIES)
133             .named("ImmutableMap.copyOf[Iterable<Entry>]")
134             .createTestSuite());
135 
136     suite.addTest(
137         MapTestSuiteBuilder.using(new ImmutableMapCopyOfEnumMapGenerator())
138             .withFeatures(
139                 CollectionSize.ANY,
140                 CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
141                 CollectionFeature.KNOWN_ORDER,
142                 CollectionFeature.ALLOWS_NULL_QUERIES)
143             .named("ImmutableMap.copyOf[EnumMap]")
144             .createTestSuite());
145 
146     suite.addTest(
147         MapTestSuiteBuilder.using(new ImmutableMapValuesAsSingletonSetGenerator())
148             .withFeatures(
149                 CollectionSize.ANY,
150                 MapFeature.REJECTS_DUPLICATES_AT_CREATION,
151                 CollectionFeature.KNOWN_ORDER,
152                 CollectionFeature.ALLOWS_NULL_QUERIES)
153             .named("ImmutableMap.asMultimap.asMap")
154             .createTestSuite());
155 
156     suite.addTest(
157         CollectionTestSuiteBuilder.using(new ImmutableMapUnhashableValuesGenerator())
158             .withFeatures(
159                 CollectionSize.ANY,
160                 CollectionFeature.KNOWN_ORDER,
161                 CollectionFeature.ALLOWS_NULL_QUERIES)
162             .named("ImmutableMap.values, unhashable")
163             .createTestSuite());
164 
165     suite.addTest(
166         ListTestSuiteBuilder.using(new ImmutableMapKeyListGenerator())
167             .named("ImmutableMap.keySet.asList")
168             .withFeatures(
169                 CollectionSize.ANY,
170                 CollectionFeature.SERIALIZABLE,
171                 CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
172                 CollectionFeature.ALLOWS_NULL_QUERIES)
173             .createTestSuite());
174 
175     suite.addTest(
176         ListTestSuiteBuilder.using(new ImmutableMapEntryListGenerator())
177             .named("ImmutableMap.entrySet.asList")
178             .withFeatures(
179                 CollectionSize.ANY,
180                 CollectionFeature.SERIALIZABLE,
181                 CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
182                 CollectionFeature.ALLOWS_NULL_QUERIES)
183             .createTestSuite());
184 
185     suite.addTest(
186         ListTestSuiteBuilder.using(new ImmutableMapValueListGenerator())
187             .named("ImmutableMap.values.asList")
188             .withFeatures(
189                 CollectionSize.ANY,
190                 CollectionFeature.SERIALIZABLE,
191                 CollectionFeature.ALLOWS_NULL_QUERIES)
192             .createTestSuite());
193 
194     return suite;
195   }
196 
197   // Creation tests
198 
testEmptyBuilder()199   public void testEmptyBuilder() {
200     ImmutableMap<String, Integer> map = new Builder<String, Integer>().buildOrThrow();
201     assertEquals(Collections.<String, Integer>emptyMap(), map);
202   }
203 
testSingletonBuilder()204   public void testSingletonBuilder() {
205     ImmutableMap<String, Integer> map = new Builder<String, Integer>().put("one", 1).buildOrThrow();
206     assertMapEquals(map, "one", 1);
207   }
208 
testBuilder()209   public void testBuilder() {
210     ImmutableMap<String, Integer> map =
211         new Builder<String, Integer>()
212             .put("one", 1)
213             .put("two", 2)
214             .put("three", 3)
215             .put("four", 4)
216             .put("five", 5)
217             .buildOrThrow();
218     assertMapEquals(map, "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
219   }
220 
221   @GwtIncompatible
testBuilderExactlySizedReusesArray()222   public void testBuilderExactlySizedReusesArray() {
223     ImmutableMap.Builder<Integer, Integer> builder = ImmutableMap.builderWithExpectedSize(10);
224     Entry<Integer, Integer>[] builderArray = builder.entries;
225     for (int i = 0; i < 10; i++) {
226       builder.put(i, i);
227     }
228     Entry<Integer, Integer>[] builderArrayAfterPuts = builder.entries;
229     RegularImmutableMap<Integer, Integer> map =
230         (RegularImmutableMap<Integer, Integer>) builder.buildOrThrow();
231     Entry<Integer, Integer>[] mapInternalArray = map.entries;
232     assertSame(builderArray, builderArrayAfterPuts);
233     assertSame(builderArray, mapInternalArray);
234   }
235 
testBuilder_orderEntriesByValue()236   public void testBuilder_orderEntriesByValue() {
237     ImmutableMap<String, Integer> map =
238         new Builder<String, Integer>()
239             .orderEntriesByValue(Ordering.natural())
240             .put("three", 3)
241             .put("one", 1)
242             .put("five", 5)
243             .put("four", 4)
244             .put("two", 2)
245             .buildOrThrow();
246     assertMapEquals(map, "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
247   }
248 
testBuilder_orderEntriesByValueAfterExactSizeBuild()249   public void testBuilder_orderEntriesByValueAfterExactSizeBuild() {
250     Builder<String, Integer> builder = new Builder<String, Integer>(2).put("four", 4).put("one", 1);
251     ImmutableMap<String, Integer> keyOrdered = builder.buildOrThrow();
252     ImmutableMap<String, Integer> valueOrdered =
253         builder.orderEntriesByValue(Ordering.natural()).buildOrThrow();
254     assertMapEquals(keyOrdered, "four", 4, "one", 1);
255     assertMapEquals(valueOrdered, "one", 1, "four", 4);
256   }
257 
testBuilder_orderEntriesByValue_usedTwiceFails()258   public void testBuilder_orderEntriesByValue_usedTwiceFails() {
259     ImmutableMap.Builder<String, Integer> builder =
260         new Builder<String, Integer>().orderEntriesByValue(Ordering.natural());
261     try {
262       builder.orderEntriesByValue(Ordering.natural());
263       fail("Expected IllegalStateException");
264     } catch (IllegalStateException expected) {
265     }
266   }
267 
268   @GwtIncompatible // we haven't implemented this
testBuilder_orderEntriesByValue_keepingLast()269   public void testBuilder_orderEntriesByValue_keepingLast() {
270     ImmutableMap.Builder<String, Integer> builder =
271         new Builder<String, Integer>()
272             .orderEntriesByValue(Ordering.natural())
273             .put("three", 3)
274             .put("one", 1)
275             .put("five", 5)
276             .put("four", 3)
277             .put("four", 5)
278             .put("four", 4) // this should win because it's last
279             .put("two", 2);
280     assertMapEquals(
281         builder.buildKeepingLast(), "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
282     try {
283       builder.buildOrThrow();
284       fail("Expected exception from duplicate keys");
285     } catch (IllegalArgumentException expected) {
286     }
287   }
288 
289   @GwtIncompatible // we haven't implemented this
testBuilder_orderEntriesByValue_keepingLast_builderSizeFieldPreserved()290   public void testBuilder_orderEntriesByValue_keepingLast_builderSizeFieldPreserved() {
291     ImmutableMap.Builder<String, Integer> builder =
292         new Builder<String, Integer>()
293             .orderEntriesByValue(Ordering.natural())
294             .put("one", 1)
295             .put("one", 1);
296     assertMapEquals(builder.buildKeepingLast(), "one", 1);
297     try {
298       builder.buildOrThrow();
299       fail("Expected exception from duplicate keys");
300     } catch (IllegalArgumentException expected) {
301     }
302   }
303 
testBuilder_withImmutableEntry()304   public void testBuilder_withImmutableEntry() {
305     ImmutableMap<String, Integer> map =
306         new Builder<String, Integer>().put(Maps.immutableEntry("one", 1)).buildOrThrow();
307     assertMapEquals(map, "one", 1);
308   }
309 
testBuilder_withImmutableEntryAndNullContents()310   public void testBuilder_withImmutableEntryAndNullContents() {
311     Builder<String, Integer> builder = new Builder<>();
312     try {
313       builder.put(Maps.immutableEntry("one", (Integer) null));
314       fail();
315     } catch (NullPointerException expected) {
316     }
317     try {
318       builder.put(Maps.immutableEntry((String) null, 1));
319       fail();
320     } catch (NullPointerException expected) {
321     }
322   }
323 
324   private static class StringHolder {
325     String string;
326   }
327 
testBuilder_withMutableEntry()328   public void testBuilder_withMutableEntry() {
329     ImmutableMap.Builder<String, Integer> builder = new Builder<>();
330     final StringHolder holder = new StringHolder();
331     holder.string = "one";
332     Entry<String, Integer> entry =
333         new AbstractMapEntry<String, Integer>() {
334           @Override
335           public String getKey() {
336             return holder.string;
337           }
338 
339           @Override
340           public Integer getValue() {
341             return 1;
342           }
343         };
344 
345     builder.put(entry);
346     holder.string = "two";
347     assertMapEquals(builder.buildOrThrow(), "one", 1);
348   }
349 
testBuilderPutAllWithEmptyMap()350   public void testBuilderPutAllWithEmptyMap() {
351     ImmutableMap<String, Integer> map =
352         new Builder<String, Integer>()
353             .putAll(Collections.<String, Integer>emptyMap())
354             .buildOrThrow();
355     assertEquals(Collections.<String, Integer>emptyMap(), map);
356   }
357 
testBuilderPutAll()358   public void testBuilderPutAll() {
359     Map<String, Integer> toPut = new LinkedHashMap<>();
360     toPut.put("one", 1);
361     toPut.put("two", 2);
362     toPut.put("three", 3);
363     Map<String, Integer> moreToPut = new LinkedHashMap<>();
364     moreToPut.put("four", 4);
365     moreToPut.put("five", 5);
366 
367     ImmutableMap<String, Integer> map =
368         new Builder<String, Integer>().putAll(toPut).putAll(moreToPut).buildOrThrow();
369     assertMapEquals(map, "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
370   }
371 
testBuilderReuse()372   public void testBuilderReuse() {
373     Builder<String, Integer> builder = new Builder<>();
374     ImmutableMap<String, Integer> mapOne = builder.put("one", 1).put("two", 2).buildOrThrow();
375     ImmutableMap<String, Integer> mapTwo = builder.put("three", 3).put("four", 4).buildOrThrow();
376 
377     assertMapEquals(mapOne, "one", 1, "two", 2);
378     assertMapEquals(mapTwo, "one", 1, "two", 2, "three", 3, "four", 4);
379   }
380 
testBuilderPutNullKeyFailsAtomically()381   public void testBuilderPutNullKeyFailsAtomically() {
382     Builder<String, Integer> builder = new Builder<>();
383     try {
384       builder.put(null, 1);
385       fail();
386     } catch (NullPointerException expected) {
387     }
388     builder.put("foo", 2);
389     assertMapEquals(builder.buildOrThrow(), "foo", 2);
390   }
391 
testBuilderPutImmutableEntryWithNullKeyFailsAtomically()392   public void testBuilderPutImmutableEntryWithNullKeyFailsAtomically() {
393     Builder<String, Integer> builder = new Builder<>();
394     try {
395       builder.put(Maps.immutableEntry((String) null, 1));
396       fail();
397     } catch (NullPointerException expected) {
398     }
399     builder.put("foo", 2);
400     assertMapEquals(builder.buildOrThrow(), "foo", 2);
401   }
402 
403   // for GWT compatibility
404   static class SimpleEntry<K, V> extends AbstractMapEntry<K, V> {
405     public K key;
406     public V value;
407 
SimpleEntry(K key, V value)408     SimpleEntry(K key, V value) {
409       this.key = key;
410       this.value = value;
411     }
412 
413     @Override
getKey()414     public K getKey() {
415       return key;
416     }
417 
418     @Override
getValue()419     public V getValue() {
420       return value;
421     }
422   }
423 
testBuilderPutMutableEntryWithNullKeyFailsAtomically()424   public void testBuilderPutMutableEntryWithNullKeyFailsAtomically() {
425     Builder<String, Integer> builder = new Builder<>();
426     try {
427       builder.put(new SimpleEntry<String, Integer>(null, 1));
428       fail();
429     } catch (NullPointerException expected) {
430     }
431     builder.put("foo", 2);
432     assertMapEquals(builder.buildOrThrow(), "foo", 2);
433   }
434 
testBuilderPutNullKey()435   public void testBuilderPutNullKey() {
436     Builder<String, Integer> builder = new Builder<>();
437     try {
438       builder.put(null, 1);
439       fail();
440     } catch (NullPointerException expected) {
441     }
442   }
443 
testBuilderPutNullValue()444   public void testBuilderPutNullValue() {
445     Builder<String, Integer> builder = new Builder<>();
446     try {
447       builder.put("one", null);
448       fail();
449     } catch (NullPointerException expected) {
450     }
451   }
452 
testBuilderPutNullKeyViaPutAll()453   public void testBuilderPutNullKeyViaPutAll() {
454     Builder<String, Integer> builder = new Builder<>();
455     try {
456       builder.putAll(Collections.<String, Integer>singletonMap(null, 1));
457       fail();
458     } catch (NullPointerException expected) {
459     }
460   }
461 
testBuilderPutNullValueViaPutAll()462   public void testBuilderPutNullValueViaPutAll() {
463     Builder<String, Integer> builder = new Builder<>();
464     try {
465       builder.putAll(Collections.<String, Integer>singletonMap("one", null));
466       fail();
467     } catch (NullPointerException expected) {
468     }
469   }
470 
testPuttingTheSameKeyTwiceThrowsOnBuild()471   public void testPuttingTheSameKeyTwiceThrowsOnBuild() {
472     Builder<String, Integer> builder =
473         new Builder<String, Integer>()
474             .put("one", 1)
475             .put("one", 1); // throwing on this line might be better but it's too late to change
476 
477     try {
478       builder.buildOrThrow();
479       fail();
480     } catch (IllegalArgumentException expected) {
481     }
482   }
483 
testBuildKeepingLast_allowsOverwrite()484   public void testBuildKeepingLast_allowsOverwrite() {
485     Builder<Integer, String> builder =
486         new Builder<Integer, String>()
487             .put(1, "un")
488             .put(2, "deux")
489             .put(70, "soixante-dix")
490             .put(70, "septante")
491             .put(70, "seventy")
492             .put(1, "one")
493             .put(2, "two");
494     ImmutableMap<Integer, String> map = builder.buildKeepingLast();
495     assertMapEquals(map, 1, "one", 2, "two", 70, "seventy");
496   }
497 
testBuildKeepingLast_smallTableSameHash()498   public void testBuildKeepingLast_smallTableSameHash() {
499     String key1 = "QED";
500     String key2 = "R&D";
501     assertThat(key1.hashCode()).isEqualTo(key2.hashCode());
502     ImmutableMap<String, Integer> map =
503         ImmutableMap.<String, Integer>builder()
504             .put(key1, 1)
505             .put(key2, 2)
506             .put(key1, 3)
507             .put(key2, 4)
508             .buildKeepingLast();
509     assertMapEquals(map, key1, 3, key2, 4);
510   }
511 
512   // The java7 branch has different code depending on whether the entry indexes fit in a byte,
513   // short, or int. The small table in testBuildKeepingLast_allowsOverwrite will test the byte
514   // case. This method tests the short case.
testBuildKeepingLast_shortTable()515   public void testBuildKeepingLast_shortTable() {
516     Builder<Integer, String> builder = ImmutableMap.builder();
517     Map<Integer, String> expected = new LinkedHashMap<>();
518     for (int i = 0; i < 1000; i++) {
519       // Truncate to even key, so we have put(0, "0") then put(0, "1"). Half the entries are
520       // duplicates.
521       Integer key = i & ~1;
522       String value = String.valueOf(i);
523       builder.put(key, value);
524       expected.put(key, value);
525     }
526     ImmutableMap<Integer, String> map = builder.buildKeepingLast();
527     assertThat(map).hasSize(500);
528     assertThat(map).containsExactlyEntriesIn(expected).inOrder();
529   }
530 
531   // This method tests the int case.
testBuildKeepingLast_bigTable()532   public void testBuildKeepingLast_bigTable() {
533     Builder<Integer, String> builder = ImmutableMap.builder();
534     Map<Integer, String> expected = new LinkedHashMap<>();
535     for (int i = 0; i < 200_000; i++) {
536       // Truncate to even key, so we have put(0, "0") then put(0, "1"). Half the entries are
537       // duplicates.
538       Integer key = i & ~1;
539       String value = String.valueOf(i);
540       builder.put(key, value);
541       expected.put(key, value);
542     }
543     ImmutableMap<Integer, String> map = builder.buildKeepingLast();
544     assertThat(map).hasSize(100_000);
545     assertThat(map).containsExactlyEntriesIn(expected).inOrder();
546   }
547 
548   private static class ClassWithTerribleHashCode implements Comparable<ClassWithTerribleHashCode> {
549     private final int value;
550 
ClassWithTerribleHashCode(int value)551     ClassWithTerribleHashCode(int value) {
552       this.value = value;
553     }
554 
555     @Override
compareTo(ClassWithTerribleHashCode that)556     public int compareTo(ClassWithTerribleHashCode that) {
557       return Integer.compare(this.value, that.value);
558     }
559 
560     @Override
equals(@ullable Object x)561     public boolean equals(@Nullable Object x) {
562       return x instanceof ClassWithTerribleHashCode
563           && ((ClassWithTerribleHashCode) x).value == value;
564     }
565 
566     @Override
hashCode()567     public int hashCode() {
568       return 23;
569     }
570 
571     @Override
toString()572     public String toString() {
573       return "ClassWithTerribleHashCode(" + value + ")";
574     }
575   }
576 
577   @GwtIncompatible
testBuildKeepingLast_collisions()578   public void testBuildKeepingLast_collisions() {
579     Map<ClassWithTerribleHashCode, Integer> expected = new LinkedHashMap<>();
580     Builder<ClassWithTerribleHashCode, Integer> builder = new Builder<>();
581     int size = RegularImmutableMap.MAX_HASH_BUCKET_LENGTH + 10;
582     for (int i = 0; i < size; i++) {
583       ClassWithTerribleHashCode key = new ClassWithTerribleHashCode(i);
584       builder.put(key, i);
585       builder.put(key, -i);
586       expected.put(key, -i);
587     }
588     ImmutableMap<ClassWithTerribleHashCode, Integer> map = builder.buildKeepingLast();
589     assertThat(map).containsExactlyEntriesIn(expected).inOrder();
590     assertThat(map).isInstanceOf(JdkBackedImmutableMap.class);
591   }
592 
593   @GwtIncompatible // Pattern, Matcher
testBuilder_keepingLast_thenOrThrow()594   public void testBuilder_keepingLast_thenOrThrow() {
595     ImmutableMap.Builder<String, Integer> builder =
596         new Builder<String, Integer>()
597             .put("three", 3)
598             .put("one", 1)
599             .put("five", 5)
600             .put("four", 3)
601             .put("four", 5)
602             .put("four", 4) // this should win because it's last
603             .put("two", 2);
604     assertMapEquals(
605         builder.buildKeepingLast(), "three", 3, "one", 1, "five", 5, "four", 4, "two", 2);
606     try {
607       builder.buildOrThrow();
608       fail("Expected exception from duplicate keys");
609     } catch (IllegalArgumentException expected) {
610       // We don't really care which values the exception message contains, but they should be
611       // different from each other. If buildKeepingLast() collapsed duplicates, that might end up
612       // not being true.
613       Pattern pattern = Pattern.compile("Multiple entries with same key: four=(.*) and four=(.*)");
614       assertThat(expected).hasMessageThat().matches(pattern);
615       Matcher matcher = pattern.matcher(expected.getMessage());
616       assertThat(matcher.matches()).isTrue();
617       assertThat(matcher.group(1)).isNotEqualTo(matcher.group(2));
618     }
619   }
620 
testOf()621   public void testOf() {
622     assertMapEquals(ImmutableMap.of("one", 1), "one", 1);
623     assertMapEquals(ImmutableMap.of("one", 1, "two", 2), "one", 1, "two", 2);
624     assertMapEquals(
625         ImmutableMap.of("one", 1, "two", 2, "three", 3), "one", 1, "two", 2, "three", 3);
626     assertMapEquals(
627         ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4),
628         "one",
629         1,
630         "two",
631         2,
632         "three",
633         3,
634         "four",
635         4);
636     assertMapEquals(
637         ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4, "five", 5),
638         "one",
639         1,
640         "two",
641         2,
642         "three",
643         3,
644         "four",
645         4,
646         "five",
647         5);
648     assertMapEquals(
649         ImmutableMap.of(
650             "one", 1,
651             "two", 2,
652             "three", 3,
653             "four", 4,
654             "five", 5,
655             "six", 6),
656         "one",
657         1,
658         "two",
659         2,
660         "three",
661         3,
662         "four",
663         4,
664         "five",
665         5,
666         "six",
667         6);
668     assertMapEquals(
669         ImmutableMap.of(
670             "one", 1,
671             "two", 2,
672             "three", 3,
673             "four", 4,
674             "five", 5,
675             "six", 6,
676             "seven", 7),
677         "one",
678         1,
679         "two",
680         2,
681         "three",
682         3,
683         "four",
684         4,
685         "five",
686         5,
687         "six",
688         6,
689         "seven",
690         7);
691     assertMapEquals(
692         ImmutableMap.of(
693             "one", 1,
694             "two", 2,
695             "three", 3,
696             "four", 4,
697             "five", 5,
698             "six", 6,
699             "seven", 7,
700             "eight", 8),
701         "one",
702         1,
703         "two",
704         2,
705         "three",
706         3,
707         "four",
708         4,
709         "five",
710         5,
711         "six",
712         6,
713         "seven",
714         7,
715         "eight",
716         8);
717     assertMapEquals(
718         ImmutableMap.of(
719             "one", 1,
720             "two", 2,
721             "three", 3,
722             "four", 4,
723             "five", 5,
724             "six", 6,
725             "seven", 7,
726             "eight", 8,
727             "nine", 9),
728         "one",
729         1,
730         "two",
731         2,
732         "three",
733         3,
734         "four",
735         4,
736         "five",
737         5,
738         "six",
739         6,
740         "seven",
741         7,
742         "eight",
743         8,
744         "nine",
745         9);
746     assertMapEquals(
747         ImmutableMap.of(
748             "one", 1,
749             "two", 2,
750             "three", 3,
751             "four", 4,
752             "five", 5,
753             "six", 6,
754             "seven", 7,
755             "eight", 8,
756             "nine", 9,
757             "ten", 10),
758         "one",
759         1,
760         "two",
761         2,
762         "three",
763         3,
764         "four",
765         4,
766         "five",
767         5,
768         "six",
769         6,
770         "seven",
771         7,
772         "eight",
773         8,
774         "nine",
775         9,
776         "ten",
777         10);
778   }
779 
testOfNullKey()780   public void testOfNullKey() {
781     try {
782       ImmutableMap.of(null, 1);
783       fail();
784     } catch (NullPointerException expected) {
785     }
786 
787     try {
788       ImmutableMap.of("one", 1, null, 2);
789       fail();
790     } catch (NullPointerException expected) {
791     }
792   }
793 
testOfNullValue()794   public void testOfNullValue() {
795     try {
796       ImmutableMap.of("one", null);
797       fail();
798     } catch (NullPointerException expected) {
799     }
800 
801     try {
802       ImmutableMap.of("one", 1, "two", null);
803       fail();
804     } catch (NullPointerException expected) {
805     }
806   }
807 
testOfWithDuplicateKey()808   public void testOfWithDuplicateKey() {
809     try {
810       ImmutableMap.of("one", 1, "one", 1);
811       fail();
812     } catch (IllegalArgumentException expected) {
813     }
814   }
815 
testCopyOfEmptyMap()816   public void testCopyOfEmptyMap() {
817     ImmutableMap<String, Integer> copy =
818         ImmutableMap.copyOf(Collections.<String, Integer>emptyMap());
819     assertEquals(Collections.<String, Integer>emptyMap(), copy);
820     assertSame(copy, ImmutableMap.copyOf(copy));
821   }
822 
testCopyOfSingletonMap()823   public void testCopyOfSingletonMap() {
824     ImmutableMap<String, Integer> copy = ImmutableMap.copyOf(Collections.singletonMap("one", 1));
825     assertMapEquals(copy, "one", 1);
826     assertSame(copy, ImmutableMap.copyOf(copy));
827   }
828 
testCopyOf()829   public void testCopyOf() {
830     Map<String, Integer> original = new LinkedHashMap<>();
831     original.put("one", 1);
832     original.put("two", 2);
833     original.put("three", 3);
834 
835     ImmutableMap<String, Integer> copy = ImmutableMap.copyOf(original);
836     assertMapEquals(copy, "one", 1, "two", 2, "three", 3);
837     assertSame(copy, ImmutableMap.copyOf(copy));
838   }
839 
testToImmutableMap()840   public void testToImmutableMap() {
841     Collector<Entry<String, Integer>, ?, ImmutableMap<String, Integer>> collector =
842         ImmutableMap.toImmutableMap(Entry::getKey, Entry::getValue);
843     Equivalence<ImmutableMap<String, Integer>> equivalence =
844         Equivalence.equals().<Entry<String, Integer>>pairwise().onResultOf(ImmutableMap::entrySet);
845     CollectorTester.of(collector, equivalence)
846         .expectCollects(
847             ImmutableMap.of("one", 1, "two", 2, "three", 3),
848             mapEntry("one", 1),
849             mapEntry("two", 2),
850             mapEntry("three", 3));
851   }
852 
testToImmutableMap_exceptionOnDuplicateKey()853   public void testToImmutableMap_exceptionOnDuplicateKey() {
854     Collector<Entry<String, Integer>, ?, ImmutableMap<String, Integer>> collector =
855         ImmutableMap.toImmutableMap(Entry::getKey, Entry::getValue);
856     try {
857       Stream.of(mapEntry("one", 1), mapEntry("one", 11)).collect(collector);
858       fail("Expected IllegalArgumentException");
859     } catch (IllegalArgumentException expected) {
860     }
861   }
862 
testToImmutableMapMerging()863   public void testToImmutableMapMerging() {
864     Collector<Entry<String, Integer>, ?, ImmutableMap<String, Integer>> collector =
865         ImmutableMap.toImmutableMap(Entry::getKey, Entry::getValue, Integer::sum);
866     Equivalence<ImmutableMap<String, Integer>> equivalence =
867         Equivalence.equals().<Entry<String, Integer>>pairwise().onResultOf(ImmutableMap::entrySet);
868     CollectorTester.of(collector, equivalence)
869         .expectCollects(
870             ImmutableMap.of("one", 1, "two", 4, "three", 3),
871             mapEntry("one", 1),
872             mapEntry("two", 2),
873             mapEntry("three", 3),
874             mapEntry("two", 2));
875   }
876 
877   // Non-creation tests
878 
testNullGet()879   public void testNullGet() {
880     ImmutableMap<String, Integer> map = ImmutableMap.of("one", 1);
881     assertNull(map.get(null));
882   }
883 
testAsMultimap()884   public void testAsMultimap() {
885     ImmutableMap<String, Integer> map =
886         ImmutableMap.of("one", 1, "won", 1, "two", 2, "too", 2, "three", 3);
887     ImmutableSetMultimap<String, Integer> expected =
888         ImmutableSetMultimap.of("one", 1, "won", 1, "two", 2, "too", 2, "three", 3);
889     assertEquals(expected, map.asMultimap());
890   }
891 
testAsMultimapWhenEmpty()892   public void testAsMultimapWhenEmpty() {
893     ImmutableMap<String, Integer> map = ImmutableMap.of();
894     ImmutableSetMultimap<String, Integer> expected = ImmutableSetMultimap.of();
895     assertEquals(expected, map.asMultimap());
896   }
897 
testAsMultimapCaches()898   public void testAsMultimapCaches() {
899     ImmutableMap<String, Integer> map = ImmutableMap.of("one", 1);
900     ImmutableSetMultimap<String, Integer> multimap1 = map.asMultimap();
901     ImmutableSetMultimap<String, Integer> multimap2 = map.asMultimap();
902     assertEquals(1, multimap1.asMap().size());
903     assertSame(multimap1, multimap2);
904   }
905 
906   @GwtIncompatible // NullPointerTester
907   @AndroidIncompatible // see ImmutableTableTest.testNullPointerInstance
testNullPointers()908   public void testNullPointers() {
909     NullPointerTester tester = new NullPointerTester();
910     tester.testAllPublicStaticMethods(ImmutableMap.class);
911     tester.testAllPublicInstanceMethods(new ImmutableMap.Builder<Object, Object>());
912     tester.testAllPublicInstanceMethods(ImmutableMap.of());
913     tester.testAllPublicInstanceMethods(ImmutableMap.of("one", 1));
914     tester.testAllPublicInstanceMethods(ImmutableMap.of("one", 1, "two", 2, "three", 3));
915   }
916 
assertMapEquals(Map<K, V> map, Object... alternatingKeysAndValues)917   private static <K, V> void assertMapEquals(Map<K, V> map, Object... alternatingKeysAndValues) {
918     Map<Object, Object> expected = new LinkedHashMap<>();
919     for (int i = 0; i < alternatingKeysAndValues.length; i += 2) {
920       expected.put(alternatingKeysAndValues[i], alternatingKeysAndValues[i + 1]);
921     }
922     assertThat(map).containsExactlyEntriesIn(expected).inOrder();
923   }
924 
925   private static class IntHolder implements Serializable {
926     public int value;
927 
IntHolder(int value)928     public IntHolder(int value) {
929       this.value = value;
930     }
931 
932     @Override
equals(@ullable Object o)933     public boolean equals(@Nullable Object o) {
934       return (o instanceof IntHolder) && ((IntHolder) o).value == value;
935     }
936 
937     @Override
hashCode()938     public int hashCode() {
939       return value;
940     }
941 
942     private static final long serialVersionUID = 5;
943   }
944 
testMutableValues()945   public void testMutableValues() {
946     IntHolder holderA = new IntHolder(1);
947     IntHolder holderB = new IntHolder(2);
948     Map<String, IntHolder> map = ImmutableMap.of("a", holderA, "b", holderB);
949     holderA.value = 3;
950     assertTrue(map.entrySet().contains(Maps.immutableEntry("a", new IntHolder(3))));
951     Map<String, Integer> intMap = ImmutableMap.of("a", 3, "b", 2);
952     assertEquals(intMap.hashCode(), map.entrySet().hashCode());
953     assertEquals(intMap.hashCode(), map.hashCode());
954   }
955 
testCopyOfEnumMap()956   public void testCopyOfEnumMap() {
957     EnumMap<AnEnum, String> map = new EnumMap<>(AnEnum.class);
958     map.put(AnEnum.B, "foo");
959     map.put(AnEnum.C, "bar");
960     assertTrue(ImmutableMap.copyOf(map) instanceof ImmutableEnumMap);
961   }
962 
963   @GwtIncompatible // SerializableTester
testViewSerialization()964   public void testViewSerialization() {
965     Map<String, Integer> map = ImmutableMap.of("one", 1, "two", 2, "three", 3);
966     LenientSerializableTester.reserializeAndAssertLenient(map.entrySet());
967     LenientSerializableTester.reserializeAndAssertLenient(map.keySet());
968 
969     Collection<Integer> reserializedValues = reserialize(map.values());
970     assertEquals(Lists.newArrayList(map.values()), Lists.newArrayList(reserializedValues));
971     assertTrue(reserializedValues instanceof ImmutableCollection);
972   }
973 
974   @GwtIncompatible // SerializableTester
testKeySetIsSerializable_regularImmutableMap()975   public void testKeySetIsSerializable_regularImmutableMap() {
976     class NonSerializableClass {}
977 
978     Map<String, NonSerializableClass> map =
979         RegularImmutableMap.fromEntries(ImmutableMap.entryOf("one", new NonSerializableClass()));
980     Set<String> set = map.keySet();
981 
982     LenientSerializableTester.reserializeAndAssertLenient(set);
983   }
984 
985   @GwtIncompatible // SerializableTester
testKeySetIsSerializable_jdkBackedImmutableMap()986   public void testKeySetIsSerializable_jdkBackedImmutableMap() {
987     class NonSerializableClass {}
988 
989     Entry<String, NonSerializableClass>[] entries =
990         arrayOf(ImmutableMap.entryOf("one", new NonSerializableClass()));
991 
992     ImmutableMap<String, NonSerializableClass> map =
993         JdkBackedImmutableMap.create(1, entries, /* throwIfDuplicateKeys= */ true);
994     Set<String> set = map.keySet();
995 
996     LenientSerializableTester.reserializeAndAssertLenient(set);
997   }
998 
999   @GwtIncompatible // SerializableTester
testValuesCollectionIsSerializable_regularImmutableMap()1000   public void testValuesCollectionIsSerializable_regularImmutableMap() {
1001     class NonSerializableClass {}
1002 
1003     Map<NonSerializableClass, String> map =
1004         RegularImmutableMap.fromEntries(ImmutableMap.entryOf(new NonSerializableClass(), "value"));
1005     Collection<String> collection = map.values();
1006 
1007     LenientSerializableTester.reserializeAndAssertElementsEqual(collection);
1008   }
1009 
1010   @GwtIncompatible // SerializableTester
testValuesCollectionIsSerializable_jdkBackedImmutableMap()1011   public void testValuesCollectionIsSerializable_jdkBackedImmutableMap() {
1012     class NonSerializableClass {}
1013 
1014     Entry<NonSerializableClass, String>[] entries =
1015         arrayOf(ImmutableMap.entryOf(new NonSerializableClass(), "value"));
1016 
1017     ImmutableMap<NonSerializableClass, String> map =
1018         JdkBackedImmutableMap.create(1, entries, /* throwIfDuplicateKeys= */ true);
1019     Collection<String> collection = map.values();
1020 
1021     LenientSerializableTester.reserializeAndAssertElementsEqual(collection);
1022   }
1023 
1024   // TODO: Re-enable this test after moving to new serialization format in ImmutableMap.
1025   @GwtIncompatible // SerializableTester
1026   @SuppressWarnings("unchecked")
ignore_testSerializationNoDuplication_regularImmutableMap()1027   public void ignore_testSerializationNoDuplication_regularImmutableMap() throws Exception {
1028     // Tests that serializing a map, its keySet, and values only writes the underlying data once.
1029 
1030     Entry<Integer, Integer>[] entries = (Entry<Integer, Integer>[]) new Entry<?, ?>[1000];
1031     for (int i = 0; i < 1000; i++) {
1032       entries[i] = ImmutableMap.entryOf(i, i);
1033     }
1034 
1035     ImmutableMap<Integer, Integer> map = RegularImmutableMap.fromEntries(entries);
1036     Set<Integer> keySet = map.keySet();
1037     Collection<Integer> values = map.values();
1038 
1039     ByteArrayOutputStream bytes = new ByteArrayOutputStream();
1040     ObjectOutputStream oos = new ObjectOutputStream(bytes);
1041     oos.writeObject(map);
1042     oos.flush();
1043 
1044     int mapSize = bytes.size();
1045     oos.writeObject(keySet);
1046     oos.writeObject(values);
1047     oos.close();
1048 
1049     int finalSize = bytes.size();
1050 
1051     assertThat(finalSize - mapSize).isLessThan(100);
1052   }
1053 
1054   // TODO: Re-enable this test after moving to new serialization format in ImmutableMap.
1055   @GwtIncompatible // SerializableTester
1056   @SuppressWarnings("unchecked")
ignore_testSerializationNoDuplication_jdkBackedImmutableMap()1057   public void ignore_testSerializationNoDuplication_jdkBackedImmutableMap() throws Exception {
1058     // Tests that serializing a map, its keySet, and values only writes
1059     // the underlying data once.
1060 
1061     Entry<Integer, Integer>[] entries = (Entry<Integer, Integer>[]) new Entry<?, ?>[1000];
1062     for (int i = 0; i < 1000; i++) {
1063       entries[i] = ImmutableMap.entryOf(i, i);
1064     }
1065 
1066     ImmutableMap<Integer, Integer> map =
1067         JdkBackedImmutableMap.create(entries.length, entries, /* throwIfDuplicateKeys= */ true);
1068     Set<Integer> keySet = map.keySet();
1069     Collection<Integer> values = map.values();
1070 
1071     ByteArrayOutputStream bytes = new ByteArrayOutputStream();
1072     ObjectOutputStream oos = new ObjectOutputStream(bytes);
1073     oos.writeObject(map);
1074     oos.flush();
1075 
1076     int mapSize = bytes.size();
1077     oos.writeObject(keySet);
1078     oos.writeObject(values);
1079     oos.close();
1080 
1081     int finalSize = bytes.size();
1082 
1083     assertThat(finalSize - mapSize).isLessThan(100);
1084   }
1085 
arrayOf(T... objs)1086   private static <T> T[] arrayOf(T... objs) {
1087     return objs;
1088   }
1089 
1090   @GwtIncompatible("assumptions about splitting")
testKeySetSplittable()1091   public void testKeySetSplittable() {
1092     ImmutableMap<Integer, Integer> map =
1093         ImmutableMap.<Integer, Integer>builder()
1094             .put(1, 1)
1095             .put(2, 2)
1096             .put(3, 3)
1097             .put(4, 4)
1098             .put(5, 5)
1099             .put(6, 6)
1100             .buildOrThrow();
1101     assertNotNull(map.keySet().spliterator().trySplit());
1102   }
1103 
testEquals()1104   public void testEquals() {
1105     new EqualsTester()
1106         .addEqualityGroup(
1107             ImmutableMap.of(),
1108             ImmutableMap.builder().buildOrThrow(),
1109             ImmutableMap.ofEntries(),
1110             map())
1111         .addEqualityGroup(
1112             ImmutableMap.of(1, 1),
1113             ImmutableMap.builder().put(1, 1).buildOrThrow(),
1114             ImmutableMap.ofEntries(entry(1, 1)),
1115             map(1, 1))
1116         .addEqualityGroup(
1117             ImmutableMap.of(1, 1, 2, 2),
1118             ImmutableMap.builder().put(1, 1).put(2, 2).buildOrThrow(),
1119             ImmutableMap.ofEntries(entry(1, 1), entry(2, 2)),
1120             map(1, 1, 2, 2))
1121         .addEqualityGroup(
1122             ImmutableMap.of(1, 1, 2, 2, 3, 3),
1123             ImmutableMap.builder().put(1, 1).put(2, 2).put(3, 3).buildOrThrow(),
1124             ImmutableMap.ofEntries(entry(1, 1), entry(2, 2), entry(3, 3)),
1125             map(1, 1, 2, 2, 3, 3))
1126         .addEqualityGroup(
1127             ImmutableMap.of(1, 4, 2, 2, 3, 3),
1128             ImmutableMap.builder().put(1, 4).put(2, 2).put(3, 3).buildOrThrow(),
1129             ImmutableMap.ofEntries(entry(1, 4), entry(2, 2), entry(3, 3)),
1130             map(1, 4, 2, 2, 3, 3))
1131         .addEqualityGroup(
1132             ImmutableMap.of(1, 1, 2, 4, 3, 3),
1133             ImmutableMap.builder().put(1, 1).put(2, 4).put(3, 3).buildOrThrow(),
1134             ImmutableMap.ofEntries(entry(1, 1), entry(2, 4), entry(3, 3)),
1135             map(1, 1, 2, 4, 3, 3))
1136         .addEqualityGroup(
1137             ImmutableMap.of(1, 1, 2, 2, 3, 4),
1138             ImmutableMap.builder().put(1, 1).put(2, 2).put(3, 4).buildOrThrow(),
1139             ImmutableMap.ofEntries(entry(1, 1), entry(2, 2), entry(3, 4)),
1140             map(1, 1, 2, 2, 3, 4))
1141         .addEqualityGroup(
1142             ImmutableMap.of(1, 2, 2, 3, 3, 1),
1143             ImmutableMap.builder().put(1, 2).put(2, 3).put(3, 1).buildOrThrow(),
1144             ImmutableMap.ofEntries(entry(1, 2), entry(2, 3), entry(3, 1)),
1145             map(1, 2, 2, 3, 3, 1))
1146         .addEqualityGroup(
1147             ImmutableMap.of(1, 1, 2, 2, 3, 3, 4, 4),
1148             ImmutableMap.builder().put(1, 1).put(2, 2).put(3, 3).put(4, 4).buildOrThrow(),
1149             ImmutableMap.ofEntries(entry(1, 1), entry(2, 2), entry(3, 3), entry(4, 4)),
1150             map(1, 1, 2, 2, 3, 3, 4, 4))
1151         .addEqualityGroup(
1152             ImmutableMap.of(1, 1, 2, 2, 3, 3, 4, 4, 5, 5),
1153             ImmutableMap.builder().put(1, 1).put(2, 2).put(3, 3).put(4, 4).put(5, 5).buildOrThrow(),
1154             ImmutableMap.ofEntries(entry(1, 1), entry(2, 2), entry(3, 3), entry(4, 4), entry(5, 5)),
1155             map(1, 1, 2, 2, 3, 3, 4, 4, 5, 5))
1156         .testEquals();
1157   }
1158 
testOfEntriesNull()1159   public void testOfEntriesNull() {
1160     Entry<Integer, Integer> nullKey = entry(null, 23);
1161     try {
1162       ImmutableMap.ofEntries(nullKey);
1163       fail();
1164     } catch (NullPointerException expected) {
1165     }
1166     Entry<Integer, Integer> nullValue = entry(23, null);
1167     try {
1168       ImmutableMap.ofEntries(nullValue);
1169       fail();
1170     } catch (NullPointerException expected) {
1171     }
1172   }
1173 
map(T... keysAndValues)1174   private static <T> Map<T, T> map(T... keysAndValues) {
1175     assertThat(keysAndValues.length % 2).isEqualTo(0);
1176     LinkedHashMap<T, T> map = new LinkedHashMap<>();
1177     for (int i = 0; i < keysAndValues.length; i += 2) {
1178       T key = keysAndValues[i];
1179       T value = keysAndValues[i + 1];
1180       T old = map.put(key, value);
1181       assertWithMessage("Key %s set to %s and %s", key, value, old).that(old).isNull();
1182     }
1183     return map;
1184   }
1185 
entry(T key, T value)1186   private static <T> Entry<T, T> entry(T key, T value) {
1187     return new AbstractMap.SimpleImmutableEntry<>(key, value);
1188   }
1189 
testCopyOfMutableEntryList()1190   public void testCopyOfMutableEntryList() {
1191     List<Entry<String, String>> entryList =
1192         Arrays.asList(
1193             new AbstractMap.SimpleEntry<>("a", "1"), new AbstractMap.SimpleEntry<>("b", "2"));
1194     ImmutableMap<String, String> map = ImmutableMap.copyOf(entryList);
1195     assertThat(map).containsExactly("a", "1", "b", "2").inOrder();
1196     entryList.get(0).setValue("3");
1197     assertThat(map).containsExactly("a", "1", "b", "2").inOrder();
1198   }
1199 
testBuilderPutAllEntryList()1200   public void testBuilderPutAllEntryList() {
1201     List<Entry<String, String>> entryList =
1202         Arrays.asList(
1203             new AbstractMap.SimpleEntry<>("a", "1"), new AbstractMap.SimpleEntry<>("b", "2"));
1204     ImmutableMap<String, String> map =
1205         ImmutableMap.<String, String>builder().putAll(entryList).buildOrThrow();
1206     assertThat(map).containsExactly("a", "1", "b", "2").inOrder();
1207     entryList.get(0).setValue("3");
1208     assertThat(map).containsExactly("a", "1", "b", "2").inOrder();
1209   }
1210 
testBuilderPutAllEntryListJdkBacked()1211   public void testBuilderPutAllEntryListJdkBacked() {
1212     List<Entry<String, String>> entryList =
1213         Arrays.asList(
1214             new AbstractMap.SimpleEntry<>("a", "1"), new AbstractMap.SimpleEntry<>("b", "2"));
1215     ImmutableMap<String, String> map =
1216         ImmutableMap.<String, String>builder().putAll(entryList).buildJdkBacked();
1217     assertThat(map).containsExactly("a", "1", "b", "2").inOrder();
1218     entryList.get(0).setValue("3");
1219     assertThat(map).containsExactly("a", "1", "b", "2").inOrder();
1220   }
1221 }
1222