// 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.bazel.rules.ninja;

import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows;

import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Maps;
import com.google.devtools.build.lib.bazel.rules.ninja.file.ByteBufferFragment;
import com.google.devtools.build.lib.bazel.rules.ninja.file.GenericParsingException;
import com.google.devtools.build.lib.bazel.rules.ninja.lexer.NinjaLexer;
import com.google.devtools.build.lib.bazel.rules.ninja.parser.NinjaFileParseResult;
import com.google.devtools.build.lib.bazel.rules.ninja.parser.NinjaParserStep;
import com.google.devtools.build.lib.bazel.rules.ninja.parser.NinjaRule;
import com.google.devtools.build.lib.bazel.rules.ninja.parser.NinjaRuleVariable;
import com.google.devtools.build.lib.bazel.rules.ninja.parser.NinjaScope;
import com.google.devtools.build.lib.bazel.rules.ninja.parser.NinjaTarget;
import com.google.devtools.build.lib.bazel.rules.ninja.parser.NinjaVariableValue;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.function.Function;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link NinjaParserStep}. */
@RunWith(JUnit4.class)
public class NinjaParserStepTest {
  @Test
  public void testSimpleVariable() throws Exception {
    doTestSimpleVariable("a=b", "a", "b");
    doTestSimpleVariable("a=b\nc", "a", "b");
    doTestSimpleVariable("a=b # comment", "a", "b");
    doTestSimpleVariable("a.b.c =    some long:    value", "a.b.c", "some long:    value");
    doTestSimpleVariable("a_11_24-rt.15= ^&%=#@", "a_11_24-rt.15", "^&%=");
  }

  @Test
  public void testVariableParsingException() {
    doTestVariableParsingException(" ", "Expected identifier, but got indent");
    doTestVariableParsingException("a", "Expected = after 'a'");
    doTestVariableParsingException("a=", "Variable 'a' has no value.");
    doTestVariableParsingException(
        "^a=", "Expected identifier, but got error: 'Symbol is not allowed in the identifier.'");
  }

  private static void doTestVariableParsingException(String text, String message) {
    GenericParsingException exception =
        assertThrows(GenericParsingException.class, () -> createParser(text).parseVariable());
    assertThat(exception).hasMessageThat().isEqualTo(message);
  }

  @Test
  public void testNoValue() {
    doTestNoValue("a=");
    doTestNoValue("a=\u000018");
    doTestNoValue("a  =    ");
    doTestNoValue("a  =\nm");
    doTestNoValue("a  =    # 123");
  }

  @Test
  public void testWithVariablesInValue() throws Exception {
    doTestWithVariablesInValue("a=$a $b", "a", "${a} ${b}", ImmutableSortedSet.of("a", "b"));
    doTestWithVariablesInValue("a=a_$b_c", "a", "a_${b_c}", ImmutableSortedSet.of("b_c"));
    doTestWithVariablesInValue("a=$b a c", "a", "${b} a c", ImmutableSortedSet.of("b"));
    doTestWithVariablesInValue("a=a_$b c", "a", "a_${b} c", ImmutableSortedSet.of("b"));
    doTestWithVariablesInValue("a=a_${b.d}c", "a", "a_${b.d}c", ImmutableSortedSet.of("b.d"));
    doTestWithVariablesInValue(
        "e=a$b*c${ d }*18", "e", "a${b}*c${d}*18", ImmutableSortedSet.of("b", "d"));
    doTestWithVariablesInValue("e=a$b*${ b }", "e", "a${b}*${b}", ImmutableSortedSet.of("b"));
  }

  @Test
  public void testNormalizeVariableName() {
    assertThat(NinjaParserStep.normalizeVariableName("$a")).isEqualTo("a");
    assertThat(NinjaParserStep.normalizeVariableName("$a-b-c")).isEqualTo("a-b-c");
    assertThat(NinjaParserStep.normalizeVariableName("${abc_de-7}")).isEqualTo("abc_de-7");
    assertThat(NinjaParserStep.normalizeVariableName("${ a1.5}")).isEqualTo("a1.5");
    assertThat(NinjaParserStep.normalizeVariableName("${a1.5  }")).isEqualTo("a1.5");
  }

  @Test
  public void testInclude() throws Exception {
    NinjaVariableValue value1 = createParser("include x/multi words/z").parseIncludeStatement();
    assertThat(value1.getRawText()).isEqualTo("x/multi words/z");

    NinjaVariableValue value2 = createParser("subninja ${x}.ninja").parseSubNinjaStatement();
    assertThat(value2.getRawText()).isEqualTo("${x}.ninja");
    MockValueExpander expander = new MockValueExpander("###");
    assertThat(value2.getExpandedValue(expander)).isEqualTo("###x.ninja");
    assertThat(expander.getRequestedVariables()).containsExactly("x");
  }

  @Test
  public void testIncludeErrors() {
    GenericParsingException exception1 =
        assertThrows(
            GenericParsingException.class,
            () -> createParser("include x $").parseIncludeStatement());
    assertThat(exception1)
        .hasMessageThat()
        .isEqualTo(
            "Expected newline, but got error: "
                + "'Bad $-escape (literal $ must be written as $$)'");

    GenericParsingException exception2 =
        assertThrows(
            GenericParsingException.class, () -> createParser("include").parseIncludeStatement());
    assertThat(exception2).hasMessageThat().isEqualTo("include statement has no path.");

    GenericParsingException exception3 =
        assertThrows(
            GenericParsingException.class,
            () -> createParser("subninja  \nm").parseSubNinjaStatement());
    assertThat(exception3).hasMessageThat().isEqualTo("subninja statement has no path.");
  }

  @Test
  public void testNinjaRule() throws Exception {
    NinjaParserStep parser =
        createParser(
            "rule testRule  \n"
                + " command = executable --flag $TARGET $out && $POST_BUILD\n"
                + " description = Test rule for $TARGET\n"
                + " rspfile = $TARGET.in\n"
                + " deps = ${abc} $\n"
                + " ${cde}\n");
    NinjaRule ninjaRule = parser.parseNinjaRule();
    ImmutableSortedMap<NinjaRuleVariable, NinjaVariableValue> variables = ninjaRule.getVariables();
    assertThat(variables.keySet())
        .containsExactly(
            NinjaRuleVariable.NAME,
            NinjaRuleVariable.COMMAND,
            NinjaRuleVariable.DESCRIPTION,
            NinjaRuleVariable.RSPFILE,
            NinjaRuleVariable.DEPS);
    assertThat(variables.get(NinjaRuleVariable.NAME).getRawText()).isEqualTo("testRule");
    assertThat(variables.get(NinjaRuleVariable.DEPS).getRawText()).isEqualTo("${abc} $\n ${cde}");
    MockValueExpander expander = new MockValueExpander("###");
    assertThat(variables.get(NinjaRuleVariable.DEPS).getExpandedValue(expander))
        .isEqualTo("###abc $\n ###cde");
    assertThat(expander.getRequestedVariables()).containsExactly("abc", "cde");
  }

  @Test
  public void testNinjaRuleParsingException() {
    doTestNinjaRuleParsingException(
        "rule testRule extra-word\n", "Expected newline, but got identifier");
    doTestNinjaRuleParsingException(
        "rule testRule\n command =", "Variable 'command' has no value.");
    doTestNinjaRuleParsingException(
        "rule testRule\ncommand =", "Expected indent, but got identifier");
    doTestNinjaRuleParsingException(
        "rule testRule\n ^custom = a",
        "Expected identifier, but got error: 'Symbol is not allowed in the identifier.'");
    doTestNinjaRuleParsingException("rule testRule\n custom = a", "Unexpected variable 'custom'");
  }

  @Test
  public void testNinjaTargets() throws Exception {
    NinjaTarget target = parseNinjaTarget("build output: command input");
    assertThat(target.getRuleName()).isEqualTo("command");
    assertThat(target.getOutputs()).containsExactly(PathFragment.create("output"));
    assertThat(target.getUsualInputs()).containsExactly(PathFragment.create("input"));

    NinjaTarget target1 =
        parseNinjaTarget("build o1 o2 | io1 io2: command i1 i2 | ii1 ii2 || ooi1 ooi2");
    assertThat(target1.getRuleName()).isEqualTo("command");
    assertThat(target1.getOutputs())
        .containsExactly(PathFragment.create("o1"), PathFragment.create("o2"));
    assertThat(target1.getImplicitOutputs())
        .containsExactly(PathFragment.create("io1"), PathFragment.create("io2"));
    assertThat(target1.getUsualInputs())
        .containsExactly(PathFragment.create("i1"), PathFragment.create("i2"));
    assertThat(target1.getImplicitInputs())
        .containsExactly(PathFragment.create("ii1"), PathFragment.create("ii2"));
    assertThat(target1.getOrderOnlyInputs())
        .containsExactly(PathFragment.create("ooi1"), PathFragment.create("ooi2"));

    NinjaTarget target2 = parseNinjaTarget("build output: phony");
    assertThat(target2.getRuleName()).isEqualTo("phony");
    assertThat(target2.getOutputs()).containsExactly(PathFragment.create("output"));

    NinjaTarget target3 = parseNinjaTarget("build output: command $\n || order-only-input");
    assertThat(target3.getRuleName()).isEqualTo("command");
    assertThat(target3.getOutputs()).containsExactly(PathFragment.create("output"));
    assertThat(target3.getOrderOnlyInputs())
        .containsExactly(PathFragment.create("order-only-input"));
  }

  @Test
  public void testNinjaTargetParsingErrors() {
    testNinjaTargetParsingError("build xxx", "Unexpected end of target");
    testNinjaTargetParsingError("build xxx yyy:", "Expected rule name");
    testNinjaTargetParsingError("build xxx || yyy: command", "Unexpected token: PIPE2");
    testNinjaTargetParsingError("build xxx: command :", "Unexpected token: COLON");
    testNinjaTargetParsingError("build xxx: command | || a", "Expected paths sequence");
  }

  @Test
  public void testNinjaTargetsWithVariables() throws Exception {
    NinjaFileParseResult parseResult = new NinjaFileParseResult();
    parseResult.addVariable("output", 1, NinjaVariableValue.createPlainText("out123"));
    parseResult.addVariable("input", 2, NinjaVariableValue.createPlainText("in123"));

    NinjaScope scope = new NinjaScope();
    parseResult.expandIntoScope(scope, Maps.newHashMap());

    // Variables, defined inside build statement, are used for input and output paths,
    // but not for the values of the other variables.
    // Test it.
    NinjaTarget target =
        createParser(
                "build $output : command $input $dir/abcde\n"
                    + "  dir = def$input\n  empty = '$dir'")
            .parseNinjaTarget(scope, 5);
    assertThat(target.getRuleName()).isEqualTo("command");
    assertThat(target.getOutputs()).containsExactly(PathFragment.create("out123"));
    assertThat(target.getUsualInputs())
        .containsExactly(PathFragment.create("in123"), PathFragment.create("defin123/abcde"));
    assertThat(target.getVariables())
        .containsExactlyEntriesIn(ImmutableSortedMap.of("dir", "defin123", "empty", "''"));
  }

  @Test
  public void testPseudoCyclesOfVariables() throws Exception {
    NinjaFileParseResult parseResult = new NinjaFileParseResult();
    parseResult.addVariable(
        "output", 1, NinjaVariableValue.builder().addText("'out'").addVariable("input").build());
    parseResult.addVariable(
        "input", 2, NinjaVariableValue.builder().addText("'in'").addVariable("output").build());
    NinjaScope scope = new NinjaScope();
    parseResult.expandIntoScope(scope, Maps.newHashMap());
    assertThat(scope.findExpandedVariable(3, "input")).isEqualTo("'in''out'");
    assertThat(scope.findExpandedVariable(3, "output")).isEqualTo("'out'");
  }

  @Test
  public void testNinjaTargetsPathWithEscapedSpace() throws Exception {
    NinjaTarget target = parseNinjaTarget("build output : command input$ with$ space other");
    assertThat(target.getRuleName()).isEqualTo("command");
    assertThat(target.getOutputs()).containsExactly(PathFragment.create("output"));
    assertThat(target.getUsualInputs())
        .containsExactly(PathFragment.create("input with space"), PathFragment.create("other"));
  }

  @Test
  public void testNinjaTargetWithScope() throws Exception {
    NinjaTarget target = parseNinjaTarget("build output : command input\n  pool = abc\n");
    assertThat(target.getRuleName()).isEqualTo("command");
    assertThat(target.getOutputs()).containsExactly(PathFragment.create("output"));
    assertThat(target.getUsualInputs()).containsExactly(PathFragment.create("input"));
  }

  private static void testNinjaTargetParsingError(String text, String error) {
    GenericParsingException exception =
        assertThrows(GenericParsingException.class, () -> parseNinjaTarget(text));
    assertThat(exception).hasMessageThat().isEqualTo(error);
  }

  private static NinjaTarget parseNinjaTarget(String text) throws Exception {
    NinjaScope fileScope = new NinjaScope();
    return createParser(text).parseNinjaTarget(fileScope, 0);
  }

  private static void doTestNinjaRuleParsingException(String text, String message) {
    GenericParsingException exception =
        assertThrows(GenericParsingException.class, () -> createParser(text).parseNinjaRule());
    assertThat(exception).hasMessageThat().isEqualTo(message);
  }

  private static void doTestSimpleVariable(String text, String name, String value)
      throws Exception {
    NinjaParserStep parser = createParser(text);
    Pair<String, NinjaVariableValue> variable = parser.parseVariable();
    assertThat(variable.getFirst()).isEqualTo(name);
    assertThat(variable.getSecond()).isNotNull();
    assertThat(variable.getSecond().getRawText()).isEqualTo(value);

    MockValueExpander expander = new MockValueExpander("###");
    assertThat(variable.getSecond().getExpandedValue(expander)).isEqualTo(value);
    assertThat(expander.getRequestedVariables()).isEmpty();
  }

  private static void doTestNoValue(String text) {
    NinjaParserStep parser = createParser(text);
    GenericParsingException exception =
        assertThrows(GenericParsingException.class, parser::parseVariable);
    assertThat(exception).hasMessageThat().isEqualTo("Variable 'a' has no value.");
  }

  private static void doTestWithVariablesInValue(
      String text, String name, String value, ImmutableSortedSet<String> expectedVars)
      throws Exception {
    NinjaParserStep parser = createParser(text);
    Pair<String, NinjaVariableValue> variable = parser.parseVariable();
    assertThat(variable.getFirst()).isEqualTo(name);
    assertThat(variable.getSecond()).isNotNull();
    assertThat(variable.getSecond().getRawText()).isEqualTo(value);

    MockValueExpander expander = new MockValueExpander("###");
    assertThat(variable.getSecond().getExpandedValue(expander)).contains("###");
    assertThat(expander.getRequestedVariables()).containsExactlyElementsIn(expectedVars);
  }

  private static NinjaParserStep createParser(String text) {
    ByteBuffer buffer = ByteBuffer.wrap(text.getBytes(StandardCharsets.ISO_8859_1));
    NinjaLexer lexer = new NinjaLexer(new ByteBufferFragment(buffer, 0, buffer.limit()));
    return new NinjaParserStep(lexer);
  }

  private static class MockValueExpander implements Function<String, String> {
    private final ImmutableSortedSet.Builder<String> setBuilder;
    private final String prefix;

    private MockValueExpander(String prefix) {
      this.prefix = prefix;
      setBuilder = ImmutableSortedSet.naturalOrder();
    }

    @Override
    public String apply(String s) {
      setBuilder.add(s);
      return prefix + s;
    }

    public ImmutableSortedSet<String> getRequestedVariables() {
      return setBuilder.build();
    }
  }
}
