• 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 modifiability 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   @GwtIncompatible // not used under GWT, and super.getName() is not available under J2CL
103   @Override
getName()104   public String getName() {
105     return example == null ? super.getName() : buildTestName();
106   }
107 
108   @GwtIncompatible // not used under GWT, and super.getName() is not available under J2CL
buildTestName()109   private String buildTestName() {
110     return super.getName() + ":" + example.getName();
111   }
112 
testHashCodeImpl()113   public void testHashCodeImpl() {
114     List<Integer> base = createList(Integer.class, 1, 2, 2);
115     List<Integer> copy = createList(Integer.class, 1, 2, 2);
116     List<Integer> outOfOrder = createList(Integer.class, 2, 2, 1);
117     List<Integer> diffValue = createList(Integer.class, 1, 2, 4);
118     List<Integer> diffLength = createList(Integer.class, 1, 2);
119     List<Integer> empty = createList(Integer.class);
120 
121     assertThat(Lists.hashCodeImpl(base)).isEqualTo(Lists.hashCodeImpl(copy));
122 
123     assertThat(Lists.hashCodeImpl(base)).isNotEqualTo(Lists.hashCodeImpl(outOfOrder));
124     assertThat(Lists.hashCodeImpl(base)).isNotEqualTo(Lists.hashCodeImpl(diffValue));
125     assertThat(Lists.hashCodeImpl(base)).isNotEqualTo(Lists.hashCodeImpl(diffLength));
126     assertThat(Lists.hashCodeImpl(base)).isNotEqualTo(Lists.hashCodeImpl(empty));
127   }
128 
testEqualsImpl()129   public void testEqualsImpl() {
130     List<Integer> base = createList(Integer.class, 1, 2, 2);
131     List<Integer> copy = createList(Integer.class, 1, 2, 2);
132     ImmutableList<Integer> otherType = ImmutableList.of(1, 2, 2);
133     List<Integer> outOfOrder = createList(Integer.class, 2, 2, 1);
134     List<Integer> diffValue = createList(Integer.class, 1, 2, 3);
135     List<Integer> diffLength = createList(Integer.class, 1, 2);
136     List<Integer> empty = createList(Integer.class);
137 
138     assertThat(Lists.equalsImpl(base, copy)).isTrue();
139     assertThat(Lists.equalsImpl(base, otherType)).isTrue();
140 
141     List<Object> unEqualItems =
142         Arrays.asList(outOfOrder, diffValue, diffLength, empty, null, new Object());
143     for (Object other : unEqualItems) {
144       assertWithMessage("%s", other).that(Lists.equalsImpl(base, other)).isFalse();
145     }
146   }
147 
testAddAllImpl()148   public void testAddAllImpl() {
149     if (getExample().modifiability() != Modifiability.ALL) {
150       return;
151     }
152     List<String> toTest = createList(String.class);
153 
154     List<Iterable<String>> toAdd =
155         ImmutableList.of(
156             Collections.singleton("A"),
157             Collections.emptyList(),
158             ImmutableList.of("A", "B", "C"),
159             ImmutableList.of("D", "E"));
160     List<Integer> indexes = ImmutableList.of(0, 0, 1, 3);
161     List<List<String>> expected =
162         ImmutableList.of(
163             ImmutableList.of("A"),
164             ImmutableList.of("A"),
165             ImmutableList.of("A", "A", "B", "C"),
166             ImmutableList.of("A", "A", "D", "E", "B", "C"));
167 
168     String format = "Adding %s at %s";
169     for (int i = 0; i < toAdd.size(); i++) {
170       int index = indexes.get(i);
171       Iterable<String> iterableToAdd = toAdd.get(i);
172       boolean expectedChanged = iterableToAdd.iterator().hasNext();
173       assertWithMessage(format, iterableToAdd, index)
174           .that(Lists.addAllImpl(toTest, index, iterableToAdd))
175           .isEqualTo(expectedChanged);
176       assertWithMessage(format, iterableToAdd, index)
177           .that(toTest)
178           .containsExactlyElementsIn(expected.get(i));
179     }
180   }
181 
testIndexOfImpl_nonNull()182   public void testIndexOfImpl_nonNull() {
183     List<Integer> toTest = createList(Integer.class, 5, 2, -1, 2, 1, 10, 5);
184     int[] expected = {0, 1, 2, 1, 4, 5, 0};
185     checkIndexOf(toTest, expected);
186   }
187 
testIndexOfImpl_null()188   public void testIndexOfImpl_null() {
189     List<String> toTest;
190     try {
191       toTest = createList(String.class, null, "A", "B", null, "C", null);
192     } catch (NullPointerException e) {
193       // example cannot handle nulls, test invalid
194       return;
195     }
196     int[] expected = {0, 1, 2, 0, 4, 0};
197     checkIndexOf(toTest, expected);
198   }
199 
testLastIndexOfImpl_nonNull()200   public void testLastIndexOfImpl_nonNull() {
201     List<Integer> toTest = createList(Integer.class, 1, 5, 6, 10, 1, 3, 2, 1, 6);
202     int[] expected = {7, 1, 8, 3, 7, 5, 6, 7, 8};
203     checkLastIndexOf(toTest, expected);
204   }
205 
testLastIndexOfImpl_null()206   public void testLastIndexOfImpl_null() {
207     List<String> toTest;
208     try {
209       toTest = createList(String.class, null, "A", "B", null, "C", "B");
210     } catch (NullPointerException e) {
211       // example cannot handle nulls, test invalid
212       return;
213     }
214     int[] expected = {3, 1, 5, 3, 4, 5};
215     checkLastIndexOf(toTest, expected);
216   }
217 
checkIndexOf(List<?> toTest, int[] expected)218   private void checkIndexOf(List<?> toTest, int[] expected) {
219     int index = 0;
220     for (Object obj : toTest) {
221       String name = "toTest[" + index + "] (" + obj + ")";
222       assertWithMessage(name).that(Lists.indexOfImpl(toTest, obj)).isEqualTo(expected[index]);
223       index++;
224     }
225   }
226 
checkLastIndexOf(List<?> toTest, int[] expected)227   private void checkLastIndexOf(List<?> toTest, int[] expected) {
228     int index = 0;
229     for (Object obj : toTest) {
230       String name = "toTest[" + index + "] (" + obj + ")";
231       assertWithMessage(name).that(Lists.lastIndexOfImpl(toTest, obj)).isEqualTo(expected[index]);
232       index++;
233     }
234   }
235 
236   @SafeVarargs
237   @SuppressWarnings("varargs")
createList(Class<T> listType, T... contents)238   private final <T> List<T> createList(Class<T> listType, T... contents) {
239     return getExample().createList(listType, Arrays.asList(contents));
240   }
241 
242   private static final class ArrayListExample extends ListExample {
243 
ArrayListExample(String name)244     protected ArrayListExample(String name) {
245       super(name, Modifiability.ALL);
246     }
247 
248     @Override
createList(Class<T> listType, Collection<? extends T> contents)249     public <T> List<T> createList(Class<T> listType, Collection<? extends T> contents) {
250       return new ArrayList<>(contents);
251     }
252   }
253 
254   private static final class LinkedListExample extends ListExample {
255 
LinkedListExample(String name)256     protected LinkedListExample(String name) {
257       super(name, Modifiability.ALL);
258     }
259 
260     @Override
createList(Class<T> listType, Collection<? extends T> contents)261     public <T> List<T> createList(Class<T> listType, Collection<? extends T> contents) {
262       return new LinkedList<>(contents);
263     }
264   }
265 
266   @GwtIncompatible // Iterables.toArray
267   private static final class ArraysAsListExample extends ListExample {
268 
ArraysAsListExample(String name)269     protected ArraysAsListExample(String name) {
270       super(name, Modifiability.BY_ELEMENT);
271     }
272 
273     @Override
createList(Class<T> listType, Collection<? extends T> contents)274     public <T> List<T> createList(Class<T> listType, Collection<? extends T> contents) {
275       @SuppressWarnings("unchecked") // safe by contract
276       T[] array = Iterables.toArray(contents, listType);
277       return Arrays.asList(array);
278     }
279   }
280 
281   private static final class ImmutableListExample extends ListExample {
282 
ImmutableListExample(String name)283     protected ImmutableListExample(String name) {
284       super(name, Modifiability.NONE);
285     }
286 
287     @Override
createList(Class<T> listType, Collection<? extends T> contents)288     public <T> List<T> createList(Class<T> listType, Collection<? extends T> contents) {
289       return ImmutableList.copyOf(contents);
290     }
291   }
292 
293   @GwtIncompatible // CopyOnWriteArrayList
294   private static final class CopyOnWriteListExample extends ListExample {
295 
CopyOnWriteListExample(String name)296     protected CopyOnWriteListExample(String name) {
297       super(name, Modifiability.DIRECT_ONLY);
298     }
299 
300     @Override
createList(Class<T> listType, Collection<? extends T> contents)301     public <T> List<T> createList(Class<T> listType, Collection<? extends T> contents) {
302       return new CopyOnWriteArrayList<>(contents);
303     }
304   }
305 }
306