1 /*
2 * Copyright (c) 2003, 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 4906359 6239296
27 * @summary Basic test for content-based array object methods
28 * @author Josh Bloch, Martin Buchholz
29 * @key randomness
30 */
31
32 import java.util.*;
33 import java.io.*;
34
35 public class ArrayObjectMethods {
36 int[] sizes = {0, 10, 100, 200, 1000};
37
38 void test(String[] args) throws Throwable {
39 equal(Arrays.deepToString(null), "null");
40 equal(Arrays.deepToString(new Object[]{}), "[]");
41 equal(Arrays.deepToString(new Object[]{null}), "[null]");
42 equal(Arrays.deepToString(new Object[]{null, 1}), "[null, 1]");
43 equal(Arrays.deepToString(new Object[]{1, null}), "[1, null]");
44 equal(Arrays.deepToString(new Object[]{new Object[]{}, null}), "[[], null]");
45
46 {
47 Object[] a = {1, null};
48 a[1] = a;
49 equal(Arrays.deepToString(a), "[1, [...]]");
50 a[0] = a;
51 equal(Arrays.deepToString(a), "[[...], [...]]");
52 a[0] = a[1] = new Object[]{1, null, a};
53 equal(Arrays.deepToString(a), "[[1, null, [...]], [1, null, [...]]]");
54 }
55
56 for (int size : sizes) {
57 {
58 long[] a = Rnd.longArray(size);
59 equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString());
60 equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode());
61 }
62 {
63 int[] a = Rnd.intArray(size);
64 equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString());
65 equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode());
66 }
67 {
68 short[] a = Rnd.shortArray(size);
69 equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString());
70 equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode());
71 }
72 {
73 char[] a = Rnd.charArray(size);
74 equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString());
75 equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode());
76 }
77 {
78 byte[] a = Rnd.byteArray(size);
79 equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString());
80 equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode());
81 }
82 {
83 boolean[] a = Rnd.booleanArray(size);
84 equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString());
85 equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode());
86 }
87 {
88 double[] a = Rnd.doubleArray(size);
89 equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString());
90 equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode());
91 }
92 {
93 float[] a = Rnd.floatArray(size);
94 equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString());
95 equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode());
96 }
97 {
98 Object[] a = Rnd.flatObjectArray(size);
99 equal(Arrays.toString(a), Arrays.asList(a).toString());
100 equal(Arrays.deepToString(a), Arrays.asList(a).toString());
101 equal(Arrays.hashCode(a), Arrays.asList(a).hashCode());
102 }
103
104 if (size <= 200) {
105 Object[] a = Rnd.nestedObjectArray(size);
106 List aList = deepToList(a);
107 equal(Arrays.toString(a), Arrays.asList(a).toString());
108 equal(Arrays.deepToString(a), aList.toString());
109 equal(Arrays.deepHashCode(a), aList.hashCode());
110 equal(Arrays.hashCode(a), Arrays.asList(a).hashCode());
111
112 Object[] deepCopy = (Object[]) deepCopy(a);
113 check(Arrays.deepEquals(a, deepCopy));
114 check(Arrays.deepEquals(deepCopy, a));
115
116 // Make deepCopy != a
117 if (size == 0)
118 deepCopy = new Object[] {"foo"};
119 else if (deepCopy[deepCopy.length - 1] == null)
120 deepCopy[deepCopy.length - 1] = "baz";
121 else
122 deepCopy[deepCopy.length - 1] = null;
123 check(! Arrays.deepEquals(a, deepCopy));
124 check(! Arrays.deepEquals(deepCopy, a));
125 }
126 }
127 }
128
129 // Utility method to turn an array into a list "deeply," turning
130 // all primitives into objects
131 List<Object> deepToList(Object[] a) {
132 List<Object> result = new ArrayList<Object>();
133 for (Object e : a) {
134 if (e instanceof byte[])
135 result.add(PrimitiveArrays.asList((byte[])e));
136 else if (e instanceof short[])
137 result.add(PrimitiveArrays.asList((short[])e));
138 else if (e instanceof int[])
139 result.add(PrimitiveArrays.asList((int[])e));
140 else if (e instanceof long[])
141 result.add(PrimitiveArrays.asList((long[])e));
142 else if (e instanceof char[])
143 result.add(PrimitiveArrays.asList((char[])e));
144 else if (e instanceof double[])
145 result.add(PrimitiveArrays.asList((double[])e));
146 else if (e instanceof float[])
147 result.add(PrimitiveArrays.asList((float[])e));
148 else if (e instanceof boolean[])
149 result.add(PrimitiveArrays.asList((boolean[])e));
150 else if (e instanceof Object[])
151 result.add(deepToList((Object[])e));
152 else
153 result.add(e);
154 }
155 return result;
156 }
157
158 // Utility method to do a deep copy of an object *very slowly* using
159 // serialization/deserialization
160 Object deepCopy(Object oldObj) {
161 try {
162 ByteArrayOutputStream bos = new ByteArrayOutputStream();
163 ObjectOutputStream oos = new ObjectOutputStream(bos);
164 oos.writeObject(oldObj);
165 oos.flush();
166 ByteArrayInputStream bin = new ByteArrayInputStream(
167 bos.toByteArray());
168 ObjectInputStream ois = new ObjectInputStream(bin);
169 return ois.readObject();
170 } catch(Exception e) {
171 throw new IllegalArgumentException(e);
172 }
173 }
174
175 //--------------------- Infrastructure ---------------------------
176 volatile int passed = 0, failed = 0;
177 void pass() {passed++;}
178 void fail() {failed++; Thread.dumpStack();}
179 void fail(String msg) {System.err.println(msg); fail();}
180 void unexpected(Throwable t) {failed++; t.printStackTrace();}
181 void check(boolean cond) {if (cond) pass(); else fail();}
182 void equal(Object x, Object y) {
183 if (x == null ? y == null : x.equals(y)) pass();
184 else fail(x + " not equal to " + y);}
185 public static void main(String[] args) throws Throwable {
186 new ArrayObjectMethods().instanceMain(args);}
187 void instanceMain(String[] args) throws Throwable {
188 try {test(args);} catch (Throwable t) {unexpected(t);}
189 System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
190 if (failed > 0) throw new AssertionError("Some tests failed");}
191 }
192
193 /**
194 * Methods to generate "interesting" random primitives and primitive
195 * arrays. Unlike Random.nextXxx, these methods return small values
196 * and boundary values (e.g., 0, -1, NaN) with greater than normal
197 * likelihood.
198 */
199
200 class Rnd {
201 private static Random rnd = new Random();
202
203 public static long nextLong() {
204 switch(rnd.nextInt(10)) {
205 case 0: return 0;
206 case 1: return Long.MIN_VALUE;
207 case 2: return Long.MAX_VALUE;
208 case 3: case 4: case 5:
209 return (long) (rnd.nextInt(20) - 10);
210 default: return rnd.nextLong();
211 }
212 }
213
214 public static int nextInt() {
215 switch(rnd.nextInt(10)) {
216 case 0: return 0;
217 case 1: return Integer.MIN_VALUE;
218 case 2: return Integer.MAX_VALUE;
219 case 3: case 4: case 5:
220 return rnd.nextInt(20) - 10;
221 default: return rnd.nextInt();
222 }
223 }
224
225 public static short nextShort() {
226 switch(rnd.nextInt(10)) {
227 case 0: return 0;
228 case 1: return Short.MIN_VALUE;
229 case 2: return Short.MAX_VALUE;
230 case 3: case 4: case 5:
231 return (short) (rnd.nextInt(20) - 10);
232 default: return (short) rnd.nextInt();
233 }
234 }
235
236 public static char nextChar() {
237 switch(rnd.nextInt(10)) {
238 case 0: return 0;
239 case 1: return Character.MIN_VALUE;
240 case 2: return Character.MAX_VALUE;
241 case 3: case 4: case 5:
242 return (char) (rnd.nextInt(20) - 10);
243 default: return (char) rnd.nextInt();
244 }
245 }
246
247 public static byte nextByte() {
248 switch(rnd.nextInt(10)) {
249 case 0: return 0;
250 case 1: return Byte.MIN_VALUE;
251 case 2: return Byte.MAX_VALUE;
252 case 3: case 4: case 5:
253 return (byte) (rnd.nextInt(20) - 10);
254 default: return (byte) rnd.nextInt();
255 }
256 }
257
258 public static boolean nextBoolean() {
259 return rnd.nextBoolean();
260 }
261
262 public static double nextDouble() {
263 switch(rnd.nextInt(20)) {
264 case 0: return 0;
265 case 1: return -0.0;
266 case 2: return Double.MIN_VALUE;
267 case 3: return Double.MAX_VALUE;
268 case 4: return Double.NaN;
269 case 5: return Double.NEGATIVE_INFINITY;
270 case 6: return Double.POSITIVE_INFINITY;
271 case 7: case 8: case 9:
272 return (rnd.nextInt(20) - 10);
273 default: return rnd.nextDouble();
274 }
275 }
276
277 public static float nextFloat() {
278 switch(rnd.nextInt(20)) {
279 case 0: return 0;
280 case 1: return -0.0f;
281 case 2: return Float.MIN_VALUE;
282 case 3: return Float.MAX_VALUE;
283 case 4: return Float.NaN;
284 case 5: return Float.NEGATIVE_INFINITY;
285 case 6: return Float.POSITIVE_INFINITY;
286 case 7: case 8: case 9:
287 return (rnd.nextInt(20) - 10);
288 default: return rnd.nextFloat();
289 }
290 }
291
292 public static Object nextObject() {
293 switch(rnd.nextInt(10)) {
294 case 0: return null;
295 case 1: return "foo";
296 case 2: case 3: case 4:
297 return Double.valueOf(nextDouble());
298 default: return Integer.valueOf(nextInt());
299 }
300 }
301
302 public static long[] longArray(int length) {
303 long[] result = new long[length];
304 for (int i = 0; i < length; i++)
305 result[i] = Rnd.nextLong();
306 return result;
307 }
308
309 public static int[] intArray(int length) {
310 int[] result = new int[length];
311 for (int i = 0; i < length; i++)
312 result[i] = Rnd.nextInt();
313 return result;
314 }
315
316 public static short[] shortArray(int length) {
317 short[] result = new short[length];
318 for (int i = 0; i < length; i++)
319 result[i] = Rnd.nextShort();
320 return result;
321 }
322
323 public static char[] charArray(int length) {
324 char[] result = new char[length];
325 for (int i = 0; i < length; i++)
326 result[i] = Rnd.nextChar();
327 return result;
328 }
329
330 public static byte[] byteArray(int length) {
331 byte[] result = new byte[length];
332 for (int i = 0; i < length; i++)
333 result[i] = Rnd.nextByte();
334 return result;
335 }
336
337 public static boolean[] booleanArray(int length) {
338 boolean[] result = new boolean[length];
339 for (int i = 0; i < length; i++)
340 result[i] = Rnd.nextBoolean();
341 return result;
342 }
343
344 public static double[] doubleArray(int length) {
345 double[] result = new double[length];
346 for (int i = 0; i < length; i++)
347 result[i] = Rnd.nextDouble();
348 return result;
349 }
350
351 public static float[] floatArray(int length) {
352 float[] result = new float[length];
353 for (int i = 0; i < length; i++)
354 result[i] = Rnd.nextFloat();
355 return result;
356 }
357
358 public static Object[] flatObjectArray(int length) {
359 Object[] result = new Object[length];
360 for (int i = 0; i < length; i++)
361 result[i] = Rnd.nextObject();
362 return result;
363 }
364
365 // Calling this for length >> 100 is likely to run out of memory! It
366 // should be perhaps be tuned to allow for longer arrays
367 public static Object[] nestedObjectArray(int length) {
368 Object[] result = new Object[length];
369 for (int i = 0; i < length; i++) {
370 switch(rnd.nextInt(16)) {
371 case 0: result[i] = nestedObjectArray(length/2);
372 break;
373 case 1: result[i] = longArray(length/2);
374 break;
375 case 2: result[i] = intArray(length/2);
376 break;
377 case 3: result[i] = shortArray(length/2);
378 break;
379 case 4: result[i] = charArray(length/2);
380 break;
381 case 5: result[i] = byteArray(length/2);
382 break;
383 case 6: result[i] = floatArray(length/2);
384 break;
385 case 7: result[i] = doubleArray(length/2);
386 break;
387 case 8: result[i] = longArray(length/2);
388 break;
389 default: result[i] = Rnd.nextObject();
390 }
391 }
392 return result;
393 }
394 }
395
396 /**
397 * Primitive arrays viewed as lists. Inefficient but cool.
398 * This utility should be generally useful in writing regression/unit/basic
399 * tests.
400 */
401
402 class PrimitiveArrays {
403 public static List<Long> asList(final long[] a) {
404 return new AbstractList<Long>() {
405 public Long get(int i) { return a[i]; }
406 public int size() { return a.length; }
407
408 public Long set(int i, Long e) {
409 long oldVal = a[i];
410 a[i] = e;
411 return oldVal;
412 }
413 };
414 }
415
416 public static List<Integer> asList(final int[] a) {
417 return new AbstractList<Integer>() {
418 public Integer get(int i) { return a[i]; }
419 public int size() { return a.length; }
420
421 public Integer set(int i, Integer e) {
422 int oldVal = a[i];
423 a[i] = e;
424 return oldVal;
425 }
426 };
427 }
428
429 public static List<Short> asList(final short[] a) {
430 return new AbstractList<Short>() {
431 public Short get(int i) { return a[i]; }
432 public int size() { return a.length; }
433
434 public Short set(int i, Short e) {
435 short oldVal = a[i];
436 a[i] = e;
437 return oldVal;
438 }
439 };
440 }
441
442 public static List<Character> asList(final char[] a) {
443 return new AbstractList<Character>() {
444 public Character get(int i) { return a[i]; }
445 public int size() { return a.length; }
446
447 public Character set(int i, Character e) {
448 Character oldVal = a[i];
449 a[i] = e;
450 return oldVal;
451 }
452 };
453 }
454
455 public static List<Byte> asList(final byte[] a) {
456 return new AbstractList<Byte>() {
457 public Byte get(int i) { return a[i]; }
458 public int size() { return a.length; }
459
460 public Byte set(int i, Byte e) {
461 Byte oldVal = a[i];
462 a[i] = e;
463 return oldVal;
464 }
465 };
466 }
467
468 public static List<Boolean> asList(final boolean[] a) {
469 return new AbstractList<Boolean>() {
470 public Boolean get(int i) { return a[i]; }
471 public int size() { return a.length; }
472
473 public Boolean set(int i, Boolean e) {
474 Boolean oldVal = a[i];
475 a[i] = e;
476 return oldVal;
477 }
478 };
479 }
480
481 public static List<Double> asList(final double[] a) {
482 return new AbstractList<Double>() {
483 public Double get(int i) { return a[i]; }
484 public int size() { return a.length; }
485
486 public Double set(int i, Double e) {
487 Double oldVal = a[i];
488 a[i] = e;
489 return oldVal;
490 }
491 };
492 }
493
494 public static List<Float> asList(final float[] a) {
495 return new AbstractList<Float>() {
496 public Float get(int i) { return a[i]; }
497 public int size() { return a.length; }
498
499 public Float set(int i, Float e) {
500 Float oldVal = a[i];
501 a[i] = e;
502 return oldVal;
503 }
504 };
505 }
506 }