Search in sources :

Example 16 with TestAction

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.");
    }
}
Also used : IOException(java.io.IOException) Artifact(com.google.devtools.build.lib.actions.Artifact) Callable(java.util.concurrent.Callable) TestAction(com.google.devtools.build.lib.actions.util.TestAction) BuildFailedException(com.google.devtools.build.lib.actions.BuildFailedException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ActionExecutionContext(com.google.devtools.build.lib.actions.ActionExecutionContext) ActionExecutionException(com.google.devtools.build.lib.actions.ActionExecutionException)

Example 17 with TestAction

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);
    }
}
Also used : BuildFailedException(com.google.devtools.build.lib.actions.BuildFailedException) Artifact(com.google.devtools.build.lib.actions.Artifact) TestAction(com.google.devtools.build.lib.actions.util.TestAction) Test(org.junit.Test)

Example 18 with TestAction

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();
}
Also used : TreeFileArtifact(com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact) RootedPath(com.google.devtools.build.lib.vfs.RootedPath) Path(com.google.devtools.build.lib.vfs.Path) Action(com.google.devtools.build.lib.actions.Action) TestAction(com.google.devtools.build.lib.actions.util.TestAction) ExternalFileAction(com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction) ModifiedFileSet(com.google.devtools.build.lib.vfs.ModifiedFileSet) SpecialArtifact(com.google.devtools.build.lib.actions.Artifact.SpecialArtifact) Artifact(com.google.devtools.build.lib.actions.Artifact) ActionInputHelper.treeFileArtifact(com.google.devtools.build.lib.actions.ActionInputHelper.treeFileArtifact) TreeFileArtifact(com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact) TestAction(com.google.devtools.build.lib.actions.util.TestAction)

Example 19 with TestAction

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);
}
Also used : Path(com.google.devtools.build.lib.vfs.Path) TestAction(com.google.devtools.build.lib.actions.util.TestAction) InMemoryFileSystem(com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem) FileSystem(com.google.devtools.build.lib.vfs.FileSystem) InMemoryFileSystem(com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem) TestAction(com.google.devtools.build.lib.actions.util.TestAction) Test(org.junit.Test)

Example 20 with TestAction

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);
}
Also used : Path(com.google.devtools.build.lib.vfs.Path) TestAction(com.google.devtools.build.lib.actions.util.TestAction) InMemoryFileSystem(com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem) FileSystem(com.google.devtools.build.lib.vfs.FileSystem) InMemoryFileSystem(com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem) TestAction(com.google.devtools.build.lib.actions.util.TestAction) Test(org.junit.Test)

Aggregations

TestAction (com.google.devtools.build.lib.actions.util.TestAction)20 Artifact (com.google.devtools.build.lib.actions.Artifact)16 Test (org.junit.Test)14 BuildFailedException (com.google.devtools.build.lib.actions.BuildFailedException)10 IOException (java.io.IOException)5 Action (com.google.devtools.build.lib.actions.Action)4 Path (com.google.devtools.build.lib.vfs.Path)4 ActionInputHelper.treeFileArtifact (com.google.devtools.build.lib.actions.ActionInputHelper.treeFileArtifact)3 SpecialArtifact (com.google.devtools.build.lib.actions.Artifact.SpecialArtifact)3 TreeFileArtifact (com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact)3 FileSystem (com.google.devtools.build.lib.vfs.FileSystem)3 InMemoryFileSystem (com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem)3 Callable (java.util.concurrent.Callable)3 ActionExecutionContext (com.google.devtools.build.lib.actions.ActionExecutionContext)2 ActionExecutionException (com.google.devtools.build.lib.actions.ActionExecutionException)2 ExternalFileAction (com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction)2 ModifiedFileSet (com.google.devtools.build.lib.vfs.ModifiedFileSet)2 EventBus (com.google.common.eventbus.EventBus)1 ActionExecutedEvent (com.google.devtools.build.lib.actions.ActionExecutedEvent)1 ActionInputFileCache (com.google.devtools.build.lib.actions.ActionInputFileCache)1