private int runTests()

in src/com/facebook/buck/cli/TestCommand.java [386:523]


  private int runTests(
      Iterable<TestRule> tests,
      BuildContext buildContext,
      ExecutionContext executionContext,
      StepRunner stepRunner,
      final TestCommandOptions options) throws IOException {
    ImmutableSet<JavaLibraryRule> rulesUnderTest;
    // If needed, we first run instrumentation on the class files.
    if (options.isCodeCoverageEnabled()) {
      rulesUnderTest = getRulesUnderTest(tests);
      if (!rulesUnderTest.isEmpty()) {
        try {
          stepRunner.runStep(
              new MakeCleanDirectoryStep(JUnitStep.EMMA_OUTPUT_DIR));
          stepRunner.runStep(
              getInstrumentCommand(
                  rulesUnderTest,
                  executionContext.getProjectFilesystem()));
        } catch (StepFailedException e) {
          console.printBuildFailureWithoutStacktrace(e);
          return 1;
        }
      }
    } else {
      rulesUnderTest = ImmutableSet.of();
    }

    getBuckEventBus().post(TestRunEvent.started(
        options.isRunAllTests(), options.getArgumentsFormattedAsBuildTargets()));

    // Start running all of the tests. The result of each java_test() rule is represented as a
    // ListenableFuture.
    List<ListenableFuture<TestResults>> results = Lists.newArrayList();

    // Unless `--verbose 0` is specified, print out test results as they become available.
    // Failures with the ListenableFuture should always be printed, as they indicate an error with
    // Buck, not the test being run.
    Verbosity verbosity = console.getVerbosity();
    final boolean printTestResults = (verbosity != Verbosity.SILENT);
    FutureCallback<TestResults> onTestFinishedCallback = new FutureCallback<TestResults>() {

      @Override
      public void onSuccess(TestResults testResults) {
        if (printTestResults) {
          getBuckEventBus().post(IndividualTestEvent.finished(
              options.getArgumentsFormattedAsBuildTargets(), testResults));
        }
      }

      @Override
      public void onFailure(Throwable throwable) {
        // This should never happen, but if it does, that means that something has gone awry, so
        // we should bubble it up.
        throwable.printStackTrace(getStdErr());
      }
    };

    TestRuleKeyFileHelper testRuleKeyFileHelper = new TestRuleKeyFileHelper(
        executionContext.getProjectFilesystem());
    for (TestRule test : tests) {
      List<Step> steps;

      // Determine whether the test needs to be executed.
      boolean isTestRunRequired =
          isTestRunRequiredForTest(test, executionContext, testRuleKeyFileHelper);
      if (isTestRunRequired) {
        getBuckEventBus().post(IndividualTestEvent.started(
            options.getArgumentsFormattedAsBuildTargets()));
        ImmutableList.Builder<Step> stepsBuilder = ImmutableList.builder();
        List<Step> testSteps = test.runTests(buildContext, executionContext);
        if (!testSteps.isEmpty()) {
          stepsBuilder.addAll(testSteps);
          stepsBuilder.add(testRuleKeyFileHelper.createRuleKeyInDirStep(test));
        }
        steps = stepsBuilder.build();
      } else {
        steps = ImmutableList.of();
      }

      // Always run the commands, even if the list of commands as empty. There may be zero commands
      // because the rule is cached, but its results must still be processed.
      ListenableFuture<TestResults> testResults =
          stepRunner.runStepsAndYieldResult(steps,
              getCachingStatusTransformingCallable(
                  isTestRunRequired,
                  test.interpretTestResults(executionContext)),
              test.getBuildTarget());
      Futures.addCallback(testResults, onTestFinishedCallback);
      results.add(testResults);
    }

    // Block until all the tests have finished running.
    ListenableFuture<List<TestResults>> uberFuture = Futures.allAsList(results);
    List<TestResults> completedResults;
    try {
      completedResults = uberFuture.get();
    } catch (InterruptedException e) {
      e.printStackTrace(getStdErr());
      return 1;
    } catch (ExecutionException e) {
      e.printStackTrace(getStdErr());
      return 1;
    }

    getBuckEventBus().post(TestRunEvent.finished(
        options.getArgumentsFormattedAsBuildTargets(), completedResults));

    // Write out the results as XML, if requested.
    if (options.getPathToXmlTestOutput() != null) {
      try (Writer writer = Files.newWriter(
        new File(options.getPathToXmlTestOutput()),
        Charsets.UTF_8)) {
        writeXmlOutput(completedResults, writer);
      }
    }

    // Generate the code coverage report.
    if (options.isCodeCoverageEnabled() && !rulesUnderTest.isEmpty()) {
      try {
        Optional<DefaultJavaPackageFinder> defaultJavaPackageFinderOptional =
            options.getJavaPackageFinder();
        stepRunner.runStep(
            getReportCommand(rulesUnderTest, defaultJavaPackageFinderOptional, getProjectFilesystem()));
      } catch (StepFailedException e) {
        console.printBuildFailureWithoutStacktrace(e);
        return 1;
      }
    }

    boolean failures = Iterables.any(completedResults, new Predicate<TestResults>() {
      @Override
      public boolean apply(TestResults results) {
        return !results.isSuccess();
      }
    });

    return failures ? 1 : 0;
  }