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

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

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.testutil.FoundationTestCase;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.UnixGlob;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Pattern;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Test package-path logic.
 */
@RunWith(JUnit4.class)
public class PathPackageLocatorTest extends FoundationTestCase {
  private Path buildFile_1A;
  private Path buildFile_1B;
  private Path buildFile_2C;
  private Path buildFile_2CD;
  private Path buildFile_2F;
  private Path buildFile_2FGH;
  private Path buildFile_3A;
  private Path buildFile_3B;
  private Path buildFile_3CI;
  private Path rootDir1;
  private Path rootDir1WorkspaceFile;
  private Path rootDir2;
  private Path rootDir3ParentParent;
  private Path rootDir3;
  private Path rootDir4Parent;
  private Path rootDir4;
  private Path rootDir5;
  private PathPackageLocator locator;
  private PathPackageLocator locatorWithSymlinks;

  protected PathPackageLocator getLocator() { return locator; }


  @Before
  public final void createFiles() throws Exception {
    // Root 1:
    //   WORKSPACE
    //   /A/BUILD
    //   /B/BUILD
    //   /C/I/BUILD
    //   /C/D
    //   /C/E
    //   /F/G         // This is a file, not a directory.
    //
    // Root 2:
    //   WORKSPACE
    //   /B/BUILD
    //   /C/BUILD
    //   /C/D/BUILD
    //   /F/BUILD
    //   /F/G
    //   /F/G/H/BUILD
    //   /I/BUILD         // This is a directory, not a file.
    //
    // Root 3:
    //   /usr/local/google/jrluser-foo/READONLY -> root4
    //
    // Root 4 (not used as a package root, but root 3 points to this)
    //   /A -> root1/A
    //   /B/BUILD -> root1/B/BUILD
    //   /C/I/BUILD -> root1/C/I/BUILD
    //   /C/D -> root1/C/D
    //   /C/E -> root1/C/E
    //   /F/G -> root1/F/G
    //   /H/I -> root5/H/I
    //
    // Root 5 (pointed to by Root 4)
    //   Note: the following BUILD file will be found if explicitly specified, but it
    //     would not be found if using wildcards.  That is because isDirectory
    //     will return false since the symlink target is not in the workspace.
    //   /H/I/BUILD
    rootDir1 = scratch.resolve("/home/user/src-foo/workspace");
    rootDir2 = scratch.resolve("/somewhere/1234567/build/workspace");
    rootDir3ParentParent = scratch.resolve("/usr/local/google/jrluser-foo");
    rootDir3 = rootDir3ParentParent.getRelative("READONLY/workspace");
    rootDir4Parent =  scratch.resolve("/usr/local/symlinks/client_symlink_jrluser-foo");
    rootDir4 = rootDir4Parent.getRelative("workspace");
    rootDir5 = scratch.resolve("/foo/bar");

    rootDir1WorkspaceFile = scratch.file(rootDir1 + "/WORKSPACE");
    buildFile_1A   = createBuildFile(rootDir1, "A");
    buildFile_1B   = createBuildFile(rootDir1, "B");
    createBuildFile(rootDir1, "C/I");
    scratch.file(rootDir1.getPathString() + "/F/G");

    rootDir1.getRelative("C").createDirectory();
    rootDir1.getRelative("C/D").createDirectory();
    rootDir1.getRelative("C/E").createDirectory();

    // Workspace file in rootDir2.
    scratch.file(rootDir2 + "/WORKSPACE");
    createBuildFile(rootDir2, "B");
    buildFile_2C   = createBuildFile(rootDir2, "C");
    buildFile_2CD  = createBuildFile(rootDir2, "C/D");
    buildFile_2F   = createBuildFile(rootDir2, "F");
    buildFile_2FGH = createBuildFile(rootDir2, "F/G/H");
    scratch.file(rootDir2.getPathString() + "/C/I");

    // Root3 just needs a symlink to 4
    FileSystemUtils.ensureSymbolicLink(
        rootDir3ParentParent.getRelative("READONLY"), rootDir4Parent);
    buildFile_3A = rootDir3.getRelative("A/BUILD");
    buildFile_3B = rootDir3.getRelative("B/BUILD");
    buildFile_3CI = rootDir3.getRelative("C/I/BUILD");

    // Root4
    FileSystemUtils.ensureSymbolicLink(
        rootDir4.getRelative("A"), rootDir1.getRelative("A"));
    FileSystemUtils.ensureSymbolicLink(
        rootDir4.getRelative("B/BUILD"), rootDir1.getRelative("B/BUILD"));
    FileSystemUtils.ensureSymbolicLink(
        rootDir4.getRelative("C/I/BUILD"), rootDir1.getRelative("C/I/BUILD"));
    FileSystemUtils.ensureSymbolicLink(
        rootDir4.getRelative("C/D/BUILD"), rootDir1.getRelative("C/D/BUILD"));
    FileSystemUtils.ensureSymbolicLink(
        rootDir4.getRelative("C/E/BUILD"), rootDir1.getRelative("C/E/BUILD"));
    FileSystemUtils.ensureSymbolicLink(
        rootDir4.getRelative("F/G/BUILD"), rootDir1.getRelative("F/G/BUILD"));
    FileSystemUtils.ensureSymbolicLink(
        rootDir4.getRelative("H/I"), rootDir5.getRelative("H/I"));

    // Root5
    createBuildFile(rootDir5, "H/I");

    locator = new PathPackageLocator(outputBase, ImmutableList.of(rootDir1, rootDir2));
    locatorWithSymlinks = new PathPackageLocator(outputBase, ImmutableList.of(rootDir3));
  }

  private Path createBuildFile(Path workspace, String packageName) throws IOException {
    return scratch.file(workspace + "/" + packageName + "/BUILD");
  }

  private void checkFails(String packageName, String expectedError) {
    checkFails(getLocator(), packageName, expectedError);
  }

  private static void checkFails(
      PathPackageLocator locator, String packageName, String expectedError) {
    try {
      locator.getPackageBuildFile(PackageIdentifier.createInMainRepo(packageName));
      fail();
    } catch (NoSuchPackageException e) {
      String message = e.getMessage();
      assertThat(message)
          .containsMatch(Pattern.compile(Pattern.quote(expectedError), Pattern.CASE_INSENSITIVE));
    }
  }

  @Test
  public void testGetPackageBuildFile() throws Exception {
    AtomicReference<? extends UnixGlob.FilesystemCalls> cache = UnixGlob.DEFAULT_SYSCALLS_REF;
    assertThat(locator.getPackageBuildFile(PackageIdentifier.createInMainRepo("A")))
        .isEqualTo(buildFile_1A);
    assertThat(locator.getPackageBuildFileNullable(PackageIdentifier.createInMainRepo("A"), cache))
        .isEqualTo(buildFile_1A);
    assertThat(locator.getPackageBuildFile(PackageIdentifier.createInMainRepo("B")))
        .isEqualTo(buildFile_1B);
    assertThat(locator.getPackageBuildFileNullable(PackageIdentifier.createInMainRepo("B"), cache))
        .isEqualTo(buildFile_1B);
    assertThat(locator.getPackageBuildFile(PackageIdentifier.createInMainRepo("C")))
        .isEqualTo(buildFile_2C);
    assertThat(locator.getPackageBuildFileNullable(PackageIdentifier.createInMainRepo("C"), cache))
        .isEqualTo(buildFile_2C);
    assertThat(locator.getPackageBuildFile(PackageIdentifier.createInMainRepo("C/D")))
        .isEqualTo(buildFile_2CD);
    assertThat(
            locator.getPackageBuildFileNullable(PackageIdentifier.createInMainRepo("C/D"), cache))
        .isEqualTo(buildFile_2CD);
    checkFails("C/E",
               "no such package 'C/E': BUILD file not found on package path");
    assertThat(
            locator.getPackageBuildFileNullable(PackageIdentifier.createInMainRepo("C/E"), cache))
        .isNull();
    assertThat(locator.getPackageBuildFile(PackageIdentifier.createInMainRepo("F")))
        .isEqualTo(buildFile_2F);
    checkFails("F/G",
               "no such package 'F/G': BUILD file not found on package path");
    assertThat(
            locator.getPackageBuildFileNullable(PackageIdentifier.createInMainRepo("F/G"), cache))
        .isNull();
    assertThat(locator.getPackageBuildFile(PackageIdentifier.createInMainRepo("F/G/H")))
        .isEqualTo(buildFile_2FGH);
    assertThat(
            locator.getPackageBuildFileNullable(PackageIdentifier.createInMainRepo("F/G/H"), cache))
        .isEqualTo(buildFile_2FGH);
    checkFails("I", "no such package 'I': BUILD file not found on package path");
  }

  @Test
  public void testGetPackageBuildFileWithSymlinks() throws Exception {
    assertThat(locatorWithSymlinks.getPackageBuildFile(PackageIdentifier.createInMainRepo("A")))
        .isEqualTo(buildFile_3A);
    assertThat(locatorWithSymlinks.getPackageBuildFile(PackageIdentifier.createInMainRepo("B")))
        .isEqualTo(buildFile_3B);
    assertThat(locatorWithSymlinks.getPackageBuildFile(PackageIdentifier.createInMainRepo("C/I")))
        .isEqualTo(buildFile_3CI);
    checkFails(
        locatorWithSymlinks, "C/D", "no such package 'C/D': BUILD file not found on package path");
  }

  @Test
  public void testGetWorkspaceFile() throws Exception {
    assertThat(locator.getWorkspaceFile()).isEqualTo(rootDir1WorkspaceFile);
  }

  private Path setLocator(String root) {
    Path nonExistentRoot = scratch.resolve(root);
    this.locator = PathPackageLocator.create(null, Arrays.asList(root), reporter,
            /*workspace=*/ FileSystemUtils.getWorkingDirectory(scratch.getFileSystem()),
            /*workingDir=*/ FileSystemUtils.getWorkingDirectory(scratch.getFileSystem()));
    return nonExistentRoot;
  }

  @Test
  public void testExists() throws Exception {
    Path nonExistentRoot1 = setLocator("/non/existent/1/workspace");
    // Now let's create the root:
    createBuildFile(nonExistentRoot1, "X");
    // The package isn't found
    // The package is found, because we didn't drop the root:
    try {
      locator.getPackageBuildFile(PackageIdentifier.createInMainRepo("X"));
      fail("Exception expected");
    } catch (NoSuchPackageException e) {
    }
    Path nonExistentRoot2 = setLocator("/non/existent/2/workspace");
    // Now let's create the root:
    createBuildFile(nonExistentRoot2, "X");
    // ...but the package is still not found, because we dropped the root:
    checkFails("X",
               "no such package 'X': BUILD file not found on package path");
  }

  @Test
  public void testPathResolution() throws Exception {
    Path workspace = scratch.dir("/some/path/to/workspace");
    Path clientPath = workspace.getRelative("somewhere/below/workspace");
    scratch.dir(clientPath.getPathString());
    Path belowClient = clientPath.getRelative("below/client");
    scratch.dir(belowClient.getPathString());

    List<String> pathElements = ImmutableList.of(
        "./below/client",        // Client-relative
        ".",                     // Client-relative
        "%workspace%/somewhere", // Workspace-relative
        // Absolute
        clientPath.getRelative("below").getPathString());
    assertThat(PathPackageLocator
        .create(null, pathElements, reporter, workspace, clientPath).getPathEntries())
        .containsExactly(belowClient, clientPath, workspace.getRelative("somewhere"),
            clientPath.getRelative("below")).inOrder();
  }

  @Test
  public void testRelativePathWarning() throws Exception {
    Path workspace = scratch.dir("/some/path/to/workspace");

    // No warning if workspace == cwd.
    PathPackageLocator.create(null, ImmutableList.of("./foo"), reporter, workspace, workspace);
    assertThat(eventCollector.count()).isSameAs(0);

    PathPackageLocator.create(
        null, ImmutableList.of("./foo"), reporter, workspace, workspace.getRelative("foo"));
    assertThat(eventCollector.count()).isSameAs(1);
    assertContainsEvent("The package path element './foo' will be taken relative");
  }

  /** Regression test for bug: "IllegalArgumentException in PathPackageLocator.create()" */
  @Test
  public void testDollarSigns() throws Exception {
    Path workspace = scratch.dir("/some/path/to/workspace$1");

    PathPackageLocator.create(null, ImmutableList.of("%workspace%/blabla"), reporter, workspace,
        workspace.getRelative("foo"));
  }
}
