Search in sources :

Example 71 with StringValue

use of com.google.devtools.build.skyframe.GraphTester.StringValue in project bazel by bazelbuild.

the class MemoizingEvaluatorTest method warningAndErrorOnFailFastBuild.

@Test
public void warningAndErrorOnFailFastBuild() throws Exception {
    SkyKey topKey = GraphTester.toSkyKey("top");
    tester.set(topKey, new StringValue("top")).setWarning("warning msg").setHasError(true);
    for (int i = 0; i < 2; i++) {
        initializeReporter();
        EvaluationResult<StringValue> result = tester.eval(false, "top");
        assertTrue(result.hasError());
        if (rootCausesStored()) {
            assertThat(result.getError(topKey).getRootCauses()).containsExactly(topKey);
        }
        assertEquals(topKey.toString(), result.getError(topKey).getException().getMessage());
        assertTrue(result.getError(topKey).getException() instanceof SomeErrorException);
        if (i == 0 || eventsStored()) {
            assertContainsEvent(eventCollector, "warning msg");
            assertEventCount(1, eventCollector);
        }
    }
}
Also used : NotComparableStringValue(com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue) StringValue(com.google.devtools.build.skyframe.GraphTester.StringValue) Test(org.junit.Test)

Example 72 with StringValue

use of com.google.devtools.build.skyframe.GraphTester.StringValue in project bazel by bazelbuild.

the class MemoizingEvaluatorTest method dirtyAndChanged.

@Test
public void dirtyAndChanged() throws Exception {
    initializeTester();
    SkyKey leaf = GraphTester.toSkyKey("leaf");
    SkyKey mid = GraphTester.toSkyKey("mid");
    SkyKey top = GraphTester.toSkyKey("top");
    tester.getOrCreate(top).addDependency(mid).setComputedValue(COPY);
    tester.getOrCreate(mid).addDependency(leaf).setComputedValue(COPY);
    tester.set(leaf, new StringValue("leafy"));
    // For invalidation.
    tester.set("dummy", new StringValue("dummy"));
    StringValue topValue = (StringValue) tester.evalAndGet("top");
    assertEquals("leafy", topValue.getValue());
    tester.set(leaf, new StringValue("crunchy"));
    tester.invalidate();
    // For invalidation.
    tester.evalAndGet("dummy");
    tester.getOrCreate(mid, /*markAsModified=*/
    true);
    tester.invalidate();
    topValue = (StringValue) tester.evalAndGet("top");
    assertEquals("crunchy", topValue.getValue());
}
Also used : NotComparableStringValue(com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue) StringValue(com.google.devtools.build.skyframe.GraphTester.StringValue) Test(org.junit.Test)

Example 73 with StringValue

use of com.google.devtools.build.skyframe.GraphTester.StringValue in project bazel by bazelbuild.

the class MemoizingEvaluatorTest method incompleteDirectDepsAreClearedBeforeKeepGoing.

/**
   * Regression test: error on clearMaybeDirtyValue. Same as the previous test, but the second
   * evaluation is keepGoing, which should cause an access of the children of topKey.
   */
@Test
public void incompleteDirectDepsAreClearedBeforeKeepGoing() throws Exception {
    initializeTester();
    CountDownLatch slowStart = new CountDownLatch(1);
    CountDownLatch errorFinish = new CountDownLatch(1);
    SkyKey errorKey = GraphTester.toSkyKey("error");
    tester.getOrCreate(errorKey).setBuilder(new ChainedFunction(/*notifyStart=*/
    null, /*waitToFinish=*/
    slowStart, /*notifyFinish=*/
    errorFinish, /*waitForException=*/
    false, /*value=*/
    null, /*deps=*/
    ImmutableList.<SkyKey>of()));
    SkyKey slowKey = GraphTester.toSkyKey("slow");
    tester.getOrCreate(slowKey).setBuilder(new ChainedFunction(/*notifyStart=*/
    slowStart, /*waitToFinish=*/
    errorFinish, /*notifyFinish=*/
    null, /*waitForException=*/
    true, new StringValue("slow"), /*deps=*/
    ImmutableList.<SkyKey>of()));
    SkyKey midKey = GraphTester.toSkyKey("mid");
    tester.getOrCreate(midKey).addDependency(slowKey).setComputedValue(COPY);
    SkyKey topKey = GraphTester.toSkyKey("top");
    tester.getOrCreate(topKey).addDependency(midKey).addDependency(errorKey).setComputedValue(CONCATENATE);
    // slowKey starts -> errorKey finishes, written to graph -> slowKey finishes & (Visitor aborts)
    // -> topKey builds.
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/
    false, topKey);
    assertThat(result.getError().getRootCauses()).containsExactly(errorKey);
    // Make sure midKey didn't finish building.
    assertEquals(null, tester.getExistingValue(midKey));
    // Give slowKey a nice ordinary builder.
    tester.getOrCreate(slowKey, /*markAsModified=*/
    false).setBuilder(null).setConstantValue(new StringValue("slow"));
    // Put midKey into the graph. It won't have a reverse dependence on topKey.
    tester.evalAndGet(/*keepGoing=*/
    false, midKey);
    // topKey should not access midKey as if it were already registered as a dependency.
    // We don't invalidate errors, but because topKey wasn't actually written to the graph last
    // build, it should be rebuilt here.
    tester.eval(/*keepGoing=*/
    true, topKey);
}
Also used : CountDownLatch(java.util.concurrent.CountDownLatch) NotComparableStringValue(com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue) StringValue(com.google.devtools.build.skyframe.GraphTester.StringValue) Test(org.junit.Test)

Example 74 with StringValue

use of com.google.devtools.build.skyframe.GraphTester.StringValue in project bazel by bazelbuild.

the class MemoizingEvaluatorTest method dirtyChildEnqueuesParentDuringCheckDependencies.

/**
   * We are checking here that we are resilient to a race condition in which a value that is
   * checking its children for dirtiness is signaled by all of its children, putting it in a ready
   * state, before the thread has terminated. Optionally, one of its children may throw an error,
   * shutting down the threadpool. The essential race is that a child about to throw signals its
   * parent and the parent's builder restarts itself before the exception is thrown. Here, the
   * signaling happens while dirty dependencies are being checked. We control the timing by blocking
   * "top"'s registering itself on its deps.
   */
private void dirtyChildEnqueuesParentDuringCheckDependencies(final boolean throwError) throws Exception {
    // Value to be built. It will be signaled to rebuild before it has finished checking its deps.
    final SkyKey top = GraphTester.toSkyKey("top");
    // Dep that blocks before it acknowledges being added as a dep by top, so the firstKey value has
    // time to signal top. (Importantly its key is alphabetically after 'firstKey').
    final SkyKey slowAddingDep = GraphTester.toSkyKey("slowDep");
    // Don't perform any blocking on the first build.
    final AtomicBoolean delayTopSignaling = new AtomicBoolean(false);
    final CountDownLatch topSignaled = new CountDownLatch(1);
    final CountDownLatch topRestartedBuild = new CountDownLatch(1);
    injectGraphListenerForTesting(new Listener() {

        @Override
        public void accept(SkyKey key, EventType type, Order order, @Nullable Object context) {
            if (!delayTopSignaling.get()) {
                return;
            }
            if (key.equals(top) && type == EventType.SIGNAL && order == Order.AFTER) {
                // top is signaled by firstKey (since slowAddingDep is blocking), so slowAddingDep
                // is now free to acknowledge top as a parent.
                topSignaled.countDown();
                return;
            }
            if (key.equals(slowAddingDep) && type == EventType.ADD_REVERSE_DEP && top.equals(context) && order == Order.BEFORE) {
                // If top is trying to declare a dep on slowAddingDep, wait until firstKey has
                // signaled top. Then this add dep will return DONE and top will be signaled,
                // making it ready, so it will be enqueued.
                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(topSignaled, "first key didn't signal top in time");
            }
        }
    }, /*deterministic=*/
    true);
    // Value that is modified on the second build. Its thread won't finish until it signals top,
    // which will wait for the signal before it enqueues its next dep. We prevent the thread from
    // finishing by having the listener to which it reports its warning block until top's builder
    // starts.
    final SkyKey firstKey = GraphTester.skyKey("first");
    tester.set(firstKey, new StringValue("biding"));
    tester.set(slowAddingDep, new StringValue("dep"));
    final AtomicInteger numTopInvocations = new AtomicInteger(0);
    tester.getOrCreate(top).setBuilder(new NoExtractorFunction() {

        @Override
        public SkyValue compute(SkyKey key, SkyFunction.Environment env) throws InterruptedException {
            numTopInvocations.incrementAndGet();
            if (delayTopSignaling.get()) {
                // The reporter will be given firstKey's warning to emit when it is requested as a dep
                // below, if firstKey is already built, so we release the reporter's latch beforehand.
                topRestartedBuild.countDown();
            }
            // top's builder just requests both deps in a group.
            env.getValuesOrThrow(ImmutableList.of(firstKey, slowAddingDep), SomeErrorException.class);
            return env.valuesMissing() ? null : new StringValue("top");
        }
    });
    reporter = new DelegatingEventHandler(reporter) {

        @Override
        public void handle(Event e) {
            super.handle(e);
            if (e.getKind() == EventKind.WARNING) {
                if (!throwError) {
                    TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(topRestartedBuild, "top's builder did not start in time");
                }
            }
        }
    };
    // First build : just prime the graph.
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/
    false, top);
    assertFalse(result.hasError());
    assertEquals(new StringValue("top"), result.get(top));
    assertEquals(2, numTopInvocations.get());
    // Now dirty the graph, and maybe have firstKey throw an error.
    String warningText = "warning text";
    tester.getOrCreate(firstKey, /*markAsModified=*/
    true).setHasError(throwError).setWarning(warningText);
    tester.invalidate();
    delayTopSignaling.set(true);
    result = tester.eval(/*keepGoing=*/
    false, top);
    if (throwError) {
        assertTrue(result.hasError());
        // No successfully evaluated values.
        assertThat(result.keyNames()).isEmpty();
        ErrorInfo errorInfo = result.getError(top);
        assertThat(errorInfo.getRootCauses()).containsExactly(firstKey);
        assertEquals("on the incremental build, top's builder should have only been used in error " + "bubbling", 3, numTopInvocations.get());
    } else {
        assertEquals(new StringValue("top"), result.get(top));
        assertFalse(result.hasError());
        assertEquals("on the incremental build, top's builder should have only been executed once in " + "normal evaluation", 3, numTopInvocations.get());
    }
    assertContainsEvent(eventCollector, warningText);
    assertEquals(0, topSignaled.getCount());
    assertEquals(0, topRestartedBuild.getCount());
}
Also used : Order(com.google.devtools.build.skyframe.NotifyingHelper.Order) Listener(com.google.devtools.build.skyframe.NotifyingHelper.Listener) EventType(com.google.devtools.build.skyframe.NotifyingHelper.EventType) ErrorInfoSubjectFactory.assertThatErrorInfo(com.google.devtools.build.skyframe.ErrorInfoSubjectFactory.assertThatErrorInfo) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) DelegatingEventHandler(com.google.devtools.build.lib.events.DelegatingEventHandler) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Environment(com.google.devtools.build.skyframe.SkyFunction.Environment) MoreAsserts.assertContainsEvent(com.google.devtools.build.lib.testutil.MoreAsserts.assertContainsEvent) Event(com.google.devtools.build.lib.events.Event) NotComparableStringValue(com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue) StringValue(com.google.devtools.build.skyframe.GraphTester.StringValue)

Example 75 with StringValue

use of com.google.devtools.build.skyframe.GraphTester.StringValue in project bazel by bazelbuild.

the class MemoizingEvaluatorTest method interruptAfterFailFails.

@Test
public void interruptAfterFailFails() throws Exception {
    SkyKey failKey = GraphTester.skyKey("fail");
    SkyKey interruptedKey = GraphTester.skyKey("interrupted");
    // Given a SkyFunction implementation that is properly coded to as not to throw a
    // runtime exception when it is interrupted,
    final CountDownLatch interruptStarted = new CountDownLatch(1);
    tester.getOrCreate(interruptedKey).setBuilder(new SkyFunction() {

        @Nullable
        @Override
        public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
            interruptStarted.countDown();
            Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
            throw new AssertionError("Shouldn't have slept so long");
        }

        @Nullable
        @Override
        public String extractTag(SkyKey skyKey) {
            return null;
        }
    });
    // And another SkyFunction that waits for the first to start, and then throws,
    tester.getOrCreate(failKey).setBuilder(new ChainedFunction(null, interruptStarted, null, /*waitForException=*/
    false, null, ImmutableList.<SkyKey>of()));
    // When it is interrupted during evaluation (here, caused by the failure of a sibling node
    // during a no-keep-going evaluation),
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/
    false, interruptedKey, failKey);
    // Then the Evaluator#evaluate call returns an EvaluationResult that has no error for the
    // interrupted SkyFunction.
    assertWithMessage(result.toString()).that(result.hasError()).isTrue();
    assertWithMessage(result.toString()).that(result.getError(failKey)).isNotNull();
    assertWithMessage(result.toString()).that(result.getError(interruptedKey)).isNull();
}
Also used : CountDownLatch(java.util.concurrent.CountDownLatch) Environment(com.google.devtools.build.skyframe.SkyFunction.Environment) NotComparableStringValue(com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue) StringValue(com.google.devtools.build.skyframe.GraphTester.StringValue) Nullable(javax.annotation.Nullable) Test(org.junit.Test)

Aggregations

StringValue (com.google.devtools.build.skyframe.GraphTester.StringValue)130 Test (org.junit.Test)114 NotComparableStringValue (com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue)97 CountDownLatch (java.util.concurrent.CountDownLatch)30 Environment (com.google.devtools.build.skyframe.SkyFunction.Environment)22 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)14 EventType (com.google.devtools.build.skyframe.NotifyingHelper.EventType)11 Listener (com.google.devtools.build.skyframe.NotifyingHelper.Listener)11 Order (com.google.devtools.build.skyframe.NotifyingHelper.Order)11 Nullable (javax.annotation.Nullable)10 ErrorInfoSubjectFactory.assertThatErrorInfo (com.google.devtools.build.skyframe.ErrorInfoSubjectFactory.assertThatErrorInfo)9 ArrayList (java.util.ArrayList)7 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)7 ImmutableMap (com.google.common.collect.ImmutableMap)6 Map (java.util.Map)6 TestThread (com.google.devtools.build.lib.testutil.TestThread)5 Supplier (com.google.common.base.Supplier)3 Event (com.google.devtools.build.lib.events.Event)3 MoreAsserts.assertContainsEvent (com.google.devtools.build.lib.testutil.MoreAsserts.assertContainsEvent)3 TestFunction (com.google.devtools.build.skyframe.GraphTester.TestFunction)3