// 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.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.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 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", 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", 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()).isSameAs(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().getParentDirectory(),
            pkg.getPackageIdentifier(),
            PackageFactoryApparatus.createEmptyLocator(),
            null,
            TestUtils.getPool(),
            -1);
    assertThat(globCache.globUnsorted(include, exclude, false)).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("/tmp");
    scratch = new Scratch(tmpPath);
  }

  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, 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", 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 {

    // The BUILD language, unlike Skylark, doesn't have fail(), so instead,
    // we rely on boolean short circuit logic to only try to evaluate
    // the undefined identifier this_will_fail if the result isn't as expected,
    // in which case an error occurs (which we test in testGlobNegativeTest).
    Pair<Package, GlobCache> evaluated =
        evaluateGlob(
            includes,
            excludes,
            excludeDirs,
            Printer.format("(result == sorted(%r)) or this_will_fail()", 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(globCache.getKeySet().containsAll(createGlobCacheKeys(excludes, 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", 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"), buildFile, eventHandler);
        parsedOK = true;
      } catch (Exception e) {
        e.printStackTrace();
      }
    }

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