// 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.packages.util;

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

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.events.util.EventCollectionApparatus;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.GlobCache;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.PackageValidator;
import com.google.devtools.build.lib.packages.RawAttributeMapper;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.testutil.Scratch;
import com.google.devtools.build.lib.testutil.TestUtils;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.vfs.Dirent;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.junit.Before;

/** Base class for PackageFactory tests. */
// TODO(adonovan): merge this down into PackageFactory---one small step towards ending
//  a history abuse of the "extends" keyword.
public abstract class PackageFactoryTestBase {

  protected Scratch scratch;
  protected EventCollectionApparatus events = new EventCollectionApparatus();
  protected DummyPackageValidator dummyPackageValidator = new DummyPackageValidator();
  protected PackageFactoryApparatus packages =
      new PackageFactoryApparatus(events.reporter(), dummyPackageValidator);
  protected Root root;

  protected Package expectEvalSuccess(String... content)
      throws InterruptedException, IOException, NoSuchPackageException {
    Path file = scratch.file("pkg/BUILD", content);
    Package pkg = packages.eval("pkg", RootedPath.toRootedPath(root, file));
    assertThat(pkg.containsErrors()).isFalse();
    return pkg;
  }

  protected void expectEvalError(String expectedError, String... content) throws Exception {
    events.setFailFast(false);
    Path file = scratch.file("pkg/BUILD", content);
    Package pkg = packages.eval("pkg", RootedPath.toRootedPath(root, file));
    assertWithMessage("Expected evaluation error, but none was not reported")
        .that(pkg.containsErrors())
        .isTrue();
    events.assertContainsError(expectedError);
  }

  protected Path throwOnReaddir = null;

  protected static AttributeMap attributes(Rule rule) {
    return RawAttributeMapper.of(rule);
  }

  protected static void assertEvaluates(Package pkg, List<String> expected, String... include)
      throws Exception {
    assertEvaluates(pkg, expected, ImmutableList.copyOf(include), Collections.<String>emptyList());
  }

  protected static void assertEvaluates(
      Package pkg, List<String> expected, List<String> include, List<String> exclude)
      throws Exception {
    GlobCache globCache =
        new GlobCache(
            pkg.getFilename().asPath().getParentDirectory(),
            pkg.getPackageIdentifier(),
            ImmutableSet.of(),
            PackageFactoryApparatus.createEmptyLocator(),
            null,
            TestUtils.getPool(),
            -1);
    assertThat(globCache.globUnsorted(include, exclude, false, true))
        .containsExactlyElementsIn(expected);
  }

  @Before
  public final void initializeFileSystem() throws Exception {
    FileSystem fs =
        new InMemoryFileSystem() {
          @Override
          public Collection<Dirent> readdir(Path path, boolean followSymlinks) throws IOException {
            if (path.equals(throwOnReaddir)) {
              throw new FileNotFoundException(path.getPathString());
            }
            return super.readdir(path, followSymlinks);
          }
        };
    Path tmpPath = fs.getPath("/");
    scratch = new Scratch(tmpPath);
    root = Root.fromPath(scratch.dir("/"));
  }

  protected Path emptyBuildFile(String packageName) {
    return emptyFile("/" + packageName + "/BUILD");
  }

  protected Path emptyFile(String path) {
    try {
      return scratch.file(path);
    } catch (IOException e) {
      throw new IllegalStateException(e);
    }
  }

  protected boolean isValidPackageName(String packageName) throws Exception {
    // Write a license decl just in case it's a third_party package:
    Path buildFile = scratch.file("/" + packageName + "/BUILD", "licenses(['notice'])");
    Package pkg = packages.createPackage(packageName, RootedPath.toRootedPath(root, buildFile));
    return !pkg.containsErrors();
  }

  /********************************************************************
   *                                                                  *
   *              Test "glob" function in build language              *
   *                                                                  *
   ********************************************************************/
  protected void assertGlobFails(String globCallExpression, String expectedError) throws Exception {
    Package pkg = buildPackageWithGlob(globCallExpression);

    events.assertContainsError(expectedError);
    assertThat(pkg.containsErrors()).isTrue();
  }

  private Package buildPackageWithGlob(String globCallExpression) throws Exception {
    scratch.deleteFile("/dummypackage/BUILD");
    Path file = scratch.file("/dummypackage/BUILD", "x = " + globCallExpression);
    return packages.eval("dummypackage", RootedPath.toRootedPath(root, file));
  }

  private List<Pair<String, Boolean>> createGlobCacheKeys(
      List<String> expressions, boolean excludeDirs) {
    List<Pair<String, Boolean>> keys = Lists.newArrayListWithCapacity(expressions.size());
    for (String expression : expressions) {
      keys.add(Pair.of(expression, excludeDirs));
    }

    return keys;
  }

  /**
   * Test globbing in the context of a package, using the build language.
   * We use the specially setup "globs" test package and the files beneath it.
   * @param result the expected list of filenames that match the glob
   * @param includes an include pattern for the glob
   * @param excludes an exclude pattern for the glob
   * @param excludeDirs an exclude_directories flag for the glob
   * @throws Exception if the glob doesn't match the expected result.
   */
  protected void assertGlobMatches(
      List<String> result, List<String> includes, List<String> excludes, boolean excludeDirs)
      throws Exception {

    Pair<Package, GlobCache> evaluated =
        evaluateGlob(
            includes,
            excludes,
            excludeDirs,
            Starlark.format("(result == sorted(%r)) or fail('incorrect glob result')", result));

    Package pkg = evaluated.first;
    GlobCache globCache = evaluated.second;

    // Ensure all of the patterns are recorded against this package:
    assertThat(globCache.getKeySet().containsAll(createGlobCacheKeys(includes, excludeDirs)))
        .isTrue();
    assertThat(pkg.containsErrors()).isFalse();
  }

  /**
   * Evaluate a glob() call against a test directory and BUILD code to process the results.
   * @param includes a list of glob patterns; glob will include these files.
   * @param excludes a list of glob patterns to exclude even if previously included.
   * @param excludeDirs true if directories should be excluded from the match.
   * @param resultAssertion code in the BUILD language that can access the variable result,
   * to which the result of the glob will be bound, and that may contain an assertion on it.
   * @return a Package and a GlobCache.
   * @throws Exception if the processResult code causes a failure.
   */
  private Pair<Package, GlobCache> evaluateGlob(
      List<String> includes, List<String> excludes, boolean excludeDirs, String resultAssertion)
      throws Exception {
    Path globsDir = scratch.dir("/globs");
    globsDir.getChild("subdir").createDirectory();
    for (String file : ImmutableList.of("Wombat1.java", "Wombat2.java", "subdir/Wombat3.java")) {
      FileSystemUtils.createEmptyFile(globsDir.getRelative(file));
    }
    Path file =
        scratch.file(
            "/globs/BUILD",
            Starlark.format(
                "result = glob(%r, exclude=%r, exclude_directories=%r)",
                includes, excludes, excludeDirs ? 1 : 0),
            resultAssertion);

    return packages.evalAndReturnGlobCache(
        "globs", RootedPath.toRootedPath(root, file), packages.parse(file));
  }

  protected void assertGlobProducesError(String pattern, boolean errorExpected) throws Exception {
    events.setFailFast(false);
    Package pkg =
        evaluateGlob(ImmutableList.of(pattern), Collections.<String>emptyList(), false, "").first;
    assertThat(pkg.containsErrors()).isEqualTo(errorExpected);
    boolean foundError = false;
    for (Event event : events.collector()) {
      if (event.getMessage().contains("glob")) {
        if (!errorExpected) {
          fail("error not expected for glob pattern " + pattern + ", but got: " + event);
          return;
        }
        foundError = errorExpected;
        break;
      }
    }
    assertThat(foundError).isEqualTo(errorExpected);
  }

  /**
   * {@link PackageValidator} whose functionality can be swapped out on demand via {@link #setImpl}.
   */
  protected static class DummyPackageValidator implements PackageValidator {
    private PackageValidator underlying = PackageValidator.NOOP_VALIDATOR;

    /** Sets {@link PackageValidator} implementation to use. */
    public void setImpl(PackageValidator impl) {
      this.underlying = impl;
    }

    @Override
    public void validate(Package pkg, ExtendedEventHandler eventHandler)
        throws InvalidPackageException {
      underlying.validate(pkg, eventHandler);
    }
  }
}
