// Copyright 2019 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.devtools.build.lib.vfs.DigestHashFunction;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.JavaIoFileSystem;
import com.google.devtools.build.lib.vfs.Path;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.List;
import org.junit.After;
import org.junit.Before;

/**
 * Common code to unit test {@link RealSandboxfsProcess}.
 *
 * <p>These tests validate the communication protocol between Bazel and a sandboxfs but do so using
 * golden data. They are meant to sanity-check changes to the Bazel codebase against all supported
 * sandboxfs versions but cannot guarantee that the integration with a real sandboxfs binary work.
 */
public abstract class BaseRealSandboxfsProcessTest {

  /** Path to the mount point passed to sandboxfs. Not accessed, so it's not even created. */
  static final String FAKE_MOUNT_POINT = "/non-existent/mount/point";

  /** Sandboxfs version to return to Bazel when queried. */
  private final String version;

  /**
   * Expected mount arguments for each {@link #createAndStartFakeSandboxfs} call. Supplied as a
   * single string with all arguments concatenated as seen by sandboxfs.
   */
  private final String expectedArgs;

  private FileSystem fileSystem;
  private Path tmpDir;

  // Initialized via createAndStartFakeSandboxfs and checked by verifyFakeSandboxfsExecution.
  private Path capturedArgs;
  private Path capturedRequests;

  BaseRealSandboxfsProcessTest(String version, String expectedArgs) {
    this.version = version;
    this.expectedArgs = expectedArgs;
  }

  @Before
  public void setUp() throws Exception {
    fileSystem = new JavaIoFileSystem(DigestHashFunction.getDefaultUnchecked());
    tmpDir = fileSystem.getPath(System.getenv("TEST_TMPDIR")).getRelative("test");
    tmpDir.createDirectory();
  }

  @After
  public void tearDown() throws Exception {
    tmpDir.deleteTree();
  }

  /**
   * Starts a sandboxfs instance using a fake binary that captures all received requests and yields
   * mock responses.
   *
   * @param responses the mock responses to return to Bazel when issuing requests, broken down by
   *     line printed to stdout
   * @return a sandboxfs process handler
   * @throws IOException if the fake sandboxfs cannot be prepared or started
   */
  SandboxfsProcess createAndStartFakeSandboxfs(List<String> responses) throws IOException {
    capturedArgs = tmpDir.getRelative("captured-args");
    capturedRequests = tmpDir.getRelative("captured-requests");

    Path fakeSandboxfs = tmpDir.getRelative("fake-sandboxfs");
    try (PrintWriter writer =
        new PrintWriter(
            new BufferedWriter(
                new OutputStreamWriter(fakeSandboxfs.getOutputStream(), StandardCharsets.UTF_8)))) {
      writer.println("#! /bin/sh");

      // Ignore requests for termination. The real sandboxfs process must be sent a SIGTERM to stop
      // serving, but in our case we want to terminate cleanly after waiting for all input to be
      // recorded.
      writer.println("trap '' TERM;");

      // Handle a --version invocation and exit quickly, which is a prerequisite for the mount call.
      writer.println("if [ \"${*}\" = \"--version\" ]; then");
      writer.println("  echo sandboxfs " + version + ";");
      writer.println("  exit 0;");
      writer.println("fi;");

      // Capture all arguments for later inspection.
      writer.println("for arg in \"${@}\"; do");
      writer.println("  echo \"${arg}\" >>" + capturedArgs + ";");
      writer.println("done;");

      // Emit all responses first to avoid blocking any reads from the Java side.
      for (String response : responses) {
        writer.println("echo '" + response + "';");
      }

      // And finally capture all requests for later inspection.
      writer.println("cat >" + capturedRequests + ";");
    }
    fakeSandboxfs.setExecutable(true);

    return RealSandboxfsProcess.mount(
        fakeSandboxfs.asFragment(),
        fileSystem.getPath(FAKE_MOUNT_POINT),
        tmpDir.getRelative("log"));
  }

  /**
   * Checks that the given sandboxfs process behaved as expected.
   *
   * @param process the sandboxfs instance to stop and verify, which must have been previously
   *     started by {@link #createAndStartFakeSandboxfs}
   * @param expectedRequests a flat string containing all requests given to sandboxfs (i.e. the raw
   *     contents of its stdin)
   * @throws IOException if the fake sandboxfs instance cannot be stopped or if there is a problem
   *     reading the captured data
   */
  void verifyFakeSandboxfsExecution(SandboxfsProcess process, String expectedRequests)
      throws IOException {
    process.destroy();

    String args = FileSystemUtils.readContent(capturedArgs, StandardCharsets.UTF_8);
    assertThat(args).isEqualTo(expectedArgs);

    String requests = FileSystemUtils.readContent(capturedRequests, StandardCharsets.UTF_8);
    assertThat(requests).isEqualTo(expectedRequests);
  }
}
