// Copyright 2020 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.bugreport;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.testing.TestLogHandler;
import com.google.devtools.build.lib.bugreport.BugReport.BlazeRuntimeInterface;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.build.lib.server.FailureDetails;
import com.google.devtools.build.lib.server.FailureDetails.Crash.Code;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.testutil.TestThread;
import com.google.devtools.build.lib.testutil.TestUtils;
import com.google.devtools.build.lib.util.CrashFailureDetails;
import com.google.devtools.build.lib.util.CustomExitCodePublisher;
import com.google.devtools.build.lib.util.CustomFailureDetailPublisher;
import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.build.lib.util.LoggingUtil;
import com.google.protobuf.ExtensionRegistry;
import com.google.testing.junit.runner.util.GoogleTestSecurityManager;
import com.google.testing.junit.testparameterinjector.TestParameter;
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.Permission;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.function.ThrowingRunnable;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;

/**
 * Tests for {@link BugReport}.
 *
 * <p>Assuming that {@link GoogleTestSecurityManager} is not already installed, uses {@link
 * ExitProhibitingSecurityManager} to exercise attempting to halt the JVM without aborting the whole
 * test.
 */
// TODO(b/222158599): Remove handling for GoogleTestSecurityManager.
@RunWith(TestParameterInjector.class)
public final class BugReportTest {

  private static final ExitCode EXIT_CODE_BLAZE_OOMING = ExitCode.OOM_ERROR;
  private static final Code FAILURE_DETAIL_CODE_BLAZE_OOMING = Code.CRASH_OOM;

  @TestParameter private boolean oomDetectorOverride;

  @BeforeClass
  public static void installCustomSecurityManager() {
    if (System.getSecurityManager() == null) {
      System.setSecurityManager(new ExitProhibitingSecurityManager());
    } else {
      assertThat(System.getSecurityManager()).isInstanceOf(GoogleTestSecurityManager.class);
    }
  }

  @Before
  public void maybeSetOomDetector() {
    if (oomDetectorOverride) {
      CrashFailureDetails.setOomDetector(() -> true);
    }
  }

  @AfterClass
  public static void uninstallCustomSecurityManager() {
    if (System.getSecurityManager() instanceof ExitProhibitingSecurityManager) {
      System.setSecurityManager(null);
    }
  }

  @After
  public void restoreDefaultOomDetector() {
    if (oomDetectorOverride) {
      CrashFailureDetails.setOomDetector(() -> false);
    }
  }

  private enum CrashType {
    CRASH(ExitCode.BLAZE_INTERNAL_ERROR, Code.CRASH_UNKNOWN) {
      @Override
      Throwable createThrowable() {
        return new IllegalStateException("Crashed");
      }
    },
    OOM(ExitCode.OOM_ERROR, Code.CRASH_OOM) {
      @Override
      Throwable createThrowable() {
        return new OutOfMemoryError("Java heap space");
      }
    };

    private final ExitCode expectedExitCode;
    private final Code expectedFailureDetailCode;

    CrashType(ExitCode expectedExitCode, Code expectedFailureDetailCode) {
      this.expectedExitCode = expectedExitCode;
      this.expectedFailureDetailCode = expectedFailureDetailCode;
    }

    abstract Throwable createThrowable();
  }

  private enum ExceptionType {
    FATAL(
        new RuntimeException("fatal exception"),
        /* isFatal= */ true,
        Level.SEVERE,
        "myProductName crashed with args: arg foo"),
    NONFATAL(
        new IllegalStateException("bug report"),
        /* isFatal= */ false,
        Level.WARNING,
        "myProductName had a non fatal error with args: arg foo"),
    OOM(
        new OutOfMemoryError("Java heap space"),
        /* isFatal= */ true,
        Level.SEVERE,
        "myProductName OOMError: arg foo");

    @SuppressWarnings("ImmutableEnumChecker") // I'm pretty sure no one will mutate this Throwable.
    private final Throwable throwable;

    @SuppressWarnings("ImmutableEnumChecker") // Same here.
    private final Level level;

    private final boolean isFatal;

    private final String expectedMessage;

    ExceptionType(Throwable throwable, boolean isFatal, Level level, String expectedMessage) {
      this.throwable = throwable;
      this.isFatal = isFatal;
      this.level = level;
      this.expectedMessage = expectedMessage;
    }

    private String getExpectedMessage() {
      return expectedMessage;
    }

    private String getExpectedMessageWhileOoming() {
      return "While OOMing, " + expectedMessage;
    }
  }

  @Rule public final TemporaryFolder tmp = new TemporaryFolder();

  private final BlazeRuntimeInterface mockRuntime = mock(BlazeRuntimeInterface.class);

  private Path exitCodeFile;
  private Path failureDetailFile;

  @Before
  public void setup() throws Exception {
    when(mockRuntime.getProductName()).thenReturn("myProductName");
    BugReport.setRuntime(mockRuntime);

    exitCodeFile = tmp.newFolder().toPath().resolve("exit_code_to_use_on_abrupt_exit");
    failureDetailFile = tmp.newFolder().toPath().resolve("failure_detail");

    CustomExitCodePublisher.setAbruptExitStatusFileDir(exitCodeFile.getParent().toString());
    CustomFailureDetailPublisher.setFailureDetailFilePath(failureDetailFile.toString());
  }

  @After
  public void resetPublishers() {
    CustomExitCodePublisher.resetAbruptExitStatusFile();
    CustomFailureDetailPublisher.resetFailureDetailFilePath();
  }

  @Test
  public void logException(@TestParameter ExceptionType exceptionType) {
    TestLogHandler handler = new TestLogHandler();
    Logger logger = Logger.getLogger("build.lib.bugreport");
    logger.addHandler(handler);
    LoggingUtil.installRemoteLoggerForTesting(immediateFuture(logger));

    BugReport.logException(
        exceptionType.throwable, exceptionType.isFatal, ImmutableList.of("arg", "foo"));
    LogRecord got = handler.getStoredLogRecords().get(0);
    if (oomDetectorOverride) {
      assertThat(got.getMessage()).isEqualTo(exceptionType.getExpectedMessageWhileOoming());
    } else {
      assertThat(got.getMessage()).isEqualTo(exceptionType.getExpectedMessage());
    }
    assertThat(got.getThrown()).isSameInstanceAs(exceptionType.throwable);
    assertThat(got.getLevel()).isEqualTo(exceptionType.level);
  }

  @Test
  public void convenienceMethod(@TestParameter CrashType crashType) throws Exception {
    Throwable t = crashType.createThrowable();
    FailureDetail expectedFailureDetail =
        createExpectedFailureDetail(t, crashType, oomDetectorOverride);
    // TODO(b/222158599): This should always be ExitException.
    SecurityException e = assertThrows(SecurityException.class, () -> BugReport.handleCrash(t));
    if (e instanceof ExitException) {
      int code = ((ExitException) e).code;
      assertThat(code).isEqualTo(crashType.expectedExitCode.getNumericExitCode());
    }
    assertThat(BugReport.getAndResetLastCrashingThrowableIfInTest()).isSameInstanceAs(t);

    verify(mockRuntime)
        .cleanUpForCrash(
            DetailedExitCode.of(
                oomDetectorOverride ? EXIT_CODE_BLAZE_OOMING : crashType.expectedExitCode,
                expectedFailureDetail));
    verifyExitCodeWritten(
        oomDetectorOverride
            ? EXIT_CODE_BLAZE_OOMING.getNumericExitCode()
            : crashType.expectedExitCode.getNumericExitCode());
    verifyFailureDetailWritten(expectedFailureDetail);
  }

  @Test
  public void halt(@TestParameter CrashType crashType) throws Exception {
    Throwable t = crashType.createThrowable();
    FailureDetail expectedFailureDetail =
        createExpectedFailureDetail(t, crashType, oomDetectorOverride);

    // TODO(b/222158599): This should always be ExitException.
    SecurityException e =
        assertThrows(
            SecurityException.class,
            () -> BugReport.handleCrash(Crash.from(t), CrashContext.halt()));
    if (e instanceof ExitException) {
      int code = ((ExitException) e).code;
      assertThat(code).isEqualTo(crashType.expectedExitCode.getNumericExitCode());
    }
    assertThat(BugReport.getAndResetLastCrashingThrowableIfInTest()).isSameInstanceAs(t);

    verify(mockRuntime)
        .cleanUpForCrash(
            DetailedExitCode.of(
                oomDetectorOverride ? EXIT_CODE_BLAZE_OOMING : crashType.expectedExitCode,
                expectedFailureDetail));
    verifyExitCodeWritten(
        oomDetectorOverride
            ? EXIT_CODE_BLAZE_OOMING.getNumericExitCode()
            : crashType.expectedExitCode.getNumericExitCode());
    verifyFailureDetailWritten(expectedFailureDetail);
  }

  @Test
  public void keepAlive(@TestParameter CrashType crashType) throws Exception {
    Throwable t = crashType.createThrowable();
    FailureDetail expectedFailureDetail =
        createExpectedFailureDetail(t, crashType, oomDetectorOverride);

    BugReport.handleCrash(Crash.from(t), CrashContext.keepAlive());
    assertThat(BugReport.getAndResetLastCrashingThrowableIfInTest()).isSameInstanceAs(t);

    verify(mockRuntime)
        .cleanUpForCrash(
            DetailedExitCode.of(
                oomDetectorOverride ? EXIT_CODE_BLAZE_OOMING : crashType.expectedExitCode,
                expectedFailureDetail));
    verifyNoExitCodeWritten();
    verifyFailureDetailWritten(expectedFailureDetail);
  }

  @Test
  public void haltOrReturnIfCrashInProgress_otherCrashInProgress_returnsEagerly(
      @TestParameter CrashType crashType) throws Throwable {
    // Arrange:
    // A first thread will crash with CrashContext.halt(). We mock out the BlazeRuntimeInterface to
    // force this thread to block while holding the BugReport global lock.
    CountDownLatch cleanupBegunLatch = new CountDownLatch(1);
    CountDownLatch cleanupMayFinishLatch = new CountDownLatch(1);
    doAnswer(
            (inv) -> {
              cleanupBegunLatch.countDown();
              cleanupMayFinishLatch.await();
              return null;
            })
        .when(mockRuntime)
        .cleanUpForCrash(any(DetailedExitCode.class));

    Throwable firstThrown = new IllegalStateException("second crash in background thread");
    ThrowingRunnable doFirstCrash =
        () -> BugReport.handleCrash(Crash.from(firstThrown), CrashContext.halt());
    AtomicReference<SecurityException> firstCrashThrownRef = new AtomicReference<>(null);
    TestThread firstCrashThread =
        new TestThread(
            () -> firstCrashThrownRef.set(assertThrows(SecurityException.class, doFirstCrash)));
    firstCrashThread.start();
    cleanupBegunLatch.await();

    // Act:
    // Try to crash on a second thread, with a `haltOrReturnIfCrashInProgress` CrashContext. This
    // should return without throwing because the BugReport global lock is held.
    Throwable secondThrown = crashType.createThrowable();
    CrashContext haltOrReturnCtx = CrashContext.haltOrReturnIfCrashInProgress();
    ThrowingRunnable doSecondCrash =
        () -> BugReport.handleCrash(Crash.from(secondThrown), haltOrReturnCtx);
    doSecondCrash.run();

    // Assert:
    // Allow the first crashing thread to finish, then confirm that the
    // `CrashContext.haltOrReturnIfCrashInProgress()` will halt when BugReport's lock is free.
    cleanupMayFinishLatch.countDown();
    firstCrashThread.joinAndAssertState(TestUtils.WAIT_TIMEOUT_MILLISECONDS);

    // TODO(b/222158599): These should always be ExitException.
    SecurityException firstException = firstCrashThrownRef.get();
    if (firstException instanceof ExitException) {
      int code = ((ExitException) firstException).code;
      assertThat(code).isEqualTo(ExitCode.BLAZE_INTERNAL_ERROR.getNumericExitCode());
    }

    SecurityException secondException = assertThrows(SecurityException.class, doSecondCrash);
    if (secondException instanceof ExitException) {
      int code = ((ExitException) secondException).code;
      assertThat(code).isEqualTo(crashType.expectedExitCode.getNumericExitCode());
    }
  }

  @Test
  public void customContext_setUpFront(@TestParameter CrashType crashType) {
    Throwable t = crashType.createThrowable();
    EventHandler handler = mock(EventHandler.class);
    ArgumentCaptor<Event> event = ArgumentCaptor.forClass(Event.class);

    BugReport.handleCrash(
        Crash.from(t),
        CrashContext.keepAlive().withExtraOomInfo("Build fewer targets!").reportingTo(handler));
    assertThat(BugReport.getAndResetLastCrashingThrowableIfInTest()).isSameInstanceAs(t);

    verify(handler).handle(event.capture());
    assertThat(event.getValue().getKind()).isEqualTo(EventKind.FATAL);
    assertThat(event.getValue().getMessage()).contains(Throwables.getStackTraceAsString(t));
    if (oomDetectorOverride || crashType == CrashType.OOM) {
      assertThat(event.getValue().getMessage()).contains("ran out of memory and crashed.");
      assertThat(event.getValue().getMessage()).contains("Build fewer targets!");
    } else {
      assertThat(event.getValue().getMessage()).doesNotContain("Build fewer targets!");
    }
  }

  @Test
  public void customContext_filledInByRuntime(@TestParameter CrashType crashType) {
    Throwable t = crashType.createThrowable();
    EventHandler handler = mock(EventHandler.class);
    ArgumentCaptor<Event> event = ArgumentCaptor.forClass(Event.class);
    doAnswer(
            inv ->
                inv.getArgument(0, CrashContext.class)
                    .withExtraOomInfo("Build fewer targets!")
                    .reportingTo(handler))
        .when(mockRuntime)
        .fillInCrashContext(any());

    BugReport.handleCrash(Crash.from(t), CrashContext.keepAlive());
    assertThat(BugReport.getAndResetLastCrashingThrowableIfInTest()).isSameInstanceAs(t);

    verify(handler).handle(event.capture());
    assertThat(event.getValue().getKind()).isEqualTo(EventKind.FATAL);
    assertThat(event.getValue().getMessage()).contains(Throwables.getStackTraceAsString(t));

    if (oomDetectorOverride || crashType == CrashType.OOM) {
      assertThat(event.getValue().getMessage()).contains("ran out of memory and crashed.");
      assertThat(event.getValue().getMessage()).contains("Build fewer targets!");
    } else {
      assertThat(event.getValue().getMessage()).doesNotContain("Build fewer targets!");
    }
  }

  private void verifyExitCodeWritten(int exitCode) throws Exception {
    assertThat(Files.readAllLines(exitCodeFile)).containsExactly(String.valueOf(exitCode));
  }

  private void verifyNoExitCodeWritten() {
    assertThat(exitCodeFile.toFile().exists()).isFalse();
  }

  private void verifyFailureDetailWritten(FailureDetail expected) throws Exception {
    assertThat(
            FailureDetail.parseFrom(
                Files.readAllBytes(failureDetailFile), ExtensionRegistry.getEmptyRegistry()))
        .isEqualTo(expected);
  }

  private static FailureDetail createExpectedFailureDetail(
      Throwable t, CrashType crashType, boolean oomDetectorOverride) {
    FailureDetails.Crash.Builder crash =
        FailureDetails.Crash.newBuilder()
            .setCode(
                oomDetectorOverride
                    ? FAILURE_DETAIL_CODE_BLAZE_OOMING
                    : crashType.expectedFailureDetailCode)
            .addCauses(
                FailureDetails.Throwable.newBuilder()
                    .setThrowableClass(t.getClass().getName())
                    .setMessage(t.getMessage())
                    .addAllStackTrace(
                        Lists.transform(
                            Arrays.asList(t.getStackTrace()), StackTraceElement::toString)));
    if (oomDetectorOverride && crashType == CrashType.CRASH) {
      crash.setOomDetectorOverride(true);
    }
    return FailureDetail.newBuilder()
        .setMessage(String.format("Crashed: (%s) %s", t.getClass().getName(), t.getMessage()))
        .setCrash(crash)
        .build();
  }

  private static final class ExitException extends SecurityException {
    private final int code;

    ExitException(int code) {
      super("Tried to exit JVM with code " + code);
      this.code = code;
    }
  }

  /** Instead of exiting the JVM, throws {@link ExitException} to keep the test alive. */
  private static final class ExitProhibitingSecurityManager extends SecurityManager {

    @Override
    public void checkExit(int code) {
      throw new ExitException(code);
    }

    @Override
    public void checkPermission(Permission p) {} // Allow everything else.
  }
}
