Coverage Summary for Class: AbstractMapTester (com.google.common.collect.testing)

Class Class, % Method, % Line, %
AbstractMapTester 100% (1/1) 94.6% (35/37) 91.2% (73/80)


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.testing; 18  19 import com.google.common.annotations.GwtCompatible; 20 import java.util.Collection; 21 import java.util.Iterator; 22 import java.util.List; 23 import java.util.ListIterator; 24 import java.util.Map; 25 import java.util.Map.Entry; 26 import org.junit.Ignore; 27  28 /** 29  * Base class for map testers. 30  * 31  * <p>TODO: see how much of this is actually needed once Map testers are written. (It was cloned 32  * from AbstractCollectionTester.) 33  * 34  * @param <K> the key type of the map to be tested. 35  * @param <V> the value type of the map to be tested. 36  * @author George van den Driessche 37  */ 38 @GwtCompatible 39 @Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests. 40 public abstract class AbstractMapTester<K, V> 41  extends AbstractContainerTester<Map<K, V>, Entry<K, V>> { 42  protected Map<K, V> getMap() { 43  return container; 44  } 45  46  @Override 47  protected Collection<Entry<K, V>> actualContents() { 48  return getMap().entrySet(); 49  } 50  51  /** @see AbstractContainerTester#resetContainer() */ 52  protected final void resetMap() { 53  resetContainer(); 54  } 55  56  protected void resetMap(Entry<K, V>[] entries) { 57  resetContainer(getSubjectGenerator().create((Object[]) entries)); 58  } 59  60  protected void expectMissingKeys(K... elements) { 61  for (K element : elements) { 62  assertFalse("Should not contain key " + element, getMap().containsKey(element)); 63  } 64  } 65  66  protected void expectMissingValues(V... elements) { 67  for (V element : elements) { 68  assertFalse("Should not contain value " + element, getMap().containsValue(element)); 69  } 70  } 71  72  /** @return an array of the proper size with {@code null} as the key of the middle element. */ 73  protected Entry<K, V>[] createArrayWithNullKey() { 74  Entry<K, V>[] array = createSamplesArray(); 75  final int nullKeyLocation = getNullLocation(); 76  final Entry<K, V> oldEntry = array[nullKeyLocation]; 77  array[nullKeyLocation] = entry(null, oldEntry.getValue()); 78  return array; 79  } 80  81  protected V getValueForNullKey() { 82  return getEntryNullReplaces().getValue(); 83  } 84  85  protected K getKeyForNullValue() { 86  return getEntryNullReplaces().getKey(); 87  } 88  89  private Entry<K, V> getEntryNullReplaces() { 90  Iterator<Entry<K, V>> entries = getSampleElements().iterator(); 91  for (int i = 0; i < getNullLocation(); i++) { 92  entries.next(); 93  } 94  return entries.next(); 95  } 96  97  /** @return an array of the proper size with {@code null} as the value of the middle element. */ 98  protected Entry<K, V>[] createArrayWithNullValue() { 99  Entry<K, V>[] array = createSamplesArray(); 100  final int nullValueLocation = getNullLocation(); 101  final Entry<K, V> oldEntry = array[nullValueLocation]; 102  array[nullValueLocation] = entry(oldEntry.getKey(), null); 103  return array; 104  } 105  106  protected void initMapWithNullKey() { 107  resetMap(createArrayWithNullKey()); 108  } 109  110  protected void initMapWithNullValue() { 111  resetMap(createArrayWithNullValue()); 112  } 113  114  /** 115  * Equivalent to {@link #expectMissingKeys(Object[]) expectMissingKeys} {@code (null)} except that 116  * the call to {@code contains(null)} is permitted to throw a {@code NullPointerException}. 117  * 118  * @param message message to use upon assertion failure 119  */ 120  protected void expectNullKeyMissingWhenNullKeysUnsupported(String message) { 121  try { 122  assertFalse(message, getMap().containsKey(null)); 123  } catch (NullPointerException tolerated) { 124  // Tolerated 125  } 126  } 127  128  /** 129  * Equivalent to {@link #expectMissingValues(Object[]) expectMissingValues} {@code (null)} except 130  * that the call to {@code contains(null)} is permitted to throw a {@code NullPointerException}. 131  * 132  * @param message message to use upon assertion failure 133  */ 134  protected void expectNullValueMissingWhenNullValuesUnsupported(String message) { 135  try { 136  assertFalse(message, getMap().containsValue(null)); 137  } catch (NullPointerException tolerated) { 138  // Tolerated 139  } 140  } 141  142  @SuppressWarnings("unchecked") 143  @Override 144  protected MinimalCollection<Entry<K, V>> createDisjointCollection() { 145  return MinimalCollection.of(e3(), e4()); 146  } 147  148  protected int getNumEntries() { 149  return getNumElements(); 150  } 151  152  protected Collection<Entry<K, V>> getSampleEntries(int howMany) { 153  return getSampleElements(howMany); 154  } 155  156  protected Collection<Entry<K, V>> getSampleEntries() { 157  return getSampleElements(); 158  } 159  160  @Override 161  protected void expectMissing(Entry<K, V>... entries) { 162  for (Entry<K, V> entry : entries) { 163  assertFalse("Should not contain entry " + entry, actualContents().contains(entry)); 164  assertFalse( 165  "Should not contain key " + entry.getKey() + " mapped to value " + entry.getValue(), 166  equal(getMap().get(entry.getKey()), entry.getValue())); 167  } 168  } 169  170  private static boolean equal(Object a, Object b) { 171  return a == b || (a != null && a.equals(b)); 172  } 173  174  // This one-liner saves us from some ugly casts 175  protected Entry<K, V> entry(K key, V value) { 176  return Helpers.mapEntry(key, value); 177  } 178  179  @Override 180  protected void expectContents(Collection<Entry<K, V>> expected) { 181  // TODO: move this to invariant checks once the appropriate hook exists? 182  super.expectContents(expected); 183  for (Entry<K, V> entry : expected) { 184  assertEquals( 185  "Wrong value for key " + entry.getKey(), entry.getValue(), getMap().get(entry.getKey())); 186  } 187  } 188  189  protected final void expectReplacement(Entry<K, V> newEntry) { 190  List<Entry<K, V>> expected = Helpers.copyToList(getSampleElements()); 191  replaceValue(expected, newEntry); 192  expectContents(expected); 193  } 194  195  private void replaceValue(List<Entry<K, V>> expected, Entry<K, V> newEntry) { 196  for (ListIterator<Entry<K, V>> i = expected.listIterator(); i.hasNext(); ) { 197  if (Helpers.equal(i.next().getKey(), newEntry.getKey())) { 198  i.set(newEntry); 199  return; 200  } 201  } 202  203  throw new IllegalArgumentException( 204  Platform.format("key %s not found in entries %s", newEntry.getKey(), expected)); 205  } 206  207  /** 208  * Wrapper for {@link Map#get(Object)} that forces the caller to pass in a key of the same type as 209  * the map. Besides being slightly shorter than code that uses {@link #getMap()}, it also ensures 210  * that callers don't pass an {@link Entry} by mistake. 211  */ 212  protected V get(K key) { 213  return getMap().get(key); 214  } 215  216  protected final K k0() { 217  return e0().getKey(); 218  } 219  220  protected final V v0() { 221  return e0().getValue(); 222  } 223  224  protected final K k1() { 225  return e1().getKey(); 226  } 227  228  protected final V v1() { 229  return e1().getValue(); 230  } 231  232  protected final K k2() { 233  return e2().getKey(); 234  } 235  236  protected final V v2() { 237  return e2().getValue(); 238  } 239  240  protected final K k3() { 241  return e3().getKey(); 242  } 243  244  protected final V v3() { 245  return e3().getValue(); 246  } 247  248  protected final K k4() { 249  return e4().getKey(); 250  } 251  252  protected final V v4() { 253  return e4().getValue(); 254  } 255 }