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

Thu, 24 Oct 2013 16:52:27 -0700

author
rfield
date
Thu, 24 Oct 2013 16:52:27 -0700
changeset 2170
860f1d21763a
parent 1448
7d34e91f66bb
child 2174
62a67e0875ff
permissions
-rw-r--r--

8027220: DefaultMethodsTest: Change test to match spec
Reviewed-by: ksrini

rfield@1422 1 /*
katleman@1448 2 * Copyright (c) 2012, 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) {
rfield@1422 201 fail("Unexpected exception thrown: " + 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) {
rfield@1422 230 assertInvokeVirtualEquals(
rfield@1422 231 new Integer(value), target, stdCM, "-1");
rfield@1422 232 }
rfield@1422 233
rfield@1422 234 /**
rfield@1422 235 * Creates a class which calls target::method(args) via invokeinterface
rfield@1422 236 * through 'iface', compiles and loads both it and 'target', and
rfield@1422 237 * then invokes the method. If the returned value does not match
rfield@1422 238 * 'value' then a test failure is indicated.
rfield@1422 239 */
rfield@1422 240 public void assertInvokeInterfaceEquals(Object value, Class target,
rfield@1422 241 Extends iface, AbstractMethod method, String ... args) {
rfield@1422 242
rfield@1422 243 Compiler compiler = compilerLocal.get();
rfield@1422 244 compiler.setFlags(compilerFlags());
rfield@1422 245
rfield@1422 246 Class ii = invokeInterfaceHarness(target, iface, method, args);
rfield@1422 247 ClassLoader loader = compiler.compile(ii, target);
rfield@1422 248
rfield@1422 249 assertStaticCallEquals(loader, ii, method.getName(), value);
rfield@1422 250 compiler.cleanup();
rfield@1422 251 }
rfield@1422 252
rfield@1422 253 /**
rfield@1422 254 * Convenience method for above, which assumes stdMethodName,
rfield@1422 255 * a return type of 'int', and no arguments.
rfield@1422 256 */
rfield@1422 257 public void assertInvokeInterfaceEquals(
rfield@1422 258 int value, Class target, Interface iface) {
rfield@1422 259
rfield@1422 260 Compiler compiler = compilerLocal.get();
rfield@1422 261 compiler.setFlags(compilerFlags());
rfield@1422 262
rfield@1422 263 assertInvokeInterfaceEquals(
rfield@1422 264 new Integer(value), target, new Extends(iface), stdAM);
rfield@1422 265
rfield@1422 266 compiler.cleanup();
rfield@1422 267 }
rfield@1422 268
rfield@1422 269 /**
rfield@1422 270 * Creates a class which calls target::method(args) via invokevirtual,
rfield@1422 271 * compiles and loads both the new class and 'target', and then invokes
rfield@1422 272 * the method. If an exception of type 'exceptionType' is not thrown,
rfield@1422 273 * then a test failure is indicated.
rfield@1422 274 */
rfield@1422 275 public void assertThrows(java.lang.Class<?> exceptionType, Class target,
rfield@1422 276 ConcreteMethod method, String returns, String ... args) {
rfield@1422 277
rfield@1422 278 Compiler compiler = compilerLocal.get();
rfield@1422 279 compiler.setFlags(compilerFlags());
rfield@1422 280
rfield@1422 281 Class iv = invokeVirtualHarness(target, method, returns, args);
rfield@1422 282 ClassLoader loader = compiler.compile(iv, target);
rfield@1422 283
rfield@1422 284 java.lang.Class<?> cls = null;
rfield@1422 285 try {
rfield@1422 286 cls = java.lang.Class.forName(iv.getName(), true, loader);
rfield@1422 287 } catch (ClassNotFoundException e) {}
rfield@1422 288 assertNotNull(cls);
rfield@1422 289
rfield@1422 290 java.lang.reflect.Method m = null;
rfield@1422 291 try {
rfield@1422 292 m = cls.getMethod(method.getName());
rfield@1422 293 } catch (NoSuchMethodException e) {}
rfield@1422 294 assertNotNull(m);
rfield@1422 295
rfield@1422 296 try {
rfield@1422 297 m.invoke(null);
rfield@1422 298 fail("Exception should have been thrown");
rfield@1422 299 } catch (InvocationTargetException | IllegalAccessException e) {
rfield@1422 300 if (verboseLocal.get() == Boolean.TRUE) {
rfield@1422 301 System.out.println(e.getCause());
rfield@1422 302 }
rfield@2170 303 assertTrue(exceptionType.isAssignableFrom(e.getCause().getClass()));
rfield@1422 304 }
rfield@1422 305 compiler.cleanup();
rfield@1422 306 }
rfield@1422 307
rfield@1422 308 /**
rfield@1422 309 * Convenience method for above, which assumes stdMethodName,
rfield@1422 310 * a return type of 'int', and no arguments.
rfield@1422 311 */
rfield@1422 312 public void assertThrows(java.lang.Class<?> exceptionType, Class target) {
rfield@1422 313 assertThrows(exceptionType, target, stdCM, "-1");
rfield@1422 314 }
rfield@1422 315
rfield@1422 316 private static <T> String toJoinedString(T[] a, String... p) {
rfield@1422 317 return toJoinedString(Arrays.asList(a), p);
rfield@1422 318 }
rfield@1422 319
rfield@1422 320 private static <T> String toJoinedString(List<T> list, String... p) {
rfield@1422 321 StringBuilder sb = new StringBuilder();
rfield@1422 322 String sep = "";
rfield@1422 323 String init = "";
rfield@1422 324 String end = "";
rfield@1422 325 String empty = null;
rfield@1422 326 switch (p.length) {
rfield@1422 327 case 4:
rfield@1422 328 empty = p[3];
rfield@1422 329 /*fall-through*/
rfield@1422 330 case 3:
rfield@1422 331 end = p[2];
rfield@1422 332 /*fall-through*/
rfield@1422 333 case 2:
rfield@1422 334 init = p[1];
rfield@1422 335 /*fall-through*/
rfield@1422 336 case 1:
rfield@1422 337 sep = p[0];
rfield@1422 338 break;
rfield@1422 339 }
rfield@1422 340 if (empty != null && list.isEmpty()) {
rfield@1422 341 return empty;
rfield@1422 342 } else {
rfield@1422 343 sb.append(init);
rfield@1422 344 for (T x : list) {
rfield@1422 345 if (sb.length() != init.length()) {
rfield@1422 346 sb.append(sep);
rfield@1422 347 }
rfield@1422 348 sb.append(x.toString());
rfield@1422 349 }
rfield@1422 350 sb.append(end);
rfield@1422 351 return sb.toString();
rfield@1422 352 }
rfield@1422 353 }
rfield@1422 354 }

mercurial