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