use of com.google.devtools.build.lib.actions.util.TestAction in project bazel by bazelbuild.
the class ParallelBuilderTest method assertNoNewJobsAreRunAfterFirstFailure.
// Regression test for bug #735765, "ParallelBuilder still issues new jobs
// after one has failed, without --keep-going." The incorrect behaviour is
// that, when the first job fails, while no new jobs are added to the queue
// of runnable jobs, the queue may have lots of work in it, and the
// ParallelBuilder always completes these jobs before it returns. The
// correct behaviour is to discard all the jobs in the queue after the first
// one fails.
public void assertNoNewJobsAreRunAfterFirstFailure(final boolean catastrophe, boolean keepGoing) throws Exception {
// Strategy: Limit parallelism to 3. Enqueue 10 runnable tasks that run
// for an appreciable period (say 100ms). Ensure that at most 3 of those
// tasks completed. This proves that all runnable tasks were dropped from
// the queue after the first batch (which included errors) was finished.
// It should be pretty robust even in the face of timing variations.
final AtomicInteger completedTasks = new AtomicInteger(0);
int numJobs = 50;
Artifact[] artifacts = new Artifact[numJobs];
for (int ii = 0; ii < numJobs; ++ii) {
Artifact out = createDerivedArtifact(ii + ".out");
List<Artifact> inputs = (catastrophe && ii > 10) ? ImmutableList.of(artifacts[0]) : Artifact.NO_ARTIFACTS;
final int iCopy = ii;
registerAction(new TestAction(new Callable<Void>() {
@Override
public Void call() throws Exception {
// 100ms
Thread.sleep(100);
completedTasks.getAndIncrement();
throw new IOException("task failed");
}
}, inputs, ImmutableList.of(out)) {
@Override
public void execute(ActionExecutionContext actionExecutionContext) throws ActionExecutionException {
if (catastrophe && iCopy == 0) {
try {
// 300ms
Thread.sleep(300);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
completedTasks.getAndIncrement();
throw new ActionExecutionException("This is a catastrophe", this, true);
}
super.execute(actionExecutionContext);
}
});
artifacts[ii] = out;
}
// Don't fail fast when we encounter the error
reporter.removeHandler(failFastHandler);
try {
buildArtifacts(createBuilder(3, keepGoing), artifacts);
fail();
} catch (BuildFailedException e) {
assertContainsEvent("task failed");
}
if (completedTasks.get() >= numJobs) {
fail("Expected early termination due to failed task, but all tasks ran to completion.");
}
}
use of com.google.devtools.build.lib.actions.util.TestAction in project bazel by bazelbuild.
the class ParallelBuilderTest method testCycleInActionGraphBelowTwoActions.
@Test
public void testCycleInActionGraphBelowTwoActions() throws Exception {
// bar -> [action] -> foo1
// bar -> [action] -> foo2
// baz -> [action] -> bar
// bar -> [action] -> baz
Artifact foo1 = createDerivedArtifact("foo1");
Artifact foo2 = createDerivedArtifact("foo2");
Artifact bar = createDerivedArtifact("bar");
Artifact baz = createDerivedArtifact("baz");
try {
registerAction(new TestAction(TestAction.NO_EFFECT, asSet(bar), asSet(foo1)));
registerAction(new TestAction(TestAction.NO_EFFECT, asSet(bar), asSet(foo2)));
registerAction(new TestAction(TestAction.NO_EFFECT, asSet(baz), asSet(bar)));
registerAction(new TestAction(TestAction.NO_EFFECT, asSet(bar), asSet(baz)));
buildArtifacts(foo1, foo2);
fail("Builder failed to detect cyclic action graph");
} catch (BuildFailedException e) {
assertEquals(e.getMessage(), CYCLE_MSG);
}
}
use of com.google.devtools.build.lib.actions.util.TestAction in project bazel by bazelbuild.
the class FilesystemValueCheckerTest method checkDirtyTreeArtifactActions.
public void checkDirtyTreeArtifactActions(BatchStat batchStatter) throws Exception {
// Normally, an Action specifies the contents of a TreeArtifact when it executes.
// To decouple FileSystemValueTester checking from Action execution, we inject TreeArtifact
// contents into ActionExecutionValues.
Artifact out1 = createTreeArtifact("one");
TreeFileArtifact file11 = treeFileArtifact(out1, "fizz");
FileSystemUtils.createDirectoryAndParents(out1.getPath());
FileSystemUtils.writeContentAsLatin1(file11.getPath(), "buzz");
Artifact out2 = createTreeArtifact("two");
FileSystemUtils.createDirectoryAndParents(out2.getPath().getChild("subdir"));
TreeFileArtifact file21 = treeFileArtifact(out2, "moony");
TreeFileArtifact file22 = treeFileArtifact(out2, "subdir/wormtail");
FileSystemUtils.writeContentAsLatin1(file21.getPath(), "padfoot");
FileSystemUtils.writeContentAsLatin1(file22.getPath(), "prongs");
Artifact outEmpty = createTreeArtifact("empty");
FileSystemUtils.createDirectoryAndParents(outEmpty.getPath());
Artifact outUnchanging = createTreeArtifact("untouched");
FileSystemUtils.createDirectoryAndParents(outUnchanging.getPath());
Artifact last = createTreeArtifact("zzzzzzzzzz");
FileSystemUtils.createDirectoryAndParents(last.getPath());
Action action1 = new TestAction(Runnables.doNothing(), ImmutableSet.<Artifact>of(), ImmutableSet.of(out1));
Action action2 = new TestAction(Runnables.doNothing(), ImmutableSet.<Artifact>of(), ImmutableSet.of(out2));
Action actionEmpty = new TestAction(Runnables.doNothing(), ImmutableSet.<Artifact>of(), ImmutableSet.of(outEmpty));
Action actionUnchanging = new TestAction(Runnables.doNothing(), ImmutableSet.<Artifact>of(), ImmutableSet.of(outUnchanging));
Action lastAction = new TestAction(Runnables.doNothing(), ImmutableSet.<Artifact>of(), ImmutableSet.of(last));
differencer.inject(ImmutableMap.<SkyKey, SkyValue>of(ActionExecutionValue.key(action1), actionValueWithTreeArtifacts(ImmutableList.of(file11)), ActionExecutionValue.key(action2), actionValueWithTreeArtifacts(ImmutableList.of(file21, file22)), ActionExecutionValue.key(actionEmpty), actionValueWithEmptyDirectory(outEmpty), ActionExecutionValue.key(actionUnchanging), actionValueWithEmptyDirectory(outUnchanging), ActionExecutionValue.key(lastAction), actionValueWithEmptyDirectory(last)));
assertFalse(driver.evaluate(ImmutableList.<SkyKey>of(), false, 1, NullEventHandler.INSTANCE).hasError());
assertThat(new FilesystemValueChecker(null, null).getDirtyActionValues(evaluator.getValues(), batchStatter, ModifiedFileSet.EVERYTHING_MODIFIED)).isEmpty();
// Touching the TreeArtifact directory should have no effect
FileSystemUtils.touchFile(out1.getPath());
assertThat(new FilesystemValueChecker(null, null).getDirtyActionValues(evaluator.getValues(), batchStatter, ModifiedFileSet.EVERYTHING_MODIFIED)).isEmpty();
// Neither should touching a subdirectory.
FileSystemUtils.touchFile(out2.getPath().getChild("subdir"));
assertThat(new FilesystemValueChecker(null, null).getDirtyActionValues(evaluator.getValues(), batchStatter, ModifiedFileSet.EVERYTHING_MODIFIED)).isEmpty();
/* **** Tests for directories **** */
// Removing a directory (even if empty) should have an effect
outEmpty.getPath().delete();
assertThat(new FilesystemValueChecker(null, null).getDirtyActionValues(evaluator.getValues(), batchStatter, new ModifiedFileSet.Builder().modify(outEmpty.getExecPath()).build())).containsExactly(ActionExecutionValue.key(actionEmpty));
// Symbolic links should count as dirty
Path dummyEmptyDir = fs.getPath("/bin").getRelative("symlink");
FileSystemUtils.createDirectoryAndParents(dummyEmptyDir);
FileSystemUtils.ensureSymbolicLink(outEmpty.getPath(), dummyEmptyDir);
assertThat(new FilesystemValueChecker(null, null).getDirtyActionValues(evaluator.getValues(), batchStatter, new ModifiedFileSet.Builder().modify(outEmpty.getExecPath()).build())).containsExactly(ActionExecutionValue.key(actionEmpty));
// We're done fiddling with this... restore the original state
outEmpty.getPath().delete();
FileSystemUtils.deleteTree(dummyEmptyDir);
FileSystemUtils.createDirectoryAndParents(outEmpty.getPath());
/* **** Tests for files and directory contents ****/
// Test that file contents matter. This is covered by existing tests already,
// so it's just a sanity check.
FileSystemUtils.writeContentAsLatin1(file11.getPath(), "goodbye");
assertThat(new FilesystemValueChecker(null, null).getDirtyActionValues(evaluator.getValues(), batchStatter, new ModifiedFileSet.Builder().modify(file11.getExecPath()).build())).containsExactly(ActionExecutionValue.key(action1));
// Test that directory contents (and nested contents) matter
Artifact out1new = treeFileArtifact(out1, "julius/caesar");
FileSystemUtils.createDirectoryAndParents(out1.getPath().getChild("julius"));
FileSystemUtils.writeContentAsLatin1(out1new.getPath(), "octavian");
// even for empty directories
Artifact outEmptyNew = treeFileArtifact(outEmpty, "marcus");
FileSystemUtils.writeContentAsLatin1(outEmptyNew.getPath(), "aurelius");
// so does removing
file21.getPath().delete();
// now, let's test our changes are actually visible
assertThat(new FilesystemValueChecker(null, null).getDirtyActionValues(evaluator.getValues(), batchStatter, ModifiedFileSet.EVERYTHING_MODIFIED)).containsExactly(ActionExecutionValue.key(action1), ActionExecutionValue.key(action2), ActionExecutionValue.key(actionEmpty));
assertThat(new FilesystemValueChecker(null, null).getDirtyActionValues(evaluator.getValues(), batchStatter, new ModifiedFileSet.Builder().modify(file21.getExecPath()).modify(out1new.getExecPath()).modify(outEmptyNew.getExecPath()).build())).containsExactly(ActionExecutionValue.key(action1), ActionExecutionValue.key(action2), ActionExecutionValue.key(actionEmpty));
// We also check that if the modified file set does not contain our modified files on disk,
// we are not going to check and return them.
assertThat(new FilesystemValueChecker(null, null).getDirtyActionValues(evaluator.getValues(), batchStatter, new ModifiedFileSet.Builder().modify(file21.getExecPath()).modify(outEmptyNew.getExecPath()).build())).containsExactly(ActionExecutionValue.key(action2), ActionExecutionValue.key(actionEmpty));
assertThat(new FilesystemValueChecker(null, null).getDirtyActionValues(evaluator.getValues(), batchStatter, new ModifiedFileSet.Builder().modify(file21.getExecPath()).modify(out1new.getExecPath()).build())).containsExactly(ActionExecutionValue.key(action1), ActionExecutionValue.key(action2));
// Check modifying the last (lexicographically) tree artifact.
last.getPath().delete();
assertThat(new FilesystemValueChecker(null, null).getDirtyActionValues(evaluator.getValues(), batchStatter, new ModifiedFileSet.Builder().modify(file21.getExecPath()).modify(out1new.getExecPath()).modify(last.getExecPath()).build())).containsExactly(ActionExecutionValue.key(action1), ActionExecutionValue.key(action2), ActionExecutionValue.key(lastAction));
// Check ModifiedFileSet without the last (lexicographically) tree artifact.
assertThat(new FilesystemValueChecker(null, null).getDirtyActionValues(evaluator.getValues(), batchStatter, new ModifiedFileSet.Builder().modify(file21.getExecPath()).modify(out1new.getExecPath()).build())).containsExactly(ActionExecutionValue.key(action1), ActionExecutionValue.key(action2));
// Restore
last.getPath().delete();
FileSystemUtils.createDirectoryAndParents(last.getPath());
// We add a test for NOTHING_MODIFIED, because FileSystemValueChecker doesn't
// pay attention to file sets for TreeArtifact directory listings.
assertThat(new FilesystemValueChecker(null, null).getDirtyActionValues(evaluator.getValues(), batchStatter, ModifiedFileSet.NOTHING_MODIFIED)).isEmpty();
}
use of com.google.devtools.build.lib.actions.util.TestAction in project bazel by bazelbuild.
the class MapBasedActionGraphTest method testSmoke.
@Test
public void testSmoke() throws Exception {
MutableActionGraph actionGraph = new MapBasedActionGraph();
FileSystem fileSystem = new InMemoryFileSystem(BlazeClock.instance());
Path path = fileSystem.getPath("/root/foo");
Artifact output = new Artifact(path, Root.asDerivedRoot(path));
Action action = new TestAction(TestAction.NO_EFFECT, ImmutableSet.<Artifact>of(), ImmutableSet.of(output));
actionGraph.registerAction(action);
actionGraph.unregisterAction(action);
path = fileSystem.getPath("/root/bar");
output = new Artifact(path, Root.asDerivedRoot(path));
Action action2 = new TestAction(TestAction.NO_EFFECT, ImmutableSet.<Artifact>of(), ImmutableSet.of(output));
actionGraph.registerAction(action);
actionGraph.registerAction(action2);
actionGraph.unregisterAction(action);
}
use of com.google.devtools.build.lib.actions.util.TestAction in project bazel by bazelbuild.
the class MapBasedActionGraphTest method testNoActionConflictWhenUnregisteringSharedAction.
@Test
public void testNoActionConflictWhenUnregisteringSharedAction() throws Exception {
MutableActionGraph actionGraph = new MapBasedActionGraph();
FileSystem fileSystem = new InMemoryFileSystem(BlazeClock.instance());
Path path = fileSystem.getPath("/root/foo");
Artifact output = new Artifact(path, Root.asDerivedRoot(path));
Action action = new TestAction(TestAction.NO_EFFECT, ImmutableSet.<Artifact>of(), ImmutableSet.of(output));
actionGraph.registerAction(action);
Action otherAction = new TestAction(TestAction.NO_EFFECT, ImmutableSet.<Artifact>of(), ImmutableSet.of(output));
actionGraph.registerAction(otherAction);
actionGraph.unregisterAction(action);
}
Aggregations