1 /*
2  * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 package test.java.util.List;
24 
25 import java.io.ByteArrayInputStream;
26 import java.io.ByteArrayOutputStream;
27 import java.io.IOException;
28 import java.io.ObjectInputStream;
29 import java.io.ObjectOutputStream;
30 import java.io.Serializable;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Collections;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.ListIterator;
37 
38 import org.testng.annotations.DataProvider;
39 import org.testng.annotations.Test;
40 
41 import static java.util.Arrays.asList;
42 
43 import static org.testng.Assert.assertEquals;
44 import static org.testng.Assert.assertFalse;
45 import static org.testng.Assert.assertNotEquals;
46 import static org.testng.Assert.assertNotSame;
47 import static org.testng.Assert.assertSame;
48 import static org.testng.Assert.assertTrue;
49 import static org.testng.Assert.fail;
50 
51 /*
52  * @test
53  * @bug 8048330 8203184
54  * @summary Test convenience static factory methods on List.
55  * @run testng ListFactories
56  */
57 @Test
58 public class ListFactories {
59 
60     static final int NUM_STRINGS = 20; // should be larger than the largest fixed-arg overload
61     static final String[] stringArray;
62     static {
63         String[] sa = new String[NUM_STRINGS];
64         for (int i = 0; i < NUM_STRINGS; i++) {
65             sa[i] = String.valueOf((char)('a' + i));
66         }
67         stringArray = sa;
68     }
69 
70     // returns array of [actual, expected]
a(List<String> act, List<String> exp)71     static Object[] a(List<String> act, List<String> exp) {
72         return new Object[] { act, exp };
73     }
74 
75     @DataProvider(name="empty")
empty()76     public Iterator<Object[]> empty() {
77         return Collections.singletonList(
78             a(List.of(), asList())
79         ).iterator();
80     }
81 
82     @DataProvider(name="nonempty")
nonempty()83     public Iterator<Object[]> nonempty() {
84         return asList(
85             a(List.of("a"),
86                asList("a")),
87             a(List.of("a", "b"),
88                asList("a", "b")),
89             a(List.of("a", "b", "c"),
90                asList("a", "b", "c")),
91             a(List.of("a", "b", "c", "d"),
92                asList("a", "b", "c", "d")),
93             a(List.of("a", "b", "c", "d", "e"),
94                asList("a", "b", "c", "d", "e")),
95             a(List.of("a", "b", "c", "d", "e", "f"),
96                asList("a", "b", "c", "d", "e", "f")),
97             a(List.of("a", "b", "c", "d", "e", "f", "g"),
98                asList("a", "b", "c", "d", "e", "f", "g")),
99             a(List.of("a", "b", "c", "d", "e", "f", "g", "h"),
100                asList("a", "b", "c", "d", "e", "f", "g", "h")),
101             a(List.of("a", "b", "c", "d", "e", "f", "g", "h", "i"),
102                asList("a", "b", "c", "d", "e", "f", "g", "h", "i")),
103             a(List.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"),
104                asList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j")),
105             a(List.of(stringArray),
106                asList(stringArray))
107         ).iterator();
108     }
109 
110     @DataProvider(name="sublists")
sublists()111     public Iterator<Object[]> sublists() {
112         return asList(
113             a(List.<String>of().subList(0,0),
114                asList()),
115             a(List.of("a").subList(0,0),
116                asList("a").subList(0,0)),
117             a(List.of("a", "b").subList(0,1),
118                asList("a", "b").subList(0,1)),
119             a(List.of("a", "b", "c").subList(1,3),
120                asList("a", "b", "c").subList(1,3)),
121             a(List.of("a", "b", "c", "d").subList(0,4),
122                asList("a", "b", "c", "d").subList(0,4)),
123             a(List.of("a", "b", "c", "d", "e").subList(0,3),
124                asList("a", "b", "c", "d", "e").subList(0,3)),
125             a(List.of("a", "b", "c", "d", "e", "f").subList(3, 5),
126                asList("a", "b", "c", "d", "e", "f").subList(3, 5)),
127             a(List.of("a", "b", "c", "d", "e", "f", "g").subList(0, 7),
128                asList("a", "b", "c", "d", "e", "f", "g").subList(0, 7)),
129             a(List.of("a", "b", "c", "d", "e", "f", "g", "h").subList(0, 0),
130                asList("a", "b", "c", "d", "e", "f", "g", "h").subList(0, 0)),
131             a(List.of("a", "b", "c", "d", "e", "f", "g", "h", "i").subList(4, 5),
132                asList("a", "b", "c", "d", "e", "f", "g", "h", "i").subList(4, 5)),
133             a(List.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j").subList(1,10),
134                asList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j").subList(1,10)),
135             a(List.of(stringArray).subList(5, NUM_STRINGS),
136                asList(Arrays.copyOfRange(stringArray, 5, NUM_STRINGS)))
137                 ).iterator();
138     }
139 
140     @DataProvider(name="all")
all()141     public Iterator<Object[]> all() {
142         List<Object[]> all = new ArrayList<>();
143         empty().forEachRemaining(all::add);
144         nonempty().forEachRemaining(all::add);
145         sublists().forEachRemaining(all::add);
146         return all.iterator();
147     }
148 
149     @DataProvider(name="nonsublists")
nonsublists()150     public Iterator<Object[]> nonsublists() {
151         List<Object[]> all = new ArrayList<>();
152         empty().forEachRemaining(all::add);
153         nonempty().forEachRemaining(all::add);
154         return all.iterator();
155     }
156 
157     @Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class)
cannotAddLast(List<String> act, List<String> exp)158     public void cannotAddLast(List<String> act, List<String> exp) {
159         act.add("x");
160     }
161 
162     @Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class)
cannotAddFirst(List<String> act, List<String> exp)163     public void cannotAddFirst(List<String> act, List<String> exp) {
164         act.add(0, "x");
165     }
166 
167     @Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class)
cannotRemove(List<String> act, List<String> exp)168     public void cannotRemove(List<String> act, List<String> exp) {
169         act.remove(0);
170     }
171 
172     @Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class)
cannotSet(List<String> act, List<String> exp)173     public void cannotSet(List<String> act, List<String> exp) {
174         act.set(0, "x");
175     }
176 
177     @Test(dataProvider="all")
contentsMatch(List<String> act, List<String> exp)178     public void contentsMatch(List<String> act, List<String> exp) {
179         assertEquals(act, exp);
180     }
181 
182     @Test(expectedExceptions=NullPointerException.class)
nullDisallowed1()183     public void nullDisallowed1() {
184         List.of((Object)null); // force one-arg overload
185     }
186 
187     @Test(expectedExceptions=NullPointerException.class)
nullDisallowed2a()188     public void nullDisallowed2a() {
189         List.of("a", null);
190     }
191 
192     @Test(expectedExceptions=NullPointerException.class)
nullDisallowed2b()193     public void nullDisallowed2b() {
194         List.of(null, "b");
195     }
196 
197     @Test(expectedExceptions=NullPointerException.class)
nullDisallowed3()198     public void nullDisallowed3() {
199         List.of("a", "b", null);
200     }
201 
202     @Test(expectedExceptions=NullPointerException.class)
nullDisallowed4()203     public void nullDisallowed4() {
204         List.of("a", "b", "c", null);
205     }
206 
207     @Test(expectedExceptions=NullPointerException.class)
nullDisallowed5()208     public void nullDisallowed5() {
209         List.of("a", "b", "c", "d", null);
210     }
211 
212     @Test(expectedExceptions=NullPointerException.class)
nullDisallowed6()213     public void nullDisallowed6() {
214         List.of("a", "b", "c", "d", "e", null);
215     }
216 
217     @Test(expectedExceptions=NullPointerException.class)
nullDisallowed7()218     public void nullDisallowed7() {
219         List.of("a", "b", "c", "d", "e", "f", null);
220     }
221 
222     @Test(expectedExceptions=NullPointerException.class)
nullDisallowed8()223     public void nullDisallowed8() {
224         List.of("a", "b", "c", "d", "e", "f", "g", null);
225     }
226 
227     @Test(expectedExceptions=NullPointerException.class)
nullDisallowed9()228     public void nullDisallowed9() {
229         List.of("a", "b", "c", "d", "e", "f", "g", "h", null);
230     }
231 
232     @Test(expectedExceptions=NullPointerException.class)
nullDisallowed10()233     public void nullDisallowed10() {
234         List.of("a", "b", "c", "d", "e", "f", "g", "h", "i", null);
235     }
236 
237     @Test(expectedExceptions=NullPointerException.class)
nullDisallowedN()238     public void nullDisallowedN() {
239         String[] array = stringArray.clone();
240         array[0] = null;
241         List.of(array);
242     }
243 
244     @Test(expectedExceptions=NullPointerException.class)
nullArrayDisallowed()245     public void nullArrayDisallowed() {
246         List.of((Object[])null);
247     }
248 
249     @Test
ensureArrayCannotModifyList()250     public void ensureArrayCannotModifyList() {
251         String[] array = stringArray.clone();
252         List<String> list = List.of(array);
253         array[0] = "xyzzy";
254         assertEquals(list, Arrays.asList(stringArray));
255     }
256 
257     @Test(dataProvider="all", expectedExceptions=NullPointerException.class)
containsNullShouldThrowNPE(List<String> act, List<String> exp)258     public void containsNullShouldThrowNPE(List<String> act, List<String> exp) {
259         act.contains(null);
260     }
261 
262     @Test(dataProvider="all", expectedExceptions=NullPointerException.class)
indexOfNullShouldThrowNPE(List<String> act, List<String> exp)263     public void indexOfNullShouldThrowNPE(List<String> act, List<String> exp) {
264         act.indexOf(null);
265     }
266 
267     @Test(dataProvider="all", expectedExceptions=NullPointerException.class)
lastIndexOfNullShouldThrowNPE(List<String> act, List<String> exp)268     public void lastIndexOfNullShouldThrowNPE(List<String> act, List<String> exp) {
269         act.lastIndexOf(null);
270     }
271 
272     // List.of().subList views should not be Serializable
273     @Test(dataProvider="sublists")
isNotSerializable(List<String> act, List<String> exp)274     public void isNotSerializable(List<String> act, List<String> exp) {
275         assertFalse(act instanceof Serializable);
276     }
277 
278     // ... but List.of() should be
279     @Test(dataProvider="nonsublists")
serialEquality(List<String> act, List<String> exp)280     public void serialEquality(List<String> act, List<String> exp) {
281         // assume that act.equals(exp) tested elsewhere
282         List<String> copy = serialClone(act);
283         assertEquals(act, copy);
284         assertEquals(copy, exp);
285     }
286 
287     @SuppressWarnings("unchecked")
serialClone(T obj)288     static <T> T serialClone(T obj) {
289         try {
290             ByteArrayOutputStream baos = new ByteArrayOutputStream();
291             try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
292                 oos.writeObject(obj);
293             }
294             ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
295             ObjectInputStream ois = new ObjectInputStream(bais);
296             return (T) ois.readObject();
297         } catch (IOException | ClassNotFoundException e) {
298             throw new AssertionError(e);
299         }
300     }
301 
genList()302     List<Integer> genList() {
303         return new ArrayList<>(Arrays.asList(1, 2, 3));
304     }
305 
306     @Test
copyOfResultsEqual()307     public void copyOfResultsEqual() {
308         List<Integer> orig = genList();
309         List<Integer> copy = List.copyOf(orig);
310 
311         assertEquals(orig, copy);
312         assertEquals(copy, orig);
313     }
314 
315     @Test
copyOfModifiedUnequal()316     public void copyOfModifiedUnequal() {
317         List<Integer> orig = genList();
318         List<Integer> copy = List.copyOf(orig);
319         orig.add(4);
320 
321         assertNotEquals(orig, copy);
322         assertNotEquals(copy, orig);
323     }
324 
325     @Test
copyOfIdentity()326     public void copyOfIdentity() {
327         List<Integer> orig = genList();
328         List<Integer> copy1 = List.copyOf(orig);
329         List<Integer> copy2 = List.copyOf(copy1);
330 
331         assertNotSame(orig, copy1);
332         assertSame(copy1, copy2);
333     }
334 
335     @Test
copyOfSubList()336     public void copyOfSubList() {
337         List<Integer> orig = List.of(0, 1, 2, 3);
338         List<Integer> sub = orig.subList(0, 3);
339         List<Integer> copy = List.copyOf(sub);
340 
341         assertNotSame(sub, copy);
342     }
343 
344     @Test
copyOfSubSubList()345     public void copyOfSubSubList() {
346         List<Integer> orig = List.of(0, 1, 2, 3);
347         List<Integer> sub = orig.subList(0, 3).subList(0, 2);
348         List<Integer> copy = List.copyOf(sub);
349 
350         assertNotSame(sub, copy);
351     }
352 
353     @Test(expectedExceptions=NullPointerException.class)
copyOfRejectsNullCollection()354     public void copyOfRejectsNullCollection() {
355         List<Integer> list = List.copyOf(null);
356     }
357 
358     @Test(expectedExceptions=NullPointerException.class)
copyOfRejectsNullElements()359     public void copyOfRejectsNullElements() {
360         List<Integer> list = List.copyOf(Arrays.asList(1, null, 3));
361     }
362 
363     @Test
iteratorShouldNotBeListIterator()364     public void iteratorShouldNotBeListIterator() {
365         List<Integer> list = List.of(1, 2, 3, 4, 5);
366         Iterator<Integer> it = list.iterator();
367         it.next();
368         try {
369             ((ListIterator<Integer>) it).previous();
370             fail("ListIterator operation succeeded on Iterator");
371         } catch (ClassCastException|UnsupportedOperationException ignore) { }
372     }
373 }
374