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