/** * Helper for differential analysis which aggregates the TestSummary for an individual target, * reporting runs on the EventBus if necessary. */ private TestSummary.Builder aggregateAndReportSummary( ConfiguredTarget testTarget, AggregatingTestListener listener) { // If already reported by the listener, no work remains for this target. TestSummary.Builder summary = listener.getCurrentSummary(testTarget); Label testLabel = testTarget.getLabel(); Preconditions.checkNotNull( summary, "%s did not complete test filtering, but has a test result", testLabel); if (listener.targetReported(testTarget)) { return summary; } Collection<Artifact> incompleteRuns = listener.getIncompleteRuns(testTarget); Map<Artifact, TestResult> statusMap = listener.getStatusMap(); // We will get back multiple TestResult instances if test had to be retried several // times before passing. Sharding and multiple runs of the same test without retries // will be represented by separate artifacts and will produce exactly one TestResult. for (Artifact testStatus : TestProvider.getTestStatusArtifacts(testTarget)) { // When a build is interrupted ( eg. a broken target with --nokeep_going ) runResult could // be null for an unrelated test because we were not able to even try to execute the test. // In that case, for tests that were previously passing we return null ( == NO STATUS), // because checking if the cached test target is up-to-date would require running the // dependency checker transitively. TestResult runResult = statusMap.get(testStatus); boolean isIncompleteRun = incompleteRuns.contains(testStatus); if (runResult == null) { summary = markIncomplete(summary); } else if (isIncompleteRun) { // Only process results which were not recorded by the listener. boolean newlyFetched = !statusMap.containsKey(testStatus); summary = incrementalAnalyze(summary, runResult); if (newlyFetched) { eventBus.post(runResult); } Preconditions.checkState( listener.getIncompleteRuns(testTarget).contains(testStatus) == isIncompleteRun, "TestListener changed in differential analysis. Ensure it isn't still registered."); } } // The target was not posted by the listener and must be posted now. eventBus.post(summary.build()); return summary; }