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 }