001/* 002 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.test; 024 025import java.io.*; 026import java.lang.reflect.*; 027import java.util.*; 028 029import org.junit.*; 030import org.junit.internal.*; 031 032/** 033 * Base class that contains common utility methods and classes useful in unit tests. 034 */ 035public class GraalTest { 036 037 protected Method getMethod(String methodName) { 038 return getMethod(getClass(), methodName); 039 } 040 041 protected Method getMethod(Class<?> clazz, String methodName) { 042 Method found = null; 043 for (Method m : clazz.getMethods()) { 044 if (m.getName().equals(methodName)) { 045 Assert.assertNull(found); 046 found = m; 047 } 048 } 049 if (found == null) { 050 /* Now look for non-public methods (but this does not look in superclasses). */ 051 for (Method m : clazz.getDeclaredMethods()) { 052 if (m.getName().equals(methodName)) { 053 Assert.assertNull(found); 054 found = m; 055 } 056 } 057 } 058 if (found != null) { 059 return found; 060 } else { 061 throw new RuntimeException("method not found: " + methodName); 062 } 063 } 064 065 protected Method getMethod(Class<?> clazz, String methodName, Class<?>[] parameterTypes) { 066 try { 067 return clazz.getMethod(methodName, parameterTypes); 068 } catch (NoSuchMethodException | SecurityException e) { 069 throw new RuntimeException("method not found: " + methodName + "" + Arrays.toString(parameterTypes)); 070 } 071 } 072 073 /** 074 * Compares two given objects for {@linkplain Assert#assertEquals(Object, Object) equality}. 075 * Does a deep copy equality comparison if {@code expected} is an array. 076 */ 077 protected void assertDeepEquals(Object expected, Object actual) { 078 assertDeepEquals(null, expected, actual); 079 } 080 081 /** 082 * Compares two given objects for {@linkplain Assert#assertEquals(Object, Object) equality}. 083 * Does a deep copy equality comparison if {@code expected} is an array. 084 * 085 * @param message the identifying message for the {@link AssertionError} 086 */ 087 protected void assertDeepEquals(String message, Object expected, Object actual) { 088 if (ulpsDelta() > 0) { 089 assertDeepEquals(message, expected, actual, ulpsDelta()); 090 } else { 091 assertDeepEquals(message, expected, actual, equalFloatsOrDoublesDelta()); 092 } 093 } 094 095 /** 096 * Compares two given values for equality, doing a recursive test if both values are arrays of 097 * the same type. 098 * 099 * @param message the identifying message for the {@link AssertionError} 100 * @param delta the maximum delta between two doubles or floats for which both numbers are still 101 * considered equal. 102 */ 103 protected void assertDeepEquals(String message, Object expected, Object actual, double delta) { 104 if (expected != null && actual != null) { 105 Class<?> expectedClass = expected.getClass(); 106 Class<?> actualClass = actual.getClass(); 107 if (expectedClass.isArray()) { 108 Assert.assertTrue(message, expected != null); 109 Assert.assertTrue(message, actual != null); 110 Assert.assertEquals(message, expectedClass, actual.getClass()); 111 if (expected instanceof int[]) { 112 Assert.assertArrayEquals(message, (int[]) expected, (int[]) actual); 113 } else if (expected instanceof byte[]) { 114 Assert.assertArrayEquals(message, (byte[]) expected, (byte[]) actual); 115 } else if (expected instanceof char[]) { 116 Assert.assertArrayEquals(message, (char[]) expected, (char[]) actual); 117 } else if (expected instanceof short[]) { 118 Assert.assertArrayEquals(message, (short[]) expected, (short[]) actual); 119 } else if (expected instanceof float[]) { 120 Assert.assertArrayEquals(message, (float[]) expected, (float[]) actual, (float) delta); 121 } else if (expected instanceof long[]) { 122 Assert.assertArrayEquals(message, (long[]) expected, (long[]) actual); 123 } else if (expected instanceof double[]) { 124 Assert.assertArrayEquals(message, (double[]) expected, (double[]) actual, delta); 125 } else if (expected instanceof boolean[]) { 126 new ExactComparisonCriteria().arrayEquals(message, expected, actual); 127 } else if (expected instanceof Object[]) { 128 new ComparisonCriteria() { 129 @Override 130 protected void assertElementsEqual(Object e, Object a) { 131 assertDeepEquals(message, e, a, delta); 132 } 133 }.arrayEquals(message, expected, actual); 134 } else { 135 Assert.fail((message == null ? "" : message) + "non-array value encountered: " + expected); 136 } 137 } else if (expectedClass.equals(double.class) && actualClass.equals(double.class)) { 138 Assert.assertEquals((double) expected, (double) actual, delta); 139 } else if (expectedClass.equals(float.class) && actualClass.equals(float.class)) { 140 Assert.assertEquals((float) expected, (float) actual, delta); 141 } else { 142 Assert.assertEquals(message, expected, actual); 143 } 144 } else { 145 Assert.assertEquals(message, expected, actual); 146 } 147 } 148 149 /** 150 * Compares two given values for equality, doing a recursive test if both values are arrays of 151 * the same type. Uses {@linkplain StrictMath#ulp(float) ULP}s for comparison of floats. 152 * 153 * @param message the identifying message for the {@link AssertionError} 154 * @param ulpsDelta the maximum allowed ulps difference between two doubles or floats for which 155 * both numbers are still considered equal. 156 */ 157 protected void assertDeepEquals(String message, Object expected, Object actual, int ulpsDelta) { 158 ComparisonCriteria doubleUlpsDeltaCriteria = new ComparisonCriteria() { 159 @Override 160 protected void assertElementsEqual(Object e, Object a) { 161 assertTrue(message, e instanceof Double && a instanceof Double); 162 // determine acceptable error based on whether it is a normal number or a NaN/Inf 163 double de = (Double) e; 164 double epsilon = (!Double.isNaN(de) && Double.isFinite(de) ? ulpsDelta * Math.ulp(de) : 0); 165 Assert.assertEquals(message, (Double) e, (Double) a, epsilon); 166 } 167 }; 168 169 ComparisonCriteria floatUlpsDeltaCriteria = new ComparisonCriteria() { 170 @Override 171 protected void assertElementsEqual(Object e, Object a) { 172 assertTrue(message, e instanceof Float && a instanceof Float); 173 // determine acceptable error based on whether it is a normal number or a NaN/Inf 174 float fe = (Float) e; 175 float epsilon = (!Float.isNaN(fe) && Float.isFinite(fe) ? ulpsDelta * Math.ulp(fe) : 0); 176 Assert.assertEquals(message, (Float) e, (Float) a, epsilon); 177 } 178 }; 179 180 if (expected != null && actual != null) { 181 Class<?> expectedClass = expected.getClass(); 182 Class<?> actualClass = actual.getClass(); 183 if (expectedClass.isArray()) { 184 Assert.assertEquals(message, expectedClass, actualClass); 185 if (expected instanceof double[] || expected instanceof Object[]) { 186 doubleUlpsDeltaCriteria.arrayEquals(message, expected, actual); 187 return; 188 } else if (expected instanceof float[] || expected instanceof Object[]) { 189 floatUlpsDeltaCriteria.arrayEquals(message, expected, actual); 190 return; 191 } 192 } else if (expectedClass.equals(double.class) && actualClass.equals(double.class)) { 193 doubleUlpsDeltaCriteria.arrayEquals(message, expected, actual); 194 return; 195 } else if (expectedClass.equals(float.class) && actualClass.equals(float.class)) { 196 floatUlpsDeltaCriteria.arrayEquals(message, expected, actual); 197 return; 198 } 199 } 200 // anything else just use the non-ulps version 201 assertDeepEquals(message, expected, actual, equalFloatsOrDoublesDelta()); 202 } 203 204 /** 205 * Gets the value used by {@link #assertDeepEquals(Object, Object)} and 206 * {@link #assertDeepEquals(String, Object, Object)} for the maximum delta between two doubles 207 * or floats for which both numbers are still considered equal. 208 */ 209 protected double equalFloatsOrDoublesDelta() { 210 return 0.0D; 211 } 212 213 // unless overridden ulpsDelta is not used 214 protected int ulpsDelta() { 215 return 0; 216 } 217 218 @SuppressWarnings("serial") 219 public static class MultiCauseAssertionError extends AssertionError { 220 221 private Throwable[] causes; 222 223 public MultiCauseAssertionError(String message, Throwable... causes) { 224 super(message); 225 this.causes = causes; 226 } 227 228 @Override 229 public void printStackTrace(PrintStream out) { 230 super.printStackTrace(out); 231 int num = 0; 232 for (Throwable cause : causes) { 233 if (cause != null) { 234 out.print("cause " + (num++)); 235 cause.printStackTrace(out); 236 } 237 } 238 } 239 240 @Override 241 public void printStackTrace(PrintWriter out) { 242 super.printStackTrace(out); 243 int num = 0; 244 for (Throwable cause : causes) { 245 if (cause != null) { 246 out.print("cause " + (num++) + ": "); 247 cause.printStackTrace(out); 248 } 249 } 250 } 251 } 252 253 /* 254 * Overrides to the normal JUnit {@link Assert} routines that provide varargs style formatting 255 * and produce an exception stack trace with the assertion frames trimmed out. 256 */ 257 258 /** 259 * Fails a test with the given message. 260 * 261 * @param message the identifying message for the {@link AssertionError} (<code>null</code> 262 * okay) 263 * @see AssertionError 264 */ 265 public static void fail(String message, Object... objects) { 266 AssertionError e; 267 if (message == null) { 268 e = new AssertionError(); 269 } else { 270 e = new AssertionError(String.format(message, objects)); 271 } 272 // Trim the assert frames from the stack trace 273 StackTraceElement[] trace = e.getStackTrace(); 274 int start = 1; // Skip this frame 275 String thisClassName = GraalTest.class.getName(); 276 while (start < trace.length && trace[start].getClassName().equals(thisClassName) && (trace[start].getMethodName().equals("assertTrue") || trace[start].getMethodName().equals("assertFalse"))) { 277 start++; 278 } 279 e.setStackTrace(Arrays.copyOfRange(trace, start, trace.length)); 280 throw e; 281 } 282 283 /** 284 * Asserts that a condition is true. If it isn't it throws an {@link AssertionError} with the 285 * given message. 286 * 287 * @param message the identifying message for the {@link AssertionError} (<code>null</code> 288 * okay) 289 * @param condition condition to be checked 290 */ 291 public static void assertTrue(String message, boolean condition) { 292 assertTrue(condition, message); 293 } 294 295 /** 296 * Asserts that a condition is true. If it isn't it throws an {@link AssertionError} without a 297 * message. 298 * 299 * @param condition condition to be checked 300 */ 301 public static void assertTrue(boolean condition) { 302 assertTrue(condition, null); 303 } 304 305 /** 306 * Asserts that a condition is false. If it isn't it throws an {@link AssertionError} with the 307 * given message. 308 * 309 * @param message the identifying message for the {@link AssertionError} (<code>null</code> 310 * okay) 311 * @param condition condition to be checked 312 */ 313 public static void assertFalse(String message, boolean condition) { 314 assertTrue(!condition, message); 315 } 316 317 /** 318 * Asserts that a condition is false. If it isn't it throws an {@link AssertionError} without a 319 * message. 320 * 321 * @param condition condition to be checked 322 */ 323 public static void assertFalse(boolean condition) { 324 assertTrue(!condition, null); 325 } 326 327 /** 328 * Asserts that a condition is true. If it isn't it throws an {@link AssertionError} with the 329 * given message. 330 * 331 * @param condition condition to be checked 332 * @param message the identifying message for the {@link AssertionError} 333 * @param objects arguments to the format string 334 */ 335 public static void assertTrue(boolean condition, String message, Object... objects) { 336 if (!condition) { 337 fail(message, objects); 338 } 339 } 340 341 /** 342 * Asserts that a condition is false. If it isn't it throws an {@link AssertionError} with the 343 * given message produced by {@link String#format}. 344 * 345 * @param condition condition to be checked 346 * @param message the identifying message for the {@link AssertionError} 347 * @param objects arguments to the format string 348 */ 349 public static void assertFalse(boolean condition, String message, Object... objects) { 350 assertTrue(!condition, message, objects); 351 } 352 353}