test/tools/javac/lambdaShapes/org/openjdk/tests/separate/TestHarness.java

Tue, 24 Dec 2013 09:17:37 -0800

author
ksrini
date
Tue, 24 Dec 2013 09:17:37 -0800
changeset 2227
998b10c43157
parent 2174
62a67e0875ff
child 2525
2eb010b6cb22
permissions
-rw-r--r--

8029230: Update copyright year to match last edit in jdk8 langtools repository for 2013
Reviewed-by: ksrini
Contributed-by: steve.sides@oracle.com

rfield@1422 1 /*
ksrini@2227 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
rfield@1422 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
rfield@1422 4 *
rfield@1422 5 * This code is free software; you can redistribute it and/or modify it
rfield@1422 6 * under the terms of the GNU General Public License version 2 only, as
rfield@1422 7 * published by the Free Software Foundation. Oracle designates this
rfield@1422 8 * particular file as subject to the "Classpath" exception as provided
rfield@1422 9 * by Oracle in the LICENSE file that accompanied this code.
rfield@1422 10 *
rfield@1422 11 * This code is distributed in the hope that it will be useful, but WITHOUT
rfield@1422 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
rfield@1422 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
rfield@1422 14 * version 2 for more details (a copy is included in the LICENSE file that
rfield@1422 15 * accompanied this code).
rfield@1422 16 *
rfield@1422 17 * You should have received a copy of the GNU General Public License version
rfield@1422 18 * 2 along with this work; if not, write to the Free Software Foundation,
rfield@1422 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
rfield@1422 20 *
rfield@1422 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
rfield@1422 22 * or visit www.oracle.com if you need additional information or have any
rfield@1422 23 * questions.
rfield@1422 24 */
rfield@1422 25
rfield@1422 26 package org.openjdk.tests.separate;
rfield@1422 27
rfield@1422 28 import org.testng.ITestResult;
rfield@1422 29 import org.testng.annotations.AfterMethod;
rfield@1422 30
rfield@1422 31 import java.lang.reflect.InvocationTargetException;
rfield@1422 32 import java.util.Arrays;
rfield@1422 33 import java.util.HashSet;
rfield@1422 34 import java.util.List;
rfield@1422 35
rfield@1422 36 import static org.openjdk.tests.separate.SourceModel.Class;
rfield@1422 37 import static org.openjdk.tests.separate.SourceModel.*;
rfield@1422 38 import static org.testng.Assert.*;
rfield@1422 39
rfield@1422 40 public class TestHarness {
rfield@1422 41
rfield@1422 42 /**
rfield@1422 43 * Creates a per-thread persistent compiler object to allow as much
rfield@1422 44 * sharing as possible, but still allows for parallel execution of tests.
rfield@1422 45 */
rfield@1422 46 protected ThreadLocal<Compiler> compilerLocal = new ThreadLocal<Compiler>(){
rfield@1422 47 protected synchronized Compiler initialValue() {
rfield@1422 48 return new Compiler();
rfield@1422 49 }
rfield@1422 50 };
rfield@1422 51
rfield@1422 52 protected ThreadLocal<Boolean> verboseLocal = new ThreadLocal<Boolean>() {
rfield@1422 53 protected synchronized Boolean initialValue() {
rfield@1422 54 return Boolean.FALSE;
rfield@1422 55 }
rfield@1422 56 };
rfield@1422 57
rfield@1422 58 protected boolean verbose;
rfield@1422 59 protected boolean canUseCompilerCache;
rfield@1422 60 public static final String stdMethodName = SourceModel.stdMethodName;
rfield@1422 61
rfield@1422 62 private TestHarness() {
rfield@1422 63 }
rfield@1422 64
rfield@1422 65 protected TestHarness(boolean verbose, boolean canUseCompilerCache) {
rfield@1422 66 this.verbose = verbose;
rfield@1422 67 this.canUseCompilerCache = canUseCompilerCache;
rfield@1422 68 }
rfield@1422 69
rfield@1422 70 public void setTestVerbose() {
rfield@1422 71 verboseLocal.set(Boolean.TRUE);
rfield@1422 72 }
rfield@1422 73
rfield@1422 74 @AfterMethod
rfield@1422 75 public void reset() {
rfield@1422 76 if (!this.verbose) {
rfield@1422 77 verboseLocal.set(Boolean.FALSE);
rfield@1422 78 }
rfield@1422 79 }
rfield@1422 80
rfield@1422 81 public Compiler.Flags[] compilerFlags() {
rfield@1422 82 HashSet<Compiler.Flags> flags = new HashSet<>();
rfield@1422 83 if (verboseLocal.get() == Boolean.TRUE) {
rfield@1422 84 flags.add(Compiler.Flags.VERBOSE);
rfield@1422 85 }
rfield@1422 86 if (this.canUseCompilerCache) {
rfield@1422 87 flags.add(Compiler.Flags.USECACHE);
rfield@1422 88 }
rfield@1422 89 return flags.toArray(new Compiler.Flags[0]);
rfield@1422 90 }
rfield@1422 91
rfield@1422 92 @AfterMethod
rfield@1422 93 public void printError(ITestResult result) {
rfield@1422 94 if (result.getStatus() == ITestResult.FAILURE) {
rfield@1422 95 String clsName = result.getTestClass().getName();
rfield@1422 96 clsName = clsName.substring(clsName.lastIndexOf(".") + 1);
rfield@1422 97 System.out.println("Test " + clsName + "." +
rfield@1422 98 result.getName() + " FAILED");
rfield@1422 99 }
rfield@1422 100 }
rfield@1422 101
rfield@1422 102 private static final ConcreteMethod stdCM = ConcreteMethod.std("-1");
rfield@1422 103 private static final AbstractMethod stdAM =
rfield@1422 104 new AbstractMethod("int", stdMethodName);
rfield@1422 105
rfield@1422 106 /**
rfield@1422 107 * Returns a class which has a static method with the same name as
rfield@1422 108 * 'method', whose body creates an new instance of 'specimen' and invokes
rfield@1422 109 * 'method' upon it via an invokevirtual instruction with 'args' as
rfield@1422 110 * function call parameters.
rfield@1422 111 *
rfield@1422 112 * 'returns' is a dummy return value that need only match 'methods'
rfield@1422 113 * return type (it is only used in the dummy class when compiling IV).
rfield@1422 114 */
rfield@1422 115 private Class invokeVirtualHarness(
rfield@1422 116 Class specimen, ConcreteMethod method,
rfield@1422 117 String returns, String ... args) {
rfield@1422 118 Method cm = new ConcreteMethod(
rfield@1422 119 method.getReturnType(), method.getName(),
rfield@1422 120 "return " + returns + ";", method.getElements());
rfield@1422 121 Class stub = new Class(specimen.getName(), cm);
rfield@1422 122
rfield@1422 123 String params = toJoinedString(args, ", ");
rfield@1422 124
rfield@1422 125 ConcreteMethod sm = new ConcreteMethod(
rfield@1422 126 method.getReturnType(), method.getName(),
rfield@1422 127 String.format("return (new %s()).%s(%s);",
rfield@1422 128 specimen.getName(), method.getName(), params),
rfield@1422 129 new AccessFlag("public"), new AccessFlag("static"));
rfield@1422 130
rfield@1422 131 Class iv = new Class("IV_" + specimen.getName(), sm);
rfield@1422 132
rfield@1422 133 iv.addCompilationDependency(stub);
rfield@1422 134 iv.addCompilationDependency(cm);
rfield@1422 135
rfield@1422 136 return iv;
rfield@1422 137 }
rfield@1422 138
rfield@1422 139 /**
rfield@1422 140 * Returns a class which has a static method with the same name as
rfield@1422 141 * 'method', whose body creates an new instance of 'specimen', casts it
rfield@1422 142 * to 'iface' (including the type parameters) and invokes
rfield@1422 143 * 'method' upon it via an invokeinterface instruction with 'args' as
rfield@1422 144 * function call parameters.
rfield@1422 145 */
rfield@1422 146 private Class invokeInterfaceHarness(Class specimen, Extends iface,
rfield@1422 147 AbstractMethod method, String ... args) {
rfield@1422 148 Interface istub = new Interface(
rfield@1422 149 iface.getType().getName(), iface.getType().getAccessFlags(),
rfield@1422 150 iface.getType().getParameters(),
rfield@1422 151 null, Arrays.asList((Method)method));
rfield@1422 152 Class cstub = new Class(specimen.getName());
rfield@1422 153
rfield@1422 154 String params = toJoinedString(args, ", ");
rfield@1422 155
rfield@1422 156 ConcreteMethod sm = new ConcreteMethod(
rfield@1422 157 "int", SourceModel.stdMethodName,
rfield@1422 158 String.format("return ((%s)(new %s())).%s(%s);", iface.toString(),
rfield@1422 159 specimen.getName(), method.getName(), params),
rfield@1422 160 new AccessFlag("public"), new AccessFlag("static"));
rfield@1422 161 sm.suppressWarnings();
rfield@1422 162
rfield@1422 163 Class ii = new Class("II_" + specimen.getName() + "_" +
rfield@1422 164 iface.getType().getName(), sm);
rfield@1422 165 ii.addCompilationDependency(istub);
rfield@1422 166 ii.addCompilationDependency(cstub);
rfield@1422 167 ii.addCompilationDependency(method);
rfield@1422 168 return ii;
rfield@1422 169 }
rfield@1422 170
rfield@1422 171
rfield@1422 172 /**
rfield@1422 173 * Uses 'loader' to load class 'clzz', and calls the static method
rfield@1422 174 * 'method'. If the return value does not equal 'value' (or if an
rfield@1422 175 * exception is thrown), then a test failure is indicated.
rfield@1422 176 *
rfield@1422 177 * If 'value' is null, then no equality check is performed -- the assertion
rfield@1422 178 * fails only if an exception is thrown.
rfield@1422 179 */
rfield@1422 180 protected void assertStaticCallEquals(
rfield@1422 181 ClassLoader loader, Class clzz, String method, Object value) {
rfield@1422 182 java.lang.Class<?> cls = null;
rfield@1422 183 try {
rfield@1422 184 cls = java.lang.Class.forName(clzz.getName(), true, loader);
rfield@1422 185 } catch (ClassNotFoundException e) {}
rfield@1422 186 assertNotNull(cls);
rfield@1422 187
rfield@1422 188 java.lang.reflect.Method m = null;
rfield@1422 189 try {
rfield@1422 190 m = cls.getMethod(method);
rfield@1422 191 } catch (NoSuchMethodException e) {}
rfield@1422 192 assertNotNull(m);
rfield@1422 193
rfield@1422 194 try {
rfield@1422 195 Object res = m.invoke(null);
rfield@1422 196 assertNotNull(res);
rfield@1422 197 if (value != null) {
rfield@1422 198 assertEquals(res, value);
rfield@1422 199 }
rfield@1422 200 } catch (InvocationTargetException | IllegalAccessException e) {
briangoetz@2174 201 fail("Unexpected exception thrown: " + e.getCause(), e.getCause());
rfield@1422 202 }
rfield@1422 203 }
rfield@1422 204
rfield@1422 205 /**
rfield@1422 206 * Creates a class which calls target::method(args) via invokevirtual,
rfield@1422 207 * compiles and loads both the new class and 'target', and then invokes
rfield@1422 208 * the method. If the returned value does not match 'value' then a
rfield@1422 209 * test failure is indicated.
rfield@1422 210 */
rfield@1422 211 public void assertInvokeVirtualEquals(
rfield@1422 212 Object value, Class target, ConcreteMethod method,
rfield@1422 213 String returns, String ... args) {
rfield@1422 214
rfield@1422 215 Compiler compiler = compilerLocal.get();
rfield@1422 216 compiler.setFlags(compilerFlags());
rfield@1422 217
rfield@1422 218 Class iv = invokeVirtualHarness(target, method, returns, args);
rfield@1422 219 ClassLoader loader = compiler.compile(iv, target);
rfield@1422 220
rfield@1422 221 assertStaticCallEquals(loader, iv, method.getName(), value);
rfield@1422 222 compiler.cleanup();
rfield@1422 223 }
rfield@1422 224
rfield@1422 225 /**
rfield@1422 226 * Convenience method for above, which assumes stdMethodName,
rfield@1422 227 * a return type of 'int', and no arguments.
rfield@1422 228 */
rfield@1422 229 public void assertInvokeVirtualEquals(int value, Class target) {
briangoetz@2174 230 assertInvokeVirtualEquals(value, target, stdCM, "-1");
rfield@1422 231 }
rfield@1422 232
rfield@1422 233 /**
rfield@1422 234 * Creates a class which calls target::method(args) via invokeinterface
rfield@1422 235 * through 'iface', compiles and loads both it and 'target', and
rfield@1422 236 * then invokes the method. If the returned value does not match
rfield@1422 237 * 'value' then a test failure is indicated.
rfield@1422 238 */
rfield@1422 239 public void assertInvokeInterfaceEquals(Object value, Class target,
rfield@1422 240 Extends iface, AbstractMethod method, String ... args) {
rfield@1422 241
rfield@1422 242 Compiler compiler = compilerLocal.get();
rfield@1422 243 compiler.setFlags(compilerFlags());
rfield@1422 244
rfield@1422 245 Class ii = invokeInterfaceHarness(target, iface, method, args);
rfield@1422 246 ClassLoader loader = compiler.compile(ii, target);
rfield@1422 247
rfield@1422 248 assertStaticCallEquals(loader, ii, method.getName(), value);
rfield@1422 249 compiler.cleanup();
rfield@1422 250 }
rfield@1422 251
rfield@1422 252 /**
rfield@1422 253 * Convenience method for above, which assumes stdMethodName,
rfield@1422 254 * a return type of 'int', and no arguments.
rfield@1422 255 */
rfield@1422 256 public void assertInvokeInterfaceEquals(
rfield@1422 257 int value, Class target, Interface iface) {
rfield@1422 258
rfield@1422 259 Compiler compiler = compilerLocal.get();
rfield@1422 260 compiler.setFlags(compilerFlags());
rfield@1422 261
briangoetz@2174 262 assertInvokeInterfaceEquals(value, target, new Extends(iface), stdAM);
rfield@1422 263
rfield@1422 264 compiler.cleanup();
rfield@1422 265 }
rfield@1422 266
briangoetz@2174 267 protected void assertInvokeInterfaceThrows(java.lang.Class<? extends Throwable> errorClass,
briangoetz@2174 268 Class target, Extends iface, AbstractMethod method,
briangoetz@2174 269 String... args) {
briangoetz@2174 270 try {
briangoetz@2174 271 assertInvokeInterfaceEquals(0, target, iface, method, args);
briangoetz@2174 272 fail("Expected exception: " + errorClass);
briangoetz@2174 273 }
briangoetz@2174 274 catch (AssertionError e) {
briangoetz@2174 275 Throwable cause = e.getCause();
briangoetz@2174 276 if (cause == null)
briangoetz@2174 277 throw e;
briangoetz@2174 278 else if ((errorClass.isAssignableFrom(cause.getClass()))) {
briangoetz@2174 279 // this is success
briangoetz@2174 280 return;
briangoetz@2174 281 }
briangoetz@2174 282 else
briangoetz@2174 283 throw e;
briangoetz@2174 284 }
briangoetz@2174 285 }
briangoetz@2174 286
rfield@1422 287 /**
rfield@1422 288 * Creates a class which calls target::method(args) via invokevirtual,
rfield@1422 289 * compiles and loads both the new class and 'target', and then invokes
rfield@1422 290 * the method. If an exception of type 'exceptionType' is not thrown,
rfield@1422 291 * then a test failure is indicated.
rfield@1422 292 */
rfield@1422 293 public void assertThrows(java.lang.Class<?> exceptionType, Class target,
rfield@1422 294 ConcreteMethod method, String returns, String ... args) {
rfield@1422 295
rfield@1422 296 Compiler compiler = compilerLocal.get();
rfield@1422 297 compiler.setFlags(compilerFlags());
rfield@1422 298
rfield@1422 299 Class iv = invokeVirtualHarness(target, method, returns, args);
rfield@1422 300 ClassLoader loader = compiler.compile(iv, target);
rfield@1422 301
rfield@1422 302 java.lang.Class<?> cls = null;
rfield@1422 303 try {
rfield@1422 304 cls = java.lang.Class.forName(iv.getName(), true, loader);
rfield@1422 305 } catch (ClassNotFoundException e) {}
rfield@1422 306 assertNotNull(cls);
rfield@1422 307
rfield@1422 308 java.lang.reflect.Method m = null;
rfield@1422 309 try {
rfield@1422 310 m = cls.getMethod(method.getName());
rfield@1422 311 } catch (NoSuchMethodException e) {}
rfield@1422 312 assertNotNull(m);
rfield@1422 313
rfield@1422 314 try {
rfield@1422 315 m.invoke(null);
rfield@1422 316 fail("Exception should have been thrown");
rfield@1422 317 } catch (InvocationTargetException | IllegalAccessException e) {
rfield@1422 318 if (verboseLocal.get() == Boolean.TRUE) {
rfield@1422 319 System.out.println(e.getCause());
rfield@1422 320 }
rfield@2170 321 assertTrue(exceptionType.isAssignableFrom(e.getCause().getClass()));
rfield@1422 322 }
rfield@1422 323 compiler.cleanup();
rfield@1422 324 }
rfield@1422 325
rfield@1422 326 /**
rfield@1422 327 * Convenience method for above, which assumes stdMethodName,
rfield@1422 328 * a return type of 'int', and no arguments.
rfield@1422 329 */
rfield@1422 330 public void assertThrows(java.lang.Class<?> exceptionType, Class target) {
rfield@1422 331 assertThrows(exceptionType, target, stdCM, "-1");
rfield@1422 332 }
rfield@1422 333
rfield@1422 334 private static <T> String toJoinedString(T[] a, String... p) {
rfield@1422 335 return toJoinedString(Arrays.asList(a), p);
rfield@1422 336 }
rfield@1422 337
rfield@1422 338 private static <T> String toJoinedString(List<T> list, String... p) {
rfield@1422 339 StringBuilder sb = new StringBuilder();
rfield@1422 340 String sep = "";
rfield@1422 341 String init = "";
rfield@1422 342 String end = "";
rfield@1422 343 String empty = null;
rfield@1422 344 switch (p.length) {
rfield@1422 345 case 4:
rfield@1422 346 empty = p[3];
rfield@1422 347 /*fall-through*/
rfield@1422 348 case 3:
rfield@1422 349 end = p[2];
rfield@1422 350 /*fall-through*/
rfield@1422 351 case 2:
rfield@1422 352 init = p[1];
rfield@1422 353 /*fall-through*/
rfield@1422 354 case 1:
rfield@1422 355 sep = p[0];
rfield@1422 356 break;
rfield@1422 357 }
rfield@1422 358 if (empty != null && list.isEmpty()) {
rfield@1422 359 return empty;
rfield@1422 360 } else {
rfield@1422 361 sb.append(init);
rfield@1422 362 for (T x : list) {
rfield@1422 363 if (sb.length() != init.length()) {
rfield@1422 364 sb.append(sep);
rfield@1422 365 }
rfield@1422 366 sb.append(x.toString());
rfield@1422 367 }
rfield@1422 368 sb.append(end);
rfield@1422 369 return sb.toString();
rfield@1422 370 }
rfield@1422 371 }
rfield@1422 372 }

mercurial