aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java')
-rw-r--r--src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java413
1 files changed, 224 insertions, 189 deletions
diff --git a/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java b/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java
index 9c87572818..c8464b4291 100644
--- a/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java
+++ b/src/test/java/com/google/devtools/build/skyframe/ParallelEvaluatorTest.java
@@ -48,14 +48,6 @@ import com.google.devtools.build.skyframe.NotifyingHelper.Listener;
import com.google.devtools.build.skyframe.NotifyingHelper.Order;
import com.google.devtools.build.skyframe.ParallelEvaluator.EventFilter;
import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -67,8 +59,13 @@ import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
-
import javax.annotation.Nullable;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
/**
* Tests for {@link ParallelEvaluator}.
@@ -202,36 +199,38 @@ public class ParallelEvaluatorTest {
*/
@Test
public void interruptedEvaluatorThread() throws Exception {
- runInterruptionTest(new SkyFunctionFactory() {
- @Override
- public SkyFunction create(final Semaphore threadStarted, final String[] errorMessage) {
- return new SkyFunction() {
- // No need to synchronize access to this field; we always request just one more
- // dependency, so it's only one SkyFunction running at any time.
- private int valueIdCounter = 0;
-
+ runInterruptionTest(
+ new SkyFunctionFactory() {
@Override
- public SkyValue compute(SkyKey key, Environment env) {
- // Signal the waiting test thread that the Evaluator thread has really started.
- threadStarted.release();
+ public SkyFunction create(final Semaphore threadStarted, final String[] errorMessage) {
+ return new SkyFunction() {
+ // No need to synchronize access to this field; we always request just one more
+ // dependency, so it's only one SkyFunction running at any time.
+ private int valueIdCounter = 0;
- // Keep the evaluator busy until the test's thread gets scheduled and can
- // interrupt the Evaluator's thread.
- env.getValue(GraphTester.toSkyKey("a" + valueIdCounter++));
+ @Override
+ public SkyValue compute(SkyKey key, Environment env) throws InterruptedException {
+ // Signal the waiting test thread that the Evaluator thread has really started.
+ threadStarted.release();
- // This method never throws InterruptedException, therefore it's the responsibility
- // of the Evaluator to detect the interrupt and avoid calling subsequent SkyFunctions.
- return null;
- }
+ // Keep the evaluator busy until the test's thread gets scheduled and can
+ // interrupt the Evaluator's thread.
+ env.getValue(GraphTester.toSkyKey("a" + valueIdCounter++));
- @Nullable
- @Override
- public String extractTag(SkyKey skyKey) {
- return null;
+ // This method never throws InterruptedException, therefore it's the responsibility
+ // of the Evaluator to detect the interrupt and avoid calling subsequent
+ // SkyFunctions.
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public String extractTag(SkyKey skyKey) {
+ return null;
+ }
+ };
}
- };
- }
- });
+ });
}
private void runPartialResultOnInterruption(boolean buildFastFirst) throws Exception {
@@ -1263,7 +1262,8 @@ public class ParallelEvaluatorTest {
new SkyFunction() {
@Nullable
@Override
- public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
+ public SkyValue compute(SkyKey skyKey, Environment env)
+ throws SkyFunctionException, InterruptedException {
Map<SkyKey, ValueOrException<SomeErrorException>> values =
env.getValuesOrThrow(
ImmutableList.of(errorKey, otherKey), SomeErrorException.class);
@@ -1488,7 +1488,7 @@ public class ParallelEvaluatorTest {
class ParentFunction implements SkyFunction {
@Override
- public SkyValue compute(SkyKey skyKey, Environment env) {
+ public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
SkyValue dep = env.getValue(SkyKey.create(childType, "billy the kid"));
if (dep == null) {
return null;
@@ -1579,27 +1579,32 @@ public class ParallelEvaluatorTest {
SkyKey topKey = GraphTester.toSkyKey("top");
final SkyKey parentKey = GraphTester.toSkyKey("parent");
tester.getOrCreate(parentKey).addDependency(errorKey).setComputedValue(CONCATENATE);
- tester.getOrCreate(topKey).setBuilder(new SkyFunction() {
- @Override
- public SkyValue compute(SkyKey skyKey, Environment env) throws GenericFunctionException {
- try {
- if (env.getValueOrThrow(parentKey, SomeErrorException.class) == null) {
- return null;
- }
- } catch (SomeErrorException e) {
- assertEquals(e.toString(), exception, e);
- }
- if (keepGoing) {
- return topValue;
- } else {
- throw new GenericFunctionException(topException, Transience.PERSISTENT);
- }
- }
- @Override
- public String extractTag(SkyKey skyKey) {
- throw new UnsupportedOperationException();
- }
- });
+ tester
+ .getOrCreate(topKey)
+ .setBuilder(
+ new SkyFunction() {
+ @Override
+ public SkyValue compute(SkyKey skyKey, Environment env)
+ throws GenericFunctionException, InterruptedException {
+ try {
+ if (env.getValueOrThrow(parentKey, SomeErrorException.class) == null) {
+ return null;
+ }
+ } catch (SomeErrorException e) {
+ assertEquals(e.toString(), exception, e);
+ }
+ if (keepGoing) {
+ return topValue;
+ } else {
+ throw new GenericFunctionException(topException, Transience.PERSISTENT);
+ }
+ }
+
+ @Override
+ public String extractTag(SkyKey skyKey) {
+ throw new UnsupportedOperationException();
+ }
+ });
tester.getOrCreate(topKey).addErrorDependency(errorKey, new StringValue("recovered"))
.setComputedValue(CONCATENATE);
EvaluationResult<StringValue> result = eval(keepGoing, ImmutableList.of(topKey));
@@ -1742,29 +1747,33 @@ public class ParallelEvaluatorTest {
tester.set(dep, new StringValue("child" + i));
}
final SomeErrorException parentExn = new SomeErrorException("parent error");
- tester.getOrCreate(parentKey).setBuilder(new SkyFunction() {
- @Override
- public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
- try {
- SkyValue value = env.getValueOrThrow(errorDep, SomeErrorException.class);
- if (value == null) {
- return null;
- }
- } catch (SomeErrorException e) {
- // Recover from the child error.
- }
- env.getValues(deps);
- if (env.valuesMissing()) {
- return null;
- }
- throw new GenericFunctionException(parentExn, Transience.PERSISTENT);
- }
+ tester
+ .getOrCreate(parentKey)
+ .setBuilder(
+ new SkyFunction() {
+ @Override
+ public SkyValue compute(SkyKey skyKey, Environment env)
+ throws SkyFunctionException, InterruptedException {
+ try {
+ SkyValue value = env.getValueOrThrow(errorDep, SomeErrorException.class);
+ if (value == null) {
+ return null;
+ }
+ } catch (SomeErrorException e) {
+ // Recover from the child error.
+ }
+ env.getValues(deps);
+ if (env.valuesMissing()) {
+ return null;
+ }
+ throw new GenericFunctionException(parentExn, Transience.PERSISTENT);
+ }
- @Override
- public String extractTag(SkyKey skyKey) {
- return null;
- }
- });
+ @Override
+ public String extractTag(SkyKey skyKey) {
+ return null;
+ }
+ });
EvaluationResult<StringValue> evaluationResult = eval(keepGoing, ImmutableList.of(parentKey));
assertTrue(evaluationResult.hasError());
assertEquals(keepGoing ? parentExn : childExn, evaluationResult.getError().getException());
@@ -1891,46 +1900,55 @@ public class ParallelEvaluatorTest {
// The parent should be built exactly twice: once during normal evaluation and once
// during error bubbling.
final AtomicInteger numParentInvocations = new AtomicInteger(0);
- tester.getOrCreate(parentKey).setBuilder(new SkyFunction() {
- @Override
- public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
- int invocations = numParentInvocations.incrementAndGet();
- if (handleChildError) {
- try {
- SkyValue value = env.getValueOrThrow(childKey, SomeErrorException.class);
- // On the first invocation, either the child error should already be cached and not
- // propagated, or it should be computed freshly and not propagated. On the second build
- // (error bubbling), the child error should be propagated.
- assertTrue("bogus non-null value " + value, value == null);
- assertEquals("parent incorrectly re-computed during normal evaluation", 1, invocations);
- assertFalse("child error not propagated during error bubbling",
- env.inErrorBubblingForTesting());
- return value;
- } catch (SomeErrorException e) {
- assertTrue("child error propagated during normal evaluation",
- env.inErrorBubblingForTesting());
- assertEquals(2, invocations);
- return null;
- }
- } else {
- if (invocations == 1) {
- assertFalse("parent's first computation should be during normal evaluation",
- env.inErrorBubblingForTesting());
- return env.getValue(childKey);
- } else {
- assertEquals(2, invocations);
- assertTrue("parent incorrectly re-computed during normal evaluation",
- env.inErrorBubblingForTesting());
- return env.getValue(childKey);
- }
- }
- }
+ tester
+ .getOrCreate(parentKey)
+ .setBuilder(
+ new SkyFunction() {
+ @Override
+ public SkyValue compute(SkyKey skyKey, Environment env)
+ throws SkyFunctionException, InterruptedException {
+ int invocations = numParentInvocations.incrementAndGet();
+ if (handleChildError) {
+ try {
+ SkyValue value = env.getValueOrThrow(childKey, SomeErrorException.class);
+ // On the first invocation, either the child error should already be cached and
+ // not propagated, or it should be computed freshly and not propagated. On the
+ // second build (error bubbling), the child error should be propagated.
+ assertTrue("bogus non-null value " + value, value == null);
+ assertEquals(
+ "parent incorrectly re-computed during normal evaluation", 1, invocations);
+ assertFalse(
+ "child error not propagated during error bubbling",
+ env.inErrorBubblingForTesting());
+ return value;
+ } catch (SomeErrorException e) {
+ assertTrue(
+ "child error propagated during normal evaluation",
+ env.inErrorBubblingForTesting());
+ assertEquals(2, invocations);
+ return null;
+ }
+ } else {
+ if (invocations == 1) {
+ assertFalse(
+ "parent's first computation should be during normal evaluation",
+ env.inErrorBubblingForTesting());
+ return env.getValue(childKey);
+ } else {
+ assertEquals(2, invocations);
+ assertTrue(
+ "parent incorrectly re-computed during normal evaluation",
+ env.inErrorBubblingForTesting());
+ return env.getValue(childKey);
+ }
+ }
+ }
- @Override
- public String extractTag(SkyKey skyKey) {
- return null;
- }
- });
+ @Override
+ public String extractTag(SkyKey skyKey) {
+ return null;
+ }
+ });
if (childErrorCached) {
// Ensure that the child is already in the graph.
evalValueInError(childKey);
@@ -1979,19 +1997,23 @@ public class ParallelEvaluatorTest {
final SkyKey otherKey = GraphTester.toSkyKey("otherKey");
final AtomicInteger numOtherParentInvocations = new AtomicInteger(0);
final AtomicInteger numErrorParentInvocations = new AtomicInteger(0);
- tester.getOrCreate(otherParentKey).setBuilder(new SkyFunction() {
- @Override
- public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
- int invocations = numOtherParentInvocations.incrementAndGet();
- assertEquals("otherParentKey should not be restarted", 1, invocations);
- return env.getValue(otherKey);
- }
+ tester
+ .getOrCreate(otherParentKey)
+ .setBuilder(
+ new SkyFunction() {
+ @Override
+ public SkyValue compute(SkyKey skyKey, Environment env)
+ throws SkyFunctionException, InterruptedException {
+ int invocations = numOtherParentInvocations.incrementAndGet();
+ assertEquals("otherParentKey should not be restarted", 1, invocations);
+ return env.getValue(otherKey);
+ }
- @Override
- public String extractTag(SkyKey skyKey) {
- return null;
- }
- });
+ @Override
+ public String extractTag(SkyKey skyKey) {
+ return null;
+ }
+ });
tester
.getOrCreate(otherKey)
.setBuilder(
@@ -2026,33 +2048,38 @@ public class ParallelEvaluatorTest {
return null;
}
});
- tester.getOrCreate(errorParentKey).setBuilder(new SkyFunction() {
- @Override
- public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
- int invocations = numErrorParentInvocations.incrementAndGet();
- try {
- SkyValue value = env.getValueOrThrow(errorKey, SomeErrorException.class);
- assertTrue("bogus non-null value " + value, value == null);
- if (invocations == 1) {
- return null;
- } else {
- assertFalse(env.inErrorBubblingForTesting());
- fail("RACE CONDITION: errorParentKey was restarted!");
- return null;
- }
- } catch (SomeErrorException e) {
- assertTrue("child error propagated during normal evaluation",
- env.inErrorBubblingForTesting());
- assertEquals(2, invocations);
- return null;
- }
- }
+ tester
+ .getOrCreate(errorParentKey)
+ .setBuilder(
+ new SkyFunction() {
+ @Override
+ public SkyValue compute(SkyKey skyKey, Environment env)
+ throws SkyFunctionException, InterruptedException {
+ int invocations = numErrorParentInvocations.incrementAndGet();
+ try {
+ SkyValue value = env.getValueOrThrow(errorKey, SomeErrorException.class);
+ assertTrue("bogus non-null value " + value, value == null);
+ if (invocations == 1) {
+ return null;
+ } else {
+ assertFalse(env.inErrorBubblingForTesting());
+ fail("RACE CONDITION: errorParentKey was restarted!");
+ return null;
+ }
+ } catch (SomeErrorException e) {
+ assertTrue(
+ "child error propagated during normal evaluation",
+ env.inErrorBubblingForTesting());
+ assertEquals(2, invocations);
+ return null;
+ }
+ }
- @Override
- public String extractTag(SkyKey skyKey) {
- return null;
- }
- });
+ @Override
+ public String extractTag(SkyKey skyKey) {
+ return null;
+ }
+ });
graph =
new NotifyingHelper.NotifyingProcessableGraph(
new InMemoryGraphImpl(),
@@ -2143,41 +2170,49 @@ public class ParallelEvaluatorTest {
final SkyKey parentKey = GraphTester.toSkyKey("parent");
final SkyKey childKey = GraphTester.toSkyKey("child");
final AtomicBoolean errorPropagated = new AtomicBoolean(false);
- tester.getOrCreate(grandparentKey).setBuilder(new SkyFunction() {
- @Override
- public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
- try {
- return env.getValueOrThrow(parentKey, SomeErrorException.class);
- } catch (SomeErrorException e) {
- errorPropagated.set(true);
- throw new GenericFunctionException(e, Transience.PERSISTENT);
- }
- }
+ tester
+ .getOrCreate(grandparentKey)
+ .setBuilder(
+ new SkyFunction() {
+ @Override
+ public SkyValue compute(SkyKey skyKey, Environment env)
+ throws SkyFunctionException, InterruptedException {
+ try {
+ return env.getValueOrThrow(parentKey, SomeErrorException.class);
+ } catch (SomeErrorException e) {
+ errorPropagated.set(true);
+ throw new GenericFunctionException(e, Transience.PERSISTENT);
+ }
+ }
- @Override
- public String extractTag(SkyKey skyKey) {
- return null;
- }
- });
- tester.getOrCreate(parentKey).setBuilder(new SkyFunction() {
- @Override
- public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
- if (explicitlyPropagateError) {
- try {
- return env.getValueOrThrow(childKey, SomeErrorException.class);
- } catch (SomeErrorException e) {
- throw new GenericFunctionException(e, childKey);
- }
- } else {
- return env.getValue(childKey);
- }
- }
+ @Override
+ public String extractTag(SkyKey skyKey) {
+ return null;
+ }
+ });
+ tester
+ .getOrCreate(parentKey)
+ .setBuilder(
+ new SkyFunction() {
+ @Override
+ public SkyValue compute(SkyKey skyKey, Environment env)
+ throws SkyFunctionException, InterruptedException {
+ if (explicitlyPropagateError) {
+ try {
+ return env.getValueOrThrow(childKey, SomeErrorException.class);
+ } catch (SomeErrorException e) {
+ throw new GenericFunctionException(e, childKey);
+ }
+ } else {
+ return env.getValue(childKey);
+ }
+ }
- @Override
- public String extractTag(SkyKey skyKey) {
- return null;
- }
- });
+ @Override
+ public String extractTag(SkyKey skyKey) {
+ return null;
+ }
+ });
tester.getOrCreate(childKey).setHasError(/*hasError=*/true);
EvaluationResult<StringValue> result = eval(keepGoing, ImmutableList.of(grandparentKey));
assertTrue(result.hasError());