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.testing; 18 19 import java.util.ArrayList; 20 import java.util.Arrays; 21 import java.util.Collection; 22 import java.util.Collections; 23 import java.util.List; 24 25 /** 26 * Base class for testers of classes (including {@link Collection} 27 * and {@link java.util.Map Map}) that contain elements. 28 * 29 * <p>This class is GWT compatible. 30 * 31 * @param <C> the type of the container 32 * @param <E> the type of the container's contents 33 * 34 * @author George van den Driessche 35 */ 36 public abstract class AbstractContainerTester<C, E> 37 extends AbstractTester<OneSizeTestContainerGenerator<C, E>> { 38 protected SampleElements<E> samples; 39 protected C container; 40 41 @Override public void setUp() throws Exception { 42 super.setUp(); 43 samples = this.getSubjectGenerator().samples(); 44 resetContainer(); 45 } 46 47 /** 48 * @return the contents of the container under test, for use by 49 * {@link #expectContents(Object[]) expectContents(E...)} and its friends. 50 */ 51 protected abstract Collection<E> actualContents(); 52 53 /** 54 * Replaces the existing container under test with a new container created 55 * by the subject generator. 56 * 57 * @see #resetContainer(Object) resetContainer(C) 58 * 59 * @return the new container instance. 60 */ 61 protected C resetContainer() { 62 return resetContainer(getSubjectGenerator().createTestSubject()); 63 } 64 65 /** 66 * Replaces the existing container under test with a new container. 67 * This is useful when a single test method needs to create multiple 68 * containers while retaining the ability to use 69 * {@link #expectContents(Object[]) expectContents(E...)} and other 70 * convenience methods. The creation of multiple containers in a single 71 * method is discouraged in most cases, but it is vital to the iterator tests. 72 * 73 * @return the new container instance 74 * @param newValue the new container instance 75 */ 76 protected C resetContainer(C newValue) { 77 container = newValue; 78 return container; 79 } 80 81 /** 82 * @see #expectContents(java.util.Collection) 83 * 84 * @param elements expected contents of {@link #container} 85 */ 86 protected final void expectContents(E... elements) { 87 expectContents(Arrays.asList(elements)); 88 } 89 90 /** 91 * Asserts that the collection under test contains exactly the given elements, 92 * respecting cardinality but not order. Subclasses may override this method 93 * to provide stronger assertions, e.g., to check ordering in lists, but 94 * realize that <strong>unless a test extends 95 * {@link com.google.common.collect.testing.testers.AbstractListTester 96 * AbstractListTester}, a call to {@code expectContents()} invokes this 97 * version</strong>. 98 * 99 * @param expected expected value of {@link #container} 100 */ 101 /* 102 * TODO: improve this and other implementations and move out of this framework 103 * for wider use 104 * 105 * TODO: could we incorporate the overriding logic from AbstractListTester, by 106 * examining whether the features include KNOWN_ORDER? 107 */ 108 protected void expectContents(Collection<E> expected) { 109 Helpers.assertEqualIgnoringOrder(expected, actualContents()); 110 } 111 112 protected void expectUnchanged() { 113 expectContents(getSampleElements()); 114 } 115 116 /** 117 * Asserts that the collection under test contains exactly the elements it was 118 * initialized with plus the given elements, according to 119 * {@link #expectContents(java.util.Collection)}. In other words, for the 120 * default {@code expectContents()} implementation, the number of occurrences 121 * of each given element has increased by one since the test collection was 122 * created, and the number of occurrences of all other elements has not 123 * changed. 124 * 125 * <p>Note: This means that a test like the following will fail if 126 * {@code collection} is a {@code Set}: 127 * 128 * <pre> 129 * collection.add(existingElement); 130 * expectAdded(existingElement);</pre> 131 * 132 * In this case, {@code collection} was not modified as a result of the 133 * {@code add()} call, and the test will fail because the number of 134 * occurrences of {@code existingElement} is unchanged. 135 * 136 * @param elements expected additional contents of {@link #container} 137 */ 138 protected final void expectAdded(E... elements) { 139 List<E> expected = Helpers.copyToList(getSampleElements()); 140 expected.addAll(Arrays.asList(elements)); 141 expectContents(expected); 142 } 143 144 protected final void expectAdded(int index, E... elements) { 145 expectAdded(index, Arrays.asList(elements)); 146 } 147 148 protected final void expectAdded(int index, Collection<E> elements) { 149 List<E> expected = Helpers.copyToList(getSampleElements()); 150 expected.addAll(index, elements); 151 expectContents(expected); 152 } 153 154 /* 155 * TODO: if we're testing a list, we could check indexOf(). (Doing it in 156 * AbstractListTester isn't enough because many tests that run on lists don't 157 * extends AbstractListTester.) We could also iterate over all elements to 158 * verify absence 159 */ 160 protected void expectMissing(E... elements) { 161 for (E element : elements) { 162 assertFalse("Should not contain " + element, 163 actualContents().contains(element)); 164 } 165 } 166 167 protected E[] createSamplesArray() { 168 E[] array = getSubjectGenerator().createArray(getNumElements()); 169 getSampleElements().toArray(array); 170 return array; 171 } 172 173 public static class ArrayWithDuplicate<E> { 174 public final E[] elements; 175 public final E duplicate; 176 177 private ArrayWithDuplicate(E[] elements, E duplicate) { 178 this.elements = elements; 179 this.duplicate = duplicate; 180 } 181 } 182 183 /** 184 * @return an array of the proper size with a duplicate element. 185 * The size must be at least three. 186 */ 187 protected ArrayWithDuplicate<E> createArrayWithDuplicateElement() { 188 E[] elements = createSamplesArray(); 189 E duplicate = elements[(elements.length / 2) - 1]; 190 elements[(elements.length / 2) + 1] = duplicate; 191 return new ArrayWithDuplicate<E>(elements, duplicate); 192 } 193 194 // Helper methods to improve readability of derived classes 195 196 protected int getNumElements() { 197 return getSubjectGenerator().getCollectionSize().getNumElements(); 198 } 199 200 protected Collection<E> getSampleElements(int howMany) { 201 return getSubjectGenerator().getSampleElements(howMany); 202 } 203 204 protected Collection<E> getSampleElements() { 205 return getSampleElements(getNumElements()); 206 } 207 208 /** 209 * Returns the {@linkplain #getSampleElements() sample elements} as ordered by 210 * {@link TestContainerGenerator#order(List)}. Tests should used this method 211 * only if they declare requirement {@link 212 * com.google.common.collect.testing.features.CollectionFeature#KNOWN_ORDER}. 213 */ 214 protected List<E> getOrderedElements() { 215 List<E> list = new ArrayList<E>(); 216 for (E e : getSubjectGenerator().order( 217 new ArrayList<E>(getSampleElements()))) { 218 list.add(e); 219 } 220 return Collections.unmodifiableList(list); 221 } 222 223 /** 224 * @return a suitable location for a null element, to use when initializing 225 * containers for tests that involve a null element being present. 226 */ 227 protected int getNullLocation() { 228 return getNumElements() / 2; 229 } 230 231 @SuppressWarnings("unchecked") 232 protected MinimalCollection<E> createDisjointCollection() { 233 return MinimalCollection.of(samples.e3, samples.e4); 234 } 235 236 @SuppressWarnings("unchecked") 237 protected MinimalCollection<E> emptyCollection() { 238 return MinimalCollection.<E>of(); 239 } 240 } 241