test/tools/javac/api/taskListeners/TestSimpleAddRemove.java

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

author
aoqi
date
Wed, 27 Apr 2016 01:34:52 +0800
changeset 0
959103a6100f
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, 2012, 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     7093891
    27  * @summary support multiple task listeners
    28  */
    30 import java.io.File;
    31 import java.io.IOException;
    32 import java.io.PrintWriter;
    33 import java.io.StringWriter;
    34 import java.net.URI;
    35 import java.util.ArrayList;
    36 import java.util.Arrays;
    37 import java.util.EnumMap;
    38 import java.util.List;
    39 import java.util.Set;
    41 import javax.annotation.processing.AbstractProcessor;
    42 import javax.annotation.processing.RoundEnvironment;
    43 import javax.annotation.processing.SupportedAnnotationTypes;
    44 import javax.lang.model.element.TypeElement;
    45 import javax.tools.JavaFileObject;
    46 import javax.tools.SimpleJavaFileObject;
    47 import javax.tools.StandardJavaFileManager;
    48 import javax.tools.StandardLocation;
    49 import javax.tools.ToolProvider;
    51 import com.sun.source.util.JavacTask;
    52 import com.sun.source.util.TaskEvent;
    53 import com.sun.source.util.TaskListener;
    54 import com.sun.tools.javac.api.JavacTool;
    56 public class TestSimpleAddRemove {
    57     enum AddKind {
    58         SET_IN_TASK,
    59         ADD_IN_TASK,
    60         ADD_IN_PROCESSOR,
    61         ADD_IN_LISTENER;
    62     }
    64     enum RemoveKind {
    65         REMOVE_IN_TASK,
    66         REMOVE_IN_PROCESSOR,
    67         REMOVE_IN_LISTENER,
    68     }
    70     enum CompileKind {
    71         CALL {
    72             void run(JavacTask t) {
    73                 if (!t.call()) throw new Error("compilation failed");
    74             }
    75         },
    76         GENERATE {
    77             void run(JavacTask t) throws IOException {
    78                 t.generate();
    79             }
    80         };
    81         abstract void run(JavacTask t) throws IOException;
    82     }
    84     static class EventKindCounter extends EnumMap<TaskEvent.Kind, EventKindCounter.Count> {
    85         static class Count {
    86             int started;
    87             int finished;
    89             @Override
    90             public String toString() {
    91                 return started + ":" + finished;
    92             }
    93         }
    95         EventKindCounter() {
    96             super(TaskEvent.Kind.class);
    97         }
    99         void inc(TaskEvent.Kind k, boolean started) {
   100             Count c = get(k);
   101             if (c == null)
   102                 put(k, c = new Count());
   104             if (started)
   105                 c.started++;
   106             else
   107                 c.finished++;
   108         }
   109     }
   111     static class TestListener implements TaskListener {
   112         EventKindCounter counter;
   114         TestListener(EventKindCounter c) {
   115             counter = c;
   116         }
   118         public void started(TaskEvent e) {
   119             counter.inc(e.getKind(), true);
   120         }
   122         public void finished(TaskEvent e) {
   123             counter.inc(e.getKind(), false);
   124         }
   125     }
   127     static void addInListener(final JavacTask task, final TaskEvent.Kind kind, final TaskListener listener) {
   128         task.addTaskListener(new TaskListener() {
   129             public void started(TaskEvent e) {
   130                 if (e.getKind() == kind) {
   131                     task.addTaskListener(listener);
   132                     task.removeTaskListener(this);
   133                 }
   134             }
   136             public void finished(TaskEvent e) { }
   137         });
   138     }
   140     static void removeInListener(final JavacTask task, final TaskEvent.Kind kind, final TaskListener listener) {
   141         task.addTaskListener(new TaskListener() {
   142             public void started(TaskEvent e) {
   143                 if (e.getKind() == kind) {
   144                     task.removeTaskListener(listener);
   145                     task.removeTaskListener(this);
   146                 }
   147             }
   149             public void finished(TaskEvent e) { }
   150         });
   151     }
   153     @SupportedAnnotationTypes("*")
   154     class TestProcessor extends AbstractProcessor {
   155         AddKind ak;
   156         RemoveKind rk;
   157         TaskListener listener;
   159         TestProcessor(AddKind ak, RemoveKind rk, TaskListener listener) {
   160             this.ak = ak;
   161             this.rk = rk;
   162             this.listener = listener;
   163         }
   165         int round = 0;
   167         @Override
   168         public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   169 //            System.err.println("TestProcessor.process " + roundEnv);
   170             JavacTask task = JavacTask.instance(processingEnv);
   171             if (++round == 1) {
   172                 switch (ak) {
   173                     case ADD_IN_PROCESSOR:
   174                         task.addTaskListener(listener);
   175                         break;
   176                     case ADD_IN_LISTENER:
   177                         addInListener(task, TaskEvent.Kind.ANALYZE, listener);
   178                         break;
   179                 }
   180             } else if (roundEnv.processingOver()) {
   181                 switch (rk) {
   182                     case REMOVE_IN_PROCESSOR:
   183                         task.removeTaskListener(listener);
   184                         break;
   185                     case REMOVE_IN_LISTENER:
   186                         removeInListener(task, TaskEvent.Kind.GENERATE, listener);
   187                         break;
   188                 }
   189             }
   190             return true;
   191         }
   192     }
   194     static class TestSource extends SimpleJavaFileObject {
   195         public TestSource() {
   196             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
   197         }
   199         @Override
   200         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   201             return "class Test { }";
   202         }
   203     }
   205     public static void main(String... args) throws Exception {
   206         new TestSimpleAddRemove().run();
   207     }
   209     JavacTool tool = (JavacTool) ToolProvider.getSystemJavaCompiler();
   210     StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
   212     void run() throws Exception {
   213         for (CompileKind ck: CompileKind.values()) {
   214             for (AddKind ak: AddKind.values()) {
   215                 for (RemoveKind rk: RemoveKind.values()) {
   216                     test(ck, ak, rk);
   217                 }
   218             }
   219         }
   220         if (errors > 0)
   221             throw new Exception(errors + " errors occurred");
   222     }
   224     void test(CompileKind ck, AddKind ak, RemoveKind rk) throws IOException {
   225         System.err.println("Test: " + ck + " " + ak + " " + rk);
   227         File tmpDir = new File(ck + "-" + ak + "-" + rk);
   228         tmpDir.mkdirs();
   229         fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(tmpDir));
   231         List<String> options = new ArrayList<String>();
   232         Iterable<? extends JavaFileObject> files = Arrays.asList(new TestSource());
   233         StringWriter sw = new StringWriter();
   234         PrintWriter pw = new PrintWriter(sw);
   235         JavacTask task = tool.getTask(pw, fm, null, options, null, files);
   237         EventKindCounter ec = new EventKindCounter();
   238         TaskListener listener = new TestListener(ec);
   239         boolean needProcessor = false;
   241         switch (ak) {
   242             case SET_IN_TASK:
   243                 task.setTaskListener(listener);
   244                 break;
   245             case ADD_IN_TASK:
   246                 task.addTaskListener(listener);
   247                 break;
   248             case ADD_IN_PROCESSOR:
   249             case ADD_IN_LISTENER:
   250                 needProcessor = true;
   251         }
   253         switch (rk) {
   254             case REMOVE_IN_TASK:
   255                 task.removeTaskListener(listener);
   256                 break;
   257             case REMOVE_IN_PROCESSOR:
   258             case REMOVE_IN_LISTENER:
   259                 needProcessor = true;
   260         }
   262         if (needProcessor)
   263             task.setProcessors(Arrays.asList(new TestProcessor(ak, rk, listener)));
   265         ck.run(task);
   266         System.err.println(ec);
   268         check(ck, ak, rk, ec);
   270         System.err.println();
   271     }
   273     void check(CompileKind ck, AddKind ak, RemoveKind rk, EventKindCounter ec) {
   274         // All results should be independent of ck, so we can ignore that
   276         // Quick way to compare expected values of ec, by comparing ec.toString()
   277         String expect = ec.toString();
   278         String found;
   280         switch (ak) {
   281             // Add/set in task should record all events until the listener is removed
   282             case SET_IN_TASK:
   283             case ADD_IN_TASK:
   284                 switch (rk) {
   285                     case REMOVE_IN_TASK:
   286                         // Remove will succeed, meaning no events will be recorded
   287                         found = "{}";
   288                         break;
   289                     case REMOVE_IN_PROCESSOR:
   290                         found = "{PARSE=1:1, ENTER=2:2, ANNOTATION_PROCESSING=1:0, ANNOTATION_PROCESSING_ROUND=2:1}";
   291                         break;
   292                     case REMOVE_IN_LISTENER:
   293                         found = "{PARSE=1:1, ENTER=3:3, ANALYZE=1:1, GENERATE=1:0, ANNOTATION_PROCESSING=1:1, ANNOTATION_PROCESSING_ROUND=2:2}";
   294                         break;
   295                     default:
   296                         throw new IllegalStateException();
   297                 }
   298                 break;
   300             // "Add in processor" should skip initial PARSE/ENTER events
   301             case ADD_IN_PROCESSOR:
   302                 switch (rk) {
   303                     // Remove will fail (too early), so events to end will be recorded
   304                     case REMOVE_IN_TASK:
   305                         found = "{ENTER=2:2, ANALYZE=1:1, GENERATE=1:1, ANNOTATION_PROCESSING=0:1, ANNOTATION_PROCESSING_ROUND=1:2}";
   306                         break;
   307                     case REMOVE_IN_PROCESSOR:
   308                         found = "{ENTER=1:1, ANNOTATION_PROCESSING_ROUND=1:1}";
   309                         break;
   310                     case REMOVE_IN_LISTENER:
   311                         found = "{ENTER=2:2, ANALYZE=1:1, GENERATE=1:0, ANNOTATION_PROCESSING=0:1, ANNOTATION_PROCESSING_ROUND=1:2}";
   312                         break;
   313                     default:
   314                         throw new IllegalStateException();
   315                 }
   316                 break;
   318             // "Add in listener" will occur during "ANALYSE.started" event
   319             case ADD_IN_LISTENER:
   320                 switch (rk) {
   321                     // Remove will fail (too early, so events to end will be recorded
   322                     case REMOVE_IN_TASK:
   323                     case REMOVE_IN_PROCESSOR:
   324                         found = "{ANALYZE=0:1, GENERATE=1:1}";
   325                         break;
   326                     // Remove will succeed during "GENERATE.finished" event
   327                     case REMOVE_IN_LISTENER:
   328                         found = "{ANALYZE=0:1, GENERATE=1:0}";
   329                         break;
   330                     default:
   331                         throw new IllegalStateException();
   332                 }
   333                 break;
   334             default:
   335                 throw new IllegalStateException();
   336         }
   338         if (!found.equals(expect)) {
   339             System.err.println("Expected: " + expect);
   340             System.err.println("   Found: " + found);
   341             error("unexpected value found");
   342         }
   343     }
   345     int errors;
   347     void error(String message) {
   348         System.err.println("Error: " + message);
   349         errors++;
   350     }
   351 }

mercurial