test/tools/javac/api/TestClientCodeWrapper.java

Wed, 27 Apr 2016 01:34:52 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:34:52 +0800
changeset 0
959103a6100f
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17

     1 /*
     2  * Copyright (c) 2011, 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.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  */
    24 /*
    25  * @test
    26  * @bug 6437138 6482554
    27  * @summary JSR 199: Compiler doesn't diagnose crash in user code
    28  * @library ../lib
    29  * @build JavacTestingAbstractProcessor TestClientCodeWrapper
    30  * @run main TestClientCodeWrapper
    31  */
    33 import java.io.*;
    34 import java.lang.reflect.Method;
    35 import java.net.URI;
    36 import java.util.*;
    37 import javax.annotation.processing.*;
    38 import javax.lang.model.*;
    39 import javax.lang.model.element.*;
    40 import javax.tools.*;
    41 import com.sun.source.util.*;
    42 import com.sun.tools.javac.api.*;
    43 import javax.tools.JavaFileObject.Kind;
    45 public class TestClientCodeWrapper extends JavacTestingAbstractProcessor {
    46     public static void main(String... args) throws Exception {
    47         new TestClientCodeWrapper().run();
    48     }
    50     /**
    51      * Run a series of compilations, each with a different user-provided object
    52      * configured to throw an exception when a specific method is invoked.
    53      * Then, verify the exception is thrown as expected.
    54      *
    55      * Some methods are not invoked from the compiler, and are excluded from the test.
    56      */
    57     void run() throws Exception {
    58         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    59         defaultFileManager = compiler.getStandardFileManager(null, null, null);
    61         for (Method m: getMethodsExcept(JavaFileManager.class, "close", "getJavaFileForInput")) {
    62             test(m);
    63         }
    65         for (Method m: getMethodsExcept(FileObject.class, "delete")) {
    66             test(m);
    67         }
    69         for (Method m: getMethods(JavaFileObject.class)) {
    70             test(m);
    71         }
    73         for (Method m: getMethodsExcept(Processor.class, "getCompletions")) {
    74             test(m);
    75         }
    77         for (Method m: DiagnosticListener.class.getDeclaredMethods()) {
    78             test(m);
    79         }
    81         for (Method m: TaskListener.class.getDeclaredMethods()) {
    82             test(m);
    83         }
    85         if (errors > 0)
    86             throw new Exception(errors + " errors occurred");
    87     }
    89     /** Get a sorted set of the methods declared on a class. */
    90     Set<Method> getMethods(Class<?> clazz) {
    91         return getMethodsExcept(clazz, new String[0]);
    92     }
    94     /** Get a sorted set of the methods declared on a class, excluding
    95      *  specified methods by name. */
    96     Set<Method> getMethodsExcept(Class<?> clazz, String... exclude) {
    97         Set<Method> methods = new TreeSet<Method>(new Comparator<Method>() {
    98             public int compare(Method m1, Method m2) {
    99                 return m1.toString().compareTo(m2.toString());
   100             }
   101         });
   102         Set<String> e = new HashSet<String>(Arrays.asList(exclude));
   103         for (Method m: clazz.getDeclaredMethods()) {
   104             if (!e.contains(m.getName()))
   105                 methods.add(m);
   106         }
   107         return methods;
   108     }
   110     /**
   111      * Test a method in a user supplied component, to verify javac's handling
   112      * of any exceptions thrown by that method.
   113      */
   114     void test(Method m) throws Exception {
   115         testNum++;
   117         File extDirs = new File("empty-extdirs");
   118         extDirs.mkdirs();
   120         File testClasses = new File("test" + testNum);
   121         testClasses.mkdirs();
   122         defaultFileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(testClasses));
   124         System.err.println("test " + testNum + ": "
   125                 + m.getDeclaringClass().getSimpleName() + "." + m.getName());
   127         StringWriter sw = new StringWriter();
   128         PrintWriter pw = new PrintWriter(sw);
   130         List<String> javacOptions = Arrays.asList(
   131                 "-extdirs", extDirs.getPath(), // for use by filemanager handleOption
   132                 "-processor", TestClientCodeWrapper.class.getName()
   133                 );
   135         List<String> classes = Collections.emptyList();
   137         JavacTool tool = JavacTool.create();
   138         try {
   139             JavacTask task = tool.getTask(pw,
   140                     getFileManager(m, defaultFileManager),
   141                     getDiagnosticListener(m, pw),
   142                     javacOptions,
   143                     classes,
   144                     getCompilationUnits(m));
   146             if (isDeclaredIn(m, Processor.class))
   147                 task.setProcessors(getProcessors(m));
   149             if (isDeclaredIn(m, TaskListener.class))
   150                 task.setTaskListener(getTaskListener(m, pw));
   152             boolean ok = task.call();
   153             error("compilation " + (ok ? "succeeded" : "failed") + " unexpectedly");
   154         } catch (RuntimeException e) {
   155             System.err.println("caught " + e);
   156             if (e.getClass() == RuntimeException.class) {
   157                 Throwable cause = e.getCause();
   158                 if (cause instanceof UserError) {
   159                     String expect = m.getName();
   160                     String found = cause.getMessage();
   161                     checkEqual("exception messaqe", expect, found);
   162                 } else {
   163                     cause.printStackTrace(System.err);
   164                     error("Unexpected exception: " + cause);
   165                 }
   166             } else {
   167                 e.printStackTrace(System.err);
   168                 error("Unexpected exception: " + e);
   169             }
   170         }
   172         pw.close();
   173         String out = sw.toString();
   174         System.err.println(out);
   175     }
   177     /** Get a file manager to use for the test compilation. */
   178     JavaFileManager getFileManager(Method m, JavaFileManager defaultFileManager) {
   179         return isDeclaredIn(m, JavaFileManager.class, FileObject.class, JavaFileObject.class)
   180                 ? new UserFileManager(m, defaultFileManager)
   181                 : defaultFileManager;
   182     }
   184     /** Get a diagnostic listener to use for the test compilation. */
   185     DiagnosticListener<JavaFileObject> getDiagnosticListener(Method m, PrintWriter out) {
   186         return isDeclaredIn(m, DiagnosticListener.class)
   187                 ? new UserDiagnosticListener(m, out)
   188                 : null;
   189     }
   191     /** Get a set of file objects to use for the test compilation. */
   192     Iterable<? extends JavaFileObject> getCompilationUnits(Method m) {
   193         File testSrc = new File(System.getProperty("test.src"));
   194         File thisSrc = new File(testSrc, TestClientCodeWrapper.class.getName() + ".java");
   195         Iterable<? extends JavaFileObject> files = defaultFileManager.getJavaFileObjects(thisSrc);
   196         if (isDeclaredIn(m, FileObject.class, JavaFileObject.class))
   197             return Arrays.asList(new UserFileObject(m, files.iterator().next()));
   198         else
   199             return files;
   200     }
   202     /** Get a set of annotation processors to use for the test compilation. */
   203     Iterable<? extends Processor> getProcessors(Method m) {
   204         return Arrays.asList(new UserProcessor(m));
   205     }
   207     /** Get a task listener to use for the test compilation. */
   208     TaskListener getTaskListener(Method m, PrintWriter out) {
   209         return new UserTaskListener(m, out);
   210     }
   212     /** Check if two values are .equal, and report an error if not. */
   213     <T> void checkEqual(String label, T expect, T found) {
   214         if (!expect.equals(found))
   215             error("Unexpected value for " + label + ": " + found + "; expected: " + expect);
   216     }
   218     /** Report an error. */
   219     void error(String msg) {
   220         System.err.println("Error: " + msg);
   221         errors++;
   222     }
   224     /** Check if a method is declared in any of a set of classes */
   225     static boolean isDeclaredIn(Method m, Class<?>... classes) {
   226         Class<?> dc = m.getDeclaringClass();
   227         for (Class<?> c: classes) {
   228             if (c == dc) return true;
   229         }
   230         return false;
   231     }
   233     /** Throw an intentional error if the method has a given name. */
   234     static void throwUserExceptionIfNeeded(Method m, String name) {
   235         if (m != null && m.getName().equals(name))
   236             throw new UserError(name);
   237     }
   239     StandardJavaFileManager defaultFileManager;
   240     int testNum;
   241     int errors;
   243     //--------------------------------------------------------------------------
   245     /**
   246      * Processor used to trigger use of methods not normally used by javac.
   247      */
   248     @Override
   249     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   250         boolean firstRound = false;
   251         for (Element e: roundEnv.getRootElements()) {
   252             if (e.getSimpleName().contentEquals(TestClientCodeWrapper.class.getSimpleName()))
   253                 firstRound = true;
   254         }
   255         if (firstRound) {
   256             try {
   257                 FileObject f1 = filer.getResource(StandardLocation.CLASS_PATH, "",
   258                     TestClientCodeWrapper.class.getName() + ".java");
   259                 f1.openInputStream().close();
   260                 f1.openReader(false).close();
   262                 FileObject f2 = filer.createResource(
   263                         StandardLocation.CLASS_OUTPUT, "", "f2.txt", (Element[]) null);
   264                 f2.openOutputStream().close();
   266                 FileObject f3 = filer.createResource(
   267                         StandardLocation.CLASS_OUTPUT, "", "f3.txt", (Element[]) null);
   268                 f3.openWriter().close();
   270                 JavaFileObject f4 = filer.createSourceFile("f4", (Element[]) null);
   271                 f4.openWriter().close();
   272                 f4.getNestingKind();
   273                 f4.getAccessLevel();
   275                 messager.printMessage(Diagnostic.Kind.NOTE, "informational note",
   276                         roundEnv.getRootElements().iterator().next());
   278             } catch (IOException e) {
   279                 throw new UserError(e);
   280             }
   281         }
   282         return true;
   283     }
   285     //--------------------------------------------------------------------------
   287     // <editor-fold defaultstate="collapsed" desc="User classes">
   289     static class UserError extends Error {
   290         private static final long serialVersionUID = 1L;
   291         UserError(String msg) {
   292             super(msg);
   293         }
   294         UserError(Throwable t) {
   295             super(t);
   296         }
   297     }
   299     static class UserFileManager extends ForwardingJavaFileManager<JavaFileManager> {
   300         Method fileManagerMethod;
   301         Method fileObjectMethod;
   303         UserFileManager(Method m, JavaFileManager delegate) {
   304             super(delegate);
   305             if (isDeclaredIn(m, JavaFileManager.class)) {
   306                 fileManagerMethod = m;
   307             } else if (isDeclaredIn(m, FileObject.class, JavaFileObject.class)) {
   308                 fileObjectMethod = m;
   309             } else
   310                 assert false;
   311         }
   313         @Override
   314         public ClassLoader getClassLoader(Location location) {
   315             throwUserExceptionIfNeeded(fileManagerMethod, "getClassLoader");
   316             return super.getClassLoader(location);
   317         }
   319         @Override
   320         public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, boolean recurse) throws IOException {
   321             throwUserExceptionIfNeeded(fileManagerMethod, "list");
   322             return wrap(super.list(location, packageName, kinds, recurse));
   323         }
   325         @Override
   326         public String inferBinaryName(Location location, JavaFileObject file) {
   327             throwUserExceptionIfNeeded(fileManagerMethod, "inferBinaryName");
   328             return super.inferBinaryName(location, unwrap(file));
   329         }
   331         @Override
   332         public boolean isSameFile(FileObject a, FileObject b) {
   333             throwUserExceptionIfNeeded(fileManagerMethod, "isSameFile");
   334             return super.isSameFile(unwrap(a), unwrap(b));
   335         }
   337         @Override
   338         public boolean handleOption(String current, Iterator<String> remaining) {
   339             throwUserExceptionIfNeeded(fileManagerMethod, "handleOption");
   340             return super.handleOption(current, remaining);
   341         }
   343         @Override
   344         public boolean hasLocation(Location location) {
   345             throwUserExceptionIfNeeded(fileManagerMethod, "hasLocation");
   346             return super.hasLocation(location);
   347         }
   349         @Override
   350         public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException {
   351             throwUserExceptionIfNeeded(fileManagerMethod, "getJavaFileForInput");
   352             return wrap(super.getJavaFileForInput(location, className, kind));
   353         }
   355         @Override
   356         public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
   357             throwUserExceptionIfNeeded(fileManagerMethod, "getJavaFileForOutput");
   358             return wrap(super.getJavaFileForOutput(location, className, kind, sibling));
   359         }
   361         @Override
   362         public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
   363             throwUserExceptionIfNeeded(fileManagerMethod, "getFileForInput");
   364             return wrap(super.getFileForInput(location, packageName, relativeName));
   365         }
   367         @Override
   368         public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
   369             throwUserExceptionIfNeeded(fileManagerMethod, "getFileForOutput");
   370             return wrap(super.getFileForOutput(location, packageName, relativeName, sibling));
   371         }
   373         @Override
   374         public void flush() throws IOException {
   375             throwUserExceptionIfNeeded(fileManagerMethod, "flush");
   376             super.flush();
   377         }
   379         @Override
   380         public void close() throws IOException {
   381             throwUserExceptionIfNeeded(fileManagerMethod, "close");
   382             super.close();
   383         }
   385         @Override
   386         public int isSupportedOption(String option) {
   387             throwUserExceptionIfNeeded(fileManagerMethod, "isSupportedOption");
   388             return super.isSupportedOption(option);
   389         }
   391         public FileObject wrap(FileObject fo) {
   392             if (fileObjectMethod == null)
   393                 return fo;
   394             return new UserFileObject(fileObjectMethod, (JavaFileObject)fo);
   395         }
   397         FileObject unwrap(FileObject fo) {
   398             if (fo instanceof UserFileObject)
   399                 return ((UserFileObject) fo).unwrap();
   400             else
   401                 return fo;
   402         }
   404         public JavaFileObject wrap(JavaFileObject fo) {
   405             if (fileObjectMethod == null)
   406                 return fo;
   407             return new UserFileObject(fileObjectMethod, fo);
   408         }
   410         public Iterable<JavaFileObject> wrap(Iterable<? extends JavaFileObject> list) {
   411             List<JavaFileObject> wrapped = new ArrayList<JavaFileObject>();
   412             for (JavaFileObject fo : list)
   413                 wrapped.add(wrap(fo));
   414             return Collections.unmodifiableList(wrapped);
   415         }
   417         JavaFileObject unwrap(JavaFileObject fo) {
   418             if (fo instanceof UserFileObject)
   419                 return ((UserFileObject) fo).unwrap();
   420             else
   421                 return fo;
   422         }
   423     }
   425     static class UserFileObject extends ForwardingJavaFileObject<JavaFileObject> {
   426         Method method;
   428         UserFileObject(Method m, JavaFileObject delegate) {
   429             super(delegate);
   430             assert isDeclaredIn(m, FileObject.class, JavaFileObject.class);
   431             this.method = m;
   432         }
   434         JavaFileObject unwrap() {
   435             return fileObject;
   436         }
   438         @Override
   439         public Kind getKind() {
   440             throwUserExceptionIfNeeded(method, "getKind");
   441             return super.getKind();
   442         }
   444         @Override
   445         public boolean isNameCompatible(String simpleName, Kind kind) {
   446             throwUserExceptionIfNeeded(method, "isNameCompatible");
   447             return super.isNameCompatible(simpleName, kind);
   448         }
   450         @Override
   451         public NestingKind getNestingKind() {
   452             throwUserExceptionIfNeeded(method, "getNestingKind");
   453             return super.getNestingKind();
   454         }
   456         @Override
   457         public Modifier getAccessLevel() {
   458             throwUserExceptionIfNeeded(method, "getAccessLevel");
   459             return super.getAccessLevel();
   460         }
   462         @Override
   463         public URI toUri() {
   464             throwUserExceptionIfNeeded(method, "toUri");
   465             return super.toUri();
   466         }
   468         @Override
   469         public String getName() {
   470             throwUserExceptionIfNeeded(method, "getName");
   471             return super.getName();
   472         }
   474         @Override
   475         public InputStream openInputStream() throws IOException {
   476             throwUserExceptionIfNeeded(method, "openInputStream");
   477             return super.openInputStream();
   478         }
   480         @Override
   481         public OutputStream openOutputStream() throws IOException {
   482             throwUserExceptionIfNeeded(method, "openOutputStream");
   483             return super.openOutputStream();
   484         }
   486         @Override
   487         public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
   488             throwUserExceptionIfNeeded(method, "openReader");
   489             return super.openReader(ignoreEncodingErrors);
   490         }
   492         @Override
   493         public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
   494             throwUserExceptionIfNeeded(method, "getCharContent");
   495             return super.getCharContent(ignoreEncodingErrors);
   496         }
   498         @Override
   499         public Writer openWriter() throws IOException {
   500             throwUserExceptionIfNeeded(method, "openWriter");
   501             return super.openWriter();
   502         }
   504         @Override
   505         public long getLastModified() {
   506             throwUserExceptionIfNeeded(method, "getLastModified");
   507             return super.getLastModified();
   508         }
   510         @Override
   511         public boolean delete() {
   512             throwUserExceptionIfNeeded(method, "delete");
   513             return super.delete();
   514         }
   516     }
   518     static class UserProcessor extends JavacTestingAbstractProcessor {
   519         Method method;
   521         UserProcessor(Method m) {
   522             assert isDeclaredIn(m, Processor.class);
   523             method = m;
   524         }
   526         @Override
   527         public Set<String> getSupportedOptions() {
   528             throwUserExceptionIfNeeded(method, "getSupportedOptions");
   529             return super.getSupportedOptions();
   530         }
   532         @Override
   533         public Set<String> getSupportedAnnotationTypes() {
   534             throwUserExceptionIfNeeded(method, "getSupportedAnnotationTypes");
   535             return super.getSupportedAnnotationTypes();
   536         }
   538         @Override
   539         public SourceVersion getSupportedSourceVersion() {
   540             throwUserExceptionIfNeeded(method, "getSupportedSourceVersion");
   541             return super.getSupportedSourceVersion();
   542         }
   544         @Override
   545         public void init(ProcessingEnvironment processingEnv) {
   546             throwUserExceptionIfNeeded(method, "init");
   547             super.init(processingEnv);
   548         }
   550         @Override
   551         public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   552             throwUserExceptionIfNeeded(method, "process");
   553             return true;
   554         }
   556         @Override
   557         public Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {
   558             throwUserExceptionIfNeeded(method, "getCompletions");
   559             return super.getCompletions(element, annotation, member, userText);
   560         }
   561     }
   563     static class UserDiagnosticListener implements DiagnosticListener<JavaFileObject> {
   564         Method method;
   565         PrintWriter out;
   567         UserDiagnosticListener(Method m, PrintWriter out) {
   568             assert isDeclaredIn(m, DiagnosticListener.class);
   569             this.method = m;
   570             this.out = out;
   571         }
   573         @Override
   574         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   575             throwUserExceptionIfNeeded(method, "report");
   576             out.println("report: " + diagnostic);
   577         }
   578     }
   580     static class UserTaskListener implements TaskListener {
   581         Method method;
   582         PrintWriter out;
   584         UserTaskListener(Method m, PrintWriter out) {
   585             assert isDeclaredIn(m, TaskListener.class);
   586             this.method = m;
   587             this.out = out;
   588         }
   590         @Override
   591         public void started(TaskEvent e) {
   592             throwUserExceptionIfNeeded(method, "started");
   593             out.println("started: " + e);
   594         }
   596         @Override
   597         public void finished(TaskEvent e) {
   598             throwUserExceptionIfNeeded(method, "finished");
   599             out.println("finished: " + e);
   600         }
   601     }
   603     // </editor-fold>
   604 }

mercurial