use of com.google.devtools.build.skyframe.GraphTester.StringValue in project bazel by bazelbuild.
the class MemoizingEvaluatorTest method removedNodeComesBackAndInvalidates.
// Tests that a removed and then reinstated node doesn't try to invalidate its erstwhile parent
// when it is invalidated.
@Test
public void removedNodeComesBackAndInvalidates() throws Exception {
removedNodeComesBack();
// When leaf is invalidated again,
tester.getOrCreate(GraphTester.skyKey("leaf"), /*markAsModified=*/
true);
// Then when top is evaluated, its value is as expected.
tester.invalidate();
assertThat(tester.evalAndGet(/*keepGoing=*/
true, "top")).isEqualTo(new StringValue("leaf"));
}
use of com.google.devtools.build.skyframe.GraphTester.StringValue in project bazel by bazelbuild.
the class MemoizingEvaluatorTest method removedInvalidatedNodeComesBackAndOtherInvalidates.
// Tests that a removed and then reinstated node doesn't have a reverse dep on a former parent.
@Test
public void removedInvalidatedNodeComesBackAndOtherInvalidates() throws Exception {
SkyKey top = GraphTester.skyKey("top");
SkyKey leaf = GraphTester.skyKey("leaf");
// When top depends on leaf,
tester.getOrCreate(top).addDependency(leaf).setComputedValue(CONCATENATE);
StringValue leafValue = new StringValue("leaf");
tester.set(leaf, leafValue);
// Then when top is evaluated, its value is as expected.
assertThat(tester.evalAndGet(/*keepGoing=*/
true, top)).isEqualTo(leafValue);
// When top is changed to no longer depend on leaf,
StringValue topValue = new StringValue("top");
tester.getOrCreate(top, /*markAsModified=*/
true).removeDependency(leaf).setComputedValue(null).setConstantValue(topValue);
// And leaf is invalidated,
tester.getOrCreate(leaf, /*markAsModified=*/
true);
// Then when top is evaluated, its value is as expected,
tester.invalidate();
assertThat(tester.evalAndGet(/*keepGoing=*/
true, top)).isEqualTo(topValue);
// And there is no value for leaf in the graph.
assertThat(tester.driver.getExistingValueForTesting(leaf)).isNull();
assertThat(tester.driver.getExistingErrorForTesting(leaf)).isNull();
// When leaf is evaluated, so that it is present in the graph again,
assertThat(tester.evalAndGet(/*keepGoing=*/
true, leaf)).isEqualTo(leafValue);
// And top is changed to depend on leaf again,
tester.getOrCreate(top, /*markAsModified=*/
true).addDependency(leaf).setConstantValue(null).setComputedValue(CONCATENATE);
// Then when top is evaluated, its value is as expected.
tester.invalidate();
assertThat(tester.evalAndGet(/*keepGoing=*/
true, top)).isEqualTo(leafValue);
}
use of com.google.devtools.build.skyframe.GraphTester.StringValue in project bazel by bazelbuild.
the class EagerInvalidatorTest method interruptChild.
@Test
public void interruptChild() throws Exception {
graph = new InMemoryGraphImpl();
// More values than the invalidator has threads.
int numValues = 50;
final SkyKey[] family = new SkyKey[numValues];
final SkyKey child = GraphTester.skyKey("child");
final StringValue childValue = new StringValue("child");
tester.set(child, childValue);
family[0] = child;
for (int i = 1; i < numValues; i++) {
SkyKey member = skyKey(Integer.toString(i));
tester.getOrCreate(member).addDependency(family[i - 1]).setComputedValue(CONCATENATE);
family[i] = member;
}
SkyKey parent = GraphTester.skyKey("parent");
tester.getOrCreate(parent).addDependency(family[numValues - 1]).setComputedValue(CONCATENATE);
eval(/*keepGoing=*/
false, parent);
final Thread mainThread = Thread.currentThread();
final AtomicReference<SkyKey> badKey = new AtomicReference<>();
DirtyTrackingProgressReceiver receiver = new DirtyTrackingProgressReceiver(new EvaluationProgressReceiver() {
@Override
public void invalidated(SkyKey skyKey, InvalidationState state) {
if (skyKey.equals(child)) {
// Interrupt on the very first invalidate
mainThread.interrupt();
} else if (!skyKey.functionName().equals(NODE_TYPE)) {
// All other invalidations should have the GraphTester's key type.
// Exceptions thrown here may be silently dropped, so keep track of errors ourselves.
badKey.set(skyKey);
}
try {
assertTrue(visitor.get().getInterruptionLatchForTestingOnly().await(2, TimeUnit.HOURS));
} catch (InterruptedException e) {
// We may well have thrown here because by the time we try to await, the main
// thread is already interrupted.
}
}
@Override
public void enqueueing(SkyKey skyKey) {
throw new UnsupportedOperationException();
}
@Override
public void computed(SkyKey skyKey, long elapsedTimeNanos) {
throw new UnsupportedOperationException();
}
@Override
public void evaluated(SkyKey skyKey, Supplier<SkyValue> skyValueSupplier, EvaluationState state) {
throw new UnsupportedOperationException();
}
});
try {
invalidateWithoutError(receiver, child);
fail();
} catch (InterruptedException e) {
// Expected.
}
assertNull(badKey.get());
assertFalse(state.isEmpty());
final Set<SkyKey> invalidated = Sets.newConcurrentHashSet();
assertFalse(isInvalidated(parent));
assertNotNull(graph.get(null, Reason.OTHER, parent).getValue());
receiver = new DirtyTrackingProgressReceiver(new EvaluationProgressReceiver() {
@Override
public void invalidated(SkyKey skyKey, InvalidationState state) {
invalidated.add(skyKey);
}
@Override
public void enqueueing(SkyKey skyKey) {
throw new UnsupportedOperationException();
}
@Override
public void computed(SkyKey skyKey, long elapsedTimeNanos) {
throw new UnsupportedOperationException();
}
@Override
public void evaluated(SkyKey skyKey, Supplier<SkyValue> skyValueSupplier, EvaluationState state) {
throw new UnsupportedOperationException();
}
});
invalidateWithoutError(receiver);
assertTrue(invalidated.contains(parent));
assertThat(state.getInvalidationsForTesting()).isEmpty();
// Regression test coverage:
// "all pending values are marked changed on interrupt".
assertTrue(isInvalidated(child));
assertChanged(child);
for (int i = 1; i < numValues; i++) {
assertDirtyAndNotChanged(family[i]);
}
assertDirtyAndNotChanged(parent);
}
use of com.google.devtools.build.skyframe.GraphTester.StringValue in project bazel by bazelbuild.
the class MemoizingEvaluatorTest method passThenFailToBuild.
/**
* Regression test: tests that pass before other build actions fail yield crash in non -k builds.
*/
@Test
public void passThenFailToBuild() throws Exception {
CountDownLatch blocker = new CountDownLatch(1);
SkyKey successKey = GraphTester.toSkyKey("success");
tester.getOrCreate(successKey).setBuilder(new ChainedFunction(/*notifyStart=*/
null, /*waitToFinish=*/
null, /*notifyFinish=*/
blocker, /*waitForException=*/
false, new StringValue("yippee"), /*deps=*/
ImmutableList.<SkyKey>of()));
SkyKey slowFailKey = GraphTester.toSkyKey("slow_then_fail");
tester.getOrCreate(slowFailKey).setBuilder(new ChainedFunction(/*notifyStart=*/
null, /*waitToFinish=*/
blocker, /*notifyFinish=*/
null, /*waitForException=*/
false, /*value=*/
null, /*deps=*/
ImmutableList.<SkyKey>of()));
EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/
false, successKey, slowFailKey);
assertThat(result.getError().getRootCauses()).containsExactly(slowFailKey);
assertThat(result.values()).containsExactly(new StringValue("yippee"));
}
use of com.google.devtools.build.skyframe.GraphTester.StringValue in project bazel by bazelbuild.
the class MemoizingEvaluatorTest method incompleteDirectDepsAreClearedBeforeInvalidation.
/**
* Regression test: error on clearMaybeDirtyValue. We do an evaluation of topKey, which registers
* dependencies on midKey and errorKey. midKey enqueues slowKey, and waits. errorKey throws an
* error, which bubbles up to topKey. If topKey does not unregister its dependence on midKey, it
* will have a dangling reference to midKey after unfinished values are cleaned from the graph.
* Note that slowKey will wait until errorKey has thrown and the threadpool has caught the
* exception before returning, so the Evaluator will already have stopped enqueuing new jobs, so
* midKey is not evaluated.
*/
@Test
public void incompleteDirectDepsAreClearedBeforeInvalidation() 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);
tester.differencer.invalidate(ImmutableList.of(errorKey));
// topKey should not access midKey as if it were already registered as a dependency.
tester.eval(/*keepGoing=*/
false, topKey);
}
Aggregations