/* * Copyright (c) 2005, 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 4655503 * @summary Test for array cloning and slicing methods. * @author John Rose * @key randomness */ import java.util.*; import java.lang.reflect.*; public class CopyMethods { static int muzzle; // if !=0, suppresses ("muzzles") messages static int maxLen = 40; // maximum length of test arrays static int shortStepsNear = 4; // interesting span near critical values static int downShift = 3; static int testCasesRun = 0; static long consing = 0; // very simple tests, mainly to test the framework itself static void simpleTests() { int[] a = (int[]) makeArray(3, int.class); if (muzzle == 0) System.out.println("int[] a = "+Arrays.toString(a)); check(a.length == 3); check(a[0] == testValues[0]); check(a[1] == testValues[1]); check(a[2] == testValues[2]); checkArray(a, int.class, 3, 0, 3); // negative test of testing framework: for (int bad = -2; bad < a.length; bad++) { try { int[] aa = a.clone(); if (bad < 0) aa = new int[4]; else aa[bad] = 0; ++muzzle; // the following check should fail! if (bad == -2) checkArray(new String[3], int.class, 0, 0, a.length); else checkArray(aa, int.class, 0, 0, a.length); throw new Error("Should Not Reach Here"); } catch (RuntimeException ee) { --muzzle; if (muzzle == 0) System.out.println("Expected: "+ee); } } checkArray(Arrays.copyOf(a, 0), int.class, 0, 0, 3); checkArray(Arrays.copyOf(a, 1), int.class, 1, 0, 3); checkArray(Arrays.copyOf(a, 2), int.class, 2, 0, 3); checkArray(Arrays.copyOf(a, 3), int.class, 3, 0, 3); checkArray(Arrays.copyOf(a, 4), int.class, 4, 0, 3); // quick test of copyOfRange int[] ar = Arrays.copyOfRange(a, 1, 3); check(ar.length == 2); check(ar[0] == a[1]); check(ar[1] == a[2]); checkArray(ar, int.class, 2, 1, 2); ar = Arrays.copyOfRange(a, 2, 4); check(ar.length == 2); check(ar[0] == a[2]); check(ar[1] == 0); checkArray(ar, int.class, 2, 2, 1); ar = Arrays.copyOfRange(a, 3, 5); check(ar.length == 2); check(ar[0] == 0); check(ar[1] == 0); checkArray(ar, int.class, 2, 3, 0); byte[] ba = (byte[]) makeArray(3, byte.class); if (muzzle == 0) System.out.println("byte[] ba = "+Arrays.toString(ba)); for (int j = 0; j <= ba.length+2; j++) { byte[] bb = Arrays.copyOf(ba, j); if (muzzle == 0) System.out.println("copyOf(ba,"+j+") = "+ Arrays.toString(bb)); checkArray(bb, byte.class, j, 0, ba.length); byte[] bbr = Arrays.copyOfRange(ba, 0, j); check(Arrays.equals(bb, bbr)); } for (int i = 0; i <= a.length; i++) { for (int j = i; j <= a.length+2; j++) { byte[] br = Arrays.copyOfRange(ba, i, j); if (muzzle == 0) System.out.println("copyOfRange(ba,"+i+","+j+") = "+ Arrays.toString(br)); checkArray(br, byte.class, j-i, i, ba.length-i); } } String[] sa = (String[]) makeArray(3, String.class); if (muzzle == 0) System.out.println("String[] sa = "+Arrays.toString(sa)); check(sa[0].equals(Integer.toHexString(testValues[0]))); check(sa[1].equals(Integer.toHexString(testValues[1]))); check(sa[2].equals(Integer.toHexString(testValues[2]))); checkArray(sa, String.class, sa.length, 0, sa.length); String[] sa4 = Arrays.copyOf(sa, sa.length+1); check(sa4[0] == sa[0]); check(sa4[1] == sa[1]); check(sa4[2] == sa[2]); check(sa4[sa.length] == null); checkArray(sa4, String.class, sa4.length, 0, sa.length); String[] sr4 = Arrays.copyOfRange(sa, 1, 5); check(sr4[0] == sa[1]); check(sr4[1] == sa[2]); check(sr4[2] == null); check(sr4[3] == null); checkArray(sr4, String.class, 4, 1, sa.length-1); if (muzzle == 0) System.out.println("simpleTests done"); } // the framework: a fixed series of test values static final int[] testValues; static { testValues = new int[1000]; Random r = new Random(); for (int i = 0; i < testValues.length; i++) { testValues[i] = r.nextInt(); } } /** Return a canonical test value of a desired index and type. * The original test values are random ints. Derive other test * values as follows: *
* int tv = testValues[i] * (C)tv C is byte, short, char, long, float, double * (tv&1)!=0 C is boolean * (Integer)tv C is Object and tv%16 != 0 * null C is Object and tv%16 == 0 * Integer.toHexString(tv) C is String and tv != 0 * null C is String and tv == 0 ** are derived by ordinary Java coercions, except that boolean * samples the LSB of the int value, and String is the hex numeral. * * (Also, the 0th String is null, and the 0th Object mod 16 is null, * regardless of the original int test value.) */ static Object testValue(int i, Class> c) { int tv = testValues[i % testValues.length]; if (i >= testValues.length) tv ^= i; // Turn the canonical int to a float, boolean, String, whatever: return invoke(coercers.get(c), tv); } /** Build a test array of the given length, * packed with a subsequence of the test values. * The first element of the array is always testValue(0). */ static Object makeArray(int len, Class> c) { Object a = Array.newInstance(c, len); for (int i = 0; i < len; i++) { Array.set(a, i, testValue(i, c)); } return a; } /** Check that the given array has the required length. * Check also that it is packed, up to firstNull, with * a particular subsequence of the canonical test values. * The subsequence must begin with a[0] == testValue(offset). * At a[firstNull] and beyond, the array must contain null values. */ static void checkArray(Object a, Class> c, int requiredLen, int offset, int firstNull) { check(c == a.getClass().getComponentType()); Object nullValue = nullValues.get(c); // Note: asserts in here are not part of the test program. // They verify the integrity of the test method itself. assert(nullValues.containsKey(c)); int misses = 0; int firstMiss = -1; // Check required length first. int length = Array.getLength(a); if (length != requiredLen && requiredLen != -1) { if (muzzle == 0) System.out.println("*** a.length = "+length+" != "+requiredLen); ++misses; } for (int i = 0; i < length; i++) { Object tv = (i >= firstNull) ? nullValue : testValue(i+offset, c); Object ai = Array.get(a, i); if (!eq(ai, tv)) { if (muzzle == 0) System.out.println("*** a["+i+"] = "+ai+" != "+tv); if (misses == 0) firstMiss = i; if (++misses > 10) break; } } if (misses != 0) { Method toString = toStrings.get(c); if (toString == null) toString = toStrings.get(Object.class); throw new RuntimeException("checkArray failed at "+firstMiss +" "+c+"[]" +" : "+invoke(toString, a)); } } // Typical comparison helper. Why isn't this a method somewhere. static boolean eq(Object x, Object y) { return x == null? y == null: x.equals(y); } // Exception-ignoring invoke function. static Object invoke(Method m, Object... args) { Exception ex; try { return m.invoke(null, args); } catch (InvocationTargetException ee) { ex = ee; } catch (IllegalAccessException ee) { ex = ee; } catch (IllegalArgumentException ee) { ex = ee; } ArrayList