1 /*
2  * Copyright (c) 2005, 2006, 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 
24 /*
25  * @test
26  * @bug 6355660 6347106 6394004
27  * @summary methods taking concurrently mutating collection should work
28  * @author Martin Buchholz
29  */
30 package test.java.util.Collection;
31 
32 import java.lang.reflect.Constructor;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.List;
38 import java.util.PriorityQueue;
39 import java.util.Vector;
40 import java.util.concurrent.CopyOnWriteArrayList;
41 import java.util.concurrent.PriorityBlockingQueue;
42 import org.testng.Assert;
43 import org.testng.annotations.Test;
44 
45 @SuppressWarnings("unchecked")
46 public class HotPotatoes {
47 
48     @Test
testVector()49     public void testVector() throws Throwable {
50         testImplementation(Vector.class);
51     }
52 
53     @Test
testArrayList()54     public void testArrayList() throws Throwable {
55         testImplementation(ArrayList.class);
56     }
57 
58     @Test
testPriorityQueue()59     public void testPriorityQueue() throws Throwable {
60         testImplementation(PriorityQueue.class);
61     }
62 
63     @Test
testPriorityBlockingQueue()64     public void testPriorityBlockingQueue() throws Throwable {
65         testImplementation(PriorityBlockingQueue.class);
66     }
67 
testImplementation(Class<? extends Collection> implClazz)68     private static void testImplementation(Class<? extends Collection> implClazz) throws Throwable {
69         testPotato(implClazz, Vector.class);
70         testPotato(implClazz, CopyOnWriteArrayList.class);
71 
72         final Constructor<? extends Collection> constr
73                 = implClazz.getConstructor(Collection.class);
74         final Collection<Object> coll
75                 = constr.newInstance(Arrays.asList(new String[]{}));
76         coll.add(1);
77         Assert.assertEquals(coll.toString(), "[1]");
78     }
79 
testPotato(Class<? extends Collection> implClazz, Class<? extends List> argClazz)80     private static void testPotato(Class<? extends Collection> implClazz,
81             Class<? extends List> argClazz) throws Throwable {
82         try {
83             System.out.printf("implClazz=%s, argClazz=%s\n",
84                     implClazz.getName(), argClazz.getName());
85             final int iterations = 100000;
86             final List<Integer> list = (List<Integer>)
87                     argClazz.getDeclaredConstructor().newInstance();
88             final Integer one = Integer.valueOf(1);
89             final List<Integer> oneElementList = Collections.singletonList(one);
90             final Constructor<? extends Collection> constr
91                     = implClazz.getConstructor(Collection.class);
92             final Thread t = new CheckedThread() {
93                 public void realRun() {
94                     for (int i = 0; i < iterations; i++) {
95                         list.add(one);
96                         list.remove(one);
97                     }
98                 }
99             };
100             t.setDaemon(true);
101             t.start();
102 
103             for (int i = 0; i < iterations; i++) {
104                 Collection<?> coll = constr.newInstance(list);
105                 Object[] elts = coll.toArray();
106                 Assert.assertTrue(elts.length == 0 || (elts.length == 1 && elts[0] == one));
107             }
108         } catch (Throwable t) {
109             Assert.fail("Unexpected exception: " + t.getMessage());
110         }
111     }
112 
113     private abstract static class CheckedThread extends Thread {
114 
realRun()115         public abstract void realRun() throws Throwable;
116 
run()117         public void run() {
118             try {
119                 realRun();
120             } catch (Throwable t) {
121                 Assert.fail("Unexpected exception: " + t.getMessage());
122             }
123         }
124     }
125 }
126