// Path: junitperf-junit4/src/main/java/com/github/noconnor/junitperf/JUnitPerfAsyncRule.java
// @SuppressWarnings("WeakerAccess")
// public class JUnitPerfAsyncRule extends JUnitPerfRule {
// 
//   private long measurementsStartTimeMs;
// 
//   public JUnitPerfAsyncRule() {
//     this(new DescriptiveStatisticsCalculator(), new HtmlReportGenerator());
//   }
// 
//   public JUnitPerfAsyncRule(ReportGenerator... reportGenerator) {
//     this(new DescriptiveStatisticsCalculator(), reportGenerator);
//   }
// 
//   public JUnitPerfAsyncRule(StatisticsCalculator statisticsCalculator) {
//     this(statisticsCalculator, new HtmlReportGenerator());
//   }
// 
//   public JUnitPerfAsyncRule(StatisticsCalculator statisticsCalculator, ReportGenerator... reportGenerator) {
//     super(statisticsCalculator, reportGenerator);
//   }
// 
//   public TestContext newContext() {
//     return hasMeasurementPeriodStarted() ? new TestContext(statisticsCalculator) : NoOpTestContext.INSTANCE;
//   }
// 
//   @Override
//   public Statement apply(Statement base, Description description) {
//     setMeasurementsStartTime(description.getAnnotation(JUnitPerfTest.class));
//     return super.apply(base, description);
//   }
// 
//   @Override
//   EvaluationContext createEvaluationContext(Description description) {
//     return new EvaluationContext(description.getMethodName(), nanoTime(), true);
//   }
// 
//   private void setMeasurementsStartTime(JUnitPerfTest perfTestAnnotation) {
//     if (nonNull(perfTestAnnotation)) {
//       measurementsStartTimeMs = currentTimeMillis() + perfTestAnnotation.warmUpMs();
//     }
//   }
// 
//   private boolean hasMeasurementPeriodStarted() {
//     return currentTimeMillis() >= measurementsStartTimeMs;
//   }
// 
// }
// 
// Path: junitperf-core/src/main/java/com/github/noconnor/junitperf/data/TestContext.java
// public class TestContext {
// 
//   private final StatisticsCalculator stats;
//   private final long startTimeNs;
// 
//   public TestContext(StatisticsCalculator stats) {
//     this.stats = stats;
//     this.startTimeNs = nanoTime();
//   }
// 
//   public void success() {
//     stats.incrementEvaluationCount();
//     stats.addLatencyMeasurement(nanoTime() - startTimeNs);
//   }
// 
//   public void fail() {
//     stats.incrementEvaluationCount();
//     stats.incrementErrorCount();
//     stats.addLatencyMeasurement(nanoTime() - startTimeNs);
//   }
// }
// 
// Path: junit4-examples/src/test/java/com/github/noconnor/junitperf/examples/utils/ReportingUtils.java
// public static HtmlReportGenerator newHtmlReporter(String fileName){
//   return new HtmlReportGenerator(getProperty("user.dir") + "/build/reports/" + fileName);
// }


import com.github.noconnor.junitperf.JUnitPerfAsyncRule;
import com.github.noconnor.junitperf.JUnitPerfTest;
import com.github.noconnor.junitperf.data.TestContext;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import static com.github.noconnor.junitperf.examples.utils.ReportingUtils.newHtmlReporter;
package com.github.noconnor.junitperf.examples;




public class ExampleAsyncTests {

  @Rule
  public JUnitPerfAsyncRule rule = new JUnitPerfAsyncRule(newHtmlReporter("async_test.html"));

  private static ExecutorService pool;

  @BeforeClass
  public static void setup() {
    pool = Executors.newFixedThreadPool(100);
  }

  @AfterClass
  public static void teardown() {
    pool.shutdownNow();
  }

  @Test
  @JUnitPerfTest(durationMs = 10_000, warmUpMs = 1_000, maxExecutionsPerSecond = 100)
  public void whenTestExecutesAsynchronously_thenMeasurementsCanStillBeCaptured() {
// Path: junitperf-junit4/src/main/java/com/github/noconnor/junitperf/JUnitPerfAsyncRule.java
// @SuppressWarnings("WeakerAccess")
// public class JUnitPerfAsyncRule extends JUnitPerfRule {
// 
//   private long measurementsStartTimeMs;
// 
//   public JUnitPerfAsyncRule() {
//     this(new DescriptiveStatisticsCalculator(), new HtmlReportGenerator());
//   }
// 
//   public JUnitPerfAsyncRule(ReportGenerator... reportGenerator) {
//     this(new DescriptiveStatisticsCalculator(), reportGenerator);
//   }
// 
//   public JUnitPerfAsyncRule(StatisticsCalculator statisticsCalculator) {
//     this(statisticsCalculator, new HtmlReportGenerator());
//   }
// 
//   public JUnitPerfAsyncRule(StatisticsCalculator statisticsCalculator, ReportGenerator... reportGenerator) {
//     super(statisticsCalculator, reportGenerator);
//   }
// 
//   public TestContext newContext() {
//     return hasMeasurementPeriodStarted() ? new TestContext(statisticsCalculator) : NoOpTestContext.INSTANCE;
//   }
// 
//   @Override
//   public Statement apply(Statement base, Description description) {
//     setMeasurementsStartTime(description.getAnnotation(JUnitPerfTest.class));
//     return super.apply(base, description);
//   }
// 
//   @Override
//   EvaluationContext createEvaluationContext(Description description) {
//     return new EvaluationContext(description.getMethodName(), nanoTime(), true);
//   }
// 
//   private void setMeasurementsStartTime(JUnitPerfTest perfTestAnnotation) {
//     if (nonNull(perfTestAnnotation)) {
//       measurementsStartTimeMs = currentTimeMillis() + perfTestAnnotation.warmUpMs();
//     }
//   }
// 
//   private boolean hasMeasurementPeriodStarted() {
//     return currentTimeMillis() >= measurementsStartTimeMs;
//   }
// 
// }
// 
// Path: junitperf-core/src/main/java/com/github/noconnor/junitperf/data/TestContext.java
// public class TestContext {
// 
//   private final StatisticsCalculator stats;
//   private final long startTimeNs;
// 
//   public TestContext(StatisticsCalculator stats) {
//     this.stats = stats;
//     this.startTimeNs = nanoTime();
//   }
// 
//   public void success() {
//     stats.incrementEvaluationCount();
//     stats.addLatencyMeasurement(nanoTime() - startTimeNs);
//   }
// 
//   public void fail() {
//     stats.incrementEvaluationCount();
//     stats.incrementErrorCount();
//     stats.addLatencyMeasurement(nanoTime() - startTimeNs);
//   }
// }
// 
// Path: junit4-examples/src/test/java/com/github/noconnor/junitperf/examples/utils/ReportingUtils.java
// public static HtmlReportGenerator newHtmlReporter(String fileName){
//   return new HtmlReportGenerator(getProperty("user.dir") + "/build/reports/" + fileName);
// }


// Path: junit4-examples/src/test/java/com/github/noconnor/junitperf/examples/ExampleAsyncTests.java
import com.github.noconnor.junitperf.JUnitPerfAsyncRule;
import com.github.noconnor.junitperf.JUnitPerfTest;
import com.github.noconnor.junitperf.data.TestContext;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import static com.github.noconnor.junitperf.examples.utils.ReportingUtils.newHtmlReporter;

package com.github.noconnor.junitperf.examples;




public class ExampleAsyncTests {

  @Rule
  public JUnitPerfAsyncRule rule = new JUnitPerfAsyncRule(newHtmlReporter("async_test.html"));

  private static ExecutorService pool;

  @BeforeClass
  public static void setup() {
    pool = Executors.newFixedThreadPool(100);
  }

  @AfterClass
  public static void teardown() {
    pool.shutdownNow();
  }

  @Test
  @JUnitPerfTest(durationMs = 10_000, warmUpMs = 1_000, maxExecutionsPerSecond = 100)
  public void whenTestExecutesAsynchronously_thenMeasurementsCanStillBeCaptured() {
    TestContext context = rule.newContext();