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
17package com.google.common.collect.testing.testers;
18
19import static com.google.common.collect.testing.features.CollectionSize.ZERO;
20import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
21import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
22import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT_ALL;
23import static java.util.Collections.singletonList;
24
25import com.google.common.collect.testing.AbstractMapTester;
26import com.google.common.collect.testing.MinimalCollection;
27import com.google.common.collect.testing.features.CollectionSize;
28import com.google.common.collect.testing.features.MapFeature;
29
30import java.util.Collections;
31import java.util.LinkedHashMap;
32import java.util.List;
33import java.util.Map;
34import java.util.Map.Entry;
35
36/**
37 * A generic JUnit test which tests {@code putAll} operations on a map. Can't be
38 * invoked directly; please see
39 * {@link com.google.common.collect.testing.MapTestSuiteBuilder}.
40 *
41 * <p>This class is GWT compatible.
42 *
43 * @author Chris Povirk
44 * @author Kevin Bourrillion
45 */
46@SuppressWarnings("unchecked") // too many "unchecked generic array creations"
47public class MapPutAllTester<K, V> extends AbstractMapTester<K, V> {
48  private List<Entry<K, V>> containsNullKey;
49  private List<Entry<K, V>> containsNullValue;
50
51  @Override public void setUp() throws Exception {
52    super.setUp();
53    containsNullKey = singletonList(entry(null, samples.e3.getValue()));
54    containsNullValue = singletonList(entry(samples.e3.getKey(), null));
55  }
56
57  @MapFeature.Require(SUPPORTS_PUT_ALL)
58  public void testPutAll_supportedNothing() {
59    getMap().putAll(emptyMap());
60    expectUnchanged();
61  }
62
63  @MapFeature.Require(absent = SUPPORTS_PUT_ALL)
64  public void testPutAll_unsupportedNothing() {
65    try {
66      getMap().putAll(emptyMap());
67    } catch (UnsupportedOperationException tolerated) {
68    }
69    expectUnchanged();
70  }
71
72  @MapFeature.Require(SUPPORTS_PUT_ALL)
73  public void testPutAll_supportedNonePresent() {
74    putAll(createDisjointCollection());
75    expectAdded(samples.e3, samples.e4);
76  }
77
78  @MapFeature.Require(absent = SUPPORTS_PUT_ALL)
79  public void testPutAll_unsupportedNonePresent() {
80    try {
81      putAll(createDisjointCollection());
82      fail("putAll(nonePresent) should throw");
83    } catch (UnsupportedOperationException expected) {
84    }
85    expectUnchanged();
86    expectMissing(samples.e3, samples.e4);
87  }
88
89  @MapFeature.Require(SUPPORTS_PUT_ALL)
90  @CollectionSize.Require(absent = ZERO)
91  public void testPutAll_supportedSomePresent() {
92    putAll(MinimalCollection.of(samples.e3, samples.e0));
93    expectAdded(samples.e3);
94  }
95
96  @MapFeature.Require(absent = SUPPORTS_PUT_ALL)
97  @CollectionSize.Require(absent = ZERO)
98  public void testPutAll_unsupportedSomePresent() {
99    try {
100      putAll(MinimalCollection.of(samples.e3, samples.e0));
101      fail("putAll(somePresent) should throw");
102    } catch (UnsupportedOperationException expected) {
103    }
104    expectUnchanged();
105  }
106
107  @MapFeature.Require(absent = SUPPORTS_PUT_ALL)
108  @CollectionSize.Require(absent = ZERO)
109  public void testPutAll_unsupportedAllPresent() {
110    try {
111      putAll(MinimalCollection.of(samples.e0));
112    } catch (UnsupportedOperationException tolerated) {
113    }
114    expectUnchanged();
115  }
116
117  @MapFeature.Require({SUPPORTS_PUT_ALL,
118      ALLOWS_NULL_KEYS})
119  public void testPutAll_nullKeySupported() {
120    putAll(containsNullKey);
121    expectAdded(containsNullKey.get(0));
122  }
123
124  @MapFeature.Require(value = SUPPORTS_PUT_ALL,
125      absent = ALLOWS_NULL_KEYS)
126  public void testAdd_nullKeyUnsupported() {
127    try {
128      putAll(containsNullKey);
129      fail("putAll(containsNullKey) should throw");
130    } catch (NullPointerException expected) {
131    }
132    expectUnchanged();
133    expectNullKeyMissingWhenNullKeysUnsupported(
134        "Should not contain null key after unsupported " +
135        "putAll(containsNullKey)");
136  }
137
138  @MapFeature.Require({SUPPORTS_PUT_ALL,
139      ALLOWS_NULL_VALUES})
140  public void testPutAll_nullValueSupported() {
141    putAll(containsNullValue);
142    expectAdded(containsNullValue.get(0));
143  }
144
145  @MapFeature.Require(value = SUPPORTS_PUT_ALL,
146      absent = ALLOWS_NULL_VALUES)
147  public void testAdd_nullValueUnsupported() {
148    try {
149      putAll(containsNullValue);
150      fail("putAll(containsNullValue) should throw");
151    } catch (NullPointerException expected) {
152    }
153    expectUnchanged();
154    expectNullValueMissingWhenNullValuesUnsupported(
155        "Should not contain null value after unsupported " +
156        "putAll(containsNullValue)");
157  }
158
159  @MapFeature.Require(SUPPORTS_PUT_ALL)
160  public void testPutAll_nullCollectionReference() {
161    try {
162      getMap().putAll(null);
163      fail("putAll(null) should throw NullPointerException");
164    } catch (NullPointerException expected) {
165    }
166  }
167
168  private Map<K, V> emptyMap() {
169    return Collections.emptyMap();
170  }
171
172  private void putAll(Iterable<Entry<K, V>> entries) {
173    Map<K, V> map = new LinkedHashMap<K, V>();
174    for (Entry<K, V> entry : entries) {
175      map.put(entry.getKey(), entry.getValue());
176    }
177    getMap().putAll(map);
178  }
179}
180