Search in sources :

Example 1 with Order

use of com.google.devtools.build.skyframe.NotifyingHelper.Order in project bazel by bazelbuild.

the class MemoizingEvaluatorTest method cachedErrorCausesRestart.

/**
   * Tests that a race between a node being marked clean and another node requesting it is benign.
   * Here, we first evaluate errorKey, depending on invalidatedKey. Then we invalidate
   * invalidatedKey (without actually changing it) and evaluate errorKey and topKey together.
   * Through forced synchronization, we make sure that the following sequence of events happens:
   *
   * <ol>
   * <li>topKey requests errorKey;
   * <li>errorKey is marked clean;
   * <li>topKey finishes its first evaluation and registers its deps;
   * <li>topKey restarts, since it sees that its only dep, errorKey, is done;
   * <li>topKey sees the error thrown by errorKey and throws the error, shutting down the
   *     threadpool;
   * </ol>
   */
@Test
public void cachedErrorCausesRestart() throws Exception {
    // TrackingProgressReceiver does unnecessary examination of node values.
    initializeTester(new TrackingProgressReceiver() {

        @Override
        public void evaluated(SkyKey skyKey, Supplier<SkyValue> skyValueSupplier, EvaluationState state) {
            evaluated.add(skyKey);
        }
    });
    final SkyKey errorKey = GraphTester.toSkyKey("error");
    SkyKey invalidatedKey = GraphTester.toSkyKey("invalidated");
    final SkyKey topKey = GraphTester.toSkyKey("top");
    tester.getOrCreate(errorKey).addDependency(invalidatedKey).setHasError(true);
    tester.getOrCreate(invalidatedKey).setConstantValue(new StringValue("constant"));
    final CountDownLatch topSecondEval = new CountDownLatch(2);
    final CountDownLatch topRequestedError = new CountDownLatch(1);
    final CountDownLatch errorMarkedClean = new CountDownLatch(1);
    injectGraphListenerForTesting(new Listener() {

        @Override
        public void accept(SkyKey key, EventType type, Order order, Object context) {
            if (errorKey.equals(key) && type == EventType.MARK_CLEAN) {
                if (order == Order.BEFORE) {
                    TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(topRequestedError, "top didn't request");
                } else {
                    errorMarkedClean.countDown();
                    TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(topSecondEval, "top didn't restart");
                    // Make sure that the other thread notices the error and interrupts this thread.
                    try {
                        Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
        }
    }, /*deterministic=*/
    false);
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/
    false, errorKey);
    assertThatEvaluationResult(result).hasError();
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(errorKey).hasExceptionThat().isNotNull();
    tester.getOrCreate(topKey).setBuilder(new SkyFunction() {

        @Nullable
        @Override
        public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException, InterruptedException {
            topSecondEval.countDown();
            env.getValue(errorKey);
            topRequestedError.countDown();
            assertThat(env.valuesMissing()).isTrue();
            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(errorMarkedClean, "error not marked clean");
            return null;
        }

        @Nullable
        @Override
        public String extractTag(SkyKey skyKey) {
            return null;
        }
    });
    tester.getOrCreate(invalidatedKey, /*markAsModified=*/
    true);
    tester.invalidate();
    EvaluationResult<StringValue> result2 = tester.eval(/*keepGoing=*/
    false, errorKey, topKey);
    assertThatEvaluationResult(result2).hasError();
    assertThatEvaluationResult(result2).hasErrorEntryForKeyThat(errorKey).hasExceptionThat().isNotNull();
    assertThatEvaluationResult(result2).hasErrorEntryForKeyThat(topKey).hasExceptionThat().isNotNull();
    assertThatEvaluationResult(result2).hasErrorEntryForKeyThat(topKey).rootCauseOfExceptionIs(errorKey);
}
Also used : Order(com.google.devtools.build.skyframe.NotifyingHelper.Order) Listener(com.google.devtools.build.skyframe.NotifyingHelper.Listener) EventType(com.google.devtools.build.skyframe.NotifyingHelper.EventType) CountDownLatch(java.util.concurrent.CountDownLatch) Environment(com.google.devtools.build.skyframe.SkyFunction.Environment) NotComparableStringValue(com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue) StringValue(com.google.devtools.build.skyframe.GraphTester.StringValue) Nullable(javax.annotation.Nullable) Test(org.junit.Test)

Example 2 with Order

use of com.google.devtools.build.skyframe.NotifyingHelper.Order in project bazel by bazelbuild.

the class MemoizingEvaluatorTest method raceConditionWithNoKeepGoingErrors_InflightError.

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

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

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

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

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

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

Example 3 with Order

use of com.google.devtools.build.skyframe.NotifyingHelper.Order in project bazel by bazelbuild.

the class MemoizingEvaluatorTest method dirtyAndChangedValueIsChanged.

/**
   * Test whether a value that was already marked changed will be incorrectly marked dirty, not
   * changed, if another thread tries to mark it just dirty. To exercise this, we need to have a
   * race condition where both threads see that the value is not dirty yet, then the "changed"
   * thread marks the value changed before the "dirty" thread marks the value dirty. To accomplish
   * this, we use a countdown latch to make the "dirty" thread wait until the "changed" thread is
   * done, and another countdown latch to make both of them wait until they have both checked if the
   * value is currently clean.
   */
@Test
public void dirtyAndChangedValueIsChanged() throws Exception {
    final SkyKey parent = GraphTester.toSkyKey("parent");
    final AtomicBoolean blockingEnabled = new AtomicBoolean(false);
    final CountDownLatch waitForChanged = new CountDownLatch(1);
    // changed thread checks value entry once (to see if it is changed). dirty thread checks twice,
    // to see if it is changed, and if it is dirty.
    final CountDownLatch threadsStarted = new CountDownLatch(3);
    injectGraphListenerForTesting(new Listener() {

        @Override
        public void accept(SkyKey key, EventType type, Order order, Object context) {
            if (!blockingEnabled.get()) {
                return;
            }
            if (!key.equals(parent)) {
                return;
            }
            if (type == EventType.IS_CHANGED && order == Order.BEFORE) {
                threadsStarted.countDown();
            }
            // Dirtiness only checked by dirty thread.
            if (type == EventType.IS_DIRTY && order == Order.BEFORE) {
                threadsStarted.countDown();
            }
            if (type == EventType.MARK_DIRTY) {
                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(threadsStarted, "Both threads did not query if value isChanged in time");
                boolean isChanged = (Boolean) context;
                if (order == Order.BEFORE && !isChanged) {
                    TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(waitForChanged, "'changed' thread did not mark value changed in time");
                    return;
                }
                if (order == Order.AFTER && isChanged) {
                    waitForChanged.countDown();
                }
            }
        }
    }, /*deterministic=*/
    false);
    SkyKey leaf = GraphTester.toSkyKey("leaf");
    tester.set(leaf, new StringValue("leaf"));
    tester.getOrCreate(parent).addDependency(leaf).setComputedValue(CONCATENATE);
    EvaluationResult<StringValue> result;
    result = tester.eval(/*keepGoing=*/
    false, parent);
    assertEquals("leaf", result.get(parent).getValue());
    // Invalidate leaf, but don't actually change it. It will transitively dirty parent
    // concurrently with parent directly dirtying itself.
    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.invalidate();
    blockingEnabled.set(true);
    result = tester.eval(/*keepGoing=*/
    false, parent);
    assertEquals("leafother2", result.get(parent).getValue());
    assertEquals(0, waitForChanged.getCount());
    assertEquals(0, threadsStarted.getCount());
}
Also used : Order(com.google.devtools.build.skyframe.NotifyingHelper.Order) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Listener(com.google.devtools.build.skyframe.NotifyingHelper.Listener) EventType(com.google.devtools.build.skyframe.NotifyingHelper.EventType) CountDownLatch(java.util.concurrent.CountDownLatch) NotComparableStringValue(com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue) StringValue(com.google.devtools.build.skyframe.GraphTester.StringValue) Test(org.junit.Test)

Example 4 with Order

use of com.google.devtools.build.skyframe.NotifyingHelper.Order in project bazel by bazelbuild.

the class MemoizingEvaluatorTest method raceClearingIncompleteValues.

/**
   * 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 {
    // Make sure top is enqueued before mid, to avoid a deadlock.
    SkyKey topKey = GraphTester.toSkyKey("aatop");
    final SkyKey midKey = GraphTester.toSkyKey("zzmid");
    SkyKey badKey = GraphTester.toSkyKey("bad");
    final AtomicBoolean waitForSecondCall = new AtomicBoolean(false);
    final CountDownLatch otherThreadWinning = new CountDownLatch(1);
    final AtomicReference<Thread> firstThread = new AtomicReference<>();
    injectGraphListenerForTesting(new Listener() {

        @Override
        public void accept(SkyKey key, EventType type, Order order, Object context) {
            if (!waitForSecondCall.get()) {
                return;
            }
            if (key.equals(midKey)) {
                if (type == EventType.CREATE_IF_ABSENT) {
                    // The first thread to create midKey will not be the first thread to add a
                    // reverse dep to it.
                    firstThread.compareAndSet(null, Thread.currentThread());
                    return;
                }
                if (type == EventType.ADD_REVERSE_DEP) {
                    if (order == Order.BEFORE && Thread.currentThread().equals(firstThread.get())) {
                        // If this thread created midKey, block until the other thread adds a dep on
                        // it.
                        TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(otherThreadWinning, "other thread didn't pass this one");
                    } else if (order == Order.AFTER && !Thread.currentThread().equals(firstThread.get())) {
                        // This thread has added a dep. Allow the other thread to proceed.
                        otherThreadWinning.countDown();
                    }
                }
            }
        }
    }, /*deterministic=*/
    true);
    tester.getOrCreate(topKey).addDependency(midKey).setComputedValue(CONCATENATE);
    tester.getOrCreate(midKey).addDependency(badKey).setComputedValue(CONCATENATE);
    tester.getOrCreate(badKey).setHasError(true);
    EvaluationResult<SkyValue> result = tester.eval(/*keepGoing=*/
    false, topKey, midKey);
    assertThat(result.getError(midKey).getRootCauses()).containsExactly(badKey);
    waitForSecondCall.set(true);
    result = tester.eval(/*keepGoing=*/
    true, topKey, midKey);
    assertNotNull(firstThread.get());
    assertEquals(0, otherThreadWinning.getCount());
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(midKey).isNotNull();
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(topKey).isNotNull();
    if (rootCausesStored()) {
        assertThatEvaluationResult(result).hasErrorEntryForKeyThat(midKey).rootCauseOfExceptionIs(badKey);
        assertThatEvaluationResult(result).hasErrorEntryForKeyThat(topKey).rootCauseOfExceptionIs(badKey);
    }
}
Also used : Order(com.google.devtools.build.skyframe.NotifyingHelper.Order) Listener(com.google.devtools.build.skyframe.NotifyingHelper.Listener) EventType(com.google.devtools.build.skyframe.NotifyingHelper.EventType) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) TestThread(com.google.devtools.build.lib.testutil.TestThread) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Test(org.junit.Test)

Example 5 with Order

use of com.google.devtools.build.skyframe.NotifyingHelper.Order in project bazel by bazelbuild.

the class MemoizingEvaluatorTest method shutDownBuildOnCachedError_Verified.

/**
   * Test that the invalidated parent of a cached but invalidated error doesn't get marked clean.
   * First build the parent -- it will contain an error. Then invalidate the error via a dependency
   * (so it will not actually change) and then build the parent and another node that depends on the
   * error. The other node will wait to throw until the parent is signaled that all of its
   * dependencies are done, or until it is interrupted. If it throws, the parent will be
   * VERIFIED_CLEAN but not done, which is not a valid state once evaluation shuts down. The
   * evaluator avoids this situation by throwing when the error is encountered, even though the
   * error isn't evaluated or requested by an evaluating node.
   */
@Test
public void shutDownBuildOnCachedError_Verified() throws Exception {
    // TrackingProgressReceiver does unnecessary examination of node values.
    initializeTester(new TrackingProgressReceiver() {

        @Override
        public void evaluated(SkyKey skyKey, Supplier<SkyValue> skyValueSupplier, EvaluationState state) {
            evaluated.add(skyKey);
        }
    });
    // errorKey will be invalidated due to its dependence on invalidatedKey, but later revalidated
    // since invalidatedKey re-evaluates to the same value on a subsequent build.
    SkyKey errorKey = GraphTester.toSkyKey("error");
    SkyKey invalidatedKey = GraphTester.toSkyKey("invalidated-leaf");
    SkyKey changedKey = GraphTester.toSkyKey("changed-leaf");
    tester.set(invalidatedKey, new StringValue("invalidated-leaf-value"));
    tester.set(changedKey, new StringValue("changed-leaf-value"));
    // Names are alphabetized in reverse deps of errorKey.
    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).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.
    final AtomicBoolean synchronizeThreads = new AtomicBoolean(false);
    final CountDownLatch shutdownAwaiterStarted = new CountDownLatch(1);
    injectGraphListenerForTesting(new Listener() {

        private final CountDownLatch cachedSignaled = new CountDownLatch(1);

        @Override
        public void accept(SkyKey key, EventType type, Order order, Object context) {
            if (!synchronizeThreads.get() || order != Order.BEFORE || type != EventType.SIGNAL) {
                return;
            }
            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(shutdownAwaiterStarted, "shutdown awaiter not started");
            if (key.equals(uncachedParentKey)) {
                // we wait until the cached parent is signaled too.
                try {
                    assertTrue(cachedSignaled.await(TestUtils.WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS));
                } catch (InterruptedException e) {
                    // Before the relevant bug was fixed, this code was not interrupted, and the
                    // uncached parent got to build, yielding an inconsistent state at a later point
                    // during evaluation. With the bugfix, the cached parent is never signaled
                    // before the evaluator shuts down, and so the above code is interrupted.
                    Thread.currentThread().interrupt();
                }
            } else if (key.equals(cachedParentKey)) {
                // This branch should never be reached by a well-behaved evaluator, since when the
                // error node is reached, the evaluator should shut down. However, we don't test
                // for that behavior here because that would be brittle and we expect that such an
                // evaluator will crash hard later on in any case.
                cachedSignaled.countDown();
                try {
                    // Sleep until we're interrupted by the evaluator, so we know it's shutting
                    // down.
                    Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
                    Thread currentThread = Thread.currentThread();
                    throw new IllegalStateException("no interruption in time in " + key + " for " + (currentThread.isInterrupted() ? "" : "un") + "interrupted " + currentThread + " with hash " + System.identityHashCode(currentThread) + " at " + System.currentTimeMillis());
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }, /*deterministic=*/
    true);
    // Initialize graph.
    tester.eval(/*keepGoing=*/
    true, cachedParentKey, uncachedParentKey);
    tester.getOrCreate(invalidatedKey, /*markAsModified=*/
    true);
    tester.set(changedKey, new StringValue("new value"));
    tester.invalidate();
    synchronizeThreads.set(true);
    SkyKey waitForShutdownKey = GraphTester.skyKey("wait-for-shutdown");
    tester.getOrCreate(waitForShutdownKey).setBuilder(new SkyFunction() {

        @Override
        public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
            shutdownAwaiterStarted.countDown();
            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(((SkyFunctionEnvironment) env).getExceptionLatchForTesting(), "exception not thrown");
            // Threadpool is shutting down. Don't try to synchronize anything in the future
            // during error bubbling.
            synchronizeThreads.set(false);
            throw new InterruptedException();
        }

        @Nullable
        @Override
        public String extractTag(SkyKey skyKey) {
            return null;
        }
    });
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/
    false, cachedParentKey, uncachedParentKey, waitForShutdownKey);
    assertWithMessage(result.toString()).that(result.hasError()).isTrue();
    tester.getOrCreate(invalidatedKey, /*markAsModified=*/
    true);
    tester.invalidate();
    result = tester.eval(/*keepGoing=*/
    false, cachedParentKey, uncachedParentKey);
    assertWithMessage(result.toString()).that(result.hasError()).isTrue();
}
Also used : Order(com.google.devtools.build.skyframe.NotifyingHelper.Order) Listener(com.google.devtools.build.skyframe.NotifyingHelper.Listener) EventType(com.google.devtools.build.skyframe.NotifyingHelper.EventType) CountDownLatch(java.util.concurrent.CountDownLatch) TestThread(com.google.devtools.build.lib.testutil.TestThread) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Environment(com.google.devtools.build.skyframe.SkyFunction.Environment) NotComparableStringValue(com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue) StringValue(com.google.devtools.build.skyframe.GraphTester.StringValue) Nullable(javax.annotation.Nullable) Test(org.junit.Test)

Aggregations

EventType (com.google.devtools.build.skyframe.NotifyingHelper.EventType)15 Listener (com.google.devtools.build.skyframe.NotifyingHelper.Listener)15 Order (com.google.devtools.build.skyframe.NotifyingHelper.Order)15 Test (org.junit.Test)14 CountDownLatch (java.util.concurrent.CountDownLatch)12 StringValue (com.google.devtools.build.skyframe.GraphTester.StringValue)11 NotComparableStringValue (com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue)10 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)9 Environment (com.google.devtools.build.skyframe.SkyFunction.Environment)6 TestThread (com.google.devtools.build.lib.testutil.TestThread)3 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)3 SkyKey (com.google.devtools.build.skyframe.SkyKey)2 AtomicReference (java.util.concurrent.atomic.AtomicReference)2 Nullable (javax.annotation.Nullable)2 ImmutableMap (com.google.common.collect.ImmutableMap)1 DelegatingEventHandler (com.google.devtools.build.lib.events.DelegatingEventHandler)1 Event (com.google.devtools.build.lib.events.Event)1 TargetPatternKey (com.google.devtools.build.lib.skyframe.TargetPatternValue.TargetPatternKey)1 MoreAsserts.assertContainsEvent (com.google.devtools.build.lib.testutil.MoreAsserts.assertContainsEvent)1 ErrorInfoSubjectFactory.assertThatErrorInfo (com.google.devtools.build.skyframe.ErrorInfoSubjectFactory.assertThatErrorInfo)1