001/*
002 * Copyright (C) 2009 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;
018
019import static com.google.common.collect.testing.ReflectionFreeAssertThrows.assertThrows;
020
021import com.google.common.annotations.GwtCompatible;
022import java.util.Iterator;
023import java.util.Map.Entry;
024import java.util.SortedMap;
025
026/**
027 * Tests representing the contract of {@link SortedMap}. Concrete subclasses of this base class test
028 * conformance of concrete {@link SortedMap} subclasses to that contract.
029 *
030 * @author Jared Levy
031 */
032// TODO: Use this class to test classes besides ImmutableSortedMap.
033@GwtCompatible
034public abstract class SortedMapInterfaceTest<K, V> extends MapInterfaceTest<K, V> {
035
036  protected SortedMapInterfaceTest(
037      boolean allowsNullKeys,
038      boolean allowsNullValues,
039      boolean supportsPut,
040      boolean supportsRemove,
041      boolean supportsClear) {
042    super(allowsNullKeys, allowsNullValues, supportsPut, supportsRemove, supportsClear);
043  }
044
045  @Override
046  protected abstract SortedMap<K, V> makeEmptyMap() throws UnsupportedOperationException;
047
048  @Override
049  protected abstract SortedMap<K, V> makePopulatedMap() throws UnsupportedOperationException;
050
051  @Override
052  protected SortedMap<K, V> makeEitherMap() {
053    try {
054      return makePopulatedMap();
055    } catch (UnsupportedOperationException e) {
056      return makeEmptyMap();
057    }
058  }
059
060  public void testTailMapWriteThrough() {
061    SortedMap<K, V> map;
062    try {
063      map = makePopulatedMap();
064    } catch (UnsupportedOperationException e) {
065      return;
066    }
067    if (map.size() < 2 || !supportsPut) {
068      return;
069    }
070    Iterator<Entry<K, V>> iterator = map.entrySet().iterator();
071    Entry<K, V> firstEntry = iterator.next();
072    Entry<K, V> secondEntry = iterator.next();
073    K key = secondEntry.getKey();
074    SortedMap<K, V> subMap = map.tailMap(key);
075    V value = getValueNotInPopulatedMap();
076    subMap.put(key, value);
077    assertEquals(secondEntry.getValue(), value);
078    assertEquals(map.get(key), value);
079    assertThrows(IllegalArgumentException.class, () -> subMap.put(firstEntry.getKey(), value));
080  }
081
082  public void testTailMapRemoveThrough() {
083    SortedMap<K, V> map;
084    try {
085      map = makePopulatedMap();
086    } catch (UnsupportedOperationException e) {
087      return;
088    }
089    int oldSize = map.size();
090    if (map.size() < 2 || !supportsRemove) {
091      return;
092    }
093    Iterator<Entry<K, V>> iterator = map.entrySet().iterator();
094    Entry<K, V> firstEntry = iterator.next();
095    Entry<K, V> secondEntry = iterator.next();
096    K key = secondEntry.getKey();
097    SortedMap<K, V> subMap = map.tailMap(key);
098    subMap.remove(key);
099    assertNull(subMap.remove(firstEntry.getKey()));
100    assertEquals(map.size(), oldSize - 1);
101    assertFalse(map.containsKey(key));
102    assertEquals(subMap.size(), oldSize - 2);
103  }
104
105  public void testTailMapClearThrough() {
106    SortedMap<K, V> map;
107    try {
108      map = makePopulatedMap();
109    } catch (UnsupportedOperationException e) {
110      return;
111    }
112    int oldSize = map.size();
113    if (map.size() < 2 || !supportsClear) {
114      return;
115    }
116    Iterator<Entry<K, V>> iterator = map.entrySet().iterator();
117    iterator.next(); // advance
118    Entry<K, V> secondEntry = iterator.next();
119    K key = secondEntry.getKey();
120    SortedMap<K, V> subMap = map.tailMap(key);
121    int subMapSize = subMap.size();
122    subMap.clear();
123    assertEquals(map.size(), oldSize - subMapSize);
124    assertTrue(subMap.isEmpty());
125  }
126}