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

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

mercurial