changeset 62:d9eeb23c2825

Move from run-time to compile-time discovery for tests.
author shade
date Tue, 22 Oct 2013 21:05:54 +0400
parents 74d878c778c0
children 6dc6598907d6
files harness/pom.xml harness/src/main/java/org/openjdk/jcstress/JCStress.java harness/src/main/java/org/openjdk/jcstress/util/InterfaceListProcessor.java harness/src/main/java/org/openjdk/jcstress/util/Reflections.java harness/src/main/resources/META-INF/services/javax.annotation.processing.Processor tests-all/pom.xml tests-generated/pom.xml
diffstat 7 files changed, 216 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/harness/pom.xml	Fri Oct 11 22:18:41 2013 +0400
+++ b/harness/pom.xml	Tue Oct 22 21:05:54 2013 +0400
@@ -52,6 +52,7 @@
                 <configuration>
                     <source>1.6</source>
                     <target>1.6</target>
+                    <proc>none</proc>
                     <compilerArguments>
                         <Xlint:all/>
                         <Werror/>
--- a/harness/src/main/java/org/openjdk/jcstress/JCStress.java	Fri Oct 11 22:18:41 2013 +0400
+++ b/harness/src/main/java/org/openjdk/jcstress/JCStress.java	Tue Oct 22 21:05:54 2013 +0400
@@ -61,7 +61,6 @@
 import java.io.PrintWriter;
 import java.lang.management.ManagementFactory;
 import java.lang.management.RuntimeMXBean;
-import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -76,7 +75,6 @@
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicInteger;
-import java.util.regex.Pattern;
 
 /**
  * JCStress main entry point.
@@ -361,24 +359,13 @@
             // continue
         }
 
-        // God I miss both diamonds and lambdas here.
-
-        Pattern pattern = Pattern.compile(filter);
-
-        for (Class k : Reflections.findAllClassesImplementing(klass, "org.openjdk.jcstress")) {
-            if (!pattern.matcher(k.getName()).matches()) {
-                continue;
-            }
-            if (Modifier.isAbstract(k.getModifiers())) {
-                continue;
-            }
-
+        for (Class<?> c : Reflections.lookupClassesImplementing(klass, filter)) {
             @SuppressWarnings("unchecked")
-            Class<? extends T> k1 = k;
-
-            s.add(k1);
+            Class<? extends T> c1 = (Class<? extends T>) c;
+            s.add(c1);
         }
 
         return s;
     }
+
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/harness/src/main/java/org/openjdk/jcstress/util/InterfaceListProcessor.java	Tue Oct 22 21:05:54 2013 +0400
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jcstress.util;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.Diagnostic;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@SupportedSourceVersion(SourceVersion.RELEASE_6)
+public class InterfaceListProcessor extends AbstractProcessor {
+
+    private final List<String> lines = new ArrayList<String>();
+
+    @Override
+    public Set<String> getSupportedAnnotationTypes() {
+        return Collections.singleton(Override.class.getName());
+    }
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        Set<TypeElement> visited = new HashSet<TypeElement>();
+        try {
+            if (!roundEnv.processingOver()) {
+                for (Element element : roundEnv.getElementsAnnotatedWith(Override.class)) {
+                    if (element.getModifiers().contains(Modifier.ABSTRACT)) continue;
+                    TypeElement el = (TypeElement) element.getEnclosingElement();
+                    if (visited.add(el)) {
+                        lines.add(processingEnv.getElementUtils().getBinaryName(el).toString());
+                        for (TypeElement intf : getAllInterfaces(el)) {
+                            lines.add(processingEnv.getElementUtils().getBinaryName(intf).toString());
+                        }
+                        lines.add("");
+                    }
+                }
+            } else {
+                try {
+                    FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", Reflections.INTERFACE_LIST.substring(1));
+                    PrintWriter writer = new PrintWriter(file.openWriter());
+                    for (String line : lines) {
+                        writer.println(line);
+                    }
+                    writer.close();
+                } catch (IOException ex) {
+                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Error writing MicroBenchmark list " + ex);
+                }
+
+                // do nothing
+            }
+        } catch (Throwable t) {
+            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Annotation processor had thrown exception: " + t);
+            t.printStackTrace(System.err);
+        }
+        return true;
+    }
+
+    private Collection<TypeElement> getAllInterfaces(TypeElement t) {
+        if (t == null) return Collections.emptySet();
+
+        Collection<TypeElement> result = new HashSet<TypeElement>();
+        for (TypeMirror intf : t.getInterfaces()) {
+            TypeElement intft = (TypeElement) processingEnv.getTypeUtils().asElement(intf);
+            result.add(intft);
+            result.addAll(getAllInterfaces(intft));
+        }
+
+        TypeMirror superK = t.getSuperclass();
+        if (superK != null) {
+            result.addAll(getAllInterfaces((TypeElement) processingEnv.getTypeUtils().asElement(superK)));
+        }
+        return result;
+    }
+}
--- a/harness/src/main/java/org/openjdk/jcstress/util/Reflections.java	Fri Oct 11 22:18:41 2013 +0400
+++ b/harness/src/main/java/org/openjdk/jcstress/util/Reflections.java	Tue Oct 22 21:05:54 2013 +0400
@@ -24,11 +24,13 @@
  */
 package org.openjdk.jcstress.util;
 
+import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
@@ -39,15 +41,20 @@
 import java.util.TreeSet;
 import java.util.jar.JarEntry;
 import java.util.jar.JarInputStream;
+import java.util.regex.Pattern;
 
 public class Reflections {
 
-    private static volatile boolean INITED;
+    private static volatile boolean RESOURCE_INITED;
     private static Set<String> RESOURCES;
 
+    static String INTERFACE_LIST = "/META-INF/InterfaceList";
+    private static volatile boolean INTERFACE_INITED;
+    private static Multimap<String, String> INTERFACE_MAP;
+
     public static Collection<String> getResources(String filter, String postfix) {
         try {
-            ensureInited();
+            ensureResourceInited();
 
             List<String> res = new ArrayList<String>();
             for (String name : RESOURCES) {
@@ -62,6 +69,30 @@
         }
     }
 
+    public static Collection<Class<?>> lookupClassesImplementing(Class<?> intf, String filter) {
+        ensureInterfacesInited();
+
+        Collection<Class<?>> s = new ArrayList<Class<?>>();
+        String canonicalName = intf.getCanonicalName();
+
+        Pattern pattern = Pattern.compile(filter);
+
+        for (String k : INTERFACE_MAP.keys()) {
+            if (!k.equals(canonicalName)) continue;
+            for (String klass : INTERFACE_MAP.get(k)) {
+                if (pattern.matcher(klass).matches()) {
+                    try {
+                        s.add(Class.forName(klass));
+                    } catch (ClassNotFoundException e) {
+                        // swallow
+                    }
+                }
+            }
+        }
+
+        return s;
+    }
+
     public static Collection<Class> findAllClassesImplementing(Class<?> intf, String filter) {
         try {
             List<Class> result = new ArrayList<Class>();
@@ -78,8 +109,8 @@
         }
     }
 
-    private static void ensureInited() throws IOException {
-        if (!INITED) {
+    private static void ensureResourceInited() throws IOException {
+        if (!RESOURCE_INITED) {
             final SortedSet<String> newResources = new TreeSet<String>();
             try {
                 enumerate(new ResultCallback() {
@@ -92,7 +123,44 @@
                 throw new IOException(t);
             }
             RESOURCES = newResources;
-            INITED = true;
+            RESOURCE_INITED = true;
+        }
+    }
+
+    private static void ensureInterfacesInited() {
+        if (!INTERFACE_INITED) {
+            final Multimap<String, String> interfaceMap = new HashMultimap<String, String>();
+
+            InputStream list = null;
+            try {
+                list = Reflections.class.getResourceAsStream(INTERFACE_LIST);
+                BufferedReader reader = new BufferedReader(new InputStreamReader(list));
+
+                String currentClass = null;
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    if (currentClass == null) {
+                        currentClass = line;
+                    } else if (!line.isEmpty()) {
+                        interfaceMap.put(line, currentClass);
+                    } else {
+                        currentClass = null;
+                    }
+                }
+            } catch (IOException e) {
+                System.err.println("Warning: " + e);
+            } finally {
+                if (list != null) {
+                    try {
+                        list.close();
+                    } catch (IOException e) {
+                        // swallow
+                    }
+                }
+            }
+
+            INTERFACE_MAP = interfaceMap;
+            INTERFACE_INITED = true;
         }
     }
 
@@ -110,7 +178,7 @@
     }
 
     public static Collection<String> getClassNames(final String filter) throws IOException {
-        ensureInited();
+        ensureResourceInited();
 
         final List<String> newClasses = new ArrayList<String>();
         for (String name : RESOURCES) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/harness/src/main/resources/META-INF/services/javax.annotation.processing.Processor	Tue Oct 22 21:05:54 2013 +0400
@@ -0,0 +1,24 @@
+#    Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+#    DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+#    This code is free software; you can redistribute it and/or modify it
+#    under the terms of the GNU General Public License version 2 only, as
+#    published by the Free Software Foundation.  Oracle designates this
+#    particular file as subject to the "Classpath" exception as provided
+#    by Oracle in the LICENSE file that accompanied this code.
+#
+#    This code is distributed in the hope that it will be useful, but WITHOUT
+#    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+#    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+#    version 2 for more details (a copy is included in the LICENSE file that
+#    accompanied this code).
+#
+#    You should have received a copy of the GNU General Public License version
+#    2 along with this work; if not, write to the Free Software Foundation,
+#    Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+#    Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+#    or visit www.oracle.com if you need additional information or have any
+#    questions.
+#
+org.openjdk.jcstress.util.InterfaceListProcessor
--- a/tests-all/pom.xml	Fri Oct 11 22:18:41 2013 +0400
+++ b/tests-all/pom.xml	Tue Oct 22 21:05:54 2013 +0400
@@ -72,6 +72,9 @@
                                         implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                     <mainClass>org.openjdk.jcstress.Main</mainClass>
                                 </transformer>
+                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>META-INF/InterfaceList</resource>
+                                </transformer>
                             </transformers>
                         </configuration>
                     </execution>
--- a/tests-generated/pom.xml	Fri Oct 11 22:18:41 2013 +0400
+++ b/tests-generated/pom.xml	Tue Oct 22 21:05:54 2013 +0400
@@ -53,7 +53,6 @@
                     <source>1.6</source>
                     <target>1.6</target>
                     <debug>false</debug>
-                    <proc>none</proc>
                     <meminitial>2048</meminitial>
                     <fork>true</fork>
                 </configuration>