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