Search in sources :

Example 86 with StringValue

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

the class MemoizingEvaluatorTest method valueInErrorWithGroups.

/**
   * Regression test -- if value top requests {depA, depB}, depC, with depA and depC there and depB
   * absent, and then throws an exception, the stored deps should be depA, depC (in different
   * groups), not {depA, depC} (same group).
   */
@Test
public void valueInErrorWithGroups() throws Exception {
    initializeTester();
    SkyKey topKey = GraphTester.toSkyKey("top");
    final SkyKey groupDepA = GraphTester.toSkyKey("groupDepA");
    final SkyKey groupDepB = GraphTester.toSkyKey("groupDepB");
    SkyKey depC = GraphTester.toSkyKey("depC");
    tester.set(groupDepA, new StringValue("depC"));
    tester.set(groupDepB, new StringValue(""));
    tester.getOrCreate(depC).setHasError(true);
    tester.getOrCreate(topKey).setBuilder(new NoExtractorFunction() {

        @Override
        public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException, InterruptedException {
            StringValue val = ((StringValue) env.getValues(ImmutableList.of(groupDepA, groupDepB)).get(groupDepA));
            if (env.valuesMissing()) {
                return null;
            }
            String nextDep = val.getValue();
            try {
                env.getValueOrThrow(GraphTester.toSkyKey(nextDep), SomeErrorException.class);
            } catch (SomeErrorException e) {
                throw new GenericFunctionException(e, Transience.PERSISTENT);
            }
            return env.valuesMissing() ? null : new StringValue("top");
        }
    });
    EvaluationResult<StringValue> evaluationResult = tester.eval(/*keepGoing=*/
    true, groupDepA, depC);
    assertTrue(evaluationResult.hasError());
    assertEquals("depC", evaluationResult.get(groupDepA).getValue());
    assertThat(evaluationResult.getError(depC).getRootCauses()).containsExactly(depC).inOrder();
    evaluationResult = tester.eval(/*keepGoing=*/
    false, topKey);
    assertTrue(evaluationResult.hasError());
    assertThat(evaluationResult.getError(topKey).getRootCauses()).containsExactly(topKey).inOrder();
    tester.set(groupDepA, new StringValue("groupDepB"));
    tester.getOrCreate(depC, /*markAsModified=*/
    true);
    tester.invalidate();
    evaluationResult = tester.eval(/*keepGoing=*/
    false, topKey);
    assertFalse(evaluationResult.toString(), evaluationResult.hasError());
    assertEquals("top", evaluationResult.get(topKey).getValue());
}
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 87 with StringValue

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

the class MemoizingEvaluatorTest method cachedChildErrorDepWithSiblingDepOnNoKeepGoingEval.

@Test
public void cachedChildErrorDepWithSiblingDepOnNoKeepGoingEval() throws Exception {
    SkyKey parent1Key = GraphTester.toSkyKey("parent1");
    SkyKey parent2Key = GraphTester.toSkyKey("parent2");
    final SkyKey errorKey = GraphTester.toSkyKey("error");
    final SkyKey otherKey = GraphTester.toSkyKey("other");
    SkyFunction parentBuilder = new SkyFunction() {

        @Override
        public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
            env.getValue(errorKey);
            env.getValue(otherKey);
            if (env.valuesMissing()) {
                return null;
            }
            return new StringValue("parent");
        }

        @Override
        public String extractTag(SkyKey skyKey) {
            return null;
        }
    };
    tester.getOrCreate(parent1Key).setBuilder(parentBuilder);
    tester.getOrCreate(parent2Key).setBuilder(parentBuilder);
    tester.getOrCreate(errorKey).setConstantValue(new StringValue("no error yet"));
    tester.getOrCreate(otherKey).setConstantValue(new StringValue("other"));
    tester.eval(/*keepGoing=*/
    true, parent1Key);
    tester.eval(/*keepGoing=*/
    false, parent2Key);
    tester.getOrCreate(errorKey, /*markAsModified=*/
    true).setHasError(true);
    tester.invalidate();
    tester.eval(/*keepGoing=*/
    true, parent1Key);
    tester.eval(/*keepGoing=*/
    false, parent2Key);
}
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 88 with StringValue

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

the class MemoizingEvaluatorTest method cycleAndErrorAndReady.

/**
   * Regression test: IllegalStateException in BuildingState.isReady(). The ParallelEvaluator used
   * to assume during cycle-checking that all values had been built as fully as possible -- that
   * evaluation had not been interrupted. However, we also do cycle-checking in nokeep-going mode
   * when a value throws an error (possibly prematurely shutting down evaluation) but that error
   * then bubbles up into a cycle.
   *
   * <p>We want to achieve the following state: we are checking for a cycle; the value we examine
   * has not yet finished checking its children to see if they are dirty; but all children checked
   * so far have been unchanged. This value is "otherTop". We first build otherTop, then mark its
   * first child changed (without actually changing it), and then do a second build. On the second
   * build, we also build "top", which requests a cycle that depends on an error. We wait to signal
   * otherTop that its first child is done until the error throws and shuts down evaluation. The
   * error then bubbles up to the cycle, and so the bubbling is aborted. Finally, cycle checking
   * happens, and otherTop is examined, as desired.
   */
@Test
public void cycleAndErrorAndReady() throws Exception {
    // This value will not have finished building on the second build when the error is thrown.
    final SkyKey otherTop = GraphTester.toSkyKey("otherTop");
    final SkyKey errorKey = GraphTester.toSkyKey("error");
    // Is the graph state all set up and ready for the error to be thrown? The three values are
    // exceptionMarker, cycle2Key, and dep1 (via signaling otherTop).
    final CountDownLatch valuesReady = new CountDownLatch(3);
    // Is evaluation being shut down? This is counted down by the exceptionMarker's builder, after
    // it has waited for the threadpool's exception latch to be released.
    final CountDownLatch errorThrown = new CountDownLatch(1);
    // We don't do anything on the first build.
    final AtomicBoolean secondBuild = new AtomicBoolean(false);
    injectGraphListenerForTesting(new Listener() {

        @Override
        public void accept(SkyKey key, EventType type, Order order, Object context) {
            if (!secondBuild.get()) {
                return;
            }
            if (key.equals(otherTop) && type == EventType.SIGNAL) {
                // otherTop is being signaled that dep1 is done. Tell the error value that it is
                // ready, then wait until the error is thrown, so that otherTop's builder is not
                // re-entered.
                valuesReady.countDown();
                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(errorThrown, "error not thrown");
                return;
            }
        }
    }, /*deterministic=*/
    true);
    final SkyKey dep1 = GraphTester.toSkyKey("dep1");
    tester.set(dep1, new StringValue("dep1"));
    final SkyKey dep2 = GraphTester.toSkyKey("dep2");
    tester.set(dep2, new StringValue("dep2"));
    // otherTop should request the deps one at a time, so that it can be in the CHECK_DEPENDENCIES
    // state even after one dep is re-evaluated.
    tester.getOrCreate(otherTop).setBuilder(new NoExtractorFunction() {

        @Override
        public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
            env.getValue(dep1);
            if (env.valuesMissing()) {
                return null;
            }
            env.getValue(dep2);
            return env.valuesMissing() ? null : new StringValue("otherTop");
        }
    });
    // Prime the graph with otherTop, so we can dirty it next build.
    assertEquals(new StringValue("otherTop"), tester.evalAndGet(/*keepGoing=*/
    false, otherTop));
    // Mark dep1 changed, so otherTop will be dirty and request re-evaluation of dep1.
    tester.getOrCreate(dep1, /*markAsModified=*/
    true);
    SkyKey topKey = GraphTester.toSkyKey("top");
    // Note that since DeterministicHelper alphabetizes reverse deps, it is important that
    // "cycle2" comes before "top".
    final SkyKey cycle1Key = GraphTester.toSkyKey("cycle1");
    final SkyKey cycle2Key = GraphTester.toSkyKey("cycle2");
    tester.getOrCreate(topKey).addDependency(cycle1Key).setComputedValue(CONCATENATE);
    tester.getOrCreate(cycle1Key).addDependency(errorKey).addDependency(cycle2Key).setComputedValue(CONCATENATE);
    tester.getOrCreate(errorKey).setBuilder(new ChainedFunction(/*notifyStart=*/
    null, /*waitToFinish=*/
    valuesReady, /*notifyFinish=*/
    null, /*waitForException=*/
    false, /*value=*/
    null, ImmutableList.<SkyKey>of()));
    // Make sure cycle2Key has declared its dependence on cycle1Key before error throws.
    tester.getOrCreate(cycle2Key).setBuilder(new ChainedFunction(/*notifyStart=*/
    valuesReady, null, null, false, new StringValue("never returned"), ImmutableList.<SkyKey>of(cycle1Key)));
    // Value that waits until an exception is thrown to finish building. We use it just to be
    // informed when the threadpool is shutting down.
    final SkyKey exceptionMarker = GraphTester.toSkyKey("exceptionMarker");
    tester.getOrCreate(exceptionMarker).setBuilder(new ChainedFunction(/*notifyStart=*/
    valuesReady, /*waitToFinish=*/
    new CountDownLatch(0), /*notifyFinish=*/
    errorThrown, /*waitForException=*/
    true, new StringValue("exception marker"), ImmutableList.<SkyKey>of()));
    tester.invalidate();
    secondBuild.set(true);
    // otherTop must be first, since we check top-level values for cycles in the order in which
    // they appear here.
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/
    false, otherTop, topKey, exceptionMarker);
    Iterable<CycleInfo> cycleInfos = result.getError(topKey).getCycleInfo();
    assertWithMessage(result.toString()).that(cycleInfos).isNotEmpty();
    CycleInfo cycleInfo = Iterables.getOnlyElement(cycleInfos);
    if (cyclesDetected()) {
        assertThat(result.errorMap().keySet()).containsExactly(topKey);
        assertThat(cycleInfo.getPathToCycle()).containsExactly(topKey);
        assertThat(cycleInfo.getCycle()).containsExactly(cycle1Key, cycle2Key);
    }
}
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) CountDownLatch(java.util.concurrent.CountDownLatch) 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) Test(org.junit.Test)

Example 89 with StringValue

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

the class MemoizingEvaluatorTest method valueInjectionInvalidatesReverseDeps.

@Test
public void valueInjectionInvalidatesReverseDeps() throws Exception {
    SkyKey childKey = GraphTester.toSkyKey("child");
    SkyKey parentKey = GraphTester.toSkyKey("parent");
    StringValue oldVal = new StringValue("old_val");
    tester.getOrCreate(childKey).setConstantValue(oldVal);
    tester.getOrCreate(parentKey).addDependency("child").setComputedValue(COPY);
    EvaluationResult<SkyValue> result = tester.eval(false, parentKey);
    assertFalse(result.hasError());
    assertEquals(oldVal, result.get(parentKey));
    SkyValue val = new StringValue("val");
    tester.differencer.inject(ImmutableMap.of(childKey, val));
    assertEquals(val, tester.evalAndGet("child"));
    // Injecting a new child should have invalidated the parent.
    Assert.assertNull(tester.getExistingValue("parent"));
    tester.eval(false, childKey);
    assertEquals(val, tester.getExistingValue("child"));
    Assert.assertNull(tester.getExistingValue("parent"));
    assertEquals(val, tester.evalAndGet("parent"));
}
Also used : NotComparableStringValue(com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue) StringValue(com.google.devtools.build.skyframe.GraphTester.StringValue) Test(org.junit.Test)

Example 90 with StringValue

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

the class MemoizingEvaluatorTest method invalidationWithChangeAndThenNothingChanged.

@Test
public void invalidationWithChangeAndThenNothingChanged() throws Exception {
    tester.getOrCreate("a").addDependency("b").setComputedValue(COPY);
    tester.set("b", new StringValue("y"));
    StringValue original = (StringValue) tester.evalAndGet("a");
    assertEquals("y", original.getValue());
    tester.set("b", new StringValue("z"));
    tester.invalidate();
    StringValue old = (StringValue) tester.evalAndGet("a");
    assertEquals("z", old.getValue());
    tester.invalidate();
    StringValue current = (StringValue) tester.evalAndGet("a");
    assertThat(current).isEqualTo(old);
}
Also used : NotComparableStringValue(com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue) StringValue(com.google.devtools.build.skyframe.GraphTester.StringValue) 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