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