// 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.cmdline;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;

import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.cmdline.TargetPattern.ContainsTBDForTBDResult;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link com.google.devtools.build.lib.cmdline.TargetPattern}. */
@RunWith(JUnit4.class)
public class TargetPatternTest {
  private void expectError(String pattern) {
    assertThrows(TargetParsingException.class, () -> parse(pattern));
  }

  @Test
  public void testPassingValidations() throws TargetParsingException {
    parse("foo:bar");
    parse("foo:all");
    parse("foo/...:all");
    parse("foo:*");

    parse("//foo");
    parse("//foo:bar");
    parse("//foo:all");

    parse("//foo/all");
    parse("java/com/google/foo/Bar.java");
    parse("//foo/...:all");

    parse("//...");
    parse("@repo//foo:bar");
    parse("@repo//foo:all");
    parse("@repo//:bar");
  }

  @Test
  public void testInvalidPatterns() throws TargetParsingException {
    expectError("Bar\\java");
    expectError("");
    expectError("\\");
  }

  @Test
  public void testNormalize() {
    // Good cases.
    assertThat(TargetPattern.normalize("empty")).isEqualTo("empty");
    assertThat(TargetPattern.normalize("a/b")).isEqualTo("a/b");
    assertThat(TargetPattern.normalize("a/b/c")).isEqualTo("a/b/c");
    assertThat(TargetPattern.normalize("a/b/c.d")).isEqualTo("a/b/c.d");
    assertThat(TargetPattern.normalize("a/b/c..")).isEqualTo("a/b/c..");
    assertThat(TargetPattern.normalize("a/b/c...")).isEqualTo("a/b/c...");

    assertThat(TargetPattern.normalize("a/b/")).isEqualTo("a/b"); // Remove trailing empty segments
    assertThat(TargetPattern.normalize("a//c")).isEqualTo("a/c"); // Remove empty inner segments
    assertThat(TargetPattern.normalize("a/./d")).isEqualTo("a/d"); // Remove inner dot segments
    assertThat(TargetPattern.normalize("a/.")).isEqualTo("a"); // Remove trailing dot segments
    // Remove .. segment and its predecessor
    assertThat(TargetPattern.normalize("a/b/../e")).isEqualTo("a/e");
    // Remove trailing .. segment and its predecessor
    assertThat(TargetPattern.normalize("a/g/b/..")).isEqualTo("a/g");
    // Remove double .. segments and two predecessors
    assertThat(TargetPattern.normalize("a/b/c/../../h")).isEqualTo("a/h");
    // Don't remove leading .. segments
    assertThat(TargetPattern.normalize("../a")).isEqualTo("../a");
    assertThat(TargetPattern.normalize("../../a")).isEqualTo("../../a");
    assertThat(TargetPattern.normalize("../../../a")).isEqualTo("../../../a");
    assertThat(TargetPattern.normalize("a/../../../b")).isEqualTo("../../b");
  }

  @Test
  public void testTargetsBelowDirectoryContainsColonStar() throws Exception {
    // Given an outer pattern '//foo/...', that matches rules only,
    TargetPattern outerPattern =
        parseAsExpectedType("//foo/...", TargetPattern.Type.TARGETS_BELOW_DIRECTORY);
    // And a nested inner pattern '//foo/bar/...:*', that matches all targets,
    TargetPattern innerPattern =
        parseAsExpectedType("//foo/bar/...:*", TargetPattern.Type.TARGETS_BELOW_DIRECTORY);
    // Then a directory exclusion would exactly describe the subtraction of the inner pattern from
    // the outer pattern,
    assertThat(outerPattern.containsTBDForTBD(innerPattern))
        .isEqualTo(ContainsTBDForTBDResult.DIRECTORY_EXCLUSION_WOULD_BE_EXACT);
    // And the inner pattern does not contain the outer pattern.
    assertThat(innerPattern.containsTBDForTBD(outerPattern))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);
  }

  @Test
  public void testTargetsBelowDirectoryColonStarContains() throws Exception {
    // Given an outer pattern '//foo/...:*', that matches all targets,
    TargetPattern outerPattern =
        parseAsExpectedType("//foo/...:*", TargetPattern.Type.TARGETS_BELOW_DIRECTORY);
    // And a nested inner pattern '//foo/bar/...', that matches rules only,
    TargetPattern innerPattern =
        parseAsExpectedType("//foo/bar/...", TargetPattern.Type.TARGETS_BELOW_DIRECTORY);
    // Then a directory exclusion would be too broad,
    assertThat(outerPattern.containsTBDForTBD(innerPattern))
        .isEqualTo(ContainsTBDForTBDResult.DIRECTORY_EXCLUSION_WOULD_BE_TOO_BROAD);
    // And the inner pattern does not contain the outer pattern.
    assertThat(innerPattern.containsTBDForTBD(outerPattern))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);
  }

  @Test
  public void testTargetsBelowDirectoryContainsNestedPatterns() throws Exception {
    // Given an outer pattern '//foo/...',
    TargetPattern outerPattern =
        parseAsExpectedType("//foo/...", TargetPattern.Type.TARGETS_BELOW_DIRECTORY);
    // And a nested inner pattern '//foo/bar/...',
    TargetPattern innerPattern =
        parseAsExpectedType("//foo/bar/...", TargetPattern.Type.TARGETS_BELOW_DIRECTORY);
    // Then the outer pattern contains the inner pattern,
    assertThat(outerPattern.containsTBDForTBD(innerPattern))
        .isEqualTo(ContainsTBDForTBDResult.DIRECTORY_EXCLUSION_WOULD_BE_EXACT);
    // And the inner pattern does not contain the outer pattern.
    assertThat(innerPattern.containsTBDForTBD(outerPattern))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);
  }

  @Test
  public void testTargetsBelowDirectoryIsExcludableFromForIndependentPatterns() throws Exception {
    // Given a pattern '//foo/...',
    TargetPattern patternFoo =
        parseAsExpectedType("//foo/...", TargetPattern.Type.TARGETS_BELOW_DIRECTORY);
    // And a pattern '//bar/...',
    TargetPattern patternBar =
        parseAsExpectedType("//bar/...", TargetPattern.Type.TARGETS_BELOW_DIRECTORY);
    // Then neither pattern contains the other.
    assertThat(patternFoo.containsTBDForTBD(patternBar)).isEqualTo(ContainsTBDForTBDResult.OTHER);
    assertThat(patternBar.containsTBDForTBD(patternFoo)).isEqualTo(ContainsTBDForTBDResult.OTHER);
  }

  @Test
  public void testTargetsBelowDirectoryContainsForOtherPatternTypes() throws Exception {
    // Given a TargetsBelowDirectory pattern, tbdFoo of '//foo/...',
    TargetPattern tbdFoo =
        parseAsExpectedType("//foo/...", TargetPattern.Type.TARGETS_BELOW_DIRECTORY);

    // And target patterns of each type other than TargetsBelowDirectory, e.g. 'foo/bar',
    // '//foo:bar', and 'foo:all',
    TargetPattern pathAsTargetPattern =
        parseAsExpectedType("foo/bar", TargetPattern.Type.PATH_AS_TARGET);
    TargetPattern singleTargetPattern =
        parseAsExpectedType("//foo:bar", TargetPattern.Type.SINGLE_TARGET);
    TargetPattern targetsInPackagePattern =
        parseAsExpectedType("foo:all", TargetPattern.Type.TARGETS_IN_PACKAGE);

    // Then the non-TargetsBelowDirectory patterns do not contain tbdFoo.
    assertThat(pathAsTargetPattern.containsTBDForTBD(tbdFoo))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);
    // And are not considered to be a contained directory of the TargetsBelowDirectory pattern.
    assertThat(tbdFoo.containsTBDForTBD(pathAsTargetPattern))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);

    assertThat(singleTargetPattern.containsTBDForTBD(tbdFoo))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);
    assertThat(tbdFoo.containsTBDForTBD(singleTargetPattern))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);

    assertThat(targetsInPackagePattern.containsTBDForTBD(tbdFoo))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);
    assertThat(tbdFoo.containsTBDForTBD(targetsInPackagePattern))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);
  }

  @Test
  public void testTargetsBelowDirectoryDoesNotContainCoincidentPrefixPatterns() throws Exception {
    // Given a TargetsBelowDirectory pattern, tbdFoo of '//foo/...',
    TargetPattern tbdFoo =
        parseAsExpectedType("//foo/...", TargetPattern.Type.TARGETS_BELOW_DIRECTORY);

    // And target patterns with prefixes equal to the directory of the TBD pattern, but not below
    // it,
    TargetPattern targetsBelowDirectoryPattern =
        parseAsExpectedType("//food/...", TargetPattern.Type.TARGETS_BELOW_DIRECTORY);
    TargetPattern pathAsTargetPattern =
        parseAsExpectedType("food/bar", TargetPattern.Type.PATH_AS_TARGET);
    TargetPattern singleTargetPattern =
        parseAsExpectedType("//food:bar", TargetPattern.Type.SINGLE_TARGET);
    TargetPattern targetsInPackagePattern =
        parseAsExpectedType("food:all", TargetPattern.Type.TARGETS_IN_PACKAGE);

    // Then the non-TargetsBelowDirectory patterns are not contained by tbdFoo.
    assertThat(tbdFoo.containsTBDForTBD(targetsBelowDirectoryPattern))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);
    assertThat(tbdFoo.containsTBDForTBD(pathAsTargetPattern))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);
    assertThat(tbdFoo.containsTBDForTBD(singleTargetPattern))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);
    assertThat(tbdFoo.containsTBDForTBD(targetsInPackagePattern))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);
  }

  @Test
  public void testDepotRootTargetsBelowDirectoryContainsPatterns() throws Exception {
    // Given a TargetsBelowDirectory pattern, tbdDepot of '//...',
    TargetPattern tbdDepot =
        parseAsExpectedType("//...", TargetPattern.Type.TARGETS_BELOW_DIRECTORY);

    // And target patterns of each type other than TargetsBelowDirectory, e.g. 'foo/bar',
    // '//foo:bar', and 'foo:all',
    TargetPattern tbdFoo =
        parseAsExpectedType("//foo/...", TargetPattern.Type.TARGETS_BELOW_DIRECTORY);
    TargetPattern pathAsTargetPattern =
        parseAsExpectedType("foo/bar", TargetPattern.Type.PATH_AS_TARGET);
    TargetPattern singleTargetPattern =
        parseAsExpectedType("//foo:bar", TargetPattern.Type.SINGLE_TARGET);
    TargetPattern targetsInPackagePattern =
        parseAsExpectedType("foo:all", TargetPattern.Type.TARGETS_IN_PACKAGE);

    // Then the patterns are contained by tbdDepot, and do not contain tbdDepot.
    assertThat(tbdDepot.containsTBDForTBD(tbdFoo))
        .isEqualTo(ContainsTBDForTBDResult.DIRECTORY_EXCLUSION_WOULD_BE_EXACT);
    assertThat(tbdFoo.containsTBDForTBD(tbdDepot)).isEqualTo(ContainsTBDForTBDResult.OTHER);

    assertThat(tbdDepot.containsTBDForTBD(pathAsTargetPattern))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);
    assertThat(pathAsTargetPattern.containsTBDForTBD(tbdDepot))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);

    assertThat(tbdDepot.containsTBDForTBD(singleTargetPattern)).
        isEqualTo(ContainsTBDForTBDResult.OTHER);
    assertThat(singleTargetPattern.containsTBDForTBD(tbdDepot))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);

    assertThat(tbdDepot.containsTBDForTBD(targetsInPackagePattern))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);
    assertThat(targetsInPackagePattern.containsTBDForTBD(tbdDepot))
        .isEqualTo(ContainsTBDForTBDResult.OTHER);
  }

  @Test
  public void testRenameRepository() throws Exception {
    Map<RepositoryName, RepositoryName> renaming =
        ImmutableMap.of(
            RepositoryName.create("@foo"), RepositoryName.create("@bar"),
            RepositoryName.create("@myworkspace"), RepositoryName.create("@"));

    // Expecting renaming
    assertThat(TargetPattern.renameRepository("@foo//package:target", renaming))
        .isEqualTo("@bar//package:target");
    assertThat(TargetPattern.renameRepository("@myworkspace//package:target", renaming))
        .isEqualTo("@//package:target");
    assertThat(TargetPattern.renameRepository("@foo//foo/...", renaming))
        .isEqualTo("@bar//foo/...");
    assertThat(TargetPattern.renameRepository("@myworkspace//foo/...", renaming))
        .isEqualTo("@//foo/...");

    // No renaming should occur
    assertThat(TargetPattern.renameRepository("@//package:target", renaming))
        .isEqualTo("@//package:target");
    assertThat(TargetPattern.renameRepository("@unrelated//package:target", renaming))
        .isEqualTo("@unrelated//package:target");
    assertThat(TargetPattern.renameRepository("foo/package:target", renaming))
        .isEqualTo("foo/package:target");
    assertThat(TargetPattern.renameRepository("foo/...", renaming)).isEqualTo("foo/...");
  }

  private static TargetPattern parse(String pattern) throws TargetParsingException {
    return TargetPattern.defaultParser().parse(pattern);
  }

  private static TargetPattern parseAsExpectedType(String pattern, TargetPattern.Type expectedType)
      throws TargetParsingException {
    TargetPattern parsedPattern = parse(pattern);
    assertThat(parsedPattern.getType()).isEqualTo(expectedType);
    assertThat(parsedPattern.getOriginalPattern()).isEqualTo(pattern);
    return parsedPattern;
  }
}
