Implement proper error handling for interleaved loading and analysis.

Add test coverage by re-running BuildViewTest with the new Skyframe loading
phase runner.

--
MOS_MIGRATED_REVID=113517509
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/BuildViewTest.java b/src/test/java/com/google/devtools/build/lib/analysis/BuildViewTest.java
index 69573f7..6f3d01c 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/BuildViewTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/BuildViewTest.java
@@ -75,7 +75,7 @@
  */
 @TestSpec(size = Suite.SMALL_TESTS)
 @RunWith(JUnit4.class)
-public final class BuildViewTest extends BuildViewTestBase {
+public class BuildViewTest extends BuildViewTestBase {
 
   @Test
   public void testRuleConfiguredTarget() throws Exception {
@@ -438,7 +438,7 @@
     try {
       update("//foo:top");
       fail();
-    } catch (LoadingFailedException e) {
+    } catch (LoadingFailedException | ViewCreationFailedException e) {
       // Expected.
     }
     assertContainsEvent("no such target '//badbuild:isweird': target 'isweird' not declared in "
@@ -837,13 +837,13 @@
         "java_binary(name = 'java', srcs = ['DoesntMatter.java'])",
         "cc_binary(name = 'cpp', data = [':java'])");
     // Everything is fine - the dependency graph is acyclic.
-    update(defaultFlags(), "//foo:java", "//foo:cpp");
+    update("//foo:java", "//foo:cpp");
     // Now there will be an analysis-phase cycle because the java_binary now has an implicit dep on
     // the cc_binary launcher.
     useConfiguration("--java_launcher=//foo:cpp");
     reporter.removeHandler(failFastHandler);
     try {
-      update(defaultFlags(), "//foo:java", "//foo:cpp");
+      update("//foo:java", "//foo:cpp");
       fail();
     } catch (ViewCreationFailedException expected) {
       Truth.assertThat(expected.getMessage())
@@ -852,4 +852,33 @@
     assertContainsEvent("cycle in dependency graph");
     assertContainsEvent("This cycle occurred because of a configuration option");
   }
+
+  @Test
+  public void testDependsOnBrokenTarget() throws Exception {
+    scratch.file("foo/BUILD",
+        "sh_test(name = 'test', srcs = ['test.sh'], data = ['//bar:data'])");
+    scratch.file("bar/BUILD",
+        "BROKEN BROKEN BROKEN!!!");
+    reporter.removeHandler(failFastHandler);
+    try {
+      update("//foo:test");
+      fail();
+    } catch (LoadingFailedException expected) {
+      Truth.assertThat(expected.getMessage())
+          .matches("Loading failed; build aborted.*");
+    } catch (ViewCreationFailedException expected) {
+      Truth.assertThat(expected.getMessage())
+          .matches("Analysis of target '//foo:test' failed; build aborted.*");
+    }
+  }
+
+  /** Runs the same test with the reduced loading phase. */
+  @TestSpec(size = Suite.SMALL_TESTS)
+  @RunWith(JUnit4.class)
+  public static class WithSkyframeLoadingPhase extends BuildViewTest {
+    @Override
+    protected FlagBuilder defaultFlags() {
+      return super.defaultFlags().with(Flag.SKYFRAME_LOADING_PHASE);
+    }
+  }
 }