// 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 com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
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.SpawnResult.Status;
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.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 java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Tests for {@link DarwinSandboxedSpawnRunner}.
 *
 * <p>These tests do not require macOS to run because we have no easy means of expressing that
 * requirement. Instead, we just implement "unit-like" tests by mocking out the tools that this
 * spawn runner requires and rely on our shell-level integration tests to validate this properly.
 */
@RunWith(JUnit4.class)
public final class DarwinSandboxedSpawnRunnerTest extends SandboxedSpawnRunnerTestCase {

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

  /** Environment for the running test. */
  private CommandEnvironment commandEnvironment;

  /** Path to the base of the sandbox to pass to the spawn runner. */
  private Path sandboxBase;

  /** Location of the real {@code getconf} binary; saved while the test is running. */
  private String oldGetconf;

  /** Location of the real {@code sandbox-exec} binary; saved while the test is running. */
  private String oldSandboxExec;

  @Before
  public void setUp() throws Exception {
    commandEnvironment = runtimeWrapper.newCommand();
    commandEnvironment.setWorkspaceName("workspace");
    commandEnvironment
        .getLocalResourceManager()
        .setAvailableResources(LocalHostCapacity.getLocalHostCapacity());

    Path execRoot = commandEnvironment.getExecRoot();
    execRoot.createDirectory();
    SpawnRunnerTestUtil.copyProcessWrapperIntoPath(execRoot);

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

    // The mock getconf tool always prints an arbitrary path regardless of the arguments it
    // receives. We must print a syntactically-valid path, however, to not confuse the consumer
    // of this output.
    Path getconf = execRoot.getRelative("getconf");
    FileSystemUtils.writeContentAsLatin1(getconf, "#!/bin/sh\necho /tmp");
    getconf.setExecutable(true);
    oldGetconf = DarwinSandboxedSpawnRunner.getconfBinary;
    DarwinSandboxedSpawnRunner.getconfBinary = getconf.toString();

    // The mock sandbox-exec just executes the given command and returns its output.
    Path sandboxExec = execRoot.getRelative("sandbox-exec");
    FileSystemUtils.writeContentAsLatin1(sandboxExec,
        "#!/bin/sh\n"
        + "shift\n"  // Skip -f flag.
        + "shift\n"  // Skip target of -f flag.
        + "exec \"$@\"\n");  // Remaining arguments are the process-wrapper's ones.
    sandboxExec.setExecutable(true);
    oldSandboxExec = DarwinSandboxedSpawnRunner.sandboxExecBinary;
    DarwinSandboxedSpawnRunner.sandboxExecBinary = sandboxExec.toString();
  }

  @After
  public void tearDown() {
    DarwinSandboxedSpawnRunner.sandboxExecBinary = oldSandboxExec;
    DarwinSandboxedSpawnRunner.getconfBinary = oldGetconf;
  }

  private void doSimpleExecutionTest(DarwinSandboxedSpawnRunner runner) throws Exception {
    Spawn spawn = new SpawnBuilder("/bin/sh", "-c", "exit 42").build();

    FileOutErr fileOutErr =
        new FileOutErr(testRoot.getChild("stdout"), testRoot.getChild("stderr"));
    SpawnExecutionContextForTesting policy =
        new SpawnExecutionContextForTesting(spawn, fileOutErr, Duration.ofMinutes(1));

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

    assertThat(spawnResult.status()).isEqualTo(SpawnResult.Status.NON_ZERO_EXIT);
    assertThat(spawnResult.exitCode()).isEqualTo(42);
  }

  @Test
  public void testSimpleExecution() throws Exception {
    DarwinSandboxedSpawnRunner runner =
        new DarwinSandboxedSpawnRunner(
            new SandboxHelpers(),
            commandEnvironment,
            sandboxBase,
            /* sandboxfsProcess= */ null,
            /* sandboxfsMapSymlinkTargets= */ false,
            treeDeleter);
    doSimpleExecutionTest(runner);
  }

  @Test
  public void testSupportsParamFiles() throws Exception {
    DarwinSandboxedSpawnRunner runner =
        new DarwinSandboxedSpawnRunner(
            new SandboxHelpers(),
            commandEnvironment,
            sandboxBase,
            /* sandboxfsProcess= */ null,
            /* sandboxfsMapSymlinkTargets= */ false,
            treeDeleter);
    Spawn spawn =
        new SpawnBuilder("cp", "params/param-file", "out")
            .withInput(
                new ParamFileActionInput(
                    PathFragment.create("params/param-file"),
                    ImmutableList.of("--foo", "--bar"),
                    ParameterFileType.UNQUOTED,
                    StandardCharsets.UTF_8))
            .withOutput("out")
            .build();
    FileOutErr fileOutErr =
        new FileOutErr(testRoot.getChild("stdout"), testRoot.getChild("stderr"));
    SpawnExecutionContextForTesting policy =
        new SpawnExecutionContextForTesting(spawn, fileOutErr, Duration.ofMinutes(1));
    SpawnResult spawnResult = runner.execAsync(spawn, policy).get();
    assertThat(spawnResult.status()).isEqualTo(Status.SUCCESS);
    Path paramFile = commandEnvironment.getExecRoot().getRelative("out");
    assertThat(paramFile.exists()).isTrue();
    try (InputStream inputStream = paramFile.getInputStream()) {
      assertThat(
              new String(ByteStreams.toByteArray(inputStream), StandardCharsets.UTF_8).split("\n"))
          .asList()
          .containsExactly("--foo", "--bar");
    }
  }

  @Test
  public void testSimpleExecutionWithSandboxfs() throws Exception {
    Path mountPoint = commandEnvironment.getExecRoot().getRelative("mount");
    mountPoint.createDirectoryAndParents();
    SandboxfsProcess sandboxfsProcess = new FakeSandboxfsProcess(
        mountPoint.getFileSystem(), mountPoint.asFragment());

    DarwinSandboxedSpawnRunner runner =
        new DarwinSandboxedSpawnRunner(
            new SandboxHelpers(),
            commandEnvironment,
            sandboxBase,
            sandboxfsProcess,
            /* sandboxfsMapSymlinkTargets= */ false,
            treeDeleter);
    doSimpleExecutionTest(runner);
  }
}
