• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 
15 package com.google.caliper.runner;
16 
17 import static com.google.common.base.Preconditions.checkState;
18 
19 import com.google.caliper.config.InvalidConfigurationException;
20 import com.google.caliper.model.Trial;
21 import com.google.caliper.util.InvalidCommandException;
22 import com.google.common.collect.ImmutableList;
23 import com.google.common.collect.Lists;
24 import com.google.common.io.Files;
25 
26 import org.junit.rules.TestWatcher;
27 import org.junit.runner.Description;
28 
29 import java.io.File;
30 import java.io.PrintWriter;
31 import java.io.StringWriter;
32 import java.util.Arrays;
33 import java.util.List;
34 
35 /**
36  * A {@link TestWatcher} that can be used to configure a run of caliper.
37  *
38  * <p>Provides common test configuration utilities and redirects output to a buffer and only dumps
39  * it during a failure.
40  *
41  * <p>TODO(lukes,gak): This is a bad name since it isn't just watching the tests, it is helping you
42  * run the tests.
43  */
44 public final class CaliperTestWatcher extends TestWatcher {
45   // N.B. StringWriter is internally synchronized and is safe to write to from multiple threads.
46   private StringWriter stdout;
47   private final StringWriter stderr = new StringWriter();
48   private File workerOutput;
49 
50   private String instrument;
51   private Class<?> benchmarkClass;
52   private List<String> extraOptions = Lists.newArrayList();
53 
forBenchmark(Class<?> benchmarkClass)54   CaliperTestWatcher forBenchmark(Class<?> benchmarkClass) {
55     this.benchmarkClass = benchmarkClass;
56     return this;
57   }
58 
instrument(String instrument)59   CaliperTestWatcher instrument(String instrument) {
60     this.instrument = instrument;
61     return this;
62   }
63 
options(String... extraOptions)64   CaliperTestWatcher options(String... extraOptions) {
65     this.extraOptions = Arrays.asList(extraOptions);
66     return this;
67   }
68 
run()69   void run() throws InvalidCommandException, InvalidBenchmarkException,
70       InvalidConfigurationException {
71     checkState(benchmarkClass != null, "You must configure a benchmark!");
72     workerOutput = Files.createTempDir();
73     // configure a custom dir so the files aren't deleted when CaliperMain returns
74     List<String> options = Lists.newArrayList(
75         "-Cworker.output=" + workerOutput.getPath(),
76         "-Cresults.file.class=",
77         "-Cresults.upload.class=" + InMemoryResultsUploader.class.getName());
78     if (instrument != null) {
79       options.add("-i");
80       options.add(instrument);
81     }
82     options.addAll(extraOptions);
83     options.add(benchmarkClass.getName());
84     this.stdout = new StringWriter();
85     CaliperMain.exitlessMain(
86         options.toArray(new String[0]),
87         new PrintWriter(stdout,  true),
88         new PrintWriter(stderr,  true));
89   }
90 
finished(Description description)91   @Override protected void finished(Description description) {
92     if (workerOutput != null) {
93       for (File f : workerOutput.listFiles()) {
94         f.delete();
95       }
96       workerOutput.delete();
97     }
98   }
99 
failed(Throwable e, Description description)100   @Override protected void failed(Throwable e, Description description) {
101     // don't log if run was never called.
102     if (stdout != null) {
103       System.err.println("Caliper failed with the following output (stdout):\n"
104           + stdout.toString() + "stderr:\n" + stderr.toString());
105     }
106   }
107 
trials()108   ImmutableList<Trial> trials() {
109     return InMemoryResultsUploader.trials();
110   }
111 
getStderr()112   public StringWriter getStderr() {
113     return stderr;
114   }
115 
getStdout()116   public StringWriter getStdout() {
117     return stdout;
118   }
119 
workerOutputDirectory()120   File workerOutputDirectory() {
121     return workerOutput;
122   }
123 }
124