// 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 in fragment:\n \n");
    doTestVariableParsingException("a", "Expected = after 'a' in fragment:\na\n");
    doTestVariableParsingException(
        "^a=",
        "Expected identifier, but got error: 'Symbol '^' is not allowed in the identifier, "
            + "the text fragment with the symbol:\n^a=\n' in fragment:\n^a=\n");
  }

  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() throws Exception {
    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 $$)' in fragment:\ninclude x $\n");

    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 {
    // Additionally test the situation when we get more line separators in the end.
    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\n\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 testVariableWithoutValue() throws Exception {
    NinjaParserStep parser =
        createParser(
            "rule testRule  \n"
                + " command = executable --flag $TARGET $out && $POST_BUILD\n"
                + " description =\n");
    NinjaRule ninjaRule = parser.parseNinjaRule();
    ImmutableSortedMap<NinjaRuleVariable, NinjaVariableValue> variables = ninjaRule.getVariables();
    assertThat(variables.keySet())
        .containsExactly(
            NinjaRuleVariable.NAME, NinjaRuleVariable.COMMAND, NinjaRuleVariable.DESCRIPTION);
    assertThat(variables.get(NinjaRuleVariable.NAME).getRawText()).isEqualTo("testRule");
    assertThat(variables.get(NinjaRuleVariable.DESCRIPTION).getRawText()).isEmpty();
  }

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

  @Test
  public void testNinjaTargets() throws Exception {
    // Additionally test the situation when the target does not have the variables section and
    // we get more line separators in the end.
    NinjaTarget target = parseNinjaTarget("build output: command input\n\n");
    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) throws Exception {
    NinjaParserStep parser = createParser(text);
    NinjaVariableValue value = parser.parseVariable().getSecond();
    assertThat(value).isNotNull();
    assertThat(value.getRawText()).isEmpty();
  }

  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();
    }
  }
}
