// Copyright 2015 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.shell;

import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.shell.ShellUtils.prettyPrintArgv;
import static com.google.devtools.build.lib.shell.ShellUtils.shellEscape;
import static com.google.devtools.build.lib.shell.ShellUtils.tokenize;
import static org.junit.Assert.fail;

import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for ShellUtils. */
@RunWith(JUnit4.class)
public class ShellUtilsTest {

  @Test
  public void testShellEscape() throws Exception {
    assertThat(shellEscape("")).isEqualTo("''");
    assertThat(shellEscape("foo")).isEqualTo("foo");
    assertThat(shellEscape("foo bar")).isEqualTo("'foo bar'");
    assertThat(shellEscape("'foo'")).isEqualTo("''\\''foo'\\'''");
    assertThat(shellEscape("\\'foo\\'")).isEqualTo("'\\'\\''foo\\'\\'''");
    assertThat(shellEscape("${filename%.c}.o")).isEqualTo("'${filename%.c}.o'");
    assertThat(shellEscape("<html!>")).isEqualTo("'<html!>'");
  }

  @Test
  public void testPrettyPrintArgv() throws Exception {
    assertThat(prettyPrintArgv(Arrays.asList("echo", "$US", "100"))).isEqualTo("echo '$US' 100");
  }

  private void assertTokenize(String copts, String... expectedTokens)
      throws Exception {
    List<String> actualTokens = new ArrayList<>();
    tokenize(actualTokens, copts);
    assertThat(actualTokens).isEqualTo(Arrays.asList(expectedTokens));
  }

  @Test
  public void testTokenize() throws Exception {
    assertTokenize("-DASMV", "-DASMV");
    assertTokenize("-DNO_UNDERLINE", "-DNO_UNDERLINE");
    assertTokenize("-DASMV -DNO_UNDERLINE",
                   "-DASMV", "-DNO_UNDERLINE");
    assertTokenize("-DDES_LONG=\"unsigned int\" -wd310",
                   "-DDES_LONG=unsigned int", "-wd310");
    assertTokenize("-Wno-write-strings -Wno-pointer-sign "
                   + "-Wno-unused-variable -Wno-pointer-to-int-cast",
                   "-Wno-write-strings",
                   "-Wno-pointer-sign",
                   "-Wno-unused-variable",
                   "-Wno-pointer-to-int-cast");
  }

  @Test
  public void testTokenizeOnNestedQuotation() throws Exception {
    assertTokenize("-Dfoo='foo\"bar' -Dwiz",
                   "-Dfoo=foo\"bar",
                   "-Dwiz");
    assertTokenize("-Dfoo=\"foo'bar\" -Dwiz",
                   "-Dfoo=foo'bar",
                   "-Dwiz");
  }

  @Test
  public void testTokenizeOnBackslashEscapes() throws Exception {
    // This would be easier to grok if we forked+exec'd a shell.

    assertTokenize("-Dfoo=\\'foo -Dbar", // \' not quoted -> '
                   "-Dfoo='foo",
                   "-Dbar");
    assertTokenize("-Dfoo=\\\"foo -Dbar", // \" not quoted -> "
                   "-Dfoo=\"foo",
                   "-Dbar");
    assertTokenize("-Dfoo=\\\\foo -Dbar", // \\ not quoted -> \
                   "-Dfoo=\\foo",
                   "-Dbar");

    assertTokenize("-Dfoo='\\'foo -Dbar", // \' single quoted -> \, close quote
                   "-Dfoo=\\foo",
                   "-Dbar");
    assertTokenize("-Dfoo='\\\"foo' -Dbar", // \" single quoted -> \"
                   "-Dfoo=\\\"foo",
                   "-Dbar");
    assertTokenize("-Dfoo='\\\\foo' -Dbar", // \\ single quoted -> \\
                   "-Dfoo=\\\\foo",
                   "-Dbar");

    assertTokenize("-Dfoo=\"\\'foo\" -Dbar", // \' double quoted -> \'
                   "-Dfoo=\\'foo",
                   "-Dbar");
    assertTokenize("-Dfoo=\"\\\"foo\" -Dbar", // \" double quoted -> "
                   "-Dfoo=\"foo",
                   "-Dbar");
    assertTokenize("-Dfoo=\"\\\\foo\" -Dbar", // \\ double quoted -> \
                   "-Dfoo=\\foo",
                   "-Dbar");
  }

  private void assertTokenizeFails(String copts, String expectedError) {
    try {
      tokenize(new ArrayList<String>(), copts);
      fail();
    } catch (ShellUtils.TokenizationException e) {
      assertThat(e).hasMessage(expectedError);
    }
  }

  @Test
  public void testTokenizeEmptyString() throws Exception {
    assertTokenize("");
  }

  @Test
  public void testTokenizeFailsOnUnterminatedQuotation() {
    assertTokenizeFails("-Dfoo=\"bar", "unterminated quotation");
    assertTokenizeFails("-Dfoo='bar", "unterminated quotation");
    assertTokenizeFails("-Dfoo=\"b'ar", "unterminated quotation");
  }

  private void assertTokenizeIsDualToPrettyPrint(String... args) throws Exception {
    List<String> in = Arrays.asList(args);
    String shellCommand = prettyPrintArgv(in);

    // Assert that pretty-print is correct, i.e. dual to the actual /bin/sh
    // tokenization.  This test assumes no newlines in the input:
    String[] execArgs =  {
      "/bin/sh",
      "-c",
      "for i in " + shellCommand + "; do echo \"$i\"; done"  // tokenize, one word per line
    };
    String stdout = null;
    try {
      stdout = new String(new Command(execArgs).execute().getStdout());
    } catch (Exception e) {
      fail("/bin/sh failed:\n" + in + "\n" + shellCommand + "\n" + e.getMessage());
    }
    // We can't use stdout.split("\n") here,
    // because String.split() ignores trailing empty strings.
    ArrayList<String> words = Lists.newArrayList();
    int index;
    while ((index = stdout.indexOf('\n')) >= 0) {
      words.add(stdout.substring(0, index));
      stdout = stdout.substring(index + 1);
    }
    assertThat(words).isEqualTo(in);

    // Assert that tokenize is dual to pretty-print:
    List<String> out = new ArrayList<>();
    try {
      tokenize(out, shellCommand);
    } finally {
      if (out.isEmpty()) { // i.e. an exception
        System.err.println(in);
      }
    }
    assertThat(out).isEqualTo(in);
  }

  @Test
  public void testTokenizeIsDualToPrettyPrint() throws Exception {
    // tokenize() is the inverse of prettyPrintArgv().  (However, the reverse
    // is not true, since there are many ways to escape the same string,
    // e.g. "foo" and 'foo'.)

    assertTokenizeIsDualToPrettyPrint("foo");
    assertTokenizeIsDualToPrettyPrint("foo bar");
    assertTokenizeIsDualToPrettyPrint("foo bar", "wiz");
    assertTokenizeIsDualToPrettyPrint("'foo'");
    assertTokenizeIsDualToPrettyPrint("\\'foo\\'");
    assertTokenizeIsDualToPrettyPrint("${filename%.c}.o");
    assertTokenizeIsDualToPrettyPrint("<html!>");

    assertTokenizeIsDualToPrettyPrint("");
    assertTokenizeIsDualToPrettyPrint("!@#$%^&*()");
    assertTokenizeIsDualToPrettyPrint("x'y\" z");
  }
}
