Open source some skyframe/bazel tests.

--
MOS_MIGRATED_REVID=106308990
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/DiffAwarenessManagerTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/DiffAwarenessManagerTest.java
new file mode 100644
index 0000000..bd28c33
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/DiffAwarenessManagerTest.java
@@ -0,0 +1,266 @@
+// Copyright 2015 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.lib.skyframe;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+import com.google.devtools.build.lib.events.util.EventCollectionApparatus;
+import com.google.devtools.build.lib.skyframe.DiffAwarenessManager.ProcessableModifiedFileSet;
+import com.google.devtools.build.lib.vfs.FileSystem;
+import com.google.devtools.build.lib.vfs.ModifiedFileSet;
+import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+/**
+ * Unit tests for {@link DiffAwarenessManager}, especially of the fact that it works in a sequential
+ * manner and of its correctness in the presence of unprocesed diffs.
+ */
+public class DiffAwarenessManagerTest extends TestCase {
+
+  private FileSystem fs;
+  private Path root;
+  protected EventCollectionApparatus events;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    fs = new InMemoryFileSystem();
+    root = fs.getRootDirectory();
+    events = new EventCollectionApparatus();
+    events.setFailFast(false);
+  }
+
+  public void testEverythingModifiedIfNoDiffAwareness() throws Exception {
+    Path pathEntry = root.getRelative("pathEntry");
+    DiffAwarenessFactoryStub factory = new DiffAwarenessFactoryStub();
+    DiffAwarenessManager manager = new DiffAwarenessManager(ImmutableList.of(factory));
+    assertEquals(
+        "Expected EVERYTHING_MODIFIED since there are no factories",
+        ModifiedFileSet.EVERYTHING_MODIFIED,
+        manager.getDiff(events.reporter(), pathEntry).getModifiedFileSet());
+    events.assertNoWarningsOrErrors();
+  }
+
+  public void testResetAndSetPathEntriesCallClose() throws Exception {
+    Path pathEntry = root.getRelative("pathEntry");
+    ModifiedFileSet diff = ModifiedFileSet.NOTHING_MODIFIED;
+    DiffAwarenessStub diffAwareness1 = new DiffAwarenessStub(ImmutableList.of(diff));
+    DiffAwarenessStub diffAwareness2 = new DiffAwarenessStub(ImmutableList.of(diff));
+    DiffAwarenessFactoryStub factory = new DiffAwarenessFactoryStub();
+    factory.inject(pathEntry, diffAwareness1);
+    DiffAwarenessManager manager = new DiffAwarenessManager(ImmutableList.of(factory));
+    manager.getDiff(events.reporter(), pathEntry);
+    assertFalse("diffAwareness1 shouldn't have been closed yet", diffAwareness1.closed());
+    manager.reset();
+    assertTrue("diffAwareness1 should have been closed by reset", diffAwareness1.closed());
+    factory.inject(pathEntry, diffAwareness2);
+    manager.getDiff(events.reporter(), pathEntry);
+    assertFalse("diffAwareness2 shouldn't have been closed yet", diffAwareness2.closed());
+    events.assertNoWarningsOrErrors();
+  }
+
+  public void testHandlesUnprocessedDiffs() throws Exception {
+    Path pathEntry = root.getRelative("pathEntry");
+    ModifiedFileSet diff1 = ModifiedFileSet.builder().modify(new PathFragment("file1")).build();
+    ModifiedFileSet diff2 = ModifiedFileSet.builder().modify(new PathFragment("file2")).build();
+    ModifiedFileSet diff3 = ModifiedFileSet.builder().modify(new PathFragment("file3")).build();
+    DiffAwarenessStub diffAwareness =
+        new DiffAwarenessStub(ImmutableList.of(diff1, diff2, diff3, DiffAwarenessStub.BROKEN_DIFF));
+    DiffAwarenessFactoryStub factory = new DiffAwarenessFactoryStub();
+    factory.inject(pathEntry, diffAwareness);
+    DiffAwarenessManager manager = new DiffAwarenessManager(ImmutableList.of(factory));
+    ProcessableModifiedFileSet firstProcessableDiff = manager.getDiff(events.reporter(), pathEntry);
+    assertEquals(
+        "Expected EVERYTHING_MODIFIED on first call to getDiff",
+        ModifiedFileSet.EVERYTHING_MODIFIED,
+        firstProcessableDiff.getModifiedFileSet());
+    firstProcessableDiff.markProcessed();
+    ProcessableModifiedFileSet processableDiff1 = manager.getDiff(events.reporter(), pathEntry);
+    assertEquals(diff1, processableDiff1.getModifiedFileSet());
+    ProcessableModifiedFileSet processableDiff2 = manager.getDiff(events.reporter(), pathEntry);
+    assertEquals(ModifiedFileSet.union(diff1, diff2), processableDiff2.getModifiedFileSet());
+    processableDiff2.markProcessed();
+    ProcessableModifiedFileSet processableDiff3 = manager.getDiff(events.reporter(), pathEntry);
+    assertEquals(diff3, processableDiff3.getModifiedFileSet());
+    events.assertNoWarningsOrErrors();
+    ProcessableModifiedFileSet processableDiff4 = manager.getDiff(events.reporter(), pathEntry);
+    assertEquals(ModifiedFileSet.EVERYTHING_MODIFIED, processableDiff4.getModifiedFileSet());
+    events.assertContainsWarning("error");
+  }
+
+  public void testHandlesBrokenDiffs() throws Exception {
+    Path pathEntry = root.getRelative("pathEntry");
+    DiffAwarenessFactoryStub factory1 = new DiffAwarenessFactoryStub();
+    DiffAwarenessStub diffAwareness1 =
+        new DiffAwarenessStub(ImmutableList.<ModifiedFileSet>of(), 1);
+    factory1.inject(pathEntry, diffAwareness1);
+    DiffAwarenessFactoryStub factory2 = new DiffAwarenessFactoryStub();
+    ModifiedFileSet diff2 = ModifiedFileSet.builder().modify(new PathFragment("file2")).build();
+    DiffAwarenessStub diffAwareness2 =
+        new DiffAwarenessStub(ImmutableList.of(diff2, DiffAwarenessStub.BROKEN_DIFF));
+    factory2.inject(pathEntry, diffAwareness2);
+    DiffAwarenessFactoryStub factory3 = new DiffAwarenessFactoryStub();
+    ModifiedFileSet diff3 = ModifiedFileSet.builder().modify(new PathFragment("file3")).build();
+    DiffAwarenessStub diffAwareness3 = new DiffAwarenessStub(ImmutableList.of(diff3));
+    factory3.inject(pathEntry, diffAwareness3);
+    DiffAwarenessManager manager =
+        new DiffAwarenessManager(ImmutableList.of(factory1, factory2, factory3));
+
+    ProcessableModifiedFileSet processableDiff = manager.getDiff(events.reporter(), pathEntry);
+    events.assertNoWarningsOrErrors();
+    assertEquals(
+        "Expected EVERYTHING_MODIFIED on first call to getDiff for diffAwareness1",
+        ModifiedFileSet.EVERYTHING_MODIFIED,
+        processableDiff.getModifiedFileSet());
+    processableDiff.markProcessed();
+
+    processableDiff = manager.getDiff(events.reporter(), pathEntry);
+    events.assertContainsEventWithFrequency("error in getCurrentView", 1);
+    assertEquals(
+        "Expected EVERYTHING_MODIFIED because of broken getCurrentView",
+        ModifiedFileSet.EVERYTHING_MODIFIED,
+        processableDiff.getModifiedFileSet());
+    processableDiff.markProcessed();
+    factory1.remove(pathEntry);
+
+    processableDiff = manager.getDiff(events.reporter(), pathEntry);
+    assertEquals(
+        "Expected EVERYTHING_MODIFIED on first call to getDiff for diffAwareness2",
+        ModifiedFileSet.EVERYTHING_MODIFIED,
+        processableDiff.getModifiedFileSet());
+    processableDiff.markProcessed();
+
+    processableDiff = manager.getDiff(events.reporter(), pathEntry);
+    assertEquals(diff2, processableDiff.getModifiedFileSet());
+    processableDiff.markProcessed();
+
+    processableDiff = manager.getDiff(events.reporter(), pathEntry);
+    events.assertContainsEventWithFrequency("error in getDiff", 1);
+    assertEquals(
+        "Expected EVERYTHING_MODIFIED because of broken getDiff",
+        ModifiedFileSet.EVERYTHING_MODIFIED,
+        processableDiff.getModifiedFileSet());
+    processableDiff.markProcessed();
+    factory2.remove(pathEntry);
+
+    processableDiff = manager.getDiff(events.reporter(), pathEntry);
+    assertEquals(
+        "Expected EVERYTHING_MODIFIED on first call to getDiff for diffAwareness3",
+        ModifiedFileSet.EVERYTHING_MODIFIED,
+        processableDiff.getModifiedFileSet());
+    processableDiff.markProcessed();
+
+    processableDiff = manager.getDiff(events.reporter(), pathEntry);
+    assertEquals(diff3, processableDiff.getModifiedFileSet());
+    processableDiff.markProcessed();
+  }
+
+  private static class DiffAwarenessFactoryStub implements DiffAwareness.Factory {
+
+    private Map<Path, DiffAwareness> diffAwarenesses = Maps.newHashMap();
+
+    public void inject(Path pathEntry, DiffAwareness diffAwareness) {
+      diffAwarenesses.put(pathEntry, diffAwareness);
+    }
+
+    public void remove(Path pathEntry) {
+      diffAwarenesses.remove(pathEntry);
+    }
+
+    @Override
+    @Nullable
+    public DiffAwareness maybeCreate(Path pathEntry) {
+      return diffAwarenesses.get(pathEntry);
+    }
+  }
+
+  private static class DiffAwarenessStub implements DiffAwareness {
+
+    public static final ModifiedFileSet BROKEN_DIFF =
+        ModifiedFileSet.builder().modify(new PathFragment("special broken marker")).build();
+
+    private boolean closed = false;
+    private int curSequenceNum = 0;
+    private final List<ModifiedFileSet> sequentialDiffs;
+    private final int brokenViewNum;
+
+    public DiffAwarenessStub(List<ModifiedFileSet> sequentialDiffs) {
+      this(sequentialDiffs, -1);
+    }
+
+    public DiffAwarenessStub(List<ModifiedFileSet> sequentialDiffs, int brokenViewNum) {
+      this.sequentialDiffs = sequentialDiffs;
+      this.brokenViewNum = brokenViewNum;
+    }
+
+    private static class ViewStub implements DiffAwareness.View {
+      private final int sequenceNum;
+
+      public ViewStub(int sequenceNum) {
+        this.sequenceNum = sequenceNum;
+      }
+    }
+
+    @Override
+    public View getCurrentView() throws BrokenDiffAwarenessException {
+      if (curSequenceNum == brokenViewNum) {
+        throw new BrokenDiffAwarenessException("error in getCurrentView");
+      }
+      return new ViewStub(curSequenceNum++);
+    }
+
+    @Override
+    public ModifiedFileSet getDiff(View oldView, View newView) throws BrokenDiffAwarenessException {
+      assertThat(oldView).isInstanceOf(ViewStub.class);
+      assertThat(newView).isInstanceOf(ViewStub.class);
+      ViewStub oldViewStub = (ViewStub) oldView;
+      ViewStub newViewStub = (ViewStub) newView;
+      Preconditions.checkState(newViewStub.sequenceNum >= oldViewStub.sequenceNum);
+      ModifiedFileSet diff = ModifiedFileSet.NOTHING_MODIFIED;
+      for (int num = oldViewStub.sequenceNum; num < newViewStub.sequenceNum; num++) {
+        ModifiedFileSet incrementalDiff = sequentialDiffs.get(num);
+        if (incrementalDiff == BROKEN_DIFF) {
+          throw new BrokenDiffAwarenessException("error in getDiff");
+        }
+        diff = ModifiedFileSet.union(diff, incrementalDiff);
+      }
+      return diff;
+    }
+
+    @Override
+    public String name() {
+      return "testingstub";
+    }
+
+    @Override
+    public void close() {
+      closed = true;
+    }
+
+    public boolean closed() {
+      return closed;
+    }
+  }
+}