changeset 1170:b33187f91f94

7901330: Fork annotation value on class ignored in presence of Fork annotation on Benchmark Summary: Implement per-parameter annotation merging.
author shade
date Tue, 31 Mar 2015 11:14:26 +0300
parents f4fdf1969ee9
children a695e0c1c6b1
files jmh-core-it/src/test/java/org/openjdk/jmh/it/fork/ForkMergeTest.java jmh-core-it/src/test/java/org/openjdk/jmh/it/fork/ForkedJvmAppendPrependArgs2_Test.java jmh-core-it/src/test/java/org/openjdk/jmh/it/fork/ForkedJvmArgs2_Test.java jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGeneratorUtils.java jmh-core/src/main/java/org/openjdk/jmh/generators/core/MethodGroup.java
diffstat 5 files changed, 216 insertions(+), 115 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/fork/ForkMergeTest.java	Tue Mar 31 11:14:26 2015 +0300
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, 2015, 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.jmh.it.fork;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.it.Fixtures;
+import org.openjdk.jmh.results.RunResult;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+
+@Fork(5)
+public class ForkMergeTest {
+
+    @Benchmark
+    @Warmup(iterations = 0)
+    @Measurement(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+    @Fork(jvmArgsAppend = {"-Dbar"})
+    public void test() {
+        Fixtures.work();
+        Assert.assertNotNull(System.getProperty("bar"));
+    }
+
+    @Test
+    public void invokeAPI() throws RunnerException {
+        Options opt = new OptionsBuilder()
+                .include(Fixtures.getTestMask(this.getClass()))
+                .shouldFailOnError(true)
+                .build();
+        RunResult result = new Runner(opt).runSingle();
+        Assert.assertEquals(5, result.getAggregatedResult().getPrimaryResult().getSampleCount());
+    }
+
+}
\ No newline at end of file
--- a/jmh-core-it/src/test/java/org/openjdk/jmh/it/fork/ForkedJvmAppendPrependArgs2_Test.java	Mon Mar 30 18:57:00 2015 +0300
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/fork/ForkedJvmAppendPrependArgs2_Test.java	Tue Mar 31 11:14:26 2015 +0300
@@ -79,7 +79,8 @@
         Assert.assertNull(System.getProperty("middle"));
         Assert.assertNull(System.getProperty("appended"));
         Assert.assertNotNull(System.getProperty("prepended"));
-        Assert.assertNull(System.getProperty("appendedUp"));
+        Assert.assertNotNull(System.getProperty("appendedUp"));
+        Assert.assertNull(System.getProperty("prependedUp"));
     }
 
     @Benchmark
@@ -92,7 +93,7 @@
         Assert.assertNotNull(System.getProperty("appended"));
         Assert.assertNull(System.getProperty("prepended"));
         Assert.assertNull(System.getProperty("appendedUp"));
-        Assert.assertNull(System.getProperty("prependedUp"));
+        Assert.assertNotNull(System.getProperty("prependedUp"));
     }
 
     @Benchmark
@@ -104,8 +105,8 @@
         Assert.assertNull(System.getProperty("middle"));
         Assert.assertNull(System.getProperty("appended"));
         Assert.assertNull(System.getProperty("prepended"));
-        Assert.assertNull(System.getProperty("appendedUp"));
-        Assert.assertNull(System.getProperty("prependedUp"));
+        Assert.assertNotNull(System.getProperty("appendedUp"));
+        Assert.assertNotNull(System.getProperty("prependedUp"));
     }
 
     @Test
--- a/jmh-core-it/src/test/java/org/openjdk/jmh/it/fork/ForkedJvmArgs2_Test.java	Mon Mar 30 18:57:00 2015 +0300
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/fork/ForkedJvmArgs2_Test.java	Tue Mar 31 11:14:26 2015 +0300
@@ -74,7 +74,7 @@
         Fixtures.work();
         Assert.assertNull(System.getProperty("test1"));
         Assert.assertNull(System.getProperty("test2"));
-        Assert.assertNull(System.getProperty("testUpper"));
+        Assert.assertNotNull(System.getProperty("testUpper"));
     }
 
     @Benchmark
--- a/jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGeneratorUtils.java	Mon Mar 30 18:57:00 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/core/BenchmarkGeneratorUtils.java	Tue Mar 31 11:14:26 2015 +0300
@@ -199,6 +199,27 @@
         }
     }
 
+    public static <T extends Annotation> Collection<T> getAnnSuperAll(MethodInfo mi, ClassInfo startCi, Class<T> annClass) {
+        Collection<T> results = new ArrayList<T>();
+        {
+            T ann = mi.getAnnotation(annClass);
+            if (ann != null) {
+                results.add(ann);
+            }
+        }
+
+        ClassInfo ci = startCi;
+        do {
+            T ann = ci.getAnnotation(annClass);
+            if (ann != null) {
+                results.add(ann);
+            }
+            ci = ci.getSuperClass();
+        } while (ci != null);
+
+        return results;
+    }
+
     public static String getGeneratedName(ClassInfo ci) {
         String name = "";
         do {
--- a/jmh-core/src/main/java/org/openjdk/jmh/generators/core/MethodGroup.java	Mon Mar 30 18:57:00 2015 +0300
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/core/MethodGroup.java	Tue Mar 31 11:14:26 2015 +0300
@@ -99,8 +99,7 @@
     }
 
     public Optional<Integer> getTotalThreadCount() {
-        Threads ann = getFinal(Threads.class);
-        if (ann != null) {
+        for (Threads ann : getAll(Threads.class)) {
             return Optional.of(ann.value());
         }
         return Optional.none();
@@ -144,131 +143,147 @@
     }
 
     public Optional<Integer> getOperationsPerInvocation() {
-        OperationsPerInvocation ann = getFinal(OperationsPerInvocation.class);
-        return (ann != null) ? Optional.of(ann.value()) : Optional.<Integer>none();
+        for (OperationsPerInvocation ann : getAll(OperationsPerInvocation.class)) {
+            return Optional.of(ann.value());
+        }
+        return Optional.none();
     }
 
     public Optional<TimeUnit> getOutputTimeUnit() {
-        OutputTimeUnit ann = getFinal(OutputTimeUnit.class);
-        return (ann != null) ? Optional.of(ann.value()) : Optional.<TimeUnit>none();
+        for (OutputTimeUnit ann : getAll(OutputTimeUnit.class)) {
+            return Optional.of(ann.value());
+        }
+        return Optional.none();
     }
 
     public Optional<Integer> getWarmupIterations() {
-        Warmup ann = getFinal(Warmup.class);
-        if (ann != null && ann.iterations() != Warmup.BLANK_ITERATIONS) {
-            return Optional.of(ann.iterations());
+        for (Warmup ann : getAll(Warmup.class)) {
+            if (ann.iterations() != Warmup.BLANK_ITERATIONS) {
+                return Optional.of(ann.iterations());
+            }
         }
         return Optional.none();
     }
 
     public Optional<TimeValue> getWarmupTime() {
-        Warmup ann = getFinal(Warmup.class);
-        if (ann != null && ann.time() != Warmup.BLANK_TIME) {
+        for (Warmup ann : getAll(Warmup.class)) {
+            if (ann.time() != Warmup.BLANK_TIME) {
+                return Optional.of(new TimeValue(ann.time(), ann.timeUnit()));
+            }
+        }
+        return Optional.none();
+    }
+
+    public Optional<Integer> getWarmupBatchSize() {
+        for (Warmup ann : getAll(Warmup.class)) {
+            if (ann.batchSize() != Warmup.BLANK_BATCHSIZE) {
+                return Optional.of(ann.batchSize());
+            }
+        }
+        return Optional.none();
+    }
+
+    public Optional<Integer> getMeasurementIterations() {
+        for (Measurement ann : getAll(Measurement.class)) {
+            if (ann.iterations() != Measurement.BLANK_ITERATIONS) {
+                return Optional.of(ann.iterations());
+            }
+        }
+        return Optional.none();
+    }
+
+    public Optional<TimeValue> getMeasurementTime() {
+        for (Measurement ann : getAll(Measurement.class)) {
+            if (ann.time() != Measurement.BLANK_TIME) {
+                return Optional.of(new TimeValue(ann.time(), ann.timeUnit()));
+            }
+        }
+        return Optional.none();
+    }
+
+    public Optional<Integer> getMeasurementBatchSize() {
+        for (Measurement ann : getAll(Measurement.class)) {
+            if (ann.batchSize() != Measurement.BLANK_BATCHSIZE) {
+                return Optional.of(ann.batchSize());
+            }
+        }
+        return Optional.none();
+    }
+
+    public Optional<Integer> getForks() {
+        for (Fork ann : getAll(Fork.class)) {
+            if (ann.value() != Fork.BLANK_FORKS) {
+                return Optional.of(ann.value());
+            }
+        }
+        return Optional.none();
+    }
+
+    public Optional<Integer> getWarmupForks() {
+        for (Fork ann : getAll(Fork.class)) {
+            if (ann.warmups() != Fork.BLANK_FORKS) {
+                return Optional.of(ann.warmups());
+            }
+        }
+        return Optional.none();
+    }
+
+    public Optional<String> getJvm() {
+        for (Fork ann : getAll(Fork.class)) {
+            if (!ann.jvm().equals(Fork.BLANK_ARGS)) {
+                return Optional.of(ann.jvm());
+            }
+        }
+        return Optional.none();
+    }
+
+    public Optional<Collection<String>> getJvmArgs() {
+        for (Fork ann : getAll(Fork.class)) {
+            String[] args = ann.jvmArgs();
+            if (!(args.length == 1 && args[0].equals(Fork.BLANK_ARGS))) {
+                return Optional.<Collection<String>>of(Arrays.asList(args));
+            }
+        }
+        return Optional.none();
+    }
+
+    public Optional<Collection<String>> getJvmArgsAppend() {
+        for (Fork ann : getAll(Fork.class)) {
+            String[] args = ann.jvmArgsAppend();
+            if (!(args.length == 1 && args[0].equals(Fork.BLANK_ARGS))) {
+                return Optional.<Collection<String>>of(Arrays.asList(args));
+            }
+        }
+        return Optional.none();
+    }
+
+    public Optional<Collection<String>> getJvmArgsPrepend() {
+        for (Fork ann : getAll(Fork.class)) {
+            String[] args = ann.jvmArgsPrepend();
+            if (!(args.length == 1 && args[0].equals(Fork.BLANK_ARGS))) {
+                return Optional.<Collection<String>>of(Arrays.asList(args));
+            }
+        }
+        return Optional.none();
+    }
+
+    public Optional<TimeValue> getTimeout() {
+        for (Timeout ann : getAll(Timeout.class)) {
             return Optional.of(new TimeValue(ann.time(), ann.timeUnit()));
         }
         return Optional.none();
     }
 
-    public Optional<Integer> getWarmupBatchSize() {
-        Warmup ann = getFinal(Warmup.class);
-        if (ann != null && ann.batchSize() != Warmup.BLANK_BATCHSIZE) {
-            return Optional.of(ann.batchSize());
+    private <T extends Annotation> Collection<T> getAll(Class<T> annClass) {
+        Collection<T> results = new ArrayList<T>();
+        for (MethodInvocation mi : methods) {
+            Collection<T> anns = BenchmarkGeneratorUtils.getAnnSuperAll(mi.method, ci, annClass);
+            if (!(results.isEmpty() || anns.isEmpty() || results.equals(anns))) {
+                throw new GenerationException("Colliding annotations: " + anns + " vs. " + results, mi.method);
+            }
+            results = anns;
         }
-        return Optional.none();
-    }
-
-    public Optional<Integer> getMeasurementIterations() {
-        Measurement ann = getFinal(Measurement.class);
-        if (ann != null && ann.iterations() != Measurement.BLANK_ITERATIONS) {
-            return Optional.of(ann.iterations());
-        }
-        return Optional.none();
-    }
-
-    public Optional<TimeValue> getMeasurementTime() {
-        Measurement ann = getFinal(Measurement.class);
-        if (ann != null && ann.time() != Measurement.BLANK_TIME) {
-            return Optional.of(new TimeValue(ann.time(), ann.timeUnit()));
-        }
-        return Optional.none();
-    }
-
-    public Optional<Integer> getMeasurementBatchSize() {
-        Measurement ann = getFinal(Measurement.class);
-        if (ann != null && ann.batchSize() != Measurement.BLANK_BATCHSIZE) {
-            return Optional.of(ann.batchSize());
-        }
-        return Optional.none();
-    }
-
-    public Optional<Integer> getForks() {
-        Fork ann = getFinal(Fork.class);
-        if (ann != null && ann.value() != Fork.BLANK_FORKS) {
-            return Optional.of(ann.value());
-        }
-        return Optional.none();
-    }
-
-    public Optional<Integer> getWarmupForks() {
-        Fork ann = getFinal(Fork.class);
-        if (ann != null && ann.warmups() != Fork.BLANK_FORKS) {
-            return Optional.of(ann.warmups());
-        }
-        return Optional.none();
-    }
-
-    public Optional<String> getJvm() {
-        Fork ann = getFinal(Fork.class);
-        if (ann != null && !(ann.jvm().equals(Fork.BLANK_ARGS))) {
-            return Optional.of(ann.jvm());
-        }
-        return Optional.none();
-    }
-
-    public Optional<Collection<String>> getJvmArgs() {
-        Fork ann = getFinal(Fork.class);
-        if (ann != null && !(ann.jvmArgs().length == 1 && ann.jvmArgs()[0].equals(Fork.BLANK_ARGS))) {
-            return Optional.<Collection<String>>of(Arrays.asList(ann.jvmArgs()));
-        }
-        return Optional.none();
-    }
-
-    public Optional<Collection<String>> getJvmArgsAppend() {
-        Fork ann = getFinal(Fork.class);
-        if (ann != null && !(ann.jvmArgsAppend().length == 1 && ann.jvmArgsAppend()[0].equals(Fork.BLANK_ARGS))) {
-            return Optional.<Collection<String>>of(Arrays.asList(ann.jvmArgsAppend()));
-        }
-        return Optional.none();
-    }
-
-    public Optional<Collection<String>> getJvmArgsPrepend() {
-        Fork ann = getFinal(Fork.class);
-        if (ann != null && !(ann.jvmArgsPrepend().length == 1 && ann.jvmArgsPrepend()[0].equals(Fork.BLANK_ARGS))) {
-            return Optional.<Collection<String>>of(Arrays.asList(ann.jvmArgsPrepend()));
-        }
-        return Optional.none();
-    }
-
-    public Optional<TimeValue> getTimeout() {
-        Timeout ann = getFinal(Timeout.class);
-        if (ann != null) {
-            return Optional.of(new TimeValue(ann.time(), ann.timeUnit()));
-        }
-        return Optional.none();
-    }
-
-    private <T extends Annotation> T getFinal(Class<T> annClass) {
-        T finalAnn = null;
-        for (MethodInvocation mi : methods) {
-            T ann = BenchmarkGeneratorUtils.getAnnSuper(mi.method, ci, annClass);
-            if (ann != null) {
-                if (finalAnn != null && !finalAnn.equals(ann)) {
-                    throw new GenerationException("Colliding annotations: " + ann + " vs. " + finalAnn, mi.method);
-                }
-                finalAnn = ann;
-            }
-        }
-        return finalAnn;
+        return results;
     }
 
     public Optional<Map<String, String[]>> getParams() {