| /* |
| * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /* |
| * @test |
| * @bug 4906359 6239296 |
| * @summary Basic test for content-based array object methods |
| * @author Josh Bloch, Martin Buchholz |
| */ |
| |
| import java.util.*; |
| import java.io.*; |
| |
| public class ArrayObjectMethods { |
| int[] sizes = {0, 10, 100, 200, 1000}; |
| |
| void test(String[] args) throws Throwable { |
| equal(Arrays.deepToString(null), "null"); |
| equal(Arrays.deepToString(new Object[]{}), "[]"); |
| equal(Arrays.deepToString(new Object[]{null}), "[null]"); |
| equal(Arrays.deepToString(new Object[]{null, 1}), "[null, 1]"); |
| equal(Arrays.deepToString(new Object[]{1, null}), "[1, null]"); |
| equal(Arrays.deepToString(new Object[]{new Object[]{}, null}), "[[], null]"); |
| |
| { |
| Object[] a = {1, null}; |
| a[1] = a; |
| equal(Arrays.deepToString(a), "[1, [...]]"); |
| a[0] = a; |
| equal(Arrays.deepToString(a), "[[...], [...]]"); |
| a[0] = a[1] = new Object[]{1, null, a}; |
| equal(Arrays.deepToString(a), "[[1, null, [...]], [1, null, [...]]]"); |
| } |
| |
| for (int size : sizes) { |
| { |
| long[] a = Rnd.longArray(size); |
| equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString()); |
| equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode()); |
| } |
| { |
| int[] a = Rnd.intArray(size); |
| equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString()); |
| equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode()); |
| } |
| { |
| short[] a = Rnd.shortArray(size); |
| equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString()); |
| equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode()); |
| } |
| { |
| char[] a = Rnd.charArray(size); |
| equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString()); |
| equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode()); |
| } |
| { |
| byte[] a = Rnd.byteArray(size); |
| equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString()); |
| equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode()); |
| } |
| { |
| boolean[] a = Rnd.booleanArray(size); |
| equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString()); |
| equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode()); |
| } |
| { |
| double[] a = Rnd.doubleArray(size); |
| equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString()); |
| equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode()); |
| } |
| { |
| float[] a = Rnd.floatArray(size); |
| equal(Arrays.toString(a), PrimitiveArrays.asList(a).toString()); |
| equal(Arrays.hashCode(a), PrimitiveArrays.asList(a).hashCode()); |
| } |
| { |
| Object[] a = Rnd.flatObjectArray(size); |
| equal(Arrays.toString(a), Arrays.asList(a).toString()); |
| equal(Arrays.deepToString(a), Arrays.asList(a).toString()); |
| equal(Arrays.hashCode(a), Arrays.asList(a).hashCode()); |
| } |
| |
| if (size <= 200) { |
| Object[] a = Rnd.nestedObjectArray(size); |
| List aList = deepToList(a); |
| equal(Arrays.toString(a), Arrays.asList(a).toString()); |
| equal(Arrays.deepToString(a), aList.toString()); |
| equal(Arrays.deepHashCode(a), aList.hashCode()); |
| equal(Arrays.hashCode(a), Arrays.asList(a).hashCode()); |
| |
| Object[] deepCopy = (Object[]) deepCopy(a); |
| check(Arrays.deepEquals(a, deepCopy)); |
| check(Arrays.deepEquals(deepCopy, a)); |
| |
| // Make deepCopy != a |
| if (size == 0) |
| deepCopy = new Object[] {"foo"}; |
| else if (deepCopy[deepCopy.length - 1] == null) |
| deepCopy[deepCopy.length - 1] = "baz"; |
| else |
| deepCopy[deepCopy.length - 1] = null; |
| check(! Arrays.deepEquals(a, deepCopy)); |
| check(! Arrays.deepEquals(deepCopy, a)); |
| } |
| } |
| } |
| |
| // Utility method to turn an array into a list "deeply," turning |
| // all primitives into objects |
| List<Object> deepToList(Object[] a) { |
| List<Object> result = new ArrayList<Object>(); |
| for (Object e : a) { |
| if (e instanceof byte[]) |
| result.add(PrimitiveArrays.asList((byte[])e)); |
| else if (e instanceof short[]) |
| result.add(PrimitiveArrays.asList((short[])e)); |
| else if (e instanceof int[]) |
| result.add(PrimitiveArrays.asList((int[])e)); |
| else if (e instanceof long[]) |
| result.add(PrimitiveArrays.asList((long[])e)); |
| else if (e instanceof char[]) |
| result.add(PrimitiveArrays.asList((char[])e)); |
| else if (e instanceof double[]) |
| result.add(PrimitiveArrays.asList((double[])e)); |
| else if (e instanceof float[]) |
| result.add(PrimitiveArrays.asList((float[])e)); |
| else if (e instanceof boolean[]) |
| result.add(PrimitiveArrays.asList((boolean[])e)); |
| else if (e instanceof Object[]) |
| result.add(deepToList((Object[])e)); |
| else |
| result.add(e); |
| } |
| return result; |
| } |
| |
| // Utility method to do a deep copy of an object *very slowly* using |
| // serialization/deserialization |
| Object deepCopy(Object oldObj) { |
| try { |
| ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| ObjectOutputStream oos = new ObjectOutputStream(bos); |
| oos.writeObject(oldObj); |
| oos.flush(); |
| ByteArrayInputStream bin = new ByteArrayInputStream( |
| bos.toByteArray()); |
| ObjectInputStream ois = new ObjectInputStream(bin); |
| return ois.readObject(); |
| } catch(Exception e) { |
| throw new IllegalArgumentException(e); |
| } |
| } |
| |
| //--------------------- Infrastructure --------------------------- |
| volatile int passed = 0, failed = 0; |
| void pass() {passed++;} |
| void fail() {failed++; Thread.dumpStack();} |
| void fail(String msg) {System.err.println(msg); fail();} |
| void unexpected(Throwable t) {failed++; t.printStackTrace();} |
| void check(boolean cond) {if (cond) pass(); else fail();} |
| void equal(Object x, Object y) { |
| if (x == null ? y == null : x.equals(y)) pass(); |
| else fail(x + " not equal to " + y);} |
| public static void main(String[] args) throws Throwable { |
| new ArrayObjectMethods().instanceMain(args);} |
| void instanceMain(String[] args) throws Throwable { |
| try {test(args);} catch (Throwable t) {unexpected(t);} |
| System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); |
| if (failed > 0) throw new AssertionError("Some tests failed");} |
| } |
| |
| /** |
| * Methods to generate "interesting" random primitives and primitive |
| * arrays. Unlike Random.nextXxx, these methods return small values |
| * and boundary values (e.g., 0, -1, NaN) with greater than normal |
| * likelihood. |
| */ |
| |
| class Rnd { |
| private static Random rnd = new Random(); |
| |
| public static long nextLong() { |
| switch(rnd.nextInt(10)) { |
| case 0: return 0; |
| case 1: return Long.MIN_VALUE; |
| case 2: return Long.MAX_VALUE; |
| case 3: case 4: case 5: |
| return (long) (rnd.nextInt(20) - 10); |
| default: return rnd.nextLong(); |
| } |
| } |
| |
| public static int nextInt() { |
| switch(rnd.nextInt(10)) { |
| case 0: return 0; |
| case 1: return Integer.MIN_VALUE; |
| case 2: return Integer.MAX_VALUE; |
| case 3: case 4: case 5: |
| return rnd.nextInt(20) - 10; |
| default: return rnd.nextInt(); |
| } |
| } |
| |
| public static short nextShort() { |
| switch(rnd.nextInt(10)) { |
| case 0: return 0; |
| case 1: return Short.MIN_VALUE; |
| case 2: return Short.MAX_VALUE; |
| case 3: case 4: case 5: |
| return (short) (rnd.nextInt(20) - 10); |
| default: return (short) rnd.nextInt(); |
| } |
| } |
| |
| public static char nextChar() { |
| switch(rnd.nextInt(10)) { |
| case 0: return 0; |
| case 1: return Character.MIN_VALUE; |
| case 2: return Character.MAX_VALUE; |
| case 3: case 4: case 5: |
| return (char) (rnd.nextInt(20) - 10); |
| default: return (char) rnd.nextInt(); |
| } |
| } |
| |
| public static byte nextByte() { |
| switch(rnd.nextInt(10)) { |
| case 0: return 0; |
| case 1: return Byte.MIN_VALUE; |
| case 2: return Byte.MAX_VALUE; |
| case 3: case 4: case 5: |
| return (byte) (rnd.nextInt(20) - 10); |
| default: return (byte) rnd.nextInt(); |
| } |
| } |
| |
| public static boolean nextBoolean() { |
| return rnd.nextBoolean(); |
| } |
| |
| public static double nextDouble() { |
| switch(rnd.nextInt(20)) { |
| case 0: return 0; |
| case 1: return -0.0; |
| case 2: return Double.MIN_VALUE; |
| case 3: return Double.MAX_VALUE; |
| case 4: return Double.NaN; |
| case 5: return Double.NEGATIVE_INFINITY; |
| case 6: return Double.POSITIVE_INFINITY; |
| case 7: case 8: case 9: |
| return (rnd.nextInt(20) - 10); |
| default: return rnd.nextDouble(); |
| } |
| } |
| |
| public static float nextFloat() { |
| switch(rnd.nextInt(20)) { |
| case 0: return 0; |
| case 1: return -0.0f; |
| case 2: return Float.MIN_VALUE; |
| case 3: return Float.MAX_VALUE; |
| case 4: return Float.NaN; |
| case 5: return Float.NEGATIVE_INFINITY; |
| case 6: return Float.POSITIVE_INFINITY; |
| case 7: case 8: case 9: |
| return (rnd.nextInt(20) - 10); |
| default: return rnd.nextFloat(); |
| } |
| } |
| |
| public static Object nextObject() { |
| switch(rnd.nextInt(10)) { |
| case 0: return null; |
| case 1: return "foo"; |
| case 2: case 3: case 4: |
| return Double.valueOf(nextDouble()); |
| default: return Integer.valueOf(nextInt()); |
| } |
| } |
| |
| public static long[] longArray(int length) { |
| long[] result = new long[length]; |
| for (int i = 0; i < length; i++) |
| result[i] = Rnd.nextLong(); |
| return result; |
| } |
| |
| public static int[] intArray(int length) { |
| int[] result = new int[length]; |
| for (int i = 0; i < length; i++) |
| result[i] = Rnd.nextInt(); |
| return result; |
| } |
| |
| public static short[] shortArray(int length) { |
| short[] result = new short[length]; |
| for (int i = 0; i < length; i++) |
| result[i] = Rnd.nextShort(); |
| return result; |
| } |
| |
| public static char[] charArray(int length) { |
| char[] result = new char[length]; |
| for (int i = 0; i < length; i++) |
| result[i] = Rnd.nextChar(); |
| return result; |
| } |
| |
| public static byte[] byteArray(int length) { |
| byte[] result = new byte[length]; |
| for (int i = 0; i < length; i++) |
| result[i] = Rnd.nextByte(); |
| return result; |
| } |
| |
| public static boolean[] booleanArray(int length) { |
| boolean[] result = new boolean[length]; |
| for (int i = 0; i < length; i++) |
| result[i] = Rnd.nextBoolean(); |
| return result; |
| } |
| |
| public static double[] doubleArray(int length) { |
| double[] result = new double[length]; |
| for (int i = 0; i < length; i++) |
| result[i] = Rnd.nextDouble(); |
| return result; |
| } |
| |
| public static float[] floatArray(int length) { |
| float[] result = new float[length]; |
| for (int i = 0; i < length; i++) |
| result[i] = Rnd.nextFloat(); |
| return result; |
| } |
| |
| public static Object[] flatObjectArray(int length) { |
| Object[] result = new Object[length]; |
| for (int i = 0; i < length; i++) |
| result[i] = Rnd.nextObject(); |
| return result; |
| } |
| |
| // Calling this for length >> 100 is likely to run out of memory! It |
| // should be perhaps be tuned to allow for longer arrays |
| public static Object[] nestedObjectArray(int length) { |
| Object[] result = new Object[length]; |
| for (int i = 0; i < length; i++) { |
| switch(rnd.nextInt(16)) { |
| case 0: result[i] = nestedObjectArray(length/2); |
| break; |
| case 1: result[i] = longArray(length/2); |
| break; |
| case 2: result[i] = intArray(length/2); |
| break; |
| case 3: result[i] = shortArray(length/2); |
| break; |
| case 4: result[i] = charArray(length/2); |
| break; |
| case 5: result[i] = byteArray(length/2); |
| break; |
| case 6: result[i] = floatArray(length/2); |
| break; |
| case 7: result[i] = doubleArray(length/2); |
| break; |
| case 8: result[i] = longArray(length/2); |
| break; |
| default: result[i] = Rnd.nextObject(); |
| } |
| } |
| return result; |
| } |
| } |
| |
| /** |
| * Primitive arrays viewed as lists. Inefficient but cool. |
| * This utility should be generally useful in writing regression/unit/basic |
| * tests. |
| */ |
| |
| class PrimitiveArrays { |
| public static List<Long> asList(final long[] a) { |
| return new AbstractList<Long>() { |
| public Long get(int i) { return a[i]; } |
| public int size() { return a.length; } |
| |
| public Long set(int i, Long e) { |
| long oldVal = a[i]; |
| a[i] = e; |
| return oldVal; |
| } |
| }; |
| } |
| |
| public static List<Integer> asList(final int[] a) { |
| return new AbstractList<Integer>() { |
| public Integer get(int i) { return a[i]; } |
| public int size() { return a.length; } |
| |
| public Integer set(int i, Integer e) { |
| int oldVal = a[i]; |
| a[i] = e; |
| return oldVal; |
| } |
| }; |
| } |
| |
| public static List<Short> asList(final short[] a) { |
| return new AbstractList<Short>() { |
| public Short get(int i) { return a[i]; } |
| public int size() { return a.length; } |
| |
| public Short set(int i, Short e) { |
| short oldVal = a[i]; |
| a[i] = e; |
| return oldVal; |
| } |
| }; |
| } |
| |
| public static List<Character> asList(final char[] a) { |
| return new AbstractList<Character>() { |
| public Character get(int i) { return a[i]; } |
| public int size() { return a.length; } |
| |
| public Character set(int i, Character e) { |
| Character oldVal = a[i]; |
| a[i] = e; |
| return oldVal; |
| } |
| }; |
| } |
| |
| public static List<Byte> asList(final byte[] a) { |
| return new AbstractList<Byte>() { |
| public Byte get(int i) { return a[i]; } |
| public int size() { return a.length; } |
| |
| public Byte set(int i, Byte e) { |
| Byte oldVal = a[i]; |
| a[i] = e; |
| return oldVal; |
| } |
| }; |
| } |
| |
| public static List<Boolean> asList(final boolean[] a) { |
| return new AbstractList<Boolean>() { |
| public Boolean get(int i) { return a[i]; } |
| public int size() { return a.length; } |
| |
| public Boolean set(int i, Boolean e) { |
| Boolean oldVal = a[i]; |
| a[i] = e; |
| return oldVal; |
| } |
| }; |
| } |
| |
| public static List<Double> asList(final double[] a) { |
| return new AbstractList<Double>() { |
| public Double get(int i) { return a[i]; } |
| public int size() { return a.length; } |
| |
| public Double set(int i, Double e) { |
| Double oldVal = a[i]; |
| a[i] = e; |
| return oldVal; |
| } |
| }; |
| } |
| |
| public static List<Float> asList(final float[] a) { |
| return new AbstractList<Float>() { |
| public Float get(int i) { return a[i]; } |
| public int size() { return a.length; } |
| |
| public Float set(int i, Float e) { |
| Float oldVal = a[i]; |
| a[i] = e; |
| return oldVal; |
| } |
| }; |
| } |
| } |