001/*
002 * Copyright (C) 2013 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.google.common.collect.testing.testers;
018
019import static com.google.common.collect.testing.Helpers.getMethod;
020import static com.google.common.collect.testing.Helpers.mapEntry;
021import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ITERATOR_REMOVE;
022import static com.google.common.collect.testing.features.CollectionSize.ONE;
023import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
024import static com.google.common.collect.testing.features.CollectionSize.ZERO;
025import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEYS;
026import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_KEY_QUERIES;
027import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUES;
028import static com.google.common.collect.testing.features.MapFeature.ALLOWS_NULL_VALUE_QUERIES;
029import static com.google.common.collect.testing.features.MapFeature.SUPPORTS_PUT;
030import static org.junit.Assert.assertThrows;
031
032import com.google.common.annotations.GwtCompatible;
033import com.google.common.annotations.GwtIncompatible;
034import com.google.common.annotations.J2ktIncompatible;
035import com.google.common.collect.testing.AbstractMapTester;
036import com.google.common.collect.testing.features.CollectionFeature;
037import com.google.common.collect.testing.features.CollectionSize;
038import com.google.common.collect.testing.features.MapFeature;
039import java.lang.reflect.Method;
040import java.util.Iterator;
041import java.util.Map.Entry;
042import java.util.Set;
043
044/**
045 * Tests {@link java.util.Map#entrySet}.
046 *
047 * @author Louis Wasserman
048 * @param <K> The key type of the map implementation under test.
049 * @param <V> The value type of the map implementation under test.
050 */
051@GwtCompatible
052public class MapEntrySetTester<K, V> extends AbstractMapTester<K, V> {
053  private enum IncomparableType {
054    INSTANCE;
055  }
056
057  @CollectionSize.Require(ONE)
058  @CollectionFeature.Require(SUPPORTS_ITERATOR_REMOVE)
059  public void testIteratorRemoveOnly() {
060    Set<Entry<K, V>> entrySet = getMap().entrySet();
061    Iterator<Entry<K, V>> entryItr = entrySet.iterator();
062    assertEquals(e0(), entryItr.next());
063    entryItr.remove();
064    assertTrue(getMap().isEmpty());
065    assertFalse(entrySet.contains(e0()));
066  }
067
068  @CollectionSize.Require(SEVERAL)
069  @CollectionFeature.Require(SUPPORTS_ITERATOR_REMOVE)
070  public void testIteratorRemoveMultiple() {
071    Iterator<Entry<K, V>> entryItr = getMap().entrySet().iterator();
072    while (entryItr.hasNext()) {
073      entryItr.next();
074      entryItr.remove();
075    }
076    assertTrue(getMap().isEmpty());
077  }
078
079  @CollectionSize.Require(absent = ZERO)
080  @CollectionFeature.Require(SUPPORTS_ITERATOR_REMOVE)
081  @MapFeature.Require(SUPPORTS_PUT)
082  public void testIteratorSetValueAndRemove() {
083    Iterator<Entry<K, V>> entryItr = getMap().entrySet().iterator();
084    while (entryItr.hasNext()) {
085      Entry<K, V> entry = entryItr.next();
086      entry.setValue(e3().getValue());
087      entryItr.remove();
088    }
089    assertTrue(getMap().isEmpty());
090  }
091
092  public void testContainsEntryWithIncomparableKey() {
093    try {
094      assertFalse(getMap().entrySet().contains(mapEntry(IncomparableType.INSTANCE, v0())));
095    } catch (ClassCastException acceptable) {
096      // allowed by the spec
097    }
098  }
099
100  public void testContainsEntryWithIncomparableValue() {
101    try {
102      assertFalse(getMap().entrySet().contains(mapEntry(k0(), IncomparableType.INSTANCE)));
103    } catch (ClassCastException acceptable) {
104      // allowed by the spec
105    }
106  }
107
108  @MapFeature.Require(ALLOWS_NULL_KEY_QUERIES)
109  public void testContainsEntryWithNullKeyAbsent() {
110    assertFalse(getMap().entrySet().contains(mapEntry(null, v0())));
111  }
112
113  @CollectionSize.Require(absent = ZERO)
114  @MapFeature.Require(ALLOWS_NULL_KEYS)
115  public void testContainsEntryWithNullKeyPresent() {
116    initMapWithNullKey();
117    assertTrue(getMap().entrySet().contains(mapEntry(null, getValueForNullKey())));
118  }
119
120  @MapFeature.Require(ALLOWS_NULL_VALUE_QUERIES)
121  public void testContainsEntryWithNullValueAbsent() {
122    assertFalse(getMap().entrySet().contains(mapEntry(k0(), null)));
123  }
124
125  @CollectionSize.Require(absent = ZERO)
126  @MapFeature.Require(ALLOWS_NULL_VALUES)
127  public void testContainsEntryWithNullValuePresent() {
128    initMapWithNullValue();
129    assertTrue(getMap().entrySet().contains(mapEntry(getKeyForNullValue(), null)));
130  }
131
132  @MapFeature.Require(SUPPORTS_PUT)
133  @CollectionSize.Require(absent = ZERO)
134  public void testSetValue() {
135    for (Entry<K, V> entry : getMap().entrySet()) {
136      if (entry.getKey().equals(k0())) {
137        assertEquals("entry.setValue() should return the old value", v0(), entry.setValue(v3()));
138        break;
139      }
140    }
141    expectReplacement(entry(k0(), v3()));
142  }
143
144  @MapFeature.Require({SUPPORTS_PUT, ALLOWS_NULL_VALUES})
145  @CollectionSize.Require(absent = ZERO)
146  public void testSetValueWithNullValuesPresent() {
147    for (Entry<K, V> entry : getMap().entrySet()) {
148      if (entry.getKey().equals(k0())) {
149        assertEquals("entry.setValue() should return the old value", v0(), entry.setValue(null));
150        break;
151      }
152    }
153    expectReplacement(entry(k0(), null));
154  }
155
156  @MapFeature.Require(value = SUPPORTS_PUT, absent = ALLOWS_NULL_VALUES)
157  @CollectionSize.Require(absent = ZERO)
158  public void testSetValueWithNullValuesAbsent() {
159    for (Entry<K, V> entry : getMap().entrySet()) {
160      assertThrows(NullPointerException.class, () -> entry.setValue(null));
161      break;
162    }
163    expectUnchanged();
164  }
165
166  @J2ktIncompatible
167  @GwtIncompatible // reflection
168  public static Method getContainsEntryWithIncomparableKeyMethod() {
169    return getMethod(MapEntrySetTester.class, "testContainsEntryWithIncomparableKey");
170  }
171
172  @J2ktIncompatible
173  @GwtIncompatible // reflection
174  public static Method getContainsEntryWithIncomparableValueMethod() {
175    return getMethod(MapEntrySetTester.class, "testContainsEntryWithIncomparableValue");
176  }
177
178  @J2ktIncompatible
179  @GwtIncompatible // reflection
180  public static Method getSetValueMethod() {
181    return getMethod(MapEntrySetTester.class, "testSetValue");
182  }
183
184  @J2ktIncompatible
185  @GwtIncompatible // reflection
186  public static Method getSetValueWithNullValuesPresentMethod() {
187    return getMethod(MapEntrySetTester.class, "testSetValueWithNullValuesPresent");
188  }
189
190  @J2ktIncompatible
191  @GwtIncompatible // reflection
192  public static Method getSetValueWithNullValuesAbsentMethod() {
193    return getMethod(MapEntrySetTester.class, "testSetValueWithNullValuesAbsent");
194  }
195
196  @J2ktIncompatible
197  @GwtIncompatible // reflection
198  public static Method getIteratorSetValueAndRemove() {
199    return getMethod(MapEntrySetTester.class, "testIteratorSetValueAndRemove");
200  }
201}