use of com.facebook.buck.rules.BuildResult in project buck by facebook.
the class TestRunning method isTestRunRequiredForTest.
@VisibleForTesting
static boolean isTestRunRequiredForTest(TestRule test, BuildEngine cachingBuildEngine, ExecutionContext executionContext, TestRuleKeyFileHelper testRuleKeyFileHelper, TestRunningOptions.TestResultCacheMode resultCacheMode, Callable<TestResults> testResultInterpreter, boolean isRunningWithTestSelectors, boolean hasEnvironmentOverrides) throws IOException, ExecutionException, InterruptedException {
boolean isTestRunRequired;
BuildResult result;
if (executionContext.isDebugEnabled()) {
// If debug is enabled, then we should always run the tests as the user is expecting to
// hook up a debugger.
isTestRunRequired = true;
} else if (isRunningWithTestSelectors) {
// As a feature to aid developers, we'll assume that when we are using test selectors,
// we should always run each test (and never look at the cache.)
// TODO(edwardspeyer) When #3090004 and #3436849 are closed we can respect the cache again.
isTestRunRequired = true;
} else if (hasEnvironmentOverrides) {
// This is rather obtuse, ideally the environment overrides can be hashed and compared...
isTestRunRequired = true;
} else if (((result = cachingBuildEngine.getBuildRuleResult(test.getBuildTarget())) != null) && result.getSuccess() == BuildRuleSuccessType.MATCHING_RULE_KEY && test.hasTestResultFiles() && testRuleKeyFileHelper.isRuleKeyInDir(test) && (resultCacheMode == TestRunningOptions.TestResultCacheMode.ENABLED || (resultCacheMode == TestRunningOptions.TestResultCacheMode.ENABLED_IF_PASSED && areTestsSuccessful(testResultInterpreter)))) {
// If this build rule's artifacts (which includes the rule's output and its test result
// files) are up to date, then no commands are necessary to run the tests. The test result
// files will be read from the XML files in interpretTestResults().
isTestRunRequired = false;
} else {
isTestRunRequired = true;
}
return isTestRunRequired;
}
use of com.facebook.buck.rules.BuildResult in project buck by facebook.
the class Build method executeBuild.
/**
* If {@code isKeepGoing} is false, then this returns a future that succeeds only if all of
* {@code rulesToBuild} build successfully. Otherwise, this returns a future that should always
* succeed, even if individual rules fail to build. In that case, a failed build rule is indicated
* by a {@code null} value in the corresponding position in the iteration order of
* {@code rulesToBuild}.
* @param targetish The targets to build. All targets in this iterable must be unique.
*/
@SuppressWarnings("PMD.EmptyCatchBlock")
public BuildExecutionResult executeBuild(Iterable<? extends BuildTarget> targetish, boolean isKeepGoing) throws IOException, ExecutionException, InterruptedException {
BuildId buildId = executionContext.getBuildId();
BuildEngineBuildContext buildContext = BuildEngineBuildContext.builder().setBuildContext(BuildContext.builder().setActionGraph(actionGraph).setSourcePathResolver(new SourcePathResolver(new SourcePathRuleFinder(ruleResolver))).setJavaPackageFinder(javaPackageFinder).setEventBus(executionContext.getBuckEventBus()).setAndroidPlatformTargetSupplier(executionContext.getAndroidPlatformTargetSupplier()).build()).setClock(clock).setArtifactCache(artifactCache).setBuildId(buildId).setObjectMapper(objectMapper).putAllEnvironment(executionContext.getEnvironment()).setKeepGoing(isKeepGoing).build();
// It is important to use this logic to determine the set of rules to build rather than
// build.getActionGraph().getNodesWithNoIncomingEdges() because, due to graph enhancement,
// there could be disconnected subgraphs in the DependencyGraph that we do not want to build.
ImmutableSet<BuildTarget> targetsToBuild = StreamSupport.stream(targetish.spliterator(), false).collect(MoreCollectors.toImmutableSet());
// It is important to use this logic to determine the set of rules to build rather than
// build.getActionGraph().getNodesWithNoIncomingEdges() because, due to graph enhancement,
// there could be disconnected subgraphs in the DependencyGraph that we do not want to build.
ImmutableList<BuildRule> rulesToBuild = ImmutableList.copyOf(targetsToBuild.stream().map(buildTarget -> {
try {
return getRuleResolver().requireRule(buildTarget);
} catch (NoSuchBuildTargetException e) {
throw new HumanReadableException("No build rule found for target %s", buildTarget);
}
}).collect(MoreCollectors.toImmutableSet()));
// Calculate and post the number of rules that need to built.
int numRules = buildEngine.getNumRulesToBuild(rulesToBuild);
getExecutionContext().getBuckEventBus().post(BuildEvent.ruleCountCalculated(targetsToBuild, numRules));
// Setup symlinks required when configuring the output path.
createConfiguredBuckOutSymlinks();
List<ListenableFuture<BuildResult>> futures = rulesToBuild.stream().map(rule -> buildEngine.build(buildContext, executionContext, rule)).collect(MoreCollectors.toImmutableList());
// Get the Future representing the build and then block until everything is built.
ListenableFuture<List<BuildResult>> buildFuture = Futures.allAsList(futures);
List<BuildResult> results;
try {
results = buildFuture.get();
if (!isKeepGoing) {
for (BuildResult result : results) {
Throwable thrown = result.getFailure();
if (thrown != null) {
throw new ExecutionException(thrown);
}
}
}
} catch (ExecutionException | InterruptedException | RuntimeException e) {
Throwable t = Throwables.getRootCause(e);
if (e instanceof InterruptedException || t instanceof InterruptedException || t instanceof ClosedByInterruptException) {
try {
buildFuture.cancel(true);
} catch (CancellationException ignored) {
// Rethrow original InterruptedException instead.
}
Thread.currentThread().interrupt();
}
throw e;
}
// Insertion order matters
LinkedHashMap<BuildRule, Optional<BuildResult>> resultBuilder = new LinkedHashMap<>();
Preconditions.checkState(rulesToBuild.size() == results.size());
for (int i = 0, len = rulesToBuild.size(); i < len; i++) {
BuildRule rule = rulesToBuild.get(i);
resultBuilder.put(rule, Optional.ofNullable(results.get(i)));
}
return BuildExecutionResult.builder().setFailures(FluentIterable.from(results).filter(input -> input.getSuccess() == null)).setResults(resultBuilder).build();
}
use of com.facebook.buck.rules.BuildResult in project buck by facebook.
the class BuildReport method generateForConsole.
public String generateForConsole(Console console) {
Ansi ansi = console.getAnsi();
Map<BuildRule, Optional<BuildResult>> ruleToResult = buildExecutionResult.getResults();
StringBuilder report = new StringBuilder();
for (Map.Entry<BuildRule, Optional<BuildResult>> entry : ruleToResult.entrySet()) {
BuildRule rule = entry.getKey();
Optional<BuildRuleSuccessType> success = Optional.empty();
Optional<BuildResult> result = entry.getValue();
if (result.isPresent()) {
success = Optional.ofNullable(result.get().getSuccess());
}
String successIndicator;
String successType;
SourcePath outputFile;
if (success.isPresent()) {
successIndicator = ansi.asHighlightedSuccessText("OK ");
successType = success.get().name();
outputFile = rule.getSourcePathToOutput();
} else {
successIndicator = ansi.asHighlightedFailureText("FAIL");
successType = null;
outputFile = null;
}
report.append(String.format("%s %s%s%s\n", successIndicator, rule.getBuildTarget(), successType != null ? " " + successType : "", outputFile != null ? " " + pathResolver.getRelativePath(outputFile) : ""));
}
if (!buildExecutionResult.getFailures().isEmpty() && console.getVerbosity().shouldPrintCommand()) {
report.append("\n ** Summary of failures encountered during the build **\n");
for (BuildResult failureResult : buildExecutionResult.getFailures()) {
Throwable failure = Preconditions.checkNotNull(failureResult.getFailure());
report.append(String.format("Rule %s FAILED because %s.\n", failureResult.getRule().getFullyQualifiedName(), failure.getMessage()));
}
}
return report.toString();
}
use of com.facebook.buck.rules.BuildResult in project buck by facebook.
the class TestRunningTest method whenSomeTestsAreSeparateThenSeparateTestsRunAtEnd.
@Test
public void whenSomeTestsAreSeparateThenSeparateTestsRunAtEnd() throws Exception {
CommandRunnerParams commandRunnerParams = CommandRunnerParamsForTesting.builder().build();
AtomicInteger atomicExecutionOrder = new AtomicInteger(0);
ExecutionOrderAwareFakeStep separateTestStep1 = new ExecutionOrderAwareFakeStep("teststep1", "teststep1", 0, atomicExecutionOrder);
final TestResults fakeTestResults = FakeTestResults.of(ImmutableList.of(new TestCaseSummary("TestCase", ImmutableList.of(new TestResultSummary("TestCaseResult", "passTest", ResultType.SUCCESS, 5000, null, null, null, null)))));
BuildTarget separateTest1Target = BuildTargetFactory.newInstance("//:test1");
FakeTestRule separateTest1 = new FakeTestRule(new FakeBuildRuleParamsBuilder(separateTest1Target).build(), new SourcePathResolver(new SourcePathRuleFinder(new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()))), ImmutableSet.of(), Optional.of(Paths.get("separateTestStep1OutputDir")), // runTestSeparately
true, ImmutableList.of(separateTestStep1), () -> fakeTestResults);
ExecutionOrderAwareFakeStep separateTestStep2 = new ExecutionOrderAwareFakeStep("teststep2", "teststep2", 0, atomicExecutionOrder);
BuildTarget separateTest2Target = BuildTargetFactory.newInstance("//:test2");
FakeTestRule separateTest2 = new FakeTestRule(new FakeBuildRuleParamsBuilder(separateTest2Target).build(), new SourcePathResolver(new SourcePathRuleFinder(new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()))), ImmutableSet.of(), Optional.of(Paths.get("separateTestStep2OutputDir")), // runTestSeparately
true, ImmutableList.of(separateTestStep2), () -> fakeTestResults);
ExecutionOrderAwareFakeStep separateTestStep3 = new ExecutionOrderAwareFakeStep("teststep3", "teststep3", 0, atomicExecutionOrder);
BuildTarget separateTest3Target = BuildTargetFactory.newInstance("//:test3");
FakeTestRule separateTest3 = new FakeTestRule(new FakeBuildRuleParamsBuilder(separateTest3Target).build(), new SourcePathResolver(new SourcePathRuleFinder(new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()))), ImmutableSet.of(), Optional.of(Paths.get("separateTestStep3OutputDir")), // runTestSeparately
true, ImmutableList.of(separateTestStep3), () -> fakeTestResults);
ExecutionOrderAwareFakeStep parallelTestStep1 = new ExecutionOrderAwareFakeStep("parallelteststep1", "parallelteststep1", 0, atomicExecutionOrder);
BuildTarget parallelTest1Target = BuildTargetFactory.newInstance("//:paralleltest1");
FakeTestRule parallelTest1 = new FakeTestRule(new FakeBuildRuleParamsBuilder(parallelTest1Target).build(), new SourcePathResolver(new SourcePathRuleFinder(new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()))), ImmutableSet.of(), Optional.of(Paths.get("parallelTestStep1OutputDir")), // runTestSeparately
false, ImmutableList.of(parallelTestStep1), () -> fakeTestResults);
ExecutionOrderAwareFakeStep parallelTestStep2 = new ExecutionOrderAwareFakeStep("parallelteststep2", "parallelteststep2", 0, atomicExecutionOrder);
BuildTarget parallelTest2Target = BuildTargetFactory.newInstance("//:paralleltest2");
FakeTestRule parallelTest2 = new FakeTestRule(new FakeBuildRuleParamsBuilder(parallelTest2Target).build(), new SourcePathResolver(new SourcePathRuleFinder(new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()))), ImmutableSet.of(), Optional.of(Paths.get("parallelTestStep2OutputDir")), // runTestSeparately
false, ImmutableList.of(parallelTestStep2), () -> fakeTestResults);
ExecutionOrderAwareFakeStep parallelTestStep3 = new ExecutionOrderAwareFakeStep("parallelteststep3", "parallelteststep3", 0, atomicExecutionOrder);
BuildTarget parallelTest3Target = BuildTargetFactory.newInstance("//:paralleltest3");
FakeTestRule parallelTest3 = new FakeTestRule(new FakeBuildRuleParamsBuilder(parallelTest3Target).build(), new SourcePathResolver(new SourcePathRuleFinder(new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()))), ImmutableSet.of(), Optional.of(Paths.get("parallelTestStep3OutputDir")), // runTestSeparately
false, ImmutableList.of(parallelTestStep3), () -> fakeTestResults);
// We explicitly use an actual thread pool here; the logic should ensure the
// separate tests are run in the correct order.
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(3));
FakeBuildEngine fakeBuildEngine = new FakeBuildEngine(ImmutableMap.<BuildTarget, BuildResult>builder().put(separateTest1Target, BuildResult.success(separateTest1, BUILT_LOCALLY, CacheResult.miss())).put(separateTest2Target, BuildResult.success(separateTest2, BUILT_LOCALLY, CacheResult.miss())).put(separateTest3Target, BuildResult.success(separateTest3, BUILT_LOCALLY, CacheResult.miss())).put(parallelTest1Target, BuildResult.success(parallelTest1, BUILT_LOCALLY, CacheResult.miss())).put(parallelTest2Target, BuildResult.success(parallelTest2, BUILT_LOCALLY, CacheResult.miss())).put(parallelTest3Target, BuildResult.success(parallelTest3, BUILT_LOCALLY, CacheResult.miss())).build(), ImmutableMap.<BuildTarget, RuleKey>builder().put(separateTest1Target, new RuleKey("00")).put(separateTest2Target, new RuleKey("00")).put(separateTest3Target, new RuleKey("00")).put(parallelTest1Target, new RuleKey("00")).put(parallelTest2Target, new RuleKey("00")).put(parallelTest3Target, new RuleKey("00")).build());
ExecutionContext fakeExecutionContext = TestExecutionContext.newInstance();
DefaultStepRunner stepRunner = new DefaultStepRunner();
SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
int ret = TestRunning.runTests(commandRunnerParams, ImmutableList.of(separateTest1, parallelTest1, separateTest2, parallelTest2, separateTest3, parallelTest3), fakeExecutionContext, DEFAULT_OPTIONS, service, fakeBuildEngine, stepRunner, new SourcePathResolver(ruleFinder), ruleFinder);
assertThat(ret, equalTo(0));
// The tests not marked as separate could run in any order -- but they must run
// before the separate test steps.
ImmutableSet<Optional<Integer>> expectedParallelStepExecutionOrderSet = ImmutableSet.<Optional<Integer>>builder().add(Optional.of(0)).add(Optional.of(1)).add(Optional.of(2)).add(Optional.of(3)).add(Optional.of(4)).add(Optional.of(5)).build();
ImmutableSet<Optional<Integer>> actualParallelStepExecutionOrderSet = ImmutableSet.<Optional<Integer>>builder().add(parallelTestStep1.getExecutionBeginOrder()).add(parallelTestStep1.getExecutionEndOrder()).add(parallelTestStep2.getExecutionBeginOrder()).add(parallelTestStep2.getExecutionEndOrder()).add(parallelTestStep3.getExecutionBeginOrder()).add(parallelTestStep3.getExecutionEndOrder()).build();
LOG.debug("Expected parallel execution order: %s Actual parallel execution order: %s", expectedParallelStepExecutionOrderSet, actualParallelStepExecutionOrderSet);
// We allow the parallel steps to begin and end in any order (note the thread
// pool of size 3 above), so we use a set.
assertThat(actualParallelStepExecutionOrderSet, equalTo(expectedParallelStepExecutionOrderSet));
// The separate test steps must begin and end in a specific order, so we use a list.
ImmutableList<Optional<Integer>> expectedSeparateStepExecutionOrderList = ImmutableList.<Optional<Integer>>builder().add(Optional.of(6)).add(Optional.of(7)).add(Optional.of(8)).add(Optional.of(9)).add(Optional.of(10)).add(Optional.of(11)).build();
ImmutableList<Optional<Integer>> actualSeparateStepExecutionOrderList = ImmutableList.<Optional<Integer>>builder().add(separateTestStep1.getExecutionBeginOrder()).add(separateTestStep1.getExecutionEndOrder()).add(separateTestStep2.getExecutionBeginOrder()).add(separateTestStep2.getExecutionEndOrder()).add(separateTestStep3.getExecutionBeginOrder()).add(separateTestStep3.getExecutionEndOrder()).build();
LOG.debug("Expected separate execution order: %s Actual separate execution order: %s", expectedSeparateStepExecutionOrderList, actualSeparateStepExecutionOrderList);
assertThat(actualSeparateStepExecutionOrderList, equalTo(expectedSeparateStepExecutionOrderList));
}
use of com.facebook.buck.rules.BuildResult in project buck by facebook.
the class TestRunningTest method testIsTestRunRequiredIfRuleKeyNotPresent.
@Test
public void testIsTestRunRequiredIfRuleKeyNotPresent() throws IOException, ExecutionException, InterruptedException {
ExecutionContext executionContext = TestExecutionContext.newInstance();
assertFalse(executionContext.isDebugEnabled());
FakeTestRule testRule = new FakeTestRule(ImmutableSet.of(Label.of("windows")), BuildTargetFactory.newInstance("//:lulz"), new SourcePathResolver(new SourcePathRuleFinder(new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()))), ImmutableSortedSet.of()) {
@Override
public boolean hasTestResultFiles() {
return true;
}
};
TestRuleKeyFileHelper testRuleKeyFileHelper = createNiceMock(TestRuleKeyFileHelper.class);
expect(testRuleKeyFileHelper.isRuleKeyInDir(testRule)).andReturn(false);
CachingBuildEngine cachingBuildEngine = createMock(CachingBuildEngine.class);
BuildResult result = BuildResult.success(testRule, MATCHING_RULE_KEY, CacheResult.miss());
expect(cachingBuildEngine.getBuildRuleResult(BuildTargetFactory.newInstance("//:lulz"))).andReturn(result);
replay(cachingBuildEngine, testRuleKeyFileHelper);
assertTrue("A cached build should run the tests if the test output directory\'s rule key is not " + "present or does not matche the rule key for the test.", TestRunning.isTestRunRequiredForTest(testRule, cachingBuildEngine, executionContext, testRuleKeyFileHelper, TestRunningOptions.TestResultCacheMode.ENABLED, Callables.<TestResults>returning(null), /* running with test selectors */
false, /* hasEnvironmentOverrides */
false));
verify(cachingBuildEngine, testRuleKeyFileHelper);
}
Aggregations