From d789eda7fb9ee1b24ff643d65fd5794a920d61af Mon Sep 17 00:00:00 2001 From: nharmata Date: Mon, 6 Dec 2021 10:07:50 -0800 Subject: [PATCH] Make `MemoizingEvaluatorTest.java` compliant with the formatter. This way the diffs of my future CLs won't be cluttered by changes to make the formatter happy. PiperOrigin-RevId: 414475990 --- .../skyframe/MemoizingEvaluatorTest.java | 1070 ++++++++++------- 1 file changed, 641 insertions(+), 429 deletions(-) diff --git a/src/test/java/com/google/devtools/build/skyframe/MemoizingEvaluatorTest.java b/src/test/java/com/google/devtools/build/skyframe/MemoizingEvaluatorTest.java index f072e6a968bdd1..15690fe0d9a11b 100644 --- a/src/test/java/com/google/devtools/build/skyframe/MemoizingEvaluatorTest.java +++ b/src/test/java/com/google/devtools/build/skyframe/MemoizingEvaluatorTest.java @@ -76,7 +76,7 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** Tests for {@link MemoizingEvaluator}.*/ +/** Tests for {@link MemoizingEvaluator}. */ @RunWith(JUnit4.class) public class MemoizingEvaluatorTest { @@ -253,29 +253,36 @@ public void bubbleRace() throws Exception { // 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("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")); @@ -447,8 +454,12 @@ public String extractTag(SkyKey skyKey) { @Test public void deleteValues() throws Exception { - tester.getOrCreate("top").setComputedValue(CONCATENATE) - .addDependency("d1").addDependency("d2").addDependency("d3"); + tester + .getOrCreate("top") + .setComputedValue(CONCATENATE) + .addDependency("d1") + .addDependency("d2") + .addDependency("d3"); tester.set("d1", new StringValue("1")); StringValue d2 = new StringValue("2"); tester.set("d2", d2); @@ -510,7 +521,7 @@ public void deleteDirtyCleanedValue() throws Exception { SkyKey topKey = GraphTester.skyKey("topKey"); tester.getOrCreate(topKey).addDependency(leafKey).setComputedValue(CONCATENATE); - assertThat(tester.evalAndGet(/*keepGoing=*/false, topKey)).isEqualTo(new StringValue("value")); + assertThat(tester.evalAndGet(/*keepGoing=*/ false, topKey)).isEqualTo(new StringValue("value")); failBuildAndRemoveValue(leafKey); tester.evaluator.deleteDirty(0); } @@ -525,8 +536,11 @@ public void deleteNonexistentValues() throws Exception { @Test public void signalValueEnqueued() throws Exception { - tester.getOrCreate("top1").setComputedValue(CONCATENATE) - .addDependency("d1").addDependency("d2"); + tester + .getOrCreate("top1") + .setComputedValue(CONCATENATE) + .addDependency("d1") + .addDependency("d2"); tester.getOrCreate("top2").setComputedValue(CONCATENATE).addDependency("d3"); tester.getOrCreate("top3"); assertThat(tester.getEnqueuedValues()).isEmpty(); @@ -540,8 +554,8 @@ public void signalValueEnqueued() throws Exception { tester.eval(true, "top2"); assertThat(tester.getEnqueuedValues()) - .containsExactlyElementsIn(MemoizingEvaluatorTester.toSkyKeys( - "top1", "d1", "d2", "top2", "d3")); + .containsExactlyElementsIn( + MemoizingEvaluatorTester.toSkyKeys("top1", "d1", "d2", "top2", "d3")); } // NOTE: Some of these tests exercising errors/warnings run through a size-2 for loop in order @@ -635,7 +649,7 @@ public void twoTLTsOnOneWarningValue() throws Exception { for (int i = 0; i < 2; i++) { // Make sure we see the warning exactly once. initializeReporter(); - tester.eval(/*keepGoing=*/false, "t1", "t2"); + tester.eval(/*keepGoing=*/ false, "t1", "t2"); if (i == 0 || eventsStored()) { assertThatEvents(eventCollector).containsExactly("look both ways before crossing"); } @@ -645,7 +659,8 @@ public void twoTLTsOnOneWarningValue() throws Exception { @Test public void errorValueDepOnWarningValue() throws Exception { tester.getOrCreate("error-value").setHasError(true).addDependency("warning-value"); - tester.set("warning-value", new StringValue("warning-value")) + tester + .set("warning-value", new StringValue("warning-value")) .setWarning("don't chew with your mouth open"); for (int i = 0; i < 2; i++) { @@ -668,7 +683,9 @@ public void progressMessageOnlyPrintedTheFirstTime() throws Exception { // The framework keeps track of warning and error messages, but not progress messages. // So here we see both the progress and warning on the first build, but only the warning // on the subsequent null build. - tester.set("x", new StringValue("y")).setWarning("fizzlepop") + tester + .set("x", new StringValue("y")) + .setWarning("fizzlepop") .setProgress("just letting you know"); StringValue value = (StringValue) tester.evalAndGet("x"); @@ -771,15 +788,19 @@ public void noKeepGoingErrorAfterKeepGoingError() throws Exception { @Test public void transientErrorValueInvalidation() throws Exception { // Verify that invalidating errors causes all transient error values to be rerun. - tester.getOrCreate("error-value").setHasTransientError(true).setProgress( - "just letting you know"); + tester + .getOrCreate("error-value") + .setHasTransientError(true) + .setProgress("just letting you know"); tester.evalAndGetError(/*keepGoing=*/ true, "error-value"); assertThatEvents(eventCollector).containsExactly("just letting you know"); // Change the progress message. - tester.getOrCreate("error-value").setHasTransientError(true).setProgress( - "letting you know more"); + tester + .getOrCreate("error-value") + .setHasTransientError(true) + .setProgress("letting you know more"); // Without invalidating errors, we shouldn't show the new progress message. for (int i = 0; i < 2; i++) { @@ -801,16 +822,14 @@ public void transientPruning() throws Exception { tester.getOrCreate("top").setHasTransientError(true).addDependency(leaf); tester.set(leaf, new StringValue("leafy")); tester.evalAndGetError(/*keepGoing=*/ true, "top"); - tester.getOrCreate(leaf, /*markAsModified=*/true); + tester.getOrCreate(leaf, /*markAsModified=*/ true); tester.invalidate(); tester.evalAndGetError(/*keepGoing=*/ true, "top"); } @Test public void simpleDependency() throws Exception { - tester.getOrCreate("ab") - .addDependency("a") - .setComputedValue(COPY); + tester.getOrCreate("ab").addDependency("a").setComputedValue(COPY); tester.set("a", new StringValue("me")); StringValue value = (StringValue) tester.evalAndGet("ab"); assertThat(value.getValue()).isEqualTo("me"); @@ -851,10 +870,7 @@ public void incrementalDiamondDependency() throws Exception { private SkyKey setupDiamondDependency() { SkyKey diamondBase = GraphTester.nonHermeticKey("d"); - tester.getOrCreate("a") - .addDependency("b") - .addDependency("c") - .setComputedValue(CONCATENATE); + tester.getOrCreate("a").addDependency("b").addDependency("c").setComputedValue(CONCATENATE); tester.getOrCreate("b").addDependency(diamondBase).setComputedValue(COPY); tester.getOrCreate("c").addDependency(diamondBase).setComputedValue(COPY); return diamondBase; @@ -895,7 +911,7 @@ public void accept(SkyKey key, EventType type, Order order, Object context) { SkyKey top = GraphTester.skyKey("aatop"); tester.getOrCreate(top).addDependency(mid).setComputedValue(CONCATENATE); tester.getOrCreate(mid).setHasError(true); - tester.eval(/*keepGoing=*/false, top, mid); + tester.eval(/*keepGoing=*/ false, top, mid); assertThat(valueSet.getCount()).isEqualTo(0L); assertThat(tester.progressReceiver.evaluated).containsExactly(mid); } @@ -908,12 +924,12 @@ public void receiverToldOfVerifiedValueDependingOnCycle() throws Exception { tester.set(leaf, new StringValue("leaf")); tester.getOrCreate(cycle).addDependency(cycle); tester.getOrCreate(top).addDependency(leaf).addDependency(cycle); - tester.eval(/*keepGoing=*/true, top); + tester.eval(/*keepGoing=*/ true, top); assertThat(tester.progressReceiver.evaluated).containsExactly(leaf, top, cycle); tester.progressReceiver.clear(); - tester.getOrCreate(leaf, /*markAsModified=*/true); + tester.getOrCreate(leaf, /*markAsModified=*/ true); tester.invalidate(); - tester.eval(/*keepGoing=*/true, top); + tester.eval(/*keepGoing=*/ true, top); if (preciseEvaluationStatusStored()) { assertThat(tester.progressReceiver.evaluated).containsExactly(leaf, top); } @@ -975,8 +991,7 @@ public void singleValueDependsOnManyValues() throws Exception { expected.append(iString); } SkyKey rootKey = toSkyKey("root"); - TestFunction value = tester.getOrCreate(rootKey) - .setComputedValue(CONCATENATE); + TestFunction value = tester.getOrCreate(rootKey).setComputedValue(CONCATENATE); for (int i = 0; i < values.length; i++) { value.addDependency(values[i]); } @@ -1010,14 +1025,16 @@ public void twoRailLeftRightDependencies() throws Exception { tester.getOrCreate(leftValues[i]).addDependency(leaf).setComputedValue(COPY); tester.getOrCreate(rightValues[i]).addDependency(leaf).setComputedValue(COPY); } else { - tester.getOrCreate(leftValues[i]) - .addDependency(leftValues[i - 1]) - .addDependency(rightValues[i - 1]) - .setComputedValue(new PassThroughSelected(toSkyKey(leftValues[i - 1]))); - tester.getOrCreate(rightValues[i]) - .addDependency(leftValues[i - 1]) - .addDependency(rightValues[i - 1]) - .setComputedValue(new PassThroughSelected(toSkyKey(rightValues[i - 1]))); + tester + .getOrCreate(leftValues[i]) + .addDependency(leftValues[i - 1]) + .addDependency(rightValues[i - 1]) + .setComputedValue(new PassThroughSelected(toSkyKey(leftValues[i - 1]))); + tester + .getOrCreate(rightValues[i]) + .addDependency(leftValues[i - 1]) + .addDependency(rightValues[i - 1]) + .setComputedValue(new PassThroughSelected(toSkyKey(rightValues[i - 1]))); } } tester.set(leaf, new StringValue("leaf")); @@ -1053,7 +1070,7 @@ public void noKeepGoingAfterKeepGoingCycle() throws Exception { tester.getOrCreate(midKey).addDependency(aKey); tester.getOrCreate(aKey).addDependency(bKey); tester.getOrCreate(bKey).addDependency(aKey); - EvaluationResult result = tester.eval(/*keepGoing=*/true, topKey, goodKey); + EvaluationResult result = tester.eval(/*keepGoing=*/ true, topKey, goodKey); assertThat(result.get(goodKey)).isEqualTo(goodValue); assertThat(result.get(topKey)).isNull(); ErrorInfo errorInfo = result.getError(topKey); @@ -1064,7 +1081,7 @@ public void noKeepGoingAfterKeepGoingCycle() throws Exception { } tester.invalidate(); - result = tester.eval(/*keepGoing=*/false, topKey, goodKey); + result = tester.eval(/*keepGoing=*/ false, topKey, goodKey); assertThat(result.get(topKey)).isNull(); errorInfo = result.getError(topKey); cycleInfo = Iterables.getOnlyElement(errorInfo.getCycleInfo()); @@ -1218,10 +1235,13 @@ public void cycleAndSelfEdgeWithDirtyValue() throws Exception { makeGraphDeterministic(); SkyKey cycleKey1 = GraphTester.nonHermeticKey("ZcycleKey1"); SkyKey cycleKey2 = GraphTester.toSkyKey("AcycleKey2"); - tester.getOrCreate(cycleKey1).addDependency(cycleKey2).addDependency(cycleKey1) - .setComputedValue(CONCATENATE); + tester + .getOrCreate(cycleKey1) + .addDependency(cycleKey2) + .addDependency(cycleKey1) + .setComputedValue(CONCATENATE); tester.getOrCreate(cycleKey2).addDependency(cycleKey1).setComputedValue(COPY); - EvaluationResult result = tester.eval(/*keepGoing=*/true, cycleKey1); + EvaluationResult result = tester.eval(/*keepGoing=*/ true, cycleKey1); assertThat(result.get(cycleKey1)).isNull(); ErrorInfo errorInfo = result.getError(cycleKey1); CycleInfo cycleInfo = Iterables.getOnlyElement(errorInfo.getCycleInfo()); @@ -1229,9 +1249,9 @@ public void cycleAndSelfEdgeWithDirtyValue() throws Exception { assertThat(cycleInfo.getCycle()).containsExactly(cycleKey1).inOrder(); assertThat(cycleInfo.getPathToCycle()).isEmpty(); } - tester.getOrCreate(cycleKey1, /*markAsModified=*/true); + tester.getOrCreate(cycleKey1, /*markAsModified=*/ true); tester.invalidate(); - result = tester.eval(/*keepGoing=*/true, cycleKey1, cycleKey2); + result = tester.eval(/*keepGoing=*/ true, cycleKey1, cycleKey2); assertThat(result.get(cycleKey1)).isNull(); errorInfo = result.getError(cycleKey1); cycleInfo = Iterables.getOnlyElement(errorInfo.getCycleInfo()); @@ -1295,7 +1315,7 @@ public void cycleWithDirtyValue() throws Exception { SkyKey cycleKey2 = GraphTester.toSkyKey("cycleKey2"); tester.getOrCreate(cycleKey1).addDependency(cycleKey2).setComputedValue(COPY); tester.getOrCreate(cycleKey2).addDependency(cycleKey1).setComputedValue(COPY); - EvaluationResult result = tester.eval(/*keepGoing=*/true, cycleKey1); + EvaluationResult result = tester.eval(/*keepGoing=*/ true, cycleKey1); assertThat(result.get(cycleKey1)).isNull(); ErrorInfo errorInfo = result.getError(cycleKey1); CycleInfo cycleInfo = Iterables.getOnlyElement(errorInfo.getCycleInfo()); @@ -1303,9 +1323,9 @@ public void cycleWithDirtyValue() throws Exception { assertThat(cycleInfo.getCycle()).containsExactly(cycleKey1, cycleKey2).inOrder(); assertThat(cycleInfo.getPathToCycle()).isEmpty(); } - tester.getOrCreate(cycleKey1, /*markAsModified=*/true); + tester.getOrCreate(cycleKey1, /*markAsModified=*/ true); tester.invalidate(); - result = tester.eval(/*keepGoing=*/true, cycleKey1); + result = tester.eval(/*keepGoing=*/ true, cycleKey1); assertThat(result.get(cycleKey1)).isNull(); errorInfo = result.getError(cycleKey1); cycleInfo = Iterables.getOnlyElement(errorInfo.getCycleInfo()); @@ -1318,12 +1338,12 @@ public void cycleWithDirtyValue() throws Exception { /** * {@link ParallelEvaluator} can be configured to not store errors alongside recovered values. * - * @param errorsStoredAlongsideValues true if we expect Skyframe to store the error for the - * cycle in ErrorInfo. If true, supportsTransientExceptions must be true as well. + * @param errorsStoredAlongsideValues true if we expect Skyframe to store the error for the cycle + * in ErrorInfo. If true, supportsTransientExceptions must be true as well. * @param supportsTransientExceptions true if we expect Skyframe to mark an ErrorInfo as transient - * for certain exception types. + * for certain exception types. * @param useTransientError true if the test should set the {@link TestFunction} it creates to - * throw a transient error. + * throw a transient error. */ protected void parentOfCycleAndErrorInternal( boolean errorsStoredAlongsideValues, @@ -1346,12 +1366,22 @@ protected void parentOfCycleAndErrorInternal( } else { errorFunction.setHasError(true); } - tester.getOrCreate(mid).addErrorDependency(errorKey, new StringValue("recovered")) + tester + .getOrCreate(mid) + .addErrorDependency(errorKey, new StringValue("recovered")) .setComputedValue(COPY); SkyKey top = GraphTester.toSkyKey("top"); CountDownLatch topEvaluated = new CountDownLatch(2); - tester.getOrCreate(top).setBuilder(new ChainedFunction(topEvaluated, null, null, false, - new StringValue("unused"), ImmutableList.of(mid, cycleKey1))); + tester + .getOrCreate(top) + .setBuilder( + new ChainedFunction( + topEvaluated, + null, + null, + false, + new StringValue("unused"), + ImmutableList.of(mid, cycleKey1))); EvaluationResult evalResult = tester.eval(true, top); assertThatEvaluationResult(evalResult).hasError(); ErrorInfo errorInfo = evalResult.getError(top); @@ -1475,35 +1505,58 @@ public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedExcept assertThat(tester.evalAndGet(/*keepGoing=*/ false, otherTop)) .isEqualTo(new StringValue("otherTop")); // Mark dep1 changed, so otherTop will be dirty and request re-evaluation of dep1. - tester.getOrCreate(dep1, /*markAsModified=*/true); + 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) + 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.of())); + tester + .getOrCreate(errorKey) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ null, + /*waitToFinish=*/ valuesReady, + /*notifyFinish=*/ null, + /*waitForException=*/ false, + /*value=*/ null, + ImmutableList.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.of(cycle1Key))); + tester + .getOrCreate(cycle2Key) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ valuesReady, + null, + null, + false, + new StringValue("never returned"), + ImmutableList.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.of())); + tester + .getOrCreate(exceptionMarker) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ valuesReady, + /*waitToFinish=*/ new CountDownLatch(0), + /*notifyFinish=*/ errorThrown, + /*waitForException=*/ true, + new StringValue("exception marker"), + ImmutableList.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 result = - tester.eval(/*keepGoing=*/false, otherTop, topKey, exceptionMarker); + tester.eval(/*keepGoing=*/ false, otherTop, topKey, exceptionMarker); Iterable cycleInfos = result.getError(topKey).getCycleInfo(); assertWithMessage(result.toString()).that(cycleInfos).isNotEmpty(); CycleInfo cycleInfo = Iterables.getOnlyElement(cycleInfos); @@ -1669,8 +1722,8 @@ public SkyValue compute(Map deps, SkyFunction.Environment env) } topLevelBuilder.setConstantValue(new StringValue("xyz")); - EvaluationResult result = tester.eval( - /*keepGoing=*/true, /*numThreads=*/5, topLevel); + EvaluationResult result = + tester.eval(/*keepGoing=*/ true, /*numThreads=*/ 5, topLevel); assertThat(result.hasError()).isFalse(); assertThat(maxValue[0]).isEqualTo(5); } @@ -1734,34 +1787,51 @@ public void incompleteDirectDepsAreClearedBeforeInvalidation() throws Exception CountDownLatch slowStart = new CountDownLatch(1); CountDownLatch errorFinish = new CountDownLatch(1); SkyKey errorKey = GraphTester.nonHermeticKey("error"); - tester.getOrCreate(errorKey).setBuilder( - new ChainedFunction(/*notifyStart=*/null, /*waitToFinish=*/slowStart, - /*notifyFinish=*/errorFinish, /*waitForException=*/false, /*value=*/null, - /*deps=*/ImmutableList.of())); + tester + .getOrCreate(errorKey) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ null, + /*waitToFinish=*/ slowStart, + /*notifyFinish=*/ errorFinish, + /*waitForException=*/ false, + /*value=*/ null, + /*deps=*/ ImmutableList.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.of())); + tester + .getOrCreate(slowKey) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ slowStart, + /*waitToFinish=*/ errorFinish, + /*notifyFinish=*/ null, + /*waitForException=*/ true, + new StringValue("slow"), + /*deps=*/ ImmutableList.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) + tester + .getOrCreate(topKey) + .addDependency(midKey) + .addDependency(errorKey) .setComputedValue(CONCATENATE); // slowKey starts -> errorKey finishes, written to graph -> slowKey finishes & (Visitor aborts) // -> topKey builds. - EvaluationResult result = tester.eval(/*keepGoing=*/false, topKey); + EvaluationResult result = tester.eval(/*keepGoing=*/ false, topKey); assertThatEvaluationResult(result).hasSingletonErrorThat(topKey); // Make sure midKey didn't finish building. assertThat(tester.getExistingValue(midKey)).isNull(); // Give slowKey a nice ordinary builder. - tester.getOrCreate(slowKey, /*markAsModified=*/false).setBuilder(null) + 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.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); + tester.eval(/*keepGoing=*/ false, topKey); } /** @@ -1774,35 +1844,52 @@ public void incompleteDirectDepsAreClearedBeforeKeepGoing() throws Exception { 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.of())); + tester + .getOrCreate(errorKey) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ null, + /*waitToFinish=*/ slowStart, + /*notifyFinish=*/ errorFinish, + /*waitForException=*/ false, + /*value=*/ null, + /*deps=*/ ImmutableList.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.of())); + tester + .getOrCreate(slowKey) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ slowStart, + /*waitToFinish=*/ errorFinish, + /*notifyFinish=*/ null, + /*waitForException=*/ true, + new StringValue("slow"), + /*deps=*/ ImmutableList.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) + tester + .getOrCreate(topKey) + .addDependency(midKey) + .addDependency(errorKey) .setComputedValue(CONCATENATE); // slowKey starts -> errorKey finishes, written to graph -> slowKey finishes & (Visitor aborts) // -> topKey builds. - EvaluationResult result = tester.eval(/*keepGoing=*/false, topKey); + EvaluationResult result = tester.eval(/*keepGoing=*/ false, topKey); assertThatEvaluationResult(result).hasSingletonErrorThat(topKey); // Make sure midKey didn't finish building. assertThat(tester.getExistingValue(midKey)).isNull(); // Give slowKey a nice ordinary builder. - tester.getOrCreate(slowKey, /*markAsModified=*/false).setBuilder(null) + 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.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); + tester.eval(/*keepGoing=*/ true, topKey); } /** @@ -1811,15 +1898,27 @@ public void incompleteDirectDepsAreClearedBeforeKeepGoing() throws Exception { private void passThenFailToBuild(boolean successFirst) 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.of())); + tester + .getOrCreate(successKey) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ null, + /*waitToFinish=*/ null, + /*notifyFinish=*/ blocker, + /*waitForException=*/ false, + new StringValue("yippee"), + /*deps=*/ ImmutableList.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.of())); + tester + .getOrCreate(slowFailKey) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ null, + /*waitToFinish=*/ blocker, + /*notifyFinish=*/ null, + /*waitForException=*/ false, + /*value=*/ null, + /*deps=*/ ImmutableList.of())); EvaluationResult result; if (successFirst) { @@ -1851,36 +1950,53 @@ public void incompleteDirectDepsForDirtyValue() throws Exception { 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.of())); + tester + .getOrCreate(errorKey) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ null, + /*waitToFinish=*/ slowStart, + /*notifyFinish=*/ errorFinish, + /*waitForException=*/ false, + /*value=*/ null, + /*deps=*/ ImmutableList.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.of())); + tester + .getOrCreate(slowKey) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ slowStart, + /*waitToFinish=*/ errorFinish, + /*notifyFinish=*/ null, + /*waitForException=*/ true, + new StringValue("slow"), + /*deps=*/ ImmutableList.of())); SkyKey midKey = GraphTester.toSkyKey("mid"); tester.getOrCreate(midKey).addDependency(slowKey).setComputedValue(COPY); tester.set(topKey, null); - tester.getOrCreate(topKey).addDependency(midKey).addDependency(errorKey) + tester + .getOrCreate(topKey) + .addDependency(midKey) + .addDependency(errorKey) .setComputedValue(CONCATENATE); tester.invalidate(); // slowKey starts -> errorKey finishes, written to graph -> slowKey finishes & (Visitor aborts) // -> topKey builds. - EvaluationResult result = tester.eval(/*keepGoing=*/false, topKey); + EvaluationResult result = tester.eval(/*keepGoing=*/ false, topKey); assertThatEvaluationResult(result).hasSingletonErrorThat(topKey); // Make sure midKey didn't finish building. assertThat(tester.getExistingValue(midKey)).isNull(); // Give slowKey a nice ordinary builder. - tester.getOrCreate(slowKey, /*markAsModified=*/false).setBuilder(null) + 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.evalAndGet(/*keepGoing=*/ false, midKey); // topKey should not access midKey as if it were already registered as a dependency. // We don't invalidate errors, but since topKey wasn't actually written to the graph before, it // will be rebuilt. - tester.eval(/*keepGoing=*/true, topKey); + tester.eval(/*keepGoing=*/ true, topKey); } @Test @@ -1895,12 +2011,12 @@ public void continueWithErrorDep() throws Exception { .addErrorDependency(errorKey, new StringValue("recovered")) .setComputedValue(CONCATENATE) .addDependency(afterKey); - EvaluationResult result = tester.eval(/*keepGoing=*/true, parentKey); + EvaluationResult result = tester.eval(/*keepGoing=*/ true, parentKey); assertThat(result.errorMap()).isEmpty(); assertThat(result.get(parentKey).getValue()).isEqualTo("recoveredafter"); tester.set(afterKey, new StringValue("before")); tester.invalidate(); - result = tester.eval(/*keepGoing=*/true, parentKey); + result = tester.eval(/*keepGoing=*/ true, parentKey); assertThat(result.errorMap()).isEmpty(); assertThat(result.get(parentKey).getValue()).isEqualTo("recoveredbefore"); } @@ -1911,14 +2027,17 @@ public void continueWithErrorDepTurnedGood() throws Exception { tester.getOrCreate(errorKey).setHasError(true); tester.set("after", new StringValue("after")); SkyKey parentKey = GraphTester.toSkyKey("parent"); - tester.getOrCreate(parentKey).addErrorDependency(errorKey, new StringValue("recovered")) - .setComputedValue(CONCATENATE).addDependency("after"); - EvaluationResult result = tester.eval(/*keepGoing=*/true, parentKey); + tester + .getOrCreate(parentKey) + .addErrorDependency(errorKey, new StringValue("recovered")) + .setComputedValue(CONCATENATE) + .addDependency("after"); + EvaluationResult result = tester.eval(/*keepGoing=*/ true, parentKey); assertThat(result.errorMap()).isEmpty(); assertThat(result.get(parentKey).getValue()).isEqualTo("recoveredafter"); tester.set(errorKey, new StringValue("reformed")).setHasError(false); tester.invalidate(); - result = tester.eval(/*keepGoing=*/true, parentKey); + result = tester.eval(/*keepGoing=*/ true, parentKey); assertThat(result.errorMap()).isEmpty(); assertThat(result.get(parentKey).getValue()).isEqualTo("reformedafter"); } @@ -1928,7 +2047,9 @@ public void errorDepAlreadyThereThenTurnedGood() throws Exception { SkyKey errorKey = GraphTester.nonHermeticKey("my_error_value"); tester.getOrCreate(errorKey).setHasError(true); SkyKey parentKey = GraphTester.toSkyKey("parent"); - tester.getOrCreate(parentKey).addErrorDependency(errorKey, new StringValue("recovered")) + tester + .getOrCreate(parentKey) + .addErrorDependency(errorKey, new StringValue("recovered")) .setHasError(true); // Prime the graph by putting the error value in it beforehand. assertThat(tester.evalAndGetError(/*keepGoing=*/ true, errorKey)).isNotNull(); @@ -1937,20 +2058,22 @@ public void errorDepAlreadyThereThenTurnedGood() throws Exception { assertThatEvaluationResult(result).hasSingletonErrorThat(parentKey); // Change the error value to no longer throw. tester.set(errorKey, new StringValue("reformed")).setHasError(false); - tester.getOrCreate(parentKey, /*markAsModified=*/false).setHasError(false) + tester + .getOrCreate(parentKey, /*markAsModified=*/ false) + .setHasError(false) .setComputedValue(COPY); tester.differencer.invalidate(ImmutableList.of(errorKey)); tester.invalidate(); // Request the parent again. This time it should succeed. - result = tester.eval(/*keepGoing=*/false, parentKey); + result = tester.eval(/*keepGoing=*/ false, parentKey); assertThat(result.errorMap()).isEmpty(); assertThat(result.get(parentKey).getValue()).isEqualTo("reformed"); // Confirm that the parent no longer depends on the error transience value -- make it // unbuildable again, but without invalidating it, and invalidate transient errors. The parent // should not be rebuilt. - tester.getOrCreate(parentKey, /*markAsModified=*/false).setHasError(true); + tester.getOrCreate(parentKey, /*markAsModified=*/ false).setHasError(true); tester.invalidateTransientErrors(); - result = tester.eval(/*keepGoing=*/false, parentKey); + result = tester.eval(/*keepGoing=*/ false, parentKey); assertThat(result.errorMap()).isEmpty(); assertThat(result.get(parentKey).getValue()).isEqualTo("reformed"); } @@ -1984,15 +2107,15 @@ public void errorTransienceDepCleared() throws Exception { SkyKey leaf = GraphTester.nonHermeticKey("leaf"); tester.set(leaf, new StringValue("leaf")); tester.getOrCreate(top).addDependency(leaf).setHasTransientError(true); - EvaluationResult result = tester.eval(/*keepGoing=*/false, top); + EvaluationResult result = tester.eval(/*keepGoing=*/ false, top); assertWithMessage(result.toString()).that(result.hasError()).isTrue(); - tester.getOrCreate(leaf, /*markAsModified=*/true); + tester.getOrCreate(leaf, /*markAsModified=*/ true); tester.invalidate(); SkyKey irrelevant = GraphTester.toSkyKey("irrelevant"); tester.set(irrelevant, new StringValue("irrelevant")); - tester.eval(/*keepGoing=*/true, irrelevant); + tester.eval(/*keepGoing=*/ true, irrelevant); tester.invalidateTransientErrors(); - result = tester.eval(/*keepGoing=*/true, top); + result = tester.eval(/*keepGoing=*/ true, top); assertWithMessage(result.toString()).that(result.hasError()).isTrue(); } @@ -2002,10 +2125,14 @@ public void incompleteValueAlreadyThereNotUsed() throws Exception { SkyKey errorKey = GraphTester.toSkyKey("my_error_value"); tester.getOrCreate(errorKey).setHasError(true); SkyKey midKey = GraphTester.toSkyKey("mid"); - tester.getOrCreate(midKey).addErrorDependency(errorKey, new StringValue("recovered")) + tester + .getOrCreate(midKey) + .addErrorDependency(errorKey, new StringValue("recovered")) .setComputedValue(COPY); SkyKey parentKey = GraphTester.toSkyKey("parent"); - tester.getOrCreate(parentKey).addErrorDependency(midKey, new StringValue("don't use this")) + tester + .getOrCreate(parentKey) + .addErrorDependency(midKey, new StringValue("don't use this")) .setComputedValue(COPY); // Prime the graph by evaluating the mid-level value. It shouldn't be stored in the graph // because it was only called during the bubbling-up phase. @@ -2027,40 +2154,55 @@ public void errorInDependencyGroup() throws Exception { CountDownLatch slowStart = new CountDownLatch(1); CountDownLatch errorFinish = new CountDownLatch(1); SkyKey errorKey = GraphTester.nonHermeticKey("error"); - tester.getOrCreate(errorKey).setBuilder( - new ChainedFunction(/*notifyStart=*/null, /*waitToFinish=*/slowStart, - /*notifyFinish=*/errorFinish, /*waitForException=*/false, - // ChainedFunction throws when value is null. - /*value=*/null, /*deps=*/ImmutableList.of())); + tester + .getOrCreate(errorKey) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ null, + /*waitToFinish=*/ slowStart, + /*notifyFinish=*/ errorFinish, + /*waitForException=*/ false, + // ChainedFunction throws when value is null. + /*value=*/ null, + /*deps=*/ ImmutableList.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.of())); + tester + .getOrCreate(slowKey) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ slowStart, + /*waitToFinish=*/ errorFinish, + /*notifyFinish=*/ null, + /*waitForException=*/ true, + new StringValue("slow"), + /*deps=*/ ImmutableList.of())); final SkyKey midKey = GraphTester.toSkyKey("mid"); tester.getOrCreate(midKey).addDependency(slowKey).setComputedValue(COPY); final SkyKey mid2Key = GraphTester.toSkyKey("mid2"); tester.getOrCreate(mid2Key).addDependency(slowKey).setComputedValue(COPY); tester.set(topKey, null); - tester.getOrCreate(topKey).setBuilder(new SkyFunction() { - @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException, - InterruptedException { - env.getValues(ImmutableList.of(errorKey, midKey, mid2Key)); - if (env.valuesMissing()) { - return null; - } - return new StringValue("top"); - } + tester + .getOrCreate(topKey) + .setBuilder( + new SkyFunction() { + @Override + public SkyValue compute(SkyKey skyKey, Environment env) + throws SkyFunctionException, InterruptedException { + env.getValues(ImmutableList.of(errorKey, midKey, mid2Key)); + if (env.valuesMissing()) { + return null; + } + return new StringValue("top"); + } - @Override - public String extractTag(SkyKey skyKey) { - return null; - } - }); + @Override + public String extractTag(SkyKey skyKey) { + return null; + } + }); // Assert that build fails and "error" really is in error. - EvaluationResult result = tester.eval(/*keepGoing=*/false, topKey); + EvaluationResult result = tester.eval(/*keepGoing=*/ false, topKey); assertThat(result.hasError()).isTrue(); assertThatEvaluationResult(result).hasErrorEntryForKeyThat(topKey); @@ -2110,13 +2252,13 @@ public SkyValue compute(SkyKey skyKey, Environment env) EvaluationResult evaluationResult = tester.eval(/*keepGoing=*/ true, groupDepA, depC); assertThat(((SkyKeyValue) evaluationResult.get(groupDepA)).key).isEqualTo(depC); assertThatEvaluationResult(evaluationResult).hasErrorEntryForKeyThat(depC); - evaluationResult = tester.eval(/*keepGoing=*/false, topKey); + evaluationResult = tester.eval(/*keepGoing=*/ false, topKey); assertThatEvaluationResult(evaluationResult).hasErrorEntryForKeyThat(topKey); tester.set(groupDepA, new SkyKeyValue(groupDepB)); - tester.getOrCreate(depC, /*markAsModified=*/true); + tester.getOrCreate(depC, /*markAsModified=*/ true); tester.invalidate(); - evaluationResult = tester.eval(/*keepGoing=*/false, topKey); + evaluationResult = tester.eval(/*keepGoing=*/ false, topKey); assertWithMessage(evaluationResult.toString()).that(evaluationResult.hasError()).isFalse(); assertThat(evaluationResult.get(topKey)).isEqualTo(new StringValue("top")); } @@ -2237,7 +2379,7 @@ public SkyValue compute(SkyKey key, SkyFunction.Environment env) } }); // First build : just prime the graph. - EvaluationResult result = tester.eval(/*keepGoing=*/false, top); + EvaluationResult result = tester.eval(/*keepGoing=*/ false, top); assertThat(result.hasError()).isFalse(); assertThat(result.get(top)).isEqualTo(new StringValue("top")); assertThat(numTopInvocations.get()).isEqualTo(2); @@ -2292,12 +2434,12 @@ public SkyValue compute(SkyKey skyKey, Environment env) @Test public void dirtyChildEnqueuesParentDuringCheckDependencies_ThrowDoesntEnqueue() throws Exception { - dirtyChildEnqueuesParentDuringCheckDependencies(/*throwError=*/true); + dirtyChildEnqueuesParentDuringCheckDependencies(/*throwError=*/ true); } @Test public void dirtyChildEnqueuesParentDuringCheckDependencies_NoThrow() throws Exception { - dirtyChildEnqueuesParentDuringCheckDependencies(/*throwError=*/false); + dirtyChildEnqueuesParentDuringCheckDependencies(/*throwError=*/ false); } @Test @@ -2372,15 +2514,15 @@ public void dirtyThenDeleted() throws Exception { SkyKey leafKey = GraphTester.nonHermeticKey("leaf"); tester.getOrCreate(topKey).addDependency(leafKey).setComputedValue(CONCATENATE); tester.set(leafKey, new StringValue("leafy")); - assertThat(tester.evalAndGet(/*keepGoing=*/false, topKey)).isEqualTo(new StringValue("leafy")); - tester.getOrCreate(topKey, /*markAsModified=*/true); + assertThat(tester.evalAndGet(/*keepGoing=*/ false, topKey)).isEqualTo(new StringValue("leafy")); + tester.getOrCreate(topKey, /*markAsModified=*/ true); tester.invalidate(); - assertThat(tester.evalAndGet(/*keepGoing=*/false, leafKey)) + assertThat(tester.evalAndGet(/*keepGoing=*/ false, leafKey)) .isEqualTo(new StringValue("leafy")); tester.delete("top"); - tester.getOrCreate(leafKey, /*markAsModified=*/true); + tester.getOrCreate(leafKey, /*markAsModified=*/ true); tester.invalidate(); - assertThat(tester.evalAndGet(/*keepGoing=*/false, leafKey)) + assertThat(tester.evalAndGet(/*keepGoing=*/ false, leafKey)) .isEqualTo(new StringValue("leafy")); } @@ -2667,29 +2809,35 @@ public void accept(SkyKey key, EventType type, Order order, Object context) { // Create "top" value. It depends on all leaf values in two overlapping dependency groups. SkyKey topKey = GraphTester.toSkyKey("top"); final SkyValue topValue = new StringValue("top"); - tester.getOrCreate(topKey).setBuilder(new NoExtractorFunction() { - @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException, - InterruptedException { - // Request the first group, [leaf0, leaf1, leaf2]. - // In the first build, it has values ["leaf2", "leaf3", "leaf4"]. - // In the second build it has values ["leaf2", "leaf3", "leaf5"] - Map values = env.getValues(leaves); - if (env.valuesMissing()) { - return null; - } + tester + .getOrCreate(topKey) + .setBuilder( + new NoExtractorFunction() { + @Override + public SkyValue compute(SkyKey skyKey, Environment env) + throws SkyFunctionException, InterruptedException { + // Request the first group, [leaf0, leaf1, leaf2]. + // In the first build, it has values ["leaf2", "leaf3", "leaf4"]. + // In the second build it has values ["leaf2", "leaf3", "leaf5"] + Map values = env.getValues(leaves); + if (env.valuesMissing()) { + return null; + } - // Request the second group. In the first build it's [leaf2, leaf4]. - // In the second build it's [leaf2, leaf5] - env.getValues(ImmutableList.of(leaves.get(2), - GraphTester.toSkyKey(((StringValue) values.get(leaves.get(2))).getValue()))); - if (env.valuesMissing()) { - return null; - } + // Request the second group. In the first build it's [leaf2, leaf4]. + // In the second build it's [leaf2, leaf5] + env.getValues( + ImmutableList.of( + leaves.get(2), + GraphTester.toSkyKey( + ((StringValue) values.get(leaves.get(2))).getValue()))); + if (env.valuesMissing()) { + return null; + } - return topValue; - } - }); + return topValue; + } + }); // First build: assert we can evaluate "top". assertThat(tester.evalAndGet(/*keepGoing=*/ false, topKey)).isEqualTo(topValue); @@ -2719,7 +2867,7 @@ public void dirtyAndChanged() throws Exception { tester.invalidate(); // For invalidation. tester.evalAndGet("dummy"); - tester.getOrCreate(mid, /*markAsModified=*/true); + tester.getOrCreate(mid, /*markAsModified=*/ true); tester.invalidate(); topValue = (StringValue) tester.evalAndGet("top"); assertThat(topValue.getValue()).isEqualTo("crunchy"); @@ -2784,18 +2932,18 @@ public void accept(SkyKey key, EventType type, Order order, Object context) { tester.set(leaf, new StringValue("leaf")); tester.getOrCreate(parent).addDependency(leaf).setComputedValue(CONCATENATE); EvaluationResult result; - result = tester.eval(/*keepGoing=*/false, parent); + result = tester.eval(/*keepGoing=*/ false, parent); assertThat(result.get(parent).getValue()).isEqualTo("leaf"); // Invalidate leaf, but don't actually change it. It will transitively dirty parent // concurrently with parent directly dirtying itself. - tester.getOrCreate(leaf, /*markAsModified=*/true); + tester.getOrCreate(leaf, /*markAsModified=*/ true); SkyKey other2 = GraphTester.toSkyKey("other2"); tester.set(other2, new StringValue("other2")); // Invalidate parent, actually changing it. - tester.getOrCreate(parent, /*markAsModified=*/true).addDependency(other2); + tester.getOrCreate(parent, /*markAsModified=*/ true).addDependency(other2); tester.invalidate(); blockingEnabled.set(true); - result = tester.eval(/*keepGoing=*/false, parent); + result = tester.eval(/*keepGoing=*/ false, parent); assertThat(result.get(parent).getValue()).isEqualTo("leafother2"); assertThat(waitForChanged.getCount()).isEqualTo(0); assertThat(threadsStarted.getCount()).isEqualTo(0); @@ -2838,22 +2986,21 @@ public void singleValueDependsOnManyDirtyValues() throws Exception { expected.append(valueName); } SkyKey topKey = toSkyKey("top"); - TestFunction value = tester.getOrCreate(topKey) - .setComputedValue(CONCATENATE); + TestFunction value = tester.getOrCreate(topKey).setComputedValue(CONCATENATE); for (int i = 0; i < values.length; i++) { value.addDependency(values[i]); } - EvaluationResult result = tester.eval(/*keepGoing=*/false, topKey); + EvaluationResult result = tester.eval(/*keepGoing=*/ false, topKey); assertThat(result.get(topKey)).isEqualTo(new StringValue(expected.toString())); for (int j = 0; j < RUNS; j++) { for (int i = 0; i < values.length; i++) { - tester.getOrCreate(values[i], /*markAsModified=*/true); + tester.getOrCreate(values[i], /*markAsModified=*/ true); } // This value has an error, but we should never discover it because it is not marked changed // and all of its dependencies re-evaluate to the same thing. - tester.getOrCreate(topKey, /*markAsModified=*/false).setHasError(true); + tester.getOrCreate(topKey, /*markAsModified=*/ false).setHasError(true); tester.invalidate(); result = tester.eval(/* keepGoing= */ false, topKey); @@ -2878,12 +3025,20 @@ private void dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort( SkyKey lastKey = GraphTester.nonHermeticKey("last"); tester.set(lastKey, new StringValue("last")); SkyKey motherKey = GraphTester.toSkyKey("mother"); - tester.getOrCreate(motherKey).addDependency(errorKey) - .addDependency(midKey).addDependency(lastKey).setComputedValue(CONCATENATE); + tester + .getOrCreate(motherKey) + .addDependency(errorKey) + .addDependency(midKey) + .addDependency(lastKey) + .setComputedValue(CONCATENATE); SkyKey fatherKey = GraphTester.toSkyKey("father"); - tester.getOrCreate(fatherKey).addDependency(errorKey) - .addDependency(midKey).addDependency(lastKey).setComputedValue(CONCATENATE); - EvaluationResult result = tester.eval(/*keepGoing=*/false, motherKey, fatherKey); + tester + .getOrCreate(fatherKey) + .addDependency(errorKey) + .addDependency(midKey) + .addDependency(lastKey) + .setComputedValue(CONCATENATE); + EvaluationResult result = tester.eval(/*keepGoing=*/ false, motherKey, fatherKey); assertThat(result.get(motherKey).getValue()).isEqualTo("biding timeslowlast"); assertThat(result.get(fatherKey).getValue()).isEqualTo("biding timeslowlast"); tester.set(slowKey, null); @@ -2893,31 +3048,47 @@ private void dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort( // parent should be removed. CountDownLatch errorFinish = new CountDownLatch(1); tester.set(errorKey, null); - tester.getOrCreate(errorKey).setBuilder( - new ChainedFunction(/*notifyStart=*/null, /*waitToFinish=*/null, - /*notifyFinish=*/errorFinish, /*waitForException=*/false, /*value=*/null, - /*deps=*/ImmutableList.of())); - tester.getOrCreate(slowKey).setBuilder( - new ChainedFunction(/*notifyStart=*/null, /*waitToFinish=*/errorFinish, - /*notifyFinish=*/null, /*waitForException=*/true, new StringValue("leaf2"), - /*deps=*/ImmutableList.of())); + tester + .getOrCreate(errorKey) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ null, + /*waitToFinish=*/ null, + /*notifyFinish=*/ errorFinish, + /*waitForException=*/ false, + /*value=*/ null, + /*deps=*/ ImmutableList.of())); + tester + .getOrCreate(slowKey) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ null, + /*waitToFinish=*/ errorFinish, + /*notifyFinish=*/ null, + /*waitForException=*/ true, + new StringValue("leaf2"), + /*deps=*/ ImmutableList.of())); tester.invalidate(); // errorKey finishes, written to graph -> leafKey maybe starts+finishes & (Visitor aborts) // -> one of mother or father builds. The other one should be cleaned, and no references to it // left in the graph. - result = tester.eval(/*keepGoing=*/false, motherKey, fatherKey); + result = tester.eval(/*keepGoing=*/ false, motherKey, fatherKey); assertThat(result.hasError()).isTrue(); // Only one of mother or father should be in the graph. assertWithMessage(result.getError(motherKey) + ", " + result.getError(fatherKey)) .that((result.getError(motherKey) == null) != (result.getError(fatherKey) == null)) .isTrue(); - SkyKey parentKey = (reevaluateMissingValue == (result.getError(motherKey) == null)) - ? motherKey : fatherKey; + SkyKey parentKey = + (reevaluateMissingValue == (result.getError(motherKey) == null)) ? motherKey : fatherKey; // Give slowKey a nice ordinary builder. - tester.getOrCreate(slowKey, /*markAsModified=*/false).setBuilder(null) + tester + .getOrCreate(slowKey, /*markAsModified=*/ false) + .setBuilder(null) .setConstantValue(new StringValue("leaf2")); if (removeError) { - tester.getOrCreate(errorKey, /*markAsModified=*/true).setBuilder(null) + tester + .getOrCreate(errorKey, /*markAsModified=*/ true) + .setBuilder(null) .setConstantValue(new StringValue("reformed")); } String lastString = "last"; @@ -2928,7 +3099,7 @@ private void dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort( tester.set(lastKey, new StringValue(lastString)); } tester.invalidate(); - result = tester.eval(/*keepGoing=*/false, parentKey); + result = tester.eval(/*keepGoing=*/ false, parentKey); if (removeError) { assertThat(result.get(parentKey).getValue()).isEqualTo("reformedleaf2" + lastString); } else { @@ -2946,26 +3117,26 @@ private void dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort( */ @Test public void dirtyChildrenProperlyRemovedWithInvalidateRemoveError() throws Exception { - dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort(/*reevaluateMissingValue=*/false, - /*removeError=*/true); + dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort( + /*reevaluateMissingValue=*/ false, /*removeError=*/ true); } @Test public void dirtyChildrenProperlyRemovedWithInvalidateKeepError() throws Exception { - dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort(/*reevaluateMissingValue=*/false, - /*removeError=*/false); + dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort( + /*reevaluateMissingValue=*/ false, /*removeError=*/ false); } @Test public void dirtyChildrenProperlyRemovedWithReevaluateRemoveError() throws Exception { - dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort(/*reevaluateMissingValue=*/true, - /*removeError=*/true); + dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort( + /*reevaluateMissingValue=*/ true, /*removeError=*/ true); } @Test public void dirtyChildrenProperlyRemovedWithReevaluateKeepError() throws Exception { - dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort(/*reevaluateMissingValue=*/true, - /*removeError=*/false); + dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort( + /*reevaluateMissingValue=*/ true, /*removeError=*/ false); } /** @@ -2986,30 +3157,36 @@ private void manyDirtyValuesClearChildrenOnFail(boolean interrupt) throws Except // leaf child is enqueued for processing. for (int i = 0; i < 10000; i++) { SkyKey topKey = GraphTester.toSkyKey("top" + i); - tester.getOrCreate(topKey).addDependency(leafKey).addDependency(lastKey) + tester + .getOrCreate(topKey) + .addDependency(leafKey) + .addDependency(lastKey) .setComputedValue(CONCATENATE); tops.add(topKey); } - tester.eval(/*keepGoing=*/false, tops.toArray(new SkyKey[0])); + tester.eval(/*keepGoing=*/ false, tops.toArray(new SkyKey[0])); final CountDownLatch notifyStart = new CountDownLatch(1); tester.set(leafKey, null); if (interrupt) { // leaf will wait for an interrupt if desired. We cannot use the usual ChainedFunction // because we need to actually throw the interrupt. final AtomicBoolean shouldSleep = new AtomicBoolean(true); - tester.getOrCreate(leafKey, /*markAsModified=*/true).setBuilder( - new NoExtractorFunction() { - @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { - notifyStart.countDown(); - if (shouldSleep.get()) { - // Should be interrupted within 5 seconds. - Thread.sleep(5000); - throw new AssertionError("leaf was not interrupted"); - } - return new StringValue("crunchy"); - } - }); + tester + .getOrCreate(leafKey, /*markAsModified=*/ true) + .setBuilder( + new NoExtractorFunction() { + @Override + public SkyValue compute(SkyKey skyKey, Environment env) + throws InterruptedException { + notifyStart.countDown(); + if (shouldSleep.get()) { + // Should be interrupted within 5 seconds. + Thread.sleep(5000); + throw new AssertionError("leaf was not interrupted"); + } + return new StringValue("crunchy"); + } + }); tester.invalidate(); TestThread evalThread = new TestThread( @@ -3025,12 +3202,12 @@ public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedExcept shouldSleep.set(false); } else { // Non-interrupt case. Just throw an error in the child. - tester.getOrCreate(leafKey, /*markAsModified=*/true).setHasError(true); + tester.getOrCreate(leafKey, /*markAsModified=*/ true).setHasError(true); tester.invalidate(); // The error thrown may non-deterministically bubble up to a parent that has not yet started // processing, but has been enqueued for processing. - tester.eval(/*keepGoing=*/false, tops.toArray(new SkyKey[0])); - tester.getOrCreate(leafKey, /*markAsModified=*/true).setHasError(false); + tester.eval(/*keepGoing=*/ false, tops.toArray(new SkyKey[0])); + tester.getOrCreate(leafKey, /*markAsModified=*/ true).setHasError(false); tester.set(leafKey, new StringValue("crunchy")); } // lastKey was not touched during the previous build, but its reverse deps on its parents should @@ -3038,7 +3215,7 @@ public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedExcept tester.set(lastKey, new StringValue("new last")); tester.invalidate(); EvaluationResult result = - tester.eval(/*keepGoing=*/false, tops.toArray(new SkyKey[0])); + tester.eval(/*keepGoing=*/ false, tops.toArray(new SkyKey[0])); for (SkyKey topKey : tops) { assertWithMessage(topKey.toString()) .that(result.get(topKey).getValue()) @@ -3052,7 +3229,7 @@ public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedExcept */ @Test public void manyDirtyValuesClearChildrenOnError() throws Exception { - manyDirtyValuesClearChildrenOnFail(/*interrupt=*/false); + manyDirtyValuesClearChildrenOnFail(/*interrupt=*/ false); } /** @@ -3061,7 +3238,7 @@ public void manyDirtyValuesClearChildrenOnError() throws Exception { */ @Test public void manyDirtyValuesClearChildrenOnInterrupt() throws Exception { - manyDirtyValuesClearChildrenOnFail(/*interrupt=*/true); + manyDirtyValuesClearChildrenOnFail(/*interrupt=*/ true); } private SkyKey makeTestKey(SkyKey node0) { @@ -3122,12 +3299,12 @@ public void changePruning() throws Exception { StringValue topValue = (StringValue) tester.evalAndGet("top"); assertThat(topValue.getValue()).isEqualTo("leafy"); // Mark leaf changed, but don't actually change it. - tester.getOrCreate(leaf, /*markAsModified=*/true); + tester.getOrCreate(leaf, /*markAsModified=*/ true); // mid will give an error if re-evaluated, but it shouldn't be because it is not marked changed, // and its dirty child will evaluate to the same element. - tester.getOrCreate(mid, /*markAsModified=*/false).setHasError(true); + tester.getOrCreate(mid, /*markAsModified=*/ false).setHasError(true); tester.invalidate(); - EvaluationResult result = tester.eval(/*keepGoing=*/false, top); + EvaluationResult result = tester.eval(/*keepGoing=*/ false, top); assertThat(result.hasError()).isFalse(); topValue = result.get(top); assertThat(topValue.getValue()).isEqualTo("leafy"); @@ -3150,16 +3327,16 @@ public void changePruningWithDoneValue() throws Exception { StringValue value = (StringValue) tester.evalAndGet("top"); assertThat(value.getValue()).isEqualTo("leafysuffixsuffix"); // Mark leaf changed, but don't actually change it. - tester.getOrCreate(leaf, /*markAsModified=*/true); + tester.getOrCreate(leaf, /*markAsModified=*/ true); // mid will give an error if re-evaluated, but it shouldn't be because it is not marked changed, // and its dirty child will evaluate to the same element. - tester.getOrCreate(mid, /*markAsModified=*/false).setHasError(true); + tester.getOrCreate(mid, /*markAsModified=*/ false).setHasError(true); tester.invalidate(); value = (StringValue) tester.evalAndGet(/*keepGoing=*/ false, leaf); assertThat(value.getValue()).isEqualTo("leafy"); assertThat(tester.getDirtyKeys()).containsExactly(mid, top); assertThat(tester.getDeletedKeys()).isEmpty(); - EvaluationResult result = tester.eval(/*keepGoing=*/false, top); + EvaluationResult result = tester.eval(/*keepGoing=*/ false, top); assertWithMessage(result.toString()).that(result.hasError()).isFalse(); value = result.get(top); assertThat(value.getValue()).isEqualTo("leafysuffixsuffix"); @@ -3356,19 +3533,20 @@ public void dirtyDepIgnoresChildren() throws Exception { } } - private static final SkyFunction INTERRUPT_BUILDER = new SkyFunction() { + private static final SkyFunction INTERRUPT_BUILDER = + new SkyFunction() { - @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException, - InterruptedException { - throw new InterruptedException(); - } + @Override + public SkyValue compute(SkyKey skyKey, Environment env) + throws SkyFunctionException, InterruptedException { + throw new InterruptedException(); + } - @Override - public String extractTag(SkyKey skyKey) { - throw new UnsupportedOperationException(); - } - }; + @Override + public String extractTag(SkyKey skyKey) { + throw new UnsupportedOperationException(); + } + }; /** * Utility function to induce a graph clean of whatever value is requested, by trying to build @@ -3377,10 +3555,10 @@ public String extractTag(SkyKey skyKey) { private void failBuildAndRemoveValue(final SkyKey value) { tester.set(value, null); // Evaluator will think leaf was interrupted because it threw, so it will be cleaned from graph. - tester.getOrCreate(value, /*markAsModified=*/true).setBuilder(INTERRUPT_BUILDER); + tester.getOrCreate(value, /*markAsModified=*/ true).setBuilder(INTERRUPT_BUILDER); tester.invalidate(); assertThrows(InterruptedException.class, () -> tester.eval(/*keepGoing=*/ false, value)); - tester.getOrCreate(value, /*markAsModified=*/false).setBuilder(null); + tester.getOrCreate(value, /*markAsModified=*/ false).setBuilder(null); } /** @@ -3424,10 +3602,10 @@ public void changedBuildAfterFailedThenSuccessfulBuild() throws Exception { failBuildAndRemoveValue(leaf); tester.set(leaf, new StringValue("crunchy")); tester.invalidate(); - tester.eval(/*keepGoing=*/false, leaf); + tester.eval(/*keepGoing=*/ false, leaf); // Leaf no longer has reverse dep on top. Check that this doesn't cause problems, even if the // top value is evaluated unconditionally. - tester.getOrCreate(top, /*markAsModified=*/true); + tester.getOrCreate(top, /*markAsModified=*/ true); tester.invalidate(); topValue = (StringValue) tester.evalAndGet(/*keepGoing=*/ false, top); assertThat(topValue.getValue()).isEqualTo("crunchy"); @@ -3438,11 +3616,13 @@ public void changedBuildAfterFailedThenSuccessfulBuild() throws Exception { * longer knows it has a reverse dep on its parent. * *

Start with: + * *

    *              top0  ... top1000
    *                  \  | /
    *                   leaf
    * 
+ * * Then fail to build leaf. Now the entry for leaf should have no "memory" that it was ever * depended on by tops. Now build tops, but fail again. */ @@ -3457,11 +3637,14 @@ public void manyDirtyValuesClearChildrenOnSecondFail() throws Exception { // the leaf child is enqueued for processing. for (int i = 0; i < 10000; i++) { SkyKey topKey = GraphTester.toSkyKey("top" + i); - tester.getOrCreate(topKey).addDependency(leafKey).addDependency(lastKey) + tester + .getOrCreate(topKey) + .addDependency(leafKey) + .addDependency(lastKey) .setComputedValue(CONCATENATE); tops.add(topKey); } - tester.eval(/*keepGoing=*/false, tops.toArray(new SkyKey[0])); + tester.eval(/*keepGoing=*/ false, tops.toArray(new SkyKey[0])); failBuildAndRemoveValue(leafKey); // Request the tops. Since leaf was deleted from the graph last build, it no longer knows that // its parents depend on it. When leaf throws, at least one of its parents (hopefully) will not @@ -3469,7 +3652,7 @@ public void manyDirtyValuesClearChildrenOnSecondFail() throws Exception { // should then not try to clean the reverse dep from leaf. tester.set(leafKey, null); // Evaluator will think leaf was interrupted because it threw, so it will be cleaned from graph. - tester.getOrCreate(leafKey, /*markAsModified=*/true).setBuilder(INTERRUPT_BUILDER); + tester.getOrCreate(leafKey, /*markAsModified=*/ true).setBuilder(INTERRUPT_BUILDER); tester.invalidate(); assertThrows( InterruptedException.class, @@ -3480,7 +3663,9 @@ public void manyDirtyValuesClearChildrenOnSecondFail() throws Exception { public void failedDirtyBuild() throws Exception { SkyKey leaf = GraphTester.nonHermeticKey("leaf"); SkyKey top = GraphTester.toSkyKey("top"); - tester.getOrCreate(top).addErrorDependency(leaf, new StringValue("recover")) + tester + .getOrCreate(top) + .addErrorDependency(leaf, new StringValue("recover")) .setComputedValue(COPY); tester.set(leaf, new StringValue("leafy")); StringValue topValue = (StringValue) tester.evalAndGet("top"); @@ -3488,10 +3673,10 @@ public void failedDirtyBuild() throws Exception { assertThat(tester.getDirtyKeys()).isEmpty(); assertThat(tester.getDeletedKeys()).isEmpty(); // Change leaf. - tester.getOrCreate(leaf, /*markAsModified=*/true).setHasError(true); - tester.getOrCreate(top, /*markAsModified=*/false).setHasError(true); + tester.getOrCreate(leaf, /*markAsModified=*/ true).setHasError(true); + tester.getOrCreate(top, /*markAsModified=*/ false).setHasError(true); tester.invalidate(); - EvaluationResult result = tester.eval(/*keepGoing=*/false, top); + EvaluationResult result = tester.eval(/*keepGoing=*/ false, top); assertThatEvaluationResult(result).hasSingletonErrorThat(top); } @@ -3500,8 +3685,11 @@ public void failedDirtyBuildInBuilder() throws Exception { SkyKey leaf = GraphTester.nonHermeticKey("leaf"); SkyKey secondError = GraphTester.nonHermeticKey("secondError"); SkyKey top = GraphTester.toSkyKey("top"); - tester.getOrCreate(top).addDependency(leaf) - .addErrorDependency(secondError, new StringValue("recover")).setComputedValue(CONCATENATE); + tester + .getOrCreate(top) + .addDependency(leaf) + .addErrorDependency(secondError, new StringValue("recover")) + .setComputedValue(CONCATENATE); tester.set(secondError, new StringValue("secondError")).addDependency(leaf); tester.set(leaf, new StringValue("leafy")); StringValue topValue = (StringValue) tester.evalAndGet("top"); @@ -3509,12 +3697,12 @@ public void failedDirtyBuildInBuilder() throws Exception { assertThat(tester.getDirtyKeys()).isEmpty(); assertThat(tester.getDeletedKeys()).isEmpty(); // Invalidate leaf. - tester.getOrCreate(leaf, /*markAsModified=*/true); + tester.getOrCreate(leaf, /*markAsModified=*/ true); tester.set(leaf, new StringValue("crunchy")); - tester.getOrCreate(secondError, /*markAsModified=*/true).setHasError(true); - tester.getOrCreate(top, /*markAsModified=*/false).setHasError(true); + tester.getOrCreate(secondError, /*markAsModified=*/ true).setHasError(true); + tester.getOrCreate(top, /*markAsModified=*/ false).setHasError(true); tester.invalidate(); - EvaluationResult result = tester.eval(/*keepGoing=*/false, top); + EvaluationResult result = tester.eval(/*keepGoing=*/ false, top); assertThatEvaluationResult(result).hasSingletonErrorThat(top); } @@ -3538,13 +3726,13 @@ public void dirtyDependsOnErrorTurningGood() throws Exception { tester.getOrCreate(error).setHasError(true); SkyKey topKey = GraphTester.toSkyKey("top"); tester.getOrCreate(topKey).addDependency(error).setComputedValue(COPY); - EvaluationResult result = tester.eval(/*keepGoing=*/false, topKey); + EvaluationResult result = tester.eval(/*keepGoing=*/ false, topKey); assertThatEvaluationResult(result).hasSingletonErrorThat(topKey); tester.getOrCreate(error).setHasError(false); StringValue val = new StringValue("reformed"); tester.set(error, val); tester.invalidate(); - result = tester.eval(/*keepGoing=*/false, topKey); + result = tester.eval(/*keepGoing=*/ false, topKey); assertThatEvaluationResult(result).hasEntryThat(topKey).isEqualTo(val); assertThatEvaluationResult(result).hasNoError(); } @@ -3555,24 +3743,25 @@ public void dirtyWithOwnErrorDependsOnTransientErrorTurningGood() throws Excepti SkyKey error = GraphTester.nonHermeticKey("error"); tester.getOrCreate(error).setHasTransientError(true); SkyKey topKey = GraphTester.toSkyKey("top"); - SkyFunction errorFunction = new SkyFunction() { - @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws GenericFunctionException, - InterruptedException { - try { - return env.getValueOrThrow(error, SomeErrorException.class); - } catch (SomeErrorException e) { - throw new GenericFunctionException(e, Transience.PERSISTENT); - } - } + SkyFunction errorFunction = + new SkyFunction() { + @Override + public SkyValue compute(SkyKey skyKey, Environment env) + throws GenericFunctionException, InterruptedException { + try { + return env.getValueOrThrow(error, SomeErrorException.class); + } catch (SomeErrorException e) { + throw new GenericFunctionException(e, Transience.PERSISTENT); + } + } - @Override - public String extractTag(SkyKey skyKey) { - throw new UnsupportedOperationException(); - } - }; + @Override + public String extractTag(SkyKey skyKey) { + throw new UnsupportedOperationException(); + } + }; tester.getOrCreate(topKey).setBuilder(errorFunction); - EvaluationResult result = tester.eval(/*keepGoing=*/false, topKey); + EvaluationResult result = tester.eval(/*keepGoing=*/ false, topKey); tester.invalidateTransientErrors(); assertThatEvaluationResult(result).hasSingletonErrorThat(topKey); tester.getOrCreate(error).setHasTransientError(false); @@ -3585,7 +3774,7 @@ public String extractTag(SkyKey skyKey) { .setComputedValue(COPY); tester.invalidate(); tester.invalidateTransientErrors(); - result = tester.eval(/*keepGoing=*/false, topKey); + result = tester.eval(/*keepGoing=*/ false, topKey); assertThatEvaluationResult(result).hasEntryThat(topKey).isEqualTo(reformed); assertThatEvaluationResult(result).hasNoError(); } @@ -3620,11 +3809,14 @@ public void errorOnlyBubblesToRequestingParents() throws Exception { SkyKey topErrorFirstKey = GraphTester.toSkyKey("2nd top alphabetically"); tester.getOrCreate(topErrorFirstKey).addDependency(errorKey).setComputedValue(CONCATENATE); SkyKey topBubbleKey = GraphTester.toSkyKey("1st top alphabetically"); - tester.getOrCreate(topBubbleKey).addDependency(midKey).addDependency(errorKey) + tester + .getOrCreate(topBubbleKey) + .addDependency(midKey) + .addDependency(errorKey) .setComputedValue(CONCATENATE); // First error-free evaluation, to put all values in graph. - EvaluationResult result = tester.eval(/*keepGoing=*/false, - topErrorFirstKey, topBubbleKey); + EvaluationResult result = + tester.eval(/*keepGoing=*/ false, topErrorFirstKey, topBubbleKey); assertThat(result.get(topErrorFirstKey).getValue()).isEqualTo("biding time"); assertThat(result.get(topBubbleKey).getValue()).isEqualTo("slowbiding time"); // Set up timing of child values: slowKey waits to finish until errorKey has thrown an @@ -3632,18 +3824,30 @@ public void errorOnlyBubblesToRequestingParents() throws Exception { tester.set(slowKey, null); CountDownLatch errorFinish = new CountDownLatch(1); tester.set(errorKey, null); - tester.getOrCreate(errorKey).setBuilder( - new ChainedFunction(/*notifyStart=*/null, /*waitToFinish=*/null, - /*notifyFinish=*/errorFinish, /*waitForException=*/false, /*value=*/null, - /*deps=*/ImmutableList.of())); - tester.getOrCreate(slowKey).setBuilder( - new ChainedFunction(/*notifyStart=*/null, /*waitToFinish=*/errorFinish, - /*notifyFinish=*/null, /*waitForException=*/true, new StringValue("leaf2"), - /*deps=*/ImmutableList.of())); + tester + .getOrCreate(errorKey) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ null, + /*waitToFinish=*/ null, + /*notifyFinish=*/ errorFinish, + /*waitForException=*/ false, + /*value=*/ null, + /*deps=*/ ImmutableList.of())); + tester + .getOrCreate(slowKey) + .setBuilder( + new ChainedFunction( + /*notifyStart=*/ null, + /*waitToFinish=*/ errorFinish, + /*notifyFinish=*/ null, + /*waitForException=*/ true, + new StringValue("leaf2"), + /*deps=*/ ImmutableList.of())); tester.invalidate(); // errorKey finishes, written to graph -> slowKey maybe starts+finishes & (Visitor aborts) // -> some top key builds. - result = tester.eval(/*keepGoing=*/false, topErrorFirstKey, topBubbleKey); + result = tester.eval(/*keepGoing=*/ false, topErrorFirstKey, topBubbleKey); assertThat(result.hasError()).isTrue(); assertWithMessage(result.toString()).that(result.getError(topErrorFirstKey)).isNotNull(); } @@ -3653,32 +3857,33 @@ public void dirtyWithRecoveryErrorDependsOnErrorTurningGood() throws Exception { final SkyKey error = GraphTester.nonHermeticKey("error"); tester.getOrCreate(error).setHasError(true); SkyKey topKey = GraphTester.toSkyKey("top"); - SkyFunction recoveryErrorFunction = new SkyFunction() { - @Override - public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException, - InterruptedException { - try { - env.getValueOrThrow(error, SomeErrorException.class); - } catch (SomeErrorException e) { - throw new GenericFunctionException(e, Transience.PERSISTENT); - } - return null; - } + SkyFunction recoveryErrorFunction = + new SkyFunction() { + @Override + public SkyValue compute(SkyKey skyKey, Environment env) + throws SkyFunctionException, InterruptedException { + try { + env.getValueOrThrow(error, SomeErrorException.class); + } catch (SomeErrorException e) { + throw new GenericFunctionException(e, Transience.PERSISTENT); + } + return null; + } - @Override - public String extractTag(SkyKey skyKey) { - throw new UnsupportedOperationException(); - } - }; + @Override + public String extractTag(SkyKey skyKey) { + throw new UnsupportedOperationException(); + } + }; tester.getOrCreate(topKey).setBuilder(recoveryErrorFunction); - EvaluationResult result = tester.eval(/*keepGoing=*/false, topKey); + EvaluationResult result = tester.eval(/*keepGoing=*/ false, topKey); assertThatEvaluationResult(result).hasSingletonErrorThat(topKey); tester.getOrCreate(error).setHasError(false); StringValue reformed = new StringValue("reformed"); tester.set(error, reformed); tester.getOrCreate(topKey).setBuilder(null).addDependency(error).setComputedValue(COPY); tester.invalidate(); - result = tester.eval(/*keepGoing=*/false, topKey); + result = tester.eval(/*keepGoing=*/ false, topKey); assertThatEvaluationResult(result).hasEntryThat(topKey).isEqualTo(reformed); assertThatEvaluationResult(result).hasNoError(); } @@ -3726,10 +3931,10 @@ public void breakWithInterruptibleErrorDep() throws Exception { } /** - * Regression test: "clearing incomplete values on --keep_going build is racy". - * Tests that if a value is requested on the first (non-keep-going) build and its child throws - * an error, when the second (keep-going) build runs, there is not a race that keeps it as a - * reverse dep of its children. + * Regression test: "clearing incomplete values on --keep_going build is racy". Tests that if a + * value is requested on the first (non-keep-going) build and its child throws an error, when the + * second (keep-going) build runs, there is not a race that keeps it as a reverse dep of its + * children. */ @Test public void raceClearingIncompleteValues() throws Exception { @@ -3922,11 +4127,11 @@ public void absentParent() throws Exception { tester.getOrCreate(absentParentKey).addDependency(errorKey).setComputedValue(CONCATENATE); assertThat(tester.evalAndGet(/*keepGoing=*/ false, absentParentKey)) .isEqualTo(new StringValue("biding time")); - tester.getOrCreate(errorKey, /*markAsModified=*/true).setHasError(true); + tester.getOrCreate(errorKey, /*markAsModified=*/ true).setHasError(true); SkyKey newParent = GraphTester.toSkyKey("newParent"); tester.getOrCreate(newParent).addDependency(errorKey).setComputedValue(CONCATENATE); tester.invalidate(); - EvaluationResult result = tester.eval(/*keepGoing=*/false, newParent); + EvaluationResult result = tester.eval(/*keepGoing=*/ false, newParent); assertThatEvaluationResult(result).hasSingletonErrorThat(newParent); } @@ -3959,7 +4164,7 @@ private void checkNotComparableNotPruned(boolean hasEvent) throws Exception { parentEvaluated.incrementAndGet(); return new StringValue(val); }); - assertStringValue(val, tester.evalAndGet( /*keepGoing=*/false, parent)); + assertStringValue(val, tester.evalAndGet(/*keepGoing=*/ false, parent)); assertThat(parentEvaluated.get()).isEqualTo(1); if (hasEvent) { assertThatEvents(eventCollector).containsExactly("shmoop"); @@ -3969,9 +4174,9 @@ private void checkNotComparableNotPruned(boolean hasEvent) throws Exception { eventCollector.clear(); tester.resetPlayedEvents(); - tester.getOrCreate(child, /*markAsModified=*/true); + tester.getOrCreate(child, /*markAsModified=*/ true); tester.invalidate(); - assertStringValue(val, tester.evalAndGet( /*keepGoing=*/false, parent)); + assertStringValue(val, tester.evalAndGet(/*keepGoing=*/ false, parent)); assertThat(parentEvaluated.get()).isEqualTo(2); if (hasEvent) { assertThatEvents(eventCollector).containsExactly("shmoop"); @@ -3997,14 +4202,14 @@ public void changePruningWithEvent() throws Exception { .setBuilder( new ChainedFunction( parentEvaluated, null, null, false, parentVal, ImmutableList.of(child))); - assertThat(tester.evalAndGet( /*keepGoing=*/false, parent)).isEqualTo(parentVal); + assertThat(tester.evalAndGet(/*keepGoing=*/ false, parent)).isEqualTo(parentVal); assertThat(parentEvaluated.getCount()).isEqualTo(1); assertThatEvents(eventCollector).containsExactly("bloop"); eventCollector.clear(); tester.resetPlayedEvents(); tester.getOrCreate(child, /*markAsModified=*/ true); tester.invalidate(); - assertThat(tester.evalAndGet( /*keepGoing=*/false, parent)).isEqualTo(parentVal); + assertThat(tester.evalAndGet(/*keepGoing=*/ false, parent)).isEqualTo(parentVal); assertThatEvents(eventCollector).containsExactly("bloop"); assertThat(parentEvaluated.getCount()).isEqualTo(1); } @@ -4166,15 +4371,17 @@ public void transientErrorTurningGoodHasNoError() throws Exception { errorInfo = tester.evalAndGetError(/*keepGoing=*/ true, errorKey); assertThat(errorInfo).isNotNull(); StringValue value = new StringValue("reformed"); - tester.getOrCreate(errorKey, /*markAsModified=*/false).setHasTransientError(false) + tester + .getOrCreate(errorKey, /*markAsModified=*/ false) + .setHasTransientError(false) .setConstantValue(value); tester.invalidateTransientErrors(); - StringValue stringValue = (StringValue) tester.evalAndGet(/*keepGoing=*/true, errorKey); + StringValue stringValue = (StringValue) tester.evalAndGet(/*keepGoing=*/ true, errorKey); assertThat(value).isSameInstanceAs(stringValue); // Value builder will now throw, but we should never get to it because it isn't dirty. - tester.getOrCreate(errorKey, /*markAsModified=*/false).setHasTransientError(true); + tester.getOrCreate(errorKey, /*markAsModified=*/ false).setHasTransientError(true); tester.invalidateTransientErrors(); - stringValue = (StringValue) tester.evalAndGet(/*keepGoing=*/true, errorKey); + stringValue = (StringValue) tester.evalAndGet(/*keepGoing=*/ true, errorKey); assertThat(stringValue).isEqualTo(value); } @@ -4213,13 +4420,13 @@ public void deleteInvalidatedValue() throws Exception { SkyValue value = tester.evalAndGet("top"); SkyKey forceInvalidation = GraphTester.toSkyKey("forceInvalidation"); tester.set(forceInvalidation, new StringValue("forceInvalidation")); - tester.getOrCreate(toDelete, /*markAsModified=*/true); + tester.getOrCreate(toDelete, /*markAsModified=*/ true); tester.invalidate(); - tester.eval(/*keepGoing=*/false, forceInvalidation); + tester.eval(/*keepGoing=*/ false, forceInvalidation); tester.delete("toDelete"); WeakReference ref = new WeakReference<>(value); value = null; - tester.eval(/*keepGoing=*/false, forceInvalidation); + tester.eval(/*keepGoing=*/ false, forceInvalidation); tester.invalidate(); // So that invalidation receiver doesn't hang on to reference. GcFinalization.awaitClear(ref); } @@ -4237,21 +4444,19 @@ public void twoRailLeftRightDependenciesWithFailure() throws Exception { leftValues[i] = GraphTester.nonHermeticKey("left-" + i); rightValues[i] = GraphTester.toSkyKey("right-" + i); if (i == 0) { - tester.getOrCreate(leftValues[i]) - .addDependency("leaf") - .setComputedValue(COPY); - tester.getOrCreate(rightValues[i]) - .addDependency("leaf") - .setComputedValue(COPY); + tester.getOrCreate(leftValues[i]).addDependency("leaf").setComputedValue(COPY); + tester.getOrCreate(rightValues[i]).addDependency("leaf").setComputedValue(COPY); } else { - tester.getOrCreate(leftValues[i]) - .addDependency(leftValues[i - 1]) - .addDependency(rightValues[i - 1]) - .setComputedValue(new PassThroughSelected(leftValues[i - 1])); - tester.getOrCreate(rightValues[i]) - .addDependency(leftValues[i - 1]) - .addDependency(rightValues[i - 1]) - .setComputedValue(new PassThroughSelected(rightValues[i - 1])); + tester + .getOrCreate(leftValues[i]) + .addDependency(leftValues[i - 1]) + .addDependency(rightValues[i - 1]) + .setComputedValue(new PassThroughSelected(leftValues[i - 1])); + tester + .getOrCreate(rightValues[i]) + .addDependency(leftValues[i - 1]) + .addDependency(rightValues[i - 1]) + .setComputedValue(new PassThroughSelected(rightValues[i - 1])); } } tester.set("leaf", new StringValue("leaf")); @@ -4261,7 +4466,7 @@ public void twoRailLeftRightDependenciesWithFailure() throws Exception { for (int i = 0; i < TESTED_NODES; i++) { try { - tester.getOrCreate(leftValues[i], /*markAsModified=*/true).setHasError(true); + tester.getOrCreate(leftValues[i], /*markAsModified=*/ true).setHasError(true); tester.invalidate(); EvaluationResult result = tester.eval(/* keepGoing= */ false, lastLeft, lastRight); @@ -4270,7 +4475,7 @@ public void twoRailLeftRightDependenciesWithFailure() throws Exception { tester.invalidate(); result = tester.eval(/* keepGoing= */ false, lastLeft, lastRight); assertThat(result.hasError()).isTrue(); - tester.getOrCreate(leftValues[i], /*markAsModified=*/true).setHasError(false); + tester.getOrCreate(leftValues[i], /*markAsModified=*/ true).setHasError(false); tester.invalidate(); result = tester.eval(/* keepGoing= */ false, lastLeft, lastRight); assertThat(result.get(lastLeft)).isEqualTo(new StringValue("leaf")); @@ -4308,13 +4513,13 @@ public void valueInjectionOverExistingDirtyEntry() throws Exception { tester.getOrCreate(key).setConstantValue(new StringValue("old_val")); tester.differencer.inject(ImmutableMap.of(key, val)); - tester.eval(/*keepGoing=*/false, new SkyKey[0]); // Create the value. + tester.eval(/*keepGoing=*/ false, new SkyKey[0]); // Create the value. tester.differencer.invalidate(ImmutableList.of(key)); - tester.eval(/*keepGoing=*/false, new SkyKey[0]); // Mark value as dirty. + tester.eval(/*keepGoing=*/ false, new SkyKey[0]); // Mark value as dirty. tester.differencer.inject(ImmutableMap.of(key, val)); - tester.eval(/*keepGoing=*/false, new SkyKey[0]); // Inject again. + tester.eval(/*keepGoing=*/ false, new SkyKey[0]); // Inject again. assertThat(tester.evalAndGet(/*keepGoing=*/ false, key)).isEqualTo(val); } @@ -4467,22 +4672,25 @@ protected void runTestPersistentErrorsNotRerun(boolean includeTransientError) th SkyKey persistentErrorKey1 = GraphTester.toSkyKey("persistentError1"); SkyKey persistentErrorKey2 = GraphTester.toSkyKey("persistentError2"); - TestFunction topFunction = tester.getOrCreate(topKey) - .addErrorDependency(persistentErrorKey1, new StringValue("doesn't matter")) - .setHasError(true); + TestFunction topFunction = + tester + .getOrCreate(topKey) + .addErrorDependency(persistentErrorKey1, new StringValue("doesn't matter")) + .setHasError(true); tester.getOrCreate(persistentErrorKey1).setHasError(true); if (includeTransientError) { topFunction.addErrorDependency(transientErrorKey, new StringValue("doesn't matter")); - tester.getOrCreate(transientErrorKey) - .addErrorDependency(persistentErrorKey2, new StringValue("doesn't matter")) - .setHasTransientError(true); + tester + .getOrCreate(transientErrorKey) + .addErrorDependency(persistentErrorKey2, new StringValue("doesn't matter")) + .setHasTransientError(true); } tester.getOrCreate(persistentErrorKey2).setHasError(true); tester.evalAndGetError(/*keepGoing=*/ true, topKey); if (includeTransientError) { - assertThat(tester.getEnqueuedValues()).containsExactly( - topKey, transientErrorKey, persistentErrorKey1, persistentErrorKey2); + assertThat(tester.getEnqueuedValues()) + .containsExactly(topKey, transientErrorKey, persistentErrorKey1, persistentErrorKey2); } else { assertThat(tester.getEnqueuedValues()).containsExactly(topKey, persistentErrorKey1); } @@ -4528,7 +4736,9 @@ public void shutDownBuildOnCachedError_Done() throws Exception { // Names are alphabetized in reverse deps of errorKey. SkyKey fastToRequestSlowToSetValueKey = GraphTester.toSkyKey("A-slow-set-value-parent"); SkyKey failingKey = GraphTester.toSkyKey("B-fast-fail-parent"); - tester.getOrCreate(fastToRequestSlowToSetValueKey).addDependency(errorKey) + tester + .getOrCreate(fastToRequestSlowToSetValueKey) + .addDependency(errorKey) .setComputedValue(CONCATENATE); tester.getOrCreate(failingKey).addDependency(errorKey).setComputedValue(CONCATENATE); // We only want to force a particular order of operations at some points during evaluation. @@ -4567,11 +4777,11 @@ public void shutDownBuildOnCachedError_Done() throws Exception { }, /*deterministic=*/ true); // Initialize graph. - tester.eval(/*keepGoing=*/true, errorKey); - tester.getOrCreate(invalidatedKey, /*markAsModified=*/true); + tester.eval(/*keepGoing=*/ true, errorKey); + tester.getOrCreate(invalidatedKey, /*markAsModified=*/ true); tester.invalidate(); synchronizeThreads.set(true); - tester.eval(/*keepGoing=*/false, fastToRequestSlowToSetValueKey, failingKey); + tester.eval(/*keepGoing=*/ false, fastToRequestSlowToSetValueKey, failingKey); } /** @@ -4599,9 +4809,11 @@ public void shutDownBuildOnCachedError_Verified() throws Exception { final SkyKey cachedParentKey = GraphTester.toSkyKey("A-cached-parent"); final SkyKey uncachedParentKey = GraphTester.toSkyKey("B-uncached-parent"); tester.getOrCreate(errorKey).addDependency(invalidatedKey).setHasError(true); - tester.getOrCreate(cachedParentKey).addDependency(errorKey) - .setComputedValue(CONCATENATE); - tester.getOrCreate(uncachedParentKey).addDependency(changedKey).addDependency(errorKey) + tester.getOrCreate(cachedParentKey).addDependency(errorKey).setComputedValue(CONCATENATE); + tester + .getOrCreate(uncachedParentKey) + .addDependency(changedKey) + .addDependency(errorKey) .setComputedValue(CONCATENATE); // We only want to force a particular order of operations at some points during evaluation. In // particular, we don't want to force anything during error bubbling. @@ -4661,8 +4873,8 @@ public void accept(SkyKey key, EventType type, Order order, Object context) { }, /*deterministic=*/ true); // Initialize graph. - tester.eval(/*keepGoing=*/true, cachedParentKey, uncachedParentKey); - tester.getOrCreate(invalidatedKey, /*markAsModified=*/true); + tester.eval(/*keepGoing=*/ true, cachedParentKey, uncachedParentKey); + tester.getOrCreate(invalidatedKey, /*markAsModified=*/ true); tester.set(changedKey, new StringValue("new value")); tester.invalidate(); synchronizeThreads.set(true); @@ -4690,11 +4902,11 @@ public String extractTag(SkyKey skyKey) { } }); EvaluationResult result = - tester.eval(/*keepGoing=*/false, cachedParentKey, uncachedParentKey, waitForShutdownKey); + tester.eval(/*keepGoing=*/ false, cachedParentKey, uncachedParentKey, waitForShutdownKey); assertWithMessage(result.toString()).that(result.hasError()).isTrue(); - tester.getOrCreate(invalidatedKey, /*markAsModified=*/true); + tester.getOrCreate(invalidatedKey, /*markAsModified=*/ true); tester.invalidate(); - result = tester.eval(/*keepGoing=*/false, cachedParentKey, uncachedParentKey); + result = tester.eval(/*keepGoing=*/ false, cachedParentKey, uncachedParentKey); assertWithMessage(result.toString()).that(result.hasError()).isTrue(); } @@ -4705,12 +4917,12 @@ public String extractTag(SkyKey skyKey) { * Through forced synchronization, we make sure that the following sequence of events happens: * *
    - *
  1. topKey requests errorKey; - *
  2. errorKey is marked clean; - *
  3. topKey finishes its first evaluation and registers its deps; - *
  4. topKey restarts, since it sees that its only dep, errorKey, is done; - *
  5. topKey sees the error thrown by errorKey and throws the error, shutting down the - * threadpool; + *
  6. topKey requests errorKey; + *
  7. errorKey is marked clean; + *
  8. topKey finishes its first evaluation and registers its deps; + *
  9. topKey restarts, since it sees that its only dep, errorKey, is done; + *
  10. topKey sees the error thrown by errorKey and throws the error, shutting down the + * threadpool; *
*/ @Test @@ -4818,12 +5030,12 @@ public String extractTag(SkyKey skyKey) { 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.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); + tester.eval(/*keepGoing=*/ true, parent1Key); + tester.eval(/*keepGoing=*/ false, parent2Key); } private void injectGraphListenerForTesting(Listener listener, boolean deterministic) { @@ -5025,11 +5237,13 @@ public void errorChanged() throws Exception { SkyKey error = GraphTester.nonHermeticKey("error"); tester.getOrCreate(error).setHasError(true); assertThatErrorInfo(tester.evalAndGetError(/*keepGoing=*/ true, error)) - .hasExceptionThat().isNotNull(); + .hasExceptionThat() + .isNotNull(); tester.getOrCreate(error, /*markAsModified=*/ true); tester.invalidate(); assertThatErrorInfo(tester.evalAndGetError(/*keepGoing=*/ true, error)) - .hasExceptionThat().isNotNull(); + .hasExceptionThat() + .isNotNull(); } @Test @@ -5334,17 +5548,15 @@ public EvaluationResult eval(boolean keepGoing, String.. return eval(keepGoing, toSkyKeys(keys).toArray(new SkyKey[0])); } - public SkyValue evalAndGet(boolean keepGoing, String key) - throws InterruptedException { + public SkyValue evalAndGet(boolean keepGoing, String key) throws InterruptedException { return evalAndGet(keepGoing, toSkyKey(key)); } public SkyValue evalAndGet(String key) throws InterruptedException { - return evalAndGet(/*keepGoing=*/false, key); + return evalAndGet(/*keepGoing=*/ false, key); } - public SkyValue evalAndGet(boolean keepGoing, SkyKey key) - throws InterruptedException { + public SkyValue evalAndGet(boolean keepGoing, SkyKey key) throws InterruptedException { EvaluationResult evaluationResult = eval(keepGoing, key); SkyValue result = evaluationResult.get(key); assertWithMessage(evaluationResult.toString()).that(result).isNotNull();