1/*
2 * Copyright (C) 2013 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.caliper.runner;
18
19import static com.google.caliper.runner.Running.Benchmark;
20import static com.google.caliper.runner.Running.BenchmarkMethod;
21import static com.google.common.base.Preconditions.checkNotNull;
22
23import com.google.caliper.bridge.WorkerSpec;
24import com.google.caliper.util.Util;
25import com.google.common.collect.ImmutableList;
26import com.google.common.collect.ImmutableSortedMap;
27import dagger.Module;
28import dagger.Provides;
29
30import java.lang.reflect.Method;
31
32/**
33 * A module that binds data specific to a single experiment.
34 */
35@Module
36public final class ExperimentModule {
37  private final ImmutableSortedMap<String, String> parameters;
38  private final Method benchmarkMethod;
39
40  private ExperimentModule(
41      Method benchmarkMethod,
42      ImmutableSortedMap<String, String> parameters) {
43    this.parameters = checkNotNull(parameters);
44    this.benchmarkMethod = checkNotNull(benchmarkMethod);
45  }
46
47  public static ExperimentModule forExperiment(Experiment experiment) {
48    Method benchmarkMethod = experiment.instrumentation().benchmarkMethod();
49    return new ExperimentModule(
50        benchmarkMethod,
51        experiment.userParameters());
52  }
53
54  public static ExperimentModule forWorkerSpec(WorkerSpec spec)
55      throws ClassNotFoundException {
56    Class<?> benchmarkClass = Util.loadClass(spec.benchmarkSpec.className());
57    Method benchmarkMethod = findBenchmarkMethod(benchmarkClass, spec.benchmarkSpec.methodName(),
58        spec.methodParameterClasses);
59    benchmarkMethod.setAccessible(true);
60    return new ExperimentModule(benchmarkMethod, spec.benchmarkSpec.parameters());
61  }
62
63  @Provides
64  @Benchmark
65  static Object provideRunningBenchmark(BenchmarkCreator creator) {
66    return creator.createBenchmarkInstance();
67  }
68
69  @Provides
70  @BenchmarkMethod
71  String provideRunningBenchmarkMethodName() {
72    return benchmarkMethod.getName();
73  }
74
75  @Provides
76  @BenchmarkMethod
77  Method provideRunningBenchmarkMethod() {
78    return benchmarkMethod;
79  }
80
81  @Provides
82  @Benchmark
83  ImmutableSortedMap<String, String> provideUserParameters() {
84    return parameters;
85  }
86
87  private static Method findBenchmarkMethod(Class<?> benchmark, String methodName,
88      ImmutableList<Class<?>> methodParameterClasses) {
89    Class<?>[] params = methodParameterClasses.toArray(new Class<?>[methodParameterClasses.size()]);
90    try {
91      return benchmark.getDeclaredMethod(methodName, params);
92    } catch (NoSuchMethodException e) {
93      throw new RuntimeException(e);
94    } catch (SecurityException e) {
95      // assertion error?
96      throw new RuntimeException(e);
97    }
98  }
99}
100