• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
setUp()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    */
actualContents()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    */
resetContainer()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    */
resetContainer(C newValue)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    */
expectContents(E... elements)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    */
expectContents(Collection<E> expected)108   protected void expectContents(Collection<E> expected) {
109     Helpers.assertEqualIgnoringOrder(expected, actualContents());
110   }
111 
expectUnchanged()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    */
expectAdded(E... elements)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 
expectAdded(int index, E... elements)144   protected final void expectAdded(int index, E... elements) {
145     expectAdded(index, Arrays.asList(elements));
146   }
147 
expectAdded(int index, Collection<E> elements)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    */
expectMissing(E... elements)160   protected void expectMissing(E... elements) {
161     for (E element : elements) {
162       assertFalse("Should not contain " + element,
163           actualContents().contains(element));
164     }
165   }
166 
createSamplesArray()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 
ArrayWithDuplicate(E[] elements, E duplicate)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    */
createArrayWithDuplicateElement()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 
getNumElements()196   protected int getNumElements() {
197     return getSubjectGenerator().getCollectionSize().getNumElements();
198   }
199 
getSampleElements(int howMany)200   protected Collection<E> getSampleElements(int howMany) {
201     return getSubjectGenerator().getSampleElements(howMany);
202   }
203 
getSampleElements()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    */
getOrderedElements()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    */
getNullLocation()227   protected int getNullLocation() {
228     return getNumElements() / 2;
229   }
230 
231   @SuppressWarnings("unchecked")
createDisjointCollection()232   protected MinimalCollection<E> createDisjointCollection() {
233     return MinimalCollection.of(samples.e3, samples.e4);
234   }
235 
236   @SuppressWarnings("unchecked")
emptyCollection()237   protected MinimalCollection<E> emptyCollection() {
238     return MinimalCollection.<E>of();
239   }
240 }
241