blob: fd19f1672f6a1754b5800d47fb88e069e396bae0 [file] [log] [blame]
littlee402b49a2012-04-10 10:17:36 +08001/*
katlemand08780c2012-12-20 16:24:50 -08002 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
littlee402b49a2012-04-10 10:17:36 +08003 * 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 7121314
27 * @summary AbstractCollection.toArray(T[]) doesn't return the given array
28 * in concurrent modification.
29 * @author Ulf Zibis, David Holmes
30 */
31
32import java.util.AbstractCollection;
33import java.util.Arrays;
34import java.util.Iterator;
35
36public class ToArrayTest {
37
38 static class TestCollection<E> extends AbstractCollection<E> {
39 private final E[] elements;
40 private int[] sizes;
41 private int nextSize;
42
43 public TestCollection(E[] elements) {
44 this.elements = elements;
45 setSizeSequence(new int[] { elements.length });
46 }
47
48 /*
49 * Sets the values that size() will return on each use. The next
50 * call to size will return sizes[0], then sizes[1] etc. This allows us
51 * to emulate a concurrent change to the contents of the collection
52 * without having to perform concurrent changes. If sizes[n+1] contains
53 * a larger value, the collection will appear to have shrunk when
54 * iterated; if a smaller value then the collection will appear to have
55 * grown when iterated.
56 */
57 void setSizeSequence(int... sizes) {
58 this.sizes = sizes;
59 nextSize = 0;
60 }
61
62 /* can change collection's size after each invocation */
63 @Override
64 public int size() {
65 return sizes[nextSize == sizes.length - 1 ? nextSize : nextSize++];
66 }
67
68 @Override
69 public Iterator<E> iterator() {
70 return new Iterator<E>() {
71 int pos = 0;
72
73 public boolean hasNext() {
74 return pos < sizes[nextSize];
75 }
76 public E next() {
77 return elements[pos++];
78 }
79 public void remove() {
80 throw new UnsupportedOperationException(
81 "Not supported yet.");
82 }
83 };
84 }
85 }
86
87 static final Object[] OBJECTS = { new Object(), new Object(), new Object() };
88 static final TestCollection<?> CANDIDATE = new TestCollection<Object>(OBJECTS);
89 static final int CAP = OBJECTS.length; // capacity of the CANDIDATE
90 static final int LAST = CAP - 1; // last possible array index
91 Object[] a;
92 Object[] res;
93
94 int last() {
95 return a.length - 1;
96 }
97
98 protected void test() throws Throwable {
99 // Check array type conversion
100 res = new TestCollection<>(new Object[] { "1", "2" }).toArray(new String[0]);
101 check(res instanceof String[]);
102 check(res.length == 2);
103 check(res[1] == "2");
104
105 // Check incompatible type of target array
106 try {
107 res = CANDIDATE.toArray(new String[CAP]);
108 check(false);
109 } catch (Throwable t) {
110 check(t instanceof ArrayStoreException);
111 }
112
113 // Check more elements than a.length
114 a = new Object[CAP - 1]; // appears too small
115 res = CANDIDATE.toArray(a);
116 check(res != a);
117 check(res[LAST] != null);
118
119 // Check equal elements as a.length
120 a = new Object[CAP]; // appears to match
121 res = CANDIDATE.toArray(a);
122 check(res == a);
123 check(res[last()] != null);
124
125 // Check equal elements as a.length
126 a = new Object[CAP + 1]; // appears too big
127 res = CANDIDATE.toArray(a);
128 check(res == a);
129 check(res[last()] == null);
130
131 // Check less elements than expected, but more than a.length
132 a = new Object[CAP - 2]; // appears too small
133 CANDIDATE.setSizeSequence(CAP, CAP - 1);
134 res = CANDIDATE.toArray(a);
135 check(res != a);
136 check(res.length == CAP - 1);
137 check(res[LAST - 1] != null);
138
139 // Check less elements than expected, but equal as a.length
140 a = Arrays.copyOf(OBJECTS, CAP); // appears to match
141 CANDIDATE.setSizeSequence(CAP, CAP - 1);
142 res = CANDIDATE.toArray(a);
143 check(res == a);
144 check(res[last()] == null);
145
146 // Check more elements than expected and more than a.length
147 a = new Object[CAP - 1]; // appears to match
148 CANDIDATE.setSizeSequence(CAP - 1, CAP);
149 res = CANDIDATE.toArray(a);
150 check(res != a);
151 check(res[LAST] != null);
152
153 // Check more elements than expected, but equal as a.length
154 a = new Object[CAP - 1]; // appears to match
155 CANDIDATE.setSizeSequence(CAP - 2, CAP - 1);
156 res = CANDIDATE.toArray(a);
157 check(res == a);
158 check(res[last()] != null);
159
160 // Check more elements than expected, but less than a.length
161 a = Arrays.copyOf(OBJECTS, CAP); // appears to match
162 CANDIDATE.setSizeSequence(CAP - 2, CAP - 1);
163 res = CANDIDATE.toArray(a);
164 check(res == a);
165 check(res[last()] == null);
166
167 test_7121314();
168 }
169
170 /*
171 * Major target of this testcase, bug 7121314.
172 */
173 protected void test_7121314() throws Throwable {
174 // Check equal elements as a.length, but less than expected
175 a = new Object[CAP - 1]; // appears too small
176 CANDIDATE.setSizeSequence(CAP, CAP - 1);
177 res = CANDIDATE.toArray(a);
178 check(res == a);
179 check(res[last()] != null);
180
181 // Check less elements than a.length and less than expected
182 a = Arrays.copyOf(OBJECTS, CAP - 1); // appears too small
183 CANDIDATE.setSizeSequence(CAP, CAP - 2);
184 res = CANDIDATE.toArray(a);
185 check(res == a);
186 check(res[last()] == null);
187
188 }
189
190 public static void main(String[] args) throws Throwable {
191 ToArrayTest testcase = new ToArrayTest();
192 try {
193 testcase.test();
194 } catch (Throwable t) {
195 unexpected(t);
196 }
197
198 System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
199 if (failed > 0) throw new Exception("Some tests failed");
200 }
201
202 //--------------------- Infrastructure ---------------------------
203 static volatile int passed = 0, failed = 0;
204 static void pass() { passed++; }
205 static void fail() { failed++; Thread.dumpStack(); }
206 static void fail(String msg) { System.out.println(msg); fail(); }
207 static void unexpected(Throwable t) { failed++; t.printStackTrace(); }
208 static void check(boolean cond) { if (cond) pass(); else fail(); }
209 static void equal(Object x, Object y) {
210 if (x == null ? y == null : x.equals(y)) pass();
211 else {System.out.println(x + " not equal to " + y); fail(); }
212 }
213}
214
215