// 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.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.events.Location;
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.OutputFile;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.RawAttributeMapper;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.syntax.Printer;
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 java.util.concurrent.Semaphore;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import org.junit.Before;

/**
 * Base class for PackageFactory tests.
 */
public abstract class PackageFactoryTestBase {

  protected Scratch scratch;
  protected EventCollectionApparatus events = new EventCollectionApparatus();
  protected PackageFactoryApparatus packages = createPackageFactoryApparatus();
  protected Root root;

  protected com.google.devtools.build.lib.packages.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 abstract PackageFactoryApparatus createPackageFactoryApparatus();

  protected Path throwOnReaddir = null;

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

  protected static void assertOutputFileForRule(Package pkg, Collection<String> outNames, Rule rule)
      throws Exception {
    for (String outName : outNames) {
      OutputFile out = (OutputFile) pkg.getTarget(outName);
      assertThat(rule.getOutputFiles()).contains(out);
      assertThat(out.getGeneratingRule()).isSameInstanceAs(rule);
      assertThat(out.getName()).isEqualTo(outName);
      assertThat(out.getTargetKind()).isEqualTo("generated file");
    }
    assertThat(rule.getOutputFiles()).hasSize(outNames.size());
  }

  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(getPathPrefix() + "/" + 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(
        getPathPrefix() + "/" + 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,
            Printer.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",
            Printer.format(
                "result = glob(%r, exclude=%r, exclude_directories=%r)",
                includes, excludes, excludeDirs ? 1 : 0),
            resultAssertion);

    return packages.evalAndReturnGlobCache(
        "globs", RootedPath.toRootedPath(root, file), packages.ast(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);
  }

  /** Runnable that asks for parsing of build file and synchronizes it with
   * ErrorReporter. It consumes log messages from PackageFactory to release
   * first semaphore when parsing is started and waits for second semaphore
   * before it ends.
   */
  protected class ParsingTracker extends Handler implements Runnable {
    private final Semaphore parsingStarted;
    private final Semaphore errorReported;
    private final ExtendedEventHandler eventHandler;
    private boolean first = true;
    private boolean parsedOK;

    public ParsingTracker(Semaphore first, Semaphore second, ExtendedEventHandler eventHandler) {
      this.eventHandler = eventHandler;
      parsingStarted = first;
      errorReported = second;
    }

    @Override
    public void run() {
      try {
        Path buildFile =
            scratch.file(
                getPathPrefix() + "/isolated/BUILD",
                "# -*- python -*-",
                "",
                "java_library(name = 'mylib',",
                "  srcs = 'java/A.java')");
        packages.createPackage(
            PackageIdentifier.createInMainRepo("isolated"),
            RootedPath.toRootedPath(root, buildFile),
            eventHandler);
        parsedOK = true;
      } catch (Exception e) {
        throw new IllegalStateException(e);
      }
    }

    public boolean hasParsed() {
      return parsedOK;
    }

    @Override
    public void close() throws SecurityException {}

    @Override
    public void flush() {}

    @Override
    public void publish(LogRecord record) {
      if (!record.getMessage().contains("isolated")) {
        return;
      }

      if (first) {
        parsingStarted.release();
        first = false;
      } else {
        try {
          errorReported.acquire();
        } catch (InterruptedException e) {
          e.printStackTrace();
          fail("parsing thread interrupted");
        }
      }
    }
  }

  protected abstract String getPathPrefix();

  /** Process interfering with parsing of build files.
   *  It waits until parsing of some BUILD file is started and then reports
   *  arbitrary error. It signals that error was submitted so the parsing can be
   *  finished at the end.
   */
  protected class ErrorReporter implements Runnable {
    private final EventHandler eventHandler;
    private final Semaphore parsingStarted;
    private final Semaphore errorReported;

    public ErrorReporter(EventHandler eventHandler, Semaphore first, Semaphore second) {
      this.eventHandler = eventHandler;
      parsingStarted = first;
      errorReported = second;
    }

    @Override
    public void run() {
      try {
        parsingStarted.acquire();
        eventHandler.handle(
            Event.error(Location.fromFile(scratch.file("dummy")), "Error from other " + "thread"));
        errorReported.release();
      } catch (InterruptedException e) {
        e.printStackTrace();
        fail("ErrorReporter thread interrupted");
      } catch (IOException e) {
        e.printStackTrace();
        fail("ErrorReporter thread failed with IOException");
      }
    }
  }
}
