Search in sources :

Example 11 with StringValue

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

the class MemoizingEvaluatorTest method deleteOldNodesTest.

@Test
public void deleteOldNodesTest() throws Exception {
    tester.getOrCreate("top").setComputedValue(CONCATENATE).addDependency("d1").addDependency("d2");
    tester.set("d1", new StringValue("one"));
    tester.set("d2", new StringValue("two"));
    tester.eval(true, "top");
    tester.set("d2", new StringValue("three"));
    tester.invalidate();
    tester.eval(true, "d2");
    // The graph now contains the three above nodes (and ERROR_TRANSIENCE).
    assertThat(tester.evaluator.getValues().keySet()).containsExactly(skyKey("top"), skyKey("d1"), skyKey("d2"), ErrorTransienceValue.KEY);
    String[] noKeys = {};
    tester.evaluator.deleteDirty(2);
    tester.eval(true, noKeys);
    // The top node's value is dirty, but less than two generations old, so it wasn't deleted.
    assertThat(tester.evaluator.getValues().keySet()).containsExactly(skyKey("top"), skyKey("d1"), skyKey("d2"), ErrorTransienceValue.KEY);
    tester.evaluator.deleteDirty(2);
    tester.eval(true, noKeys);
    // The top node's value was dirty, and was two generations old, so it was deleted.
    assertThat(tester.evaluator.getValues().keySet()).containsExactly(skyKey("d1"), skyKey("d2"), ErrorTransienceValue.KEY);
}
Also used : NotComparableStringValue(com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue) StringValue(com.google.devtools.build.skyframe.GraphTester.StringValue) Test(org.junit.Test)

Example 12 with StringValue

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

the class MemoizingEvaluatorTest method raceConditionWithNoKeepGoingErrors_InflightError.

@Test
public void raceConditionWithNoKeepGoingErrors_InflightError() throws Exception {
    // Given a graph of two nodes, errorKey and otherErrorKey,
    final SkyKey errorKey = GraphTester.toSkyKey("errorKey");
    final SkyKey otherErrorKey = GraphTester.toSkyKey("otherErrorKey");
    final CountDownLatch errorCommitted = new CountDownLatch(1);
    final CountDownLatch otherStarted = new CountDownLatch(1);
    final CountDownLatch otherDone = new CountDownLatch(1);
    final AtomicInteger numOtherInvocations = new AtomicInteger(0);
    final AtomicReference<String> bogusInvocationMessage = new AtomicReference<>(null);
    final AtomicReference<String> nonNullValueMessage = new AtomicReference<>(null);
    tester.getOrCreate(errorKey).setBuilder(new SkyFunction() {

        @Override
        public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
            // Given that errorKey waits for otherErrorKey to begin evaluation before completing
            // its evaluation,
            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(otherStarted, "otherErrorKey's SkyFunction didn't start in time.");
            // And given that errorKey throws an error,
            throw new GenericFunctionException(new SomeErrorException("error"), Transience.PERSISTENT);
        }

        @Override
        public String extractTag(SkyKey skyKey) {
            return null;
        }
    });
    tester.getOrCreate(otherErrorKey).setBuilder(new SkyFunction() {

        @Override
        public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException, InterruptedException {
            otherStarted.countDown();
            int invocations = numOtherInvocations.incrementAndGet();
            // And given that otherErrorKey waits for errorKey's error to be committed before
            // trying to get errorKey's value,
            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(errorCommitted, "errorKey's error didn't get committed to the graph in time");
            try {
                SkyValue value = env.getValueOrThrow(errorKey, SomeErrorException.class);
                if (value != null) {
                    nonNullValueMessage.set("bogus non-null value " + value);
                }
                if (invocations != 1) {
                    bogusInvocationMessage.set("bogus invocation count: " + invocations);
                }
                otherDone.countDown();
                // And given that otherErrorKey throws an error,
                throw new GenericFunctionException(new SomeErrorException("other"), Transience.PERSISTENT);
            } catch (SomeErrorException e) {
                fail();
                return null;
            }
        }

        @Override
        public String extractTag(SkyKey skyKey) {
            return null;
        }
    });
    injectGraphListenerForTesting(new Listener() {

        @Override
        public void accept(SkyKey key, EventType type, Order order, Object context) {
            if (key.equals(errorKey) && type == EventType.SET_VALUE && order == Order.AFTER) {
                errorCommitted.countDown();
                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(otherDone, "otherErrorKey's SkyFunction didn't finish in time.");
            }
        }
    }, /*deterministic=*/
    false);
    // When the graph is evaluated in noKeepGoing mode,
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/
    false, errorKey, otherErrorKey);
    // Then the result reports that an error occurred because of errorKey,
    assertTrue(result.hasError());
    assertEquals(errorKey, result.getError().getRootCauseOfException());
    // And no value is committed for otherErrorKey,
    assertNull(tester.driver.getExistingErrorForTesting(otherErrorKey));
    assertNull(tester.driver.getExistingValueForTesting(otherErrorKey));
    // And no value was committed for errorKey,
    assertNull(nonNullValueMessage.get(), nonNullValueMessage.get());
    // And the SkyFunction for otherErrorKey was evaluated exactly once.
    assertEquals(numOtherInvocations.get(), 1);
    assertNull(bogusInvocationMessage.get(), bogusInvocationMessage.get());
// NB: The SkyFunction for otherErrorKey gets evaluated exactly once--it does not get
// re-evaluated during error bubbling. Why? When otherErrorKey throws, it is always the
// second error encountered, because it waited for errorKey's error to be committed before
// trying to get it. In fail-fast evaluations only the first failing SkyFunction's
// newly-discovered-dependencies are registered. Therefore, there won't be a reverse-dep from
// errorKey to otherErrorKey for the error to bubble through.
}
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) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Environment(com.google.devtools.build.skyframe.SkyFunction.Environment) NotComparableStringValue(com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue) StringValue(com.google.devtools.build.skyframe.GraphTester.StringValue) Test(org.junit.Test)

Example 13 with StringValue

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

the class MemoizingEvaluatorTest method bubbleRace.

@Test
public // Regression test for bug: "[skyframe-m1]: registerIfDone() crash".
void bubbleRace() throws Exception {
    // The top-level value declares dependencies on a "badValue" in error, and a "sleepyValue"
    // which is very slow. After "badValue" fails, the builder interrupts the "sleepyValue" and
    // attempts to re-run "top" for error bubbling. Make sure this doesn't cause a precondition
    // failure because "top" still has an outstanding dep ("sleepyValue").
    tester.getOrCreate("top").setBuilder(new NoExtractorFunction() {

        @Override
        public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
            env.getValue(toSkyKey("sleepyValue"));
            try {
                env.getValueOrThrow(toSkyKey("badValue"), SomeErrorException.class);
            } catch (SomeErrorException e) {
                // In order to trigger this bug, we need to request a dep on an already computed value.
                env.getValue(toSkyKey("otherValue1"));
            }
            if (!env.valuesMissing()) {
                throw new AssertionError("SleepyValue should always be unavailable");
            }
            return null;
        }
    });
    tester.getOrCreate("sleepyValue").setBuilder(new NoExtractorFunction() {

        @Override
        public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
            Thread.sleep(99999);
            throw new AssertionError("I should have been interrupted");
        }
    });
    tester.getOrCreate("badValue").addDependency("otherValue1").setHasError(true);
    tester.getOrCreate("otherValue1").setConstantValue(new StringValue("otherVal1"));
    EvaluationResult<SkyValue> result = tester.eval(false, "top");
    assertTrue(result.hasError());
    assertEquals(toSkyKey("badValue"), Iterables.getOnlyElement(result.getError().getRootCauses()));
    assertThat(result.keyNames()).isEmpty();
}
Also used : Environment(com.google.devtools.build.skyframe.SkyFunction.Environment) NotComparableStringValue(com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue) StringValue(com.google.devtools.build.skyframe.GraphTester.StringValue) Test(org.junit.Test)

Example 14 with StringValue

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

the class MemoizingEvaluatorTest method errorTransienceBug.

// Tests that we have a sane implementation of error transience.
@Test
public void errorTransienceBug() throws Exception {
    tester.getOrCreate("key").setHasTransientError(true);
    assertNotNull(tester.evalAndGetError("key").getException());
    StringValue value = new StringValue("hi");
    tester.getOrCreate("key").setHasTransientError(false).setConstantValue(value);
    tester.invalidateTransientErrors();
    assertEquals(value, tester.evalAndGet("key"));
// This works because the version of the ValueEntry for the ErrorTransience value is always
// increased on each InMemoryMemoizingEvaluator#evaluate call. But that's not the only way to
// implement error transience; another valid implementation would be to unconditionally mark
// values depending on the ErrorTransience value as being changed (rather than merely dirtied)
// during invalidation.
}
Also used : NotComparableStringValue(com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue) StringValue(com.google.devtools.build.skyframe.GraphTester.StringValue) Test(org.junit.Test)

Example 15 with StringValue

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

the class MemoizingEvaluatorTest method changePruningAfterParentPrunes.

@Test
public void changePruningAfterParentPrunes() throws Exception {
    initializeTester();
    final SkyKey leaf = GraphTester.toSkyKey("leaf");
    SkyKey top = GraphTester.toSkyKey("top");
    tester.set(leaf, new StringValue("leafy"));
    // When top depends on leaf, but always returns the same value,
    final StringValue fixedTopValue = new StringValue("top");
    final AtomicBoolean topEvaluated = new AtomicBoolean(false);
    tester.getOrCreate(top).setBuilder(new SkyFunction() {

        @Override
        public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
            topEvaluated.set(true);
            return env.getValue(leaf) == null ? null : fixedTopValue;
        }

        @Nullable
        @Override
        public String extractTag(SkyKey skyKey) {
            return null;
        }
    });
    // And top is evaluated,
    StringValue topValue = (StringValue) tester.evalAndGet("top");
    // Then top's value is as expected,
    assertEquals(fixedTopValue, topValue);
    // And top was actually evaluated.
    assertThat(topEvaluated.get()).isTrue();
    // When leaf is changed,
    tester.set(leaf, new StringValue("crunchy"));
    tester.invalidate();
    topEvaluated.set(false);
    // And top is evaluated,
    StringValue topValue2 = (StringValue) tester.evalAndGet("top");
    // Then top's value is as expected,
    assertEquals(fixedTopValue, topValue2);
    // And top was actually evaluated.
    assertThat(topEvaluated.get()).isTrue();
    // When leaf is invalidated but not actually changed,
    tester.getOrCreate(leaf, /*markAsModified=*/
    true);
    tester.invalidate();
    topEvaluated.set(false);
    // And top is evaluated,
    StringValue topValue3 = (StringValue) tester.evalAndGet("top");
    // Then top's value is as expected,
    assertEquals(fixedTopValue, topValue3);
    // And top was *not* actually evaluated, because change pruning cut off evaluation.
    assertThat(topEvaluated.get()).isFalse();
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) 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