// Copyright 2022 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.sandbox;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.common.truth.TruthJUnit.assume;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.ArtifactRoot.RootType;
import com.google.devtools.build.lib.actions.CommandLines.ParamFileActionInput;
import com.google.devtools.build.lib.actions.LocalHostCapacity;
import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType;
import com.google.devtools.build.lib.actions.Spawn;
import com.google.devtools.build.lib.actions.SpawnResult;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.exec.BinTools;
import com.google.devtools.build.lib.exec.SpawnRunner.SpawnExecutionContext;
import com.google.devtools.build.lib.exec.TreeDeleter;
import com.google.devtools.build.lib.exec.util.SpawnBuilder;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.sandbox.SpawnRunnerTestUtil.SpawnExecutionContextForTesting;
import com.google.devtools.build.lib.testutil.Scratch;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.util.io.FileOutErr;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import java.io.IOException;
import java.time.Duration;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

/** Tests for {@link LinuxSandboxedSpawnRunner}. */
@RunWith(TestParameterInjector.class)
public final class LinuxSandboxedSpawnRunnerTest extends SandboxedSpawnRunnerTestCase {

  /** Tree deleter to use by default for all tests. */
  private static final TreeDeleter treeDeleter = new SynchronousTreeDeleter();

  @Before
  public void assumeRunningOnLinux() {
    assume().that(OS.getCurrent()).isEqualTo(OS.LINUX);
  }

  @Test
  public void execAsync_echoCommand_executesSuccessfully() throws Exception {
    LinuxSandboxedSpawnRunner runner = setupSandboxAndCreateRunner(createCommandEnvironment());
    Spawn spawn = new SpawnBuilder("echo", "echolalia").build();
    Path stdout = testRoot.getChild("stdout");
    SpawnExecutionContext policy = createSpawnExecutionContext(spawn, stdout);

    SpawnResult spawnResult = runner.execAsync(spawn, policy).get();

    assertThat(spawnResult.status()).isEqualTo(SpawnResult.Status.SUCCESS);
    assertThat(spawnResult.exitCode()).isEqualTo(0);
    assertThat(spawnResult.setupSuccess()).isTrue();
    assertThat(spawnResult.getWallTime()).isPresent();
    assertThat(FileSystemUtils.readLines(stdout, UTF_8)).containsExactly("echolalia");
  }

  @Test
  public void execAsync_commandWithParamFiles_executesSuccessfully() throws Exception {
    CommandEnvironment commandEnvironment = createCommandEnvironment();
    LinuxSandboxedSpawnRunner runner = setupSandboxAndCreateRunner(commandEnvironment);
    Spawn spawn =
        new SpawnBuilder("cp", "params/param-file", "out")
            .withInput(
                new ParamFileActionInput(
                    PathFragment.create("params/param-file"),
                    ImmutableList.of("--foo", "--bar"),
                    ParameterFileType.UNQUOTED,
                    UTF_8))
            .withOutput("out")
            .build();
    SpawnExecutionContext policy = createSpawnExecutionContext(spawn);

    SpawnResult spawnResult = runner.execAsync(spawn, policy).get();

    assertThat(spawnResult.status()).isEqualTo(SpawnResult.Status.SUCCESS);
    Path paramFile = commandEnvironment.getExecRoot().getRelative("out");
    assertThat(paramFile.exists()).isTrue();
    assertThat(FileSystemUtils.readLines(paramFile, UTF_8))
        .containsExactly("--foo", "--bar")
        .inOrder();
  }

  @Test
  public void execAsync_spawnRunningBinTool_executesSuccessfully() throws Exception {
    CommandEnvironment commandEnvironment = createCommandEnvironment();
    LinuxSandboxedSpawnRunner runner = setupSandboxAndCreateRunner(commandEnvironment);
    BinTools.PathActionInput pathActionInput =
        new BinTools.PathActionInput(
            new Scratch().file("/execRoot/tool", "#!/bin/bash", "echo hello > $1"),
            PathFragment.create("_bin/tool"));
    Artifact output =
        ActionsTestUtil.createArtifact(
            ArtifactRoot.asDerivedRoot(
                commandEnvironment.getExecRoot(), RootType.Output, "blaze-out"),
            commandEnvironment.getExecRoot().getRelative("blaze-out/output"));
    Spawn spawn =
        new SpawnBuilder("_bin/tool", output.getExecPathString())
            .withInput(pathActionInput)
            .withOutput(output)
            .build();
    SpawnExecutionContext policy = createSpawnExecutionContext(spawn);

    SpawnResult spawnResult = runner.execAsync(spawn, policy).get();

    assertThat(spawnResult.status()).isEqualTo(SpawnResult.Status.SUCCESS);
    assertThat(FileSystemUtils.readLines(output.getPath(), UTF_8)).containsExactly("hello");
  }

  @Test
  public void execAsync_collectsExecutionStatistics() throws Exception {
    CommandEnvironment commandEnvironment = createCommandEnvironment();
    LinuxSandboxedSpawnRunner runner = setupSandboxAndCreateRunner(commandEnvironment);
    Path cpuTimeSpenderPath =
        SpawnRunnerTestUtil.copyCpuTimeSpenderIntoPath(commandEnvironment.getExecRoot());
    Duration minimumWallTimeToSpend = Duration.ofSeconds(10);
    // Because of e.g. interference, wall time taken may be much larger than CPU time used.
    Duration maximumWallTimeToSpend = Duration.ofSeconds(40);
    Duration minimumUserTimeToSpend = minimumWallTimeToSpend;
    Duration maximumUserTimeToSpend = minimumUserTimeToSpend.plus(Duration.ofSeconds(2));
    Duration minimumSystemTimeToSpend = Duration.ZERO;
    Duration maximumSystemTimeToSpend = minimumSystemTimeToSpend.plus(Duration.ofSeconds(2));
    Spawn spawn =
        new SpawnBuilder(
                cpuTimeSpenderPath.getPathString(),
                String.valueOf(minimumUserTimeToSpend.getSeconds()),
                String.valueOf(minimumSystemTimeToSpend.getSeconds()))
            .build();
    SpawnExecutionContextForTesting policy = createSpawnExecutionContext(spawn);

    SpawnResult spawnResult = runner.execAsync(spawn, policy).get();

    assertThat(spawnResult.status()).isEqualTo(SpawnResult.Status.SUCCESS);
    assertThat(spawnResult.exitCode()).isEqualTo(0);
    assertThat(spawnResult.setupSuccess()).isTrue();
    assertThat(spawnResult.getWallTime()).isPresent();
    assertThat(spawnResult.getWallTime().get()).isAtLeast(minimumWallTimeToSpend);
    assertThat(spawnResult.getWallTime().get()).isAtMost(maximumWallTimeToSpend);
    assertThat(spawnResult.getUserTime()).isPresent();
    assertThat(spawnResult.getUserTime().get()).isAtLeast(minimumUserTimeToSpend);
    assertThat(spawnResult.getUserTime().get()).isAtMost(maximumUserTimeToSpend);
    assertThat(spawnResult.getSystemTime()).isPresent();
    assertThat(spawnResult.getSystemTime().get()).isAtLeast(minimumSystemTimeToSpend);
    assertThat(spawnResult.getSystemTime().get()).isAtMost(maximumSystemTimeToSpend);
    assertThat(spawnResult.getNumBlockOutputOperations().get()).isAtLeast(0L);
    assertThat(spawnResult.getNumBlockInputOperations().get()).isAtLeast(0L);
    assertThat(spawnResult.getNumInvoluntaryContextSwitches().get()).isAtLeast(0L);
  }

  @Test
  public void execAsync_statisticsCollectionDisabled_returnsEmptyStatistics() throws Exception {
    CommandEnvironment commandEnvironment =
        getCommandEnvironmentWithExecutionStatisticsOptionDisabled("workspace");
    LinuxSandboxedSpawnRunner runner = setupSandboxAndCreateRunner(commandEnvironment);
    Path cpuTimeSpenderPath =
        SpawnRunnerTestUtil.copyCpuTimeSpenderIntoPath(commandEnvironment.getExecRoot());
    Duration minimumWallTimeToSpend = Duration.ofSeconds(10);
    // Because of e.g. interference, wall time taken may be much larger than CPU time used.
    Duration maximumWallTimeToSpend = Duration.ofSeconds(40);
    Duration minimumUserTimeToSpend = minimumWallTimeToSpend;
    Duration minimumSystemTimeToSpend = Duration.ZERO;
    Spawn spawn =
        new SpawnBuilder(
                cpuTimeSpenderPath.getPathString(),
                String.valueOf(minimumUserTimeToSpend.getSeconds()),
                String.valueOf(minimumSystemTimeToSpend.getSeconds()))
            .build();
    SpawnExecutionContext policy = createSpawnExecutionContext(spawn);

    SpawnResult spawnResult = runner.execAsync(spawn, policy).get();

    assertThat(spawnResult.status()).isEqualTo(SpawnResult.Status.SUCCESS);
    assertThat(spawnResult.exitCode()).isEqualTo(0);
    assertThat(spawnResult.setupSuccess()).isTrue();
    assertThat(spawnResult.getWallTime()).isPresent();
    assertThat(spawnResult.getWallTime().get()).isAtLeast(minimumWallTimeToSpend);
    assertThat(spawnResult.getWallTime().get()).isAtMost(maximumWallTimeToSpend);
    assertThat(spawnResult.getUserTime()).isEmpty();
    assertThat(spawnResult.getSystemTime()).isEmpty();
    assertThat(spawnResult.getNumBlockOutputOperations()).isEmpty();
    assertThat(spawnResult.getNumBlockInputOperations()).isEmpty();
    assertThat(spawnResult.getNumInvoluntaryContextSwitches()).isEmpty();
  }

  @Test
  public void hermeticTmp_tmpCreatedAndMounted() throws Exception {
    runtimeWrapper.addOptions("--incompatible_sandbox_hermetic_tmp");
    CommandEnvironment commandEnvironment = createCommandEnvironment();
    LinuxSandboxedSpawnRunner runner = setupSandboxAndCreateRunner(commandEnvironment);
    Spawn spawn = new SpawnBuilder().build();
    SandboxedSpawn sandboxedSpawn = runner.prepareSpawn(spawn, createSpawnExecutionContext(spawn));

    Path sandboxPath =
        sandboxedSpawn.getSandboxExecRoot().getParentDirectory().getParentDirectory();
    Path hermeticTmpPath = sandboxPath.getRelative("_tmp");
    assertThat(hermeticTmpPath.isDirectory()).isTrue();

    assertThat(sandboxedSpawn).isInstanceOf(SymlinkedSandboxedSpawn.class);
    String args = String.join(" ", sandboxedSpawn.getArguments());
    assertThat(args).contains("-w /tmp");
    assertThat(args).contains("-M " + hermeticTmpPath + " -m /tmp");
  }

  @Test
  public void hermeticTmp_sandboxTmpfsOnTmp_tmpNotCreatedOrMounted() throws Exception {
    runtimeWrapper.addOptions("--incompatible_sandbox_hermetic_tmp", "--sandbox_tmpfs_path=/tmp");
    CommandEnvironment commandEnvironment = createCommandEnvironment();
    LinuxSandboxedSpawnRunner runner = setupSandboxAndCreateRunner(commandEnvironment);
    Spawn spawn = new SpawnBuilder().build();
    SandboxedSpawn sandboxedSpawn = runner.prepareSpawn(spawn, createSpawnExecutionContext(spawn));

    Path sandboxPath =
        sandboxedSpawn.getSandboxExecRoot().getParentDirectory().getParentDirectory();
    Path hermeticTmpPath = sandboxPath.getRelative("_tmp");
    assertThat(hermeticTmpPath.isDirectory()).isFalse();

    assertThat(sandboxedSpawn).isInstanceOf(SymlinkedSandboxedSpawn.class);
    String args = String.join(" ", sandboxedSpawn.getArguments());
    assertThat(args).contains("-w /tmp");
    assertThat(args).contains("-e /tmp");
    assertThat(args).doesNotContain("-m /tmp");
  }

  @Test
  public void hermeticTmp_sandboxTmpfsUnderTmp_tmpNotCreatedOrMounted() throws Exception {
    runtimeWrapper.addOptions(
        "--incompatible_sandbox_hermetic_tmp", "--sandbox_tmpfs_path=/tmp/subdir");
    CommandEnvironment commandEnvironment = createCommandEnvironment();
    LinuxSandboxedSpawnRunner runner = setupSandboxAndCreateRunner(commandEnvironment);
    Spawn spawn = new SpawnBuilder().build();
    SandboxedSpawn sandboxedSpawn = runner.prepareSpawn(spawn, createSpawnExecutionContext(spawn));

    Path sandboxPath =
        sandboxedSpawn.getSandboxExecRoot().getParentDirectory().getParentDirectory();
    Path hermeticTmpPath = sandboxPath.getRelative("_tmp");
    assertThat(hermeticTmpPath.isDirectory()).isFalse();

    assertThat(sandboxedSpawn).isInstanceOf(SymlinkedSandboxedSpawn.class);
    String args = String.join(" ", sandboxedSpawn.getArguments());
    assertThat(args).contains("-w /tmp");
    assertThat(args).contains("-e /tmp");
    assertThat(args).doesNotContain("-m /tmp");
  }

  private static LinuxSandboxedSpawnRunner setupSandboxAndCreateRunner(
      CommandEnvironment commandEnvironment) throws IOException {
    Path execRoot = commandEnvironment.getExecRoot();
    execRoot.createDirectory();

    SpawnRunnerTestUtil.copyLinuxSandboxIntoPath(execRoot);

    Path sandboxBase = execRoot.getRelative("sandbox");
    sandboxBase.createDirectory();

    return LinuxSandboxedStrategy.create(
        new SandboxHelpers(),
        commandEnvironment,
        sandboxBase,
        /*timeoutKillDelay=*/ Duration.ofSeconds(2),
        /*sandboxfsProcess=*/ null,
        /*sandboxfsMapSymlinkTargets=*/ false,
        treeDeleter);
  }

  private SpawnExecutionContextForTesting createSpawnExecutionContext(Spawn spawn) {
    return createSpawnExecutionContext(spawn, testRoot.getChild("stdout"));
  }

  private SpawnExecutionContextForTesting createSpawnExecutionContext(Spawn spawn, Path stdout) {
    FileOutErr fileOutErr = new FileOutErr(stdout, testRoot.getChild("stderr"));
    return new SpawnExecutionContextForTesting(spawn, fileOutErr, Duration.ofMinutes(1));
  }

  private CommandEnvironment createCommandEnvironment() throws Exception {
    CommandEnvironment commandEnvironment = runtimeWrapper.newCommand();
    commandEnvironment.setWorkspaceName("workspace");
    commandEnvironment
        .getLocalResourceManager()
        .setAvailableResources(LocalHostCapacity.getLocalHostCapacity());
    return commandEnvironment;
  }
}
