• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static com.google.common.truth.Truth.assertWithMessage;
21 
22 import com.google.common.annotations.GwtCompatible;
23 import com.google.common.annotations.GwtIncompatible;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.Enumeration;
29 import java.util.LinkedList;
30 import java.util.List;
31 import java.util.concurrent.CopyOnWriteArrayList;
32 import junit.framework.Test;
33 import junit.framework.TestCase;
34 import junit.framework.TestSuite;
35 
36 /** Tests the package level *impl methods directly using various types of lists. */
37 @GwtCompatible(emulated = true)
38 public class ListsImplTest extends TestCase {
39 
40   /** Describes how a list is modifiable */
41   public enum Modifiability {
42     NONE, // immutable lists
43     BY_ELEMENT, // elements can change (set), but not structure
44     DIRECT_ONLY, // Element can be added and removed only via direct calls, not through iterators
45     ALL // Elements can be added and removed as well as modified.
46   }
47 
48   /** Handles the creation of lists needed for the tests */
49   public abstract static class ListExample {
50 
51     private final String name;
52     private final Modifiability modifiability;
53 
ListExample(String name, Modifiability modifiability)54     protected ListExample(String name, Modifiability modifiability) {
55       this.name = name;
56       this.modifiability = modifiability;
57     }
58 
59     /** Gets the name of the example */
getName()60     public String getName() {
61       return name;
62     }
63 
64     /** Creates a new list with the given contents. */
createList(Class<T> listType, Collection<? extends T> contents)65     public abstract <T> List<T> createList(Class<T> listType, Collection<? extends T> contents);
66 
67     /** The modifiablity of this list example. */
modifiability()68     public Modifiability modifiability() {
69       return modifiability;
70     }
71   }
72 
73   @GwtIncompatible // suite
suite()74   public static Test suite() {
75     TestSuite suite = new TestSuite();
76     suite.addTest(createExampleSuite(new ArrayListExample("ArrayList")));
77     suite.addTest(createExampleSuite(new LinkedListExample("LinkedList")));
78     suite.addTest(createExampleSuite(new ArraysAsListExample("Arrays.asList")));
79     suite.addTest(createExampleSuite(new ImmutableListExample("ImmutableList")));
80     suite.addTest(createExampleSuite(new CopyOnWriteListExample("CopyOnWriteArrayList")));
81     suite.addTestSuite(ListsImplTest.class);
82     return suite;
83   }
84 
85   @GwtIncompatible // suite sub call
createExampleSuite(ListExample example)86   private static TestSuite createExampleSuite(ListExample example) {
87     TestSuite resultSuite = new TestSuite(ListsImplTest.class);
88     for (Enumeration<Test> testEnum = resultSuite.tests(); testEnum.hasMoreElements(); ) {
89       ListsImplTest test = (ListsImplTest) testEnum.nextElement();
90       test.example = example;
91     }
92     return resultSuite;
93   }
94 
95   private ListExample example;
96 
getExample()97   private ListExample getExample() {
98     // because sometimes one version with a null example is created.
99     return example == null ? new ImmutableListExample("test") : example;
100   }
101 
102   @Override
getName()103   public String getName() {
104     return example == null ? super.getName() : buildTestName();
105   }
106 
buildTestName()107   private String buildTestName() {
108     return super.getName() + ":" + example.getName();
109   }
110 
testHashCodeImpl()111   public void testHashCodeImpl() {
112     List<Integer> base = createList(Integer.class, 1, 2, 2);
113     List<Integer> copy = createList(Integer.class, 1, 2, 2);
114     List<Integer> outOfOrder = createList(Integer.class, 2, 2, 1);
115     List<Integer> diffValue = createList(Integer.class, 1, 2, 4);
116     List<Integer> diffLength = createList(Integer.class, 1, 2);
117     List<Integer> empty = createList(Integer.class);
118 
119     assertThat(Lists.hashCodeImpl(base)).isEqualTo(Lists.hashCodeImpl(copy));
120 
121     assertThat(Lists.hashCodeImpl(base)).isNotEqualTo(Lists.hashCodeImpl(outOfOrder));
122     assertThat(Lists.hashCodeImpl(base)).isNotEqualTo(Lists.hashCodeImpl(diffValue));
123     assertThat(Lists.hashCodeImpl(base)).isNotEqualTo(Lists.hashCodeImpl(diffLength));
124     assertThat(Lists.hashCodeImpl(base)).isNotEqualTo(Lists.hashCodeImpl(empty));
125   }
126 
testEqualsImpl()127   public void testEqualsImpl() {
128     List<Integer> base = createList(Integer.class, 1, 2, 2);
129     List<Integer> copy = createList(Integer.class, 1, 2, 2);
130     ImmutableList<Integer> otherType = ImmutableList.of(1, 2, 2);
131     List<Integer> outOfOrder = createList(Integer.class, 2, 2, 1);
132     List<Integer> diffValue = createList(Integer.class, 1, 2, 3);
133     List<Integer> diffLength = createList(Integer.class, 1, 2);
134     List<Integer> empty = createList(Integer.class);
135 
136     assertThat(Lists.equalsImpl(base, copy)).isTrue();
137     assertThat(Lists.equalsImpl(base, otherType)).isTrue();
138 
139     List<Object> unEqualItems =
140         Arrays.asList(outOfOrder, diffValue, diffLength, empty, null, new Object());
141     for (Object other : unEqualItems) {
142       assertWithMessage("%s", other).that(Lists.equalsImpl(base, other)).isFalse();
143     }
144   }
145 
testAddAllImpl()146   public void testAddAllImpl() {
147     if (getExample().modifiability() != Modifiability.ALL) {
148       return;
149     }
150     List<String> toTest = createList(String.class);
151 
152     List<Iterable<String>> toAdd =
153         ImmutableList.of(
154             Collections.singleton("A"),
155             Collections.emptyList(),
156             ImmutableList.of("A", "B", "C"),
157             ImmutableList.of("D", "E"));
158     List<Integer> indexes = ImmutableList.of(0, 0, 1, 3);
159     List<List<String>> expected =
160         ImmutableList.of(
161             ImmutableList.of("A"),
162             ImmutableList.of("A"),
163             ImmutableList.of("A", "A", "B", "C"),
164             ImmutableList.of("A", "A", "D", "E", "B", "C"));
165 
166     String format = "Adding %s at %s";
167     for (int i = 0; i < toAdd.size(); i++) {
168       int index = indexes.get(i);
169       Iterable<String> iterableToAdd = toAdd.get(i);
170       boolean expectedChanged = iterableToAdd.iterator().hasNext();
171       assertWithMessage(format, iterableToAdd, index)
172           .that(Lists.addAllImpl(toTest, index, iterableToAdd))
173           .isEqualTo(expectedChanged);
174       assertWithMessage(format, iterableToAdd, index)
175           .that(toTest)
176           .containsExactlyElementsIn(expected.get(i));
177     }
178   }
179 
testIndexOfImpl_nonNull()180   public void testIndexOfImpl_nonNull() {
181     List<Integer> toTest = createList(Integer.class, 5, 2, -1, 2, 1, 10, 5);
182     int[] expected = {0, 1, 2, 1, 4, 5, 0};
183     checkIndexOf(toTest, expected);
184   }
185 
testIndexOfImpl_null()186   public void testIndexOfImpl_null() {
187     List<String> toTest;
188     try {
189       toTest = createList(String.class, null, "A", "B", null, "C", null);
190     } catch (NullPointerException e) {
191       // example cannot handle nulls, test invalid
192       return;
193     }
194     int[] expected = {0, 1, 2, 0, 4, 0};
195     checkIndexOf(toTest, expected);
196   }
197 
testLastIndexOfImpl_nonNull()198   public void testLastIndexOfImpl_nonNull() {
199     List<Integer> toTest = createList(Integer.class, 1, 5, 6, 10, 1, 3, 2, 1, 6);
200     int[] expected = {7, 1, 8, 3, 7, 5, 6, 7, 8};
201     checkLastIndexOf(toTest, expected);
202   }
203 
testLastIndexOfImpl_null()204   public void testLastIndexOfImpl_null() {
205     List<String> toTest;
206     try {
207       toTest = createList(String.class, null, "A", "B", null, "C", "B");
208     } catch (NullPointerException e) {
209       // example cannot handle nulls, test invalid
210       return;
211     }
212     int[] expected = {3, 1, 5, 3, 4, 5};
213     checkLastIndexOf(toTest, expected);
214   }
215 
checkIndexOf(List<?> toTest, int[] expected)216   private void checkIndexOf(List<?> toTest, int[] expected) {
217     int index = 0;
218     for (Object obj : toTest) {
219       String name = "toTest[" + index + "] (" + obj + ")";
220       assertWithMessage(name).that(Lists.indexOfImpl(toTest, obj)).isEqualTo(expected[index]);
221       index++;
222     }
223   }
224 
checkLastIndexOf(List<?> toTest, int[] expected)225   private void checkLastIndexOf(List<?> toTest, int[] expected) {
226     int index = 0;
227     for (Object obj : toTest) {
228       String name = "toTest[" + index + "] (" + obj + ")";
229       assertWithMessage(name).that(Lists.lastIndexOfImpl(toTest, obj)).isEqualTo(expected[index]);
230       index++;
231     }
232   }
233 
234   @SafeVarargs
235   @SuppressWarnings("varargs")
createList(Class<T> listType, T... contents)236   private final <T> List<T> createList(Class<T> listType, T... contents) {
237     return getExample().createList(listType, Arrays.asList(contents));
238   }
239 
240   private static final class ArrayListExample extends ListExample {
241 
ArrayListExample(String name)242     protected ArrayListExample(String name) {
243       super(name, Modifiability.ALL);
244     }
245 
246     @Override
createList(Class<T> listType, Collection<? extends T> contents)247     public <T> List<T> createList(Class<T> listType, Collection<? extends T> contents) {
248       return new ArrayList<>(contents);
249     }
250   }
251 
252   private static final class LinkedListExample extends ListExample {
253 
LinkedListExample(String name)254     protected LinkedListExample(String name) {
255       super(name, Modifiability.ALL);
256     }
257 
258     @Override
createList(Class<T> listType, Collection<? extends T> contents)259     public <T> List<T> createList(Class<T> listType, Collection<? extends T> contents) {
260       return new LinkedList<>(contents);
261     }
262   }
263 
264   @GwtIncompatible // Iterables.toArray
265   private static final class ArraysAsListExample extends ListExample {
266 
ArraysAsListExample(String name)267     protected ArraysAsListExample(String name) {
268       super(name, Modifiability.BY_ELEMENT);
269     }
270 
271     @Override
createList(Class<T> listType, Collection<? extends T> contents)272     public <T> List<T> createList(Class<T> listType, Collection<? extends T> contents) {
273       @SuppressWarnings("unchecked") // safe by contract
274       T[] array = Iterables.toArray(contents, listType);
275       return Arrays.asList(array);
276     }
277   }
278 
279   private static final class ImmutableListExample extends ListExample {
280 
ImmutableListExample(String name)281     protected ImmutableListExample(String name) {
282       super(name, Modifiability.NONE);
283     }
284 
285     @Override
createList(Class<T> listType, Collection<? extends T> contents)286     public <T> List<T> createList(Class<T> listType, Collection<? extends T> contents) {
287       return ImmutableList.copyOf(contents);
288     }
289   }
290 
291   @GwtIncompatible // CopyOnWriteArrayList
292   private static final class CopyOnWriteListExample extends ListExample {
293 
CopyOnWriteListExample(String name)294     protected CopyOnWriteListExample(String name) {
295       super(name, Modifiability.DIRECT_ONLY);
296     }
297 
298     @Override
createList(Class<T> listType, Collection<? extends T> contents)299     public <T> List<T> createList(Class<T> listType, Collection<? extends T> contents) {
300       return new CopyOnWriteArrayList<>(contents);
301     }
302   }
303 }
304