--- /dev/null 2016-05-31 09:42:47.975716356 -0700 +++ new/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java 2016-12-09 00:57:22.618176028 -0800 @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2013, 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. + */ +package org.graalvm.compiler.test; + +import java.io.PrintStream; +import java.io.PrintWriter; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Arrays; + +import org.junit.Assert; +import org.junit.internal.ComparisonCriteria; +import org.junit.internal.ExactComparisonCriteria; + +import sun.misc.Unsafe; + +/** + * Base class that contains common utility methods and classes useful in unit tests. + */ +public class GraalTest { + + public static final Unsafe UNSAFE; + static { + try { + Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafe.setAccessible(true); + UNSAFE = (Unsafe) theUnsafe.get(Unsafe.class); + } catch (Exception e) { + throw new RuntimeException("exception while trying to get Unsafe", e); + } + } + + public static final boolean Java8OrEarlier = System.getProperty("java.specification.version").compareTo("1.9") < 0; + + protected Method getMethod(String methodName) { + return getMethod(getClass(), methodName); + } + + protected Method getMethod(Class clazz, String methodName) { + Method found = null; + for (Method m : clazz.getMethods()) { + if (m.getName().equals(methodName)) { + Assert.assertNull(found); + found = m; + } + } + if (found == null) { + /* Now look for non-public methods (but this does not look in superclasses). */ + for (Method m : clazz.getDeclaredMethods()) { + if (m.getName().equals(methodName)) { + Assert.assertNull(found); + found = m; + } + } + } + if (found != null) { + return found; + } else { + throw new RuntimeException("method not found: " + methodName); + } + } + + protected Method getMethod(Class clazz, String methodName, Class[] parameterTypes) { + try { + return clazz.getMethod(methodName, parameterTypes); + } catch (NoSuchMethodException | SecurityException e) { + throw new RuntimeException("method not found: " + methodName + "" + Arrays.toString(parameterTypes)); + } + } + + /** + * Compares two given objects for {@linkplain Assert#assertEquals(Object, Object) equality}. + * Does a deep copy equality comparison if {@code expected} is an array. + */ + protected void assertDeepEquals(Object expected, Object actual) { + assertDeepEquals(null, expected, actual); + } + + /** + * Compares two given objects for {@linkplain Assert#assertEquals(Object, Object) equality}. + * Does a deep copy equality comparison if {@code expected} is an array. + * + * @param message the identifying message for the {@link AssertionError} + */ + protected void assertDeepEquals(String message, Object expected, Object actual) { + if (ulpsDelta() > 0) { + assertDeepEquals(message, expected, actual, ulpsDelta()); + } else { + assertDeepEquals(message, expected, actual, equalFloatsOrDoublesDelta()); + } + } + + /** + * Compares two given values for equality, doing a recursive test if both values are arrays of + * the same type. + * + * @param message the identifying message for the {@link AssertionError} + * @param delta the maximum delta between two doubles or floats for which both numbers are still + * considered equal. + */ + protected void assertDeepEquals(String message, Object expected, Object actual, double delta) { + if (expected != null && actual != null) { + Class expectedClass = expected.getClass(); + Class actualClass = actual.getClass(); + if (expectedClass.isArray()) { + Assert.assertTrue(message, expected != null); + Assert.assertTrue(message, actual != null); + Assert.assertEquals(message, expectedClass, actual.getClass()); + if (expected instanceof int[]) { + Assert.assertArrayEquals(message, (int[]) expected, (int[]) actual); + } else if (expected instanceof byte[]) { + Assert.assertArrayEquals(message, (byte[]) expected, (byte[]) actual); + } else if (expected instanceof char[]) { + Assert.assertArrayEquals(message, (char[]) expected, (char[]) actual); + } else if (expected instanceof short[]) { + Assert.assertArrayEquals(message, (short[]) expected, (short[]) actual); + } else if (expected instanceof float[]) { + Assert.assertArrayEquals(message, (float[]) expected, (float[]) actual, (float) delta); + } else if (expected instanceof long[]) { + Assert.assertArrayEquals(message, (long[]) expected, (long[]) actual); + } else if (expected instanceof double[]) { + Assert.assertArrayEquals(message, (double[]) expected, (double[]) actual, delta); + } else if (expected instanceof boolean[]) { + new ExactComparisonCriteria().arrayEquals(message, expected, actual); + } else if (expected instanceof Object[]) { + new ComparisonCriteria() { + @Override + protected void assertElementsEqual(Object e, Object a) { + assertDeepEquals(message, e, a, delta); + } + }.arrayEquals(message, expected, actual); + } else { + Assert.fail((message == null ? "" : message) + "non-array value encountered: " + expected); + } + } else if (expectedClass.equals(double.class) && actualClass.equals(double.class)) { + Assert.assertEquals((double) expected, (double) actual, delta); + } else if (expectedClass.equals(float.class) && actualClass.equals(float.class)) { + Assert.assertEquals((float) expected, (float) actual, delta); + } else { + Assert.assertEquals(message, expected, actual); + } + } else { + Assert.assertEquals(message, expected, actual); + } + } + + /** + * Compares two given values for equality, doing a recursive test if both values are arrays of + * the same type. Uses {@linkplain StrictMath#ulp(float) ULP}s for comparison of floats. + * + * @param message the identifying message for the {@link AssertionError} + * @param ulpsDelta the maximum allowed ulps difference between two doubles or floats for which + * both numbers are still considered equal. + */ + protected void assertDeepEquals(String message, Object expected, Object actual, int ulpsDelta) { + ComparisonCriteria doubleUlpsDeltaCriteria = new ComparisonCriteria() { + @Override + protected void assertElementsEqual(Object e, Object a) { + assertTrue(message, e instanceof Double && a instanceof Double); + // determine acceptable error based on whether it is a normal number or a NaN/Inf + double de = (Double) e; + double epsilon = (!Double.isNaN(de) && Double.isFinite(de) ? ulpsDelta * Math.ulp(de) : 0); + Assert.assertEquals(message, (Double) e, (Double) a, epsilon); + } + }; + + ComparisonCriteria floatUlpsDeltaCriteria = new ComparisonCriteria() { + @Override + protected void assertElementsEqual(Object e, Object a) { + assertTrue(message, e instanceof Float && a instanceof Float); + // determine acceptable error based on whether it is a normal number or a NaN/Inf + float fe = (Float) e; + float epsilon = (!Float.isNaN(fe) && Float.isFinite(fe) ? ulpsDelta * Math.ulp(fe) : 0); + Assert.assertEquals(message, (Float) e, (Float) a, epsilon); + } + }; + + if (expected != null && actual != null) { + Class expectedClass = expected.getClass(); + Class actualClass = actual.getClass(); + if (expectedClass.isArray()) { + Assert.assertEquals(message, expectedClass, actualClass); + if (expected instanceof double[] || expected instanceof Object[]) { + doubleUlpsDeltaCriteria.arrayEquals(message, expected, actual); + return; + } else if (expected instanceof float[] || expected instanceof Object[]) { + floatUlpsDeltaCriteria.arrayEquals(message, expected, actual); + return; + } + } else if (expectedClass.equals(double.class) && actualClass.equals(double.class)) { + doubleUlpsDeltaCriteria.arrayEquals(message, expected, actual); + return; + } else if (expectedClass.equals(float.class) && actualClass.equals(float.class)) { + floatUlpsDeltaCriteria.arrayEquals(message, expected, actual); + return; + } + } + // anything else just use the non-ulps version + assertDeepEquals(message, expected, actual, equalFloatsOrDoublesDelta()); + } + + /** + * Gets the value used by {@link #assertDeepEquals(Object, Object)} and + * {@link #assertDeepEquals(String, Object, Object)} for the maximum delta between two doubles + * or floats for which both numbers are still considered equal. + */ + protected double equalFloatsOrDoublesDelta() { + return 0.0D; + } + + // unless overridden ulpsDelta is not used + protected int ulpsDelta() { + return 0; + } + + @SuppressWarnings("serial") + public static class MultiCauseAssertionError extends AssertionError { + + private Throwable[] causes; + + public MultiCauseAssertionError(String message, Throwable... causes) { + super(message); + this.causes = causes; + } + + @Override + public void printStackTrace(PrintStream out) { + super.printStackTrace(out); + int num = 0; + for (Throwable cause : causes) { + if (cause != null) { + out.print("cause " + (num++)); + cause.printStackTrace(out); + } + } + } + + @Override + public void printStackTrace(PrintWriter out) { + super.printStackTrace(out); + int num = 0; + for (Throwable cause : causes) { + if (cause != null) { + out.print("cause " + (num++) + ": "); + cause.printStackTrace(out); + } + } + } + } + + /* + * Overrides to the normal JUnit {@link Assert} routines that provide varargs style formatting + * and produce an exception stack trace with the assertion frames trimmed out. + */ + + /** + * Fails a test with the given message. + * + * @param message the identifying message for the {@link AssertionError} (null + * okay) + * @see AssertionError + */ + public static void fail(String message, Object... objects) { + AssertionError e; + if (message == null) { + e = new AssertionError(); + } else { + e = new AssertionError(String.format(message, objects)); + } + // Trim the assert frames from the stack trace + StackTraceElement[] trace = e.getStackTrace(); + int start = 1; // Skip this frame + String thisClassName = GraalTest.class.getName(); + while (start < trace.length && trace[start].getClassName().equals(thisClassName) && (trace[start].getMethodName().equals("assertTrue") || trace[start].getMethodName().equals("assertFalse"))) { + start++; + } + e.setStackTrace(Arrays.copyOfRange(trace, start, trace.length)); + throw e; + } + + /** + * Asserts that a condition is true. If it isn't it throws an {@link AssertionError} with the + * given message. + * + * @param message the identifying message for the {@link AssertionError} (null + * okay) + * @param condition condition to be checked + */ + public static void assertTrue(String message, boolean condition) { + assertTrue(condition, message); + } + + /** + * Asserts that a condition is true. If it isn't it throws an {@link AssertionError} without a + * message. + * + * @param condition condition to be checked + */ + public static void assertTrue(boolean condition) { + assertTrue(condition, null); + } + + /** + * Asserts that a condition is false. If it isn't it throws an {@link AssertionError} with the + * given message. + * + * @param message the identifying message for the {@link AssertionError} (null + * okay) + * @param condition condition to be checked + */ + public static void assertFalse(String message, boolean condition) { + assertTrue(!condition, message); + } + + /** + * Asserts that a condition is false. If it isn't it throws an {@link AssertionError} without a + * message. + * + * @param condition condition to be checked + */ + public static void assertFalse(boolean condition) { + assertTrue(!condition, null); + } + + /** + * Asserts that a condition is true. If it isn't it throws an {@link AssertionError} with the + * given message. + * + * @param condition condition to be checked + * @param message the identifying message for the {@link AssertionError} + * @param objects arguments to the format string + */ + public static void assertTrue(boolean condition, String message, Object... objects) { + if (!condition) { + fail(message, objects); + } + } + + /** + * Asserts that a condition is false. If it isn't it throws an {@link AssertionError} with the + * given message produced by {@link String#format}. + * + * @param condition condition to be checked + * @param message the identifying message for the {@link AssertionError} + * @param objects arguments to the format string + */ + public static void assertFalse(boolean condition, String message, Object... objects) { + assertTrue(!condition, message, objects); + } +}