@Test
  public void whenActivityBuckFileRemovedThenRebuildFails()
      throws IOException, InterruptedException {
    AssumeAndroidPlatform.assumeSdkIsAvailable();
    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "file_watching", tmp);
    workspace.setUp();

    workspace.runBuckdCommand("build", "//java/com/example/activity:activity").assertSuccess();

    String fileName = "java/com/example/activity/BUCK";
    Files.delete(workspace.getPath(fileName));

    workspace.runBuckdCommand("build", "//java/com/example/activity:activity").assertFailure();
  }
  @Test
  public void whenAppBuckFileRemovedThenRebuildFails() throws IOException, InterruptedException {
    AssumeAndroidPlatform.assumeSdkIsAvailable();

    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "file_watching", tmp);
    workspace.setUp();

    ProcessResult result = workspace.runBuckdCommand("build", "app");
    result.assertSuccess();

    String fileName = "apps/myapp/BUCK";
    Files.delete(workspace.getPath(fileName));

    workspace.runBuckdCommand("build", "app").assertFailure();
  }
  @Test
  public void whenSourceInputInvalidatedThenRebuildFails()
      throws IOException, InterruptedException {
    AssumeAndroidPlatform.assumeSdkIsAvailable();
    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "file_watching", tmp);
    workspace.setUp();

    workspace.runBuckdCommand("build", "//java/com/example/activity:activity").assertSuccess();

    String fileName = "java/com/example/activity/MyFirstActivity.java";
    Files.delete(workspace.getPath(fileName));

    thrown.expect(HumanReadableException.class);
    thrown.expectMessage(containsString("MyFirstActivity.java"));

    workspace.runBuckdCommand("build", "//java/com/example/activity:activity");
  }
  @Test
  @Ignore
  public void hasBuckCompilerErrorOccurredThenEventsCalled()
      throws IOException, InterruptedException {
    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "buck_events/compiler_error", tmp);
    workspace.setUp();

    WebServerBuckEventListener webServerBuckEventListener =
        createMock(WebServerBuckEventListener.class);

    // Build started
    webServerBuckEventListener.buildStarted(anyObject(BuildEvent.Started.class));
    EasyMock.expectLastCall().times(1);

    // Build progress Event
    webServerBuckEventListener.buildProgressUpdated(
        anyObject(ProgressEvent.BuildProgressUpdated.class));
    EasyMock.expectLastCall().atLeastOnce();

    // Build finished
    webServerBuckEventListener.buildFinished(anyObject(BuildEvent.Finished.class));
    EasyMock.expectLastCall().times(1);

    // Parse started
    webServerBuckEventListener.parseStarted(anyObject(ParseEvent.Started.class));
    EasyMock.expectLastCall().times(1);

    // Parse progress Event
    webServerBuckEventListener.parsingProgressUpdated(
        anyObject(ProgressEvent.ParsingProgressUpdated.class));
    EasyMock.expectLastCall().atLeastOnce();

    // Parse finished
    webServerBuckEventListener.parseFinished(anyObject(ParseEvent.Finished.class));
    EasyMock.expectLastCall().times(1);

    // Compiler error
    webServerBuckEventListener.compilerErrorEvent(anyObject(CompilerErrorEvent.class));
    EasyMock.expectLastCall().times(1);

    // Console event
    webServerBuckEventListener.consoleEvent(anyObject(ConsoleEvent.class));
    EasyMock.expectLastCall().times(1);

    // Output trace
    webServerBuckEventListener.outputTrace(anyObject(BuildId.class));
    EasyMock.expectLastCall().times(1);

    EasyMock.replay(webServerBuckEventListener);

    ProjectWorkspace.ProcessResult build =
        workspace.runBuckdCommand(new TestContext(), "build", "//:broken");
    build.assertFailure();

    verify(webServerBuckEventListener);
  }
  @Test
  public void whenAppBuckFileInvalidatedThenRebuildFails()
      throws IOException, InterruptedException {
    AssumeAndroidPlatform.assumeSdkIsAvailable();
    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "file_watching", tmp);
    workspace.setUp();

    workspace.runBuckdCommand("build", "app").assertSuccess();

    String fileName = "apps/myapp/BUCK";
    Files.write(workspace.getPath(fileName), "Some Illegal Python".getBytes(Charsets.US_ASCII));

    ProcessResult result = workspace.runBuckdCommand("build", "app");
    assertThat(
        "Failure should be due to syntax error.",
        result.getStderr(),
        containsString("SyntaxError: invalid syntax"));
    result.assertFailure();
  }
  @Test
  public void whenBuckBuiltTwiceLogIsPresent() throws IOException, InterruptedException {
    AssumeAndroidPlatform.assumeSdkIsAvailable();
    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "file_watching", tmp);
    workspace.setUp();

    workspace.runBuckdCommand("build", "//java/com/example/activity:activity").assertSuccess();

    Path buildLogFile = workspace.getPath("buck-out/bin/build.log");

    assertTrue(Files.isRegularFile(buildLogFile));
    Files.delete(buildLogFile);

    ProcessResult rebuild =
        workspace.runBuckdCommand("build", "//java/com/example/activity:activity");
    rebuild.assertSuccess();

    buildLogFile = workspace.getPath("buck-out/bin/build.log");
    assertTrue(Files.isRegularFile(buildLogFile));
  }
  @Test
  public void whenSourceInputRemovedThenRebuildFails() throws IOException, InterruptedException {
    AssumeAndroidPlatform.assumeNdkIsAvailable();
    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "file_watching", tmp);
    workspace.setUp();

    workspace.runBuckdCommand("build", "//java/com/example/activity:activity").assertSuccess();

    String fileName = "java/com/example/activity/MyFirstActivity.java";
    Files.delete(workspace.getPath(fileName));

    try {
      workspace.runBuckdCommand("build", "//java/com/example/activity:activity");
      fail("Should have thrown HumanReadableException.");
    } catch (java.lang.RuntimeException e) {
      assertThat(
          "Failure should have been due to file removal.",
          e.getMessage(),
          containsString("MyFirstActivity.java"));
    }
  }
  @Test
  @Ignore
  public void hasBuckProjectGenerationStartedThenEventsCalled()
      throws IOException, InterruptedException {
    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "buck_events", tmp);
    workspace.setUp();

    WebServerBuckEventListener webServerBuckEventListener =
        createMock(WebServerBuckEventListener.class);

    // Parse started
    webServerBuckEventListener.parseStarted(anyObject(ParseEvent.Started.class));
    EasyMock.expectLastCall().times(1);

    // Parse progress Event
    webServerBuckEventListener.parsingProgressUpdated(
        anyObject(ProgressEvent.ParsingProgressUpdated.class));
    EasyMock.expectLastCall().atLeastOnce();

    // Parse finished
    webServerBuckEventListener.parseFinished(anyObject(ParseEvent.Finished.class));
    EasyMock.expectLastCall().times(1);

    // Project generation started
    webServerBuckEventListener.projectGenerationStarted(
        anyObject(ProjectGenerationEvent.Started.class));
    EasyMock.expectLastCall().times(1);

    // Project generation finished
    webServerBuckEventListener.projectGenerationFinished(
        anyObject(ProjectGenerationEvent.Finished.class));
    EasyMock.expectLastCall().times(1);

    // Output trace
    webServerBuckEventListener.outputTrace(anyObject(BuildId.class));
    EasyMock.expectLastCall().times(1);

    EasyMock.replay(webServerBuckEventListener);

    ProjectWorkspace.ProcessResult build =
        workspace.runBuckdCommand(new TestContext(), "project", "//:foo");
    build.assertSuccess();

    verify(webServerBuckEventListener);
  }
  /**
   * This verifies that a client disconnection will be detected by a Nailgun NGInputStream reading
   * from an empty heartbeat stream and that the generated InterruptedException will interrupt
   * command execution causing it to fail.
   */
  @Test
  public void whenClientDisconnectionDetectedThenTestIsInterrupted()
      throws InterruptedException, IOException {

    // Sub process interruption not supported on Windows.
    assumeTrue(Platform.detect() != Platform.WINDOWS);

    final long timeoutMillis = 2000; // Stream timeout > test timeout.
    final long disconnectMillis = 100; // Disconnect before test timeout.
    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "exclusive_execution", tmp);
    workspace.setUp();

    // Start with an input stream that sends heartbeats at a regular rate.
    final DelegatingInputStream inputStream =
        new DelegatingInputStream(TestContext.createHeartBeatStream(timeoutMillis / 10));

    // Build an NGContext connected to an NGInputStream reading from stream that will timeout.
    try (TestContext context =
        new TestContext(ImmutableMap.copyOf(System.getenv()), inputStream, timeoutMillis)) {
      BuckEventListener listener =
          new BuckEventListener() {
            @Subscribe
            @SuppressWarnings("unused")
            public void onEvent(TestRunEvent.Started event) {
              // When tests start running, make the heartbeat stream simulate a disconnection.
              inputStream.setDelegate(TestContext.createDisconnectionStream(disconnectMillis));
            }

            @Override
            public void outputTrace(BuildId buildId) throws InterruptedException {
              // do nothing
            }
          };
      ProcessResult result = workspace.runBuckdCommand(context, listener, "test", "//:test");
      result.assertFailure();
      assertThat(result.getStderr(), containsString("InterruptedException"));
    }
  }
  /**
   * This verifies that a client timeout will be detected by a Nailgun NGInputStream reading from an
   * empty heartbeat stream and that the generated InterruptedException will cause command execution
   * to fail after timeout.
   */
  @Test
  public void whenClientDisconnectionDetectedThenBuildIsInterrupted()
      throws InterruptedException, IOException {

    // Sub process interruption not supported on Windows.
    assumeTrue(Platform.detect() != Platform.WINDOWS);

    final long timeoutMillis = 2000; // Stream timeout > test timeout.
    final long disconnectMillis = 100; // Disconnect before test timeout.
    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "exclusive_execution", tmp);
    workspace.setUp();

    // Build an NGContext connected to an NGInputStream reading from stream that will timeout.
    try (TestContext context =
        new TestContext(
            ImmutableMap.copyOf(System.getenv()),
            TestContext.createDisconnectionStream(disconnectMillis),
            timeoutMillis)) {
      ProcessResult result = workspace.runBuckdCommand(context, "build", "//:sleep");
      result.assertFailure();
      assertThat(result.getStderr(), containsString("InterruptedException"));
    }
  }
  @Test
  @Ignore
  public void hasBuckTestStartedThenEventsCalled() throws IOException, InterruptedException {
    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "buck_events/test", tmp);
    workspace.setUp();

    WebServerBuckEventListener webServerBuckEventListener =
        createMock(WebServerBuckEventListener.class);

    // Build started
    webServerBuckEventListener.buildStarted(anyObject(BuildEvent.Started.class));
    EasyMock.expectLastCall().times(1);

    // Build progress Event
    webServerBuckEventListener.buildProgressUpdated(
        anyObject(ProgressEvent.BuildProgressUpdated.class));
    EasyMock.expectLastCall().atLeastOnce();

    // Build finished
    webServerBuckEventListener.buildFinished(anyObject(BuildEvent.Finished.class));
    EasyMock.expectLastCall().times(1);

    // Parse started
    webServerBuckEventListener.parseStarted(anyObject(ParseEvent.Started.class));
    EasyMock.expectLastCall().times(1);

    // Parse progress Event
    webServerBuckEventListener.parsingProgressUpdated(
        anyObject(ProgressEvent.ParsingProgressUpdated.class));
    EasyMock.expectLastCall().atLeastOnce();

    // Parse finished
    webServerBuckEventListener.parseFinished(anyObject(ParseEvent.Finished.class));
    EasyMock.expectLastCall().times(1);

    // Individual test started
    // This target has only 1 test
    webServerBuckEventListener.testAwaitingResults(anyObject(IndividualTestEvent.Started.class));
    EasyMock.expectLastCall().times(1);

    // Individual test finished
    webServerBuckEventListener.testResultsAvailable(anyObject(IndividualTestEvent.Finished.class));
    EasyMock.expectLastCall().times(1);

    // Test started
    webServerBuckEventListener.testRunStarted(anyObject(TestRunEvent.Started.class));
    EasyMock.expectLastCall().times(1);

    // Test finished
    webServerBuckEventListener.testRunCompleted(anyObject(TestRunEvent.Finished.class));
    EasyMock.expectLastCall().times(1);

    // Output trace
    webServerBuckEventListener.outputTrace(anyObject(BuildId.class));
    EasyMock.expectLastCall().times(1);

    EasyMock.replay(webServerBuckEventListener);

    ProjectWorkspace.ProcessResult build =
        workspace.runBuckdCommand(new TestContext(), "test", "//:simple_test");
    build.assertSuccess();

    verify(webServerBuckEventListener);
  }