// Copyright 2016 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.windows;

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

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.shell.Subprocess;
import com.google.devtools.build.lib.shell.SubprocessBuilder;
import com.google.devtools.build.lib.testutil.TestSpec;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.windows.jni.WindowsProcesses;
import com.google.devtools.build.runfiles.Runfiles;
import java.io.File;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Unit tests for {@link WindowsSubprocess}.
 */
@RunWith(JUnit4.class)
@TestSpec(localOnly = true, supportedOs = OS.WINDOWS)
public class WindowsSubprocessTest {
  private String mockSubprocess;
  private String mockBinary;
  private Subprocess process;
  private Runfiles runfiles;

  @Before
  public void loadJni() throws Exception {
    runfiles = Runfiles.create();
    mockSubprocess =
        runfiles.rlocation(
            "io_bazel/src/test/java/com/google/devtools/build/lib/MockSubprocess_deploy.jar");
    mockBinary = System.getProperty("java.home") + "\\bin\\java.exe";

    process = null;
  }

  @After
  public void terminateProcess() throws Exception {
    if (process != null) {
      process.destroy();
      process.close();
      process = null;
    }
  }

  @Test
  public void testSystemRootIsSetByDefault() throws Exception {
    SubprocessBuilder subprocessBuilder = new SubprocessBuilder();
    subprocessBuilder.setWorkingDirectory(new File("."));
    subprocessBuilder.setSubprocessFactory(WindowsSubprocessFactory.INSTANCE);
    subprocessBuilder.setArgv(mockBinary, "-jar", mockSubprocess, "O$SYSTEMROOT");
    process = subprocessBuilder.start();
    process.waitFor();
    assertThat(process.exitValue()).isEqualTo(0);

    byte[] buf = new byte[11];
    process.getInputStream().read(buf);
    assertThat(new String(buf, UTF_8).trim()).isEqualTo(System.getenv("SYSTEMROOT").trim());
  }

  @Test
  public void testSystemDriveIsSetByDefault() throws Exception {
    SubprocessBuilder subprocessBuilder = new SubprocessBuilder();
    subprocessBuilder.setWorkingDirectory(new File("."));
    subprocessBuilder.setSubprocessFactory(WindowsSubprocessFactory.INSTANCE);
    subprocessBuilder.setArgv(mockBinary, "-jar", mockSubprocess, "O$SYSTEMDRIVE");
    process = subprocessBuilder.start();
    process.waitFor();
    assertThat(process.exitValue()).isEqualTo(0);

    byte[] buf = new byte[3];
    process.getInputStream().read(buf);
    assertThat(new String(buf, UTF_8).trim()).isEqualTo(System.getenv("SYSTEMDRIVE").trim());
  }

  @Test
  public void testSystemRootIsSet() throws Exception {
    SubprocessBuilder subprocessBuilder = new SubprocessBuilder();
    subprocessBuilder.setWorkingDirectory(new File("."));
    subprocessBuilder.setSubprocessFactory(WindowsSubprocessFactory.INSTANCE);
    subprocessBuilder.setArgv(mockBinary, "-jar", mockSubprocess, "O$SYSTEMROOT");
    // Case shouldn't matter on Windows
    subprocessBuilder.setEnv(ImmutableMap.of("SystemRoot", "C:\\MySystemRoot"));
    process = subprocessBuilder.start();
    process.waitFor();
    assertThat(process.exitValue()).isEqualTo(0);

    byte[] buf = new byte[16];
    process.getInputStream().read(buf);
    assertThat(new String(buf, UTF_8).trim()).isEqualTo("C:\\MySystemRoot");
  }

  @Test
  public void testSystemDriveIsSet() throws Exception {
    SubprocessBuilder subprocessBuilder = new SubprocessBuilder();
    subprocessBuilder.setWorkingDirectory(new File("."));
    subprocessBuilder.setSubprocessFactory(WindowsSubprocessFactory.INSTANCE);
    subprocessBuilder.setArgv(mockBinary, "-jar", mockSubprocess, "O$SYSTEMDRIVE");
    // Case shouldn't matter on Windows
    subprocessBuilder.setEnv(ImmutableMap.of("SystemDrive", "X:"));
    process = subprocessBuilder.start();
    process.waitFor();
    assertThat(process.exitValue()).isEqualTo(0);

    byte[] buf = new byte[3];
    process.getInputStream().read(buf);
    assertThat(new String(buf, UTF_8).trim()).isEqualTo("X:");
  }

  /**
   * An argument and its command-line-escaped counterpart.
   *
   * <p>Such escaping ensures that Bazel correctly forwards arguments to subprocesses.
   */
  private static final class ArgPair {
    public final String original;
    public final String escaped;

    public ArgPair(String original, String escaped) {
      this.original = original;
      this.escaped = escaped;
    }
  };

  /** Asserts that a subprocess correctly receives command line arguments. */
  private void assertSubprocessReceivesArgsAsIntended(ArgPair... args) throws Exception {
    // Look up the path of the printarg.exe utility.
    String printArgExe =
        runfiles.rlocation("io_bazel/src/test/java/com/google/devtools/build/lib/printarg.exe");
    assertThat(printArgExe).isNotEmpty();

    for (ArgPair arg : args) {
      // Assert that the command-line encoding logic works as intended.
      assertThat(WindowsProcesses.quoteCommandLine(ImmutableList.of(arg.original)))
          .isEqualTo(arg.escaped);

      // Create a separate subprocess just for this argument.
      SubprocessBuilder subprocessBuilder = new SubprocessBuilder();
      subprocessBuilder.setWorkingDirectory(new File("."));
      subprocessBuilder.setSubprocessFactory(WindowsSubprocessFactory.INSTANCE);
      subprocessBuilder.setArgv(printArgExe, arg.original);
      process = subprocessBuilder.start();
      process.waitFor();
      assertThat(process.exitValue()).isEqualTo(0);

      // The subprocess printed its argv[1] in parentheses, e.g. (foo).
      // Assert that it printed exactly the *original* argument in parentheses.
      byte[] buf = new byte[1000];
      process.getInputStream().read(buf);
      String actual = new String(buf, UTF_8).trim();
      assertThat(actual).isEqualTo("(" + arg.original + ")");
    }
  }

  @Test
  public void testSubprocessReceivesArgsAsIntended() throws Exception {
    assertSubprocessReceivesArgsAsIntended(
        new ArgPair("", "\"\""),
        new ArgPair(" ", "\" \""),
        new ArgPair("foo", "foo"),
        new ArgPair("foo\\bar", "foo\\bar"),
        new ArgPair("foo bar", "\"foo bar\""));
    // TODO(laszlocsomor): the escaping logic in WindowsProcesses.quoteCommandLine is wrong, because
    // it fails to properly escape things like a single backslash followed by a quote, e.g. a\"b
    // Fix the escaping logic and add more test here.
  }
}
