/*
 * Copyright 2012-present Facebook, Inc.
 *
 * 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.facebook.buck.java;

import com.facebook.buck.android.UberRDotJavaUtil;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.rules.ArtifactCache;
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.CachingBuildRuleParams;
import com.facebook.buck.rules.LabelsAttributeBuilder;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.rules.TestCaseSummary;
import com.facebook.buck.rules.TestResults;
import com.facebook.buck.rules.TestRule;
import com.facebook.buck.rules.XmlTestResultParser;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.fs.MakeCleanDirectoryStep;
import com.facebook.buck.util.BuckConstant;
import com.facebook.buck.util.Functions;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.buck.util.ZipFileTraversal;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import java.io.File;
import java.io.IOException;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import javax.annotation.Nullable;

public class JavaTestRule extends DefaultJavaLibraryRule implements TestRule {

  private final ImmutableList<String> vmArgs;

  /**
   * Build rules for which this test rule will be testing.
   */
  private final ImmutableSet<JavaLibraryRule> sourceUnderTest;

  private CompiledClassFileFinder compiledClassFileFinder;

  private final ImmutableSet<String> labels;

  private final String tmpDirectory;

  protected JavaTestRule(CachingBuildRuleParams cachingBuildRuleParams,
      Set<String> srcs,
      Set<String> resources,
      Set<String> labels,
      Optional<String> proguardConfig,
      AnnotationProcessingParams annotationProcessors,
      List<String> vmArgs,
      ImmutableSet<JavaLibraryRule> sourceUnderTest,
      String sourceLevel,
      String targetLevel,
      Function<String, String> relativeToAbsolutePathFunction) {
    super(cachingBuildRuleParams,
        srcs,
        resources,
        proguardConfig,
        annotationProcessors,
        /* exportDeps */ false,
        sourceLevel,
        targetLevel);
    this.vmArgs = ImmutableList.copyOf(vmArgs);
    this.sourceUnderTest = Preconditions.checkNotNull(sourceUnderTest);
    this.labels = ImmutableSet.copyOf(labels);

    String temp = String.format("%s/%s/%s__tmp",
	        BuckConstant.GEN_DIR,
	        cachingBuildRuleParams.getBuildTarget().getBasePath(),
	        getBuildTarget().getShortName()
	        );
    this.tmpDirectory = relativeToAbsolutePathFunction.apply(temp);
  }

  @Override
  public BuildRuleType getType() {
    return BuildRuleType.JAVA_TEST;
  }

  @Override
  public ImmutableSet<String> getLabels() {
    return labels;
  }

  @Override
  protected RuleKey.Builder ruleKeyBuilder() {
    // Convert sourceUnderTest to a form that RuleKey can handle.  Ideally RuleKey would directly
    // handle sourceUnderTest, but type erasure would cause method overload ambiguity.  The other
    // alternative would be to add a converter method to JavaLibraryRule, but that will not work
    // because JavaLibraryRule is an interface.
    Comparator<BuildRule> comparator = new Comparator<BuildRule>() {
      @Override
      public int compare(BuildRule o1, BuildRule o2) {
        return o1.compareTo(o2);
      }
    };
    ImmutableSortedSet.Builder<BuildRule> builder
        = new ImmutableSortedSet.Builder<BuildRule>(comparator);
    for (JavaLibraryRule rule : sourceUnderTest) {
      builder.add(rule);
    }
    ImmutableSortedSet<BuildRule> srcUnderTest = builder.build();

    return super.ruleKeyBuilder()
        .set("vmArgs", vmArgs)
        .set("sourceUnderTest", srcUnderTest)
        ;
  }

  /**
   * @return A set of rules that this test rule will be testing.
   */
  public ImmutableSet<JavaLibraryRule> getSourceUnderTest() {
    return sourceUnderTest;
  }

  public ImmutableList<String> getVmArgs() {
    return vmArgs;
  }

  /**
   * Runs the tests specified by the "srcs" of this class. If this rule transitively depends on
   * other {@code java_test()} rules, then they will be run separately.
   */
  @Override
  public List<Step> runTests(BuildContext buildContext, ExecutionContext executionContext) {
    Preconditions.checkState(isRuleBuilt(), "%s must be built before tests can be run.", this);

    // If no classes were generated, then this is probably a java_test() that declares a number of
    // other java_test() rules as deps, functioning as a test suite. In this case, simply return an
    // empty list of commands.
    Set<String> testClassNames = getClassNamesForSources();
    if (testClassNames.isEmpty()) {
      return ImmutableList.of();
    }

    // androidResourceDeps will be null if this test is re-run without being rebuilt.
    if (androidResourceDeps == null) {
      androidResourceDeps = UberRDotJavaUtil.getAndroidResourceDeps(this,
          buildContext.getDependencyGraph());
    }

    ImmutableList.Builder<Step> steps = ImmutableList.builder();

    String pathToTestOutput = getPathToTestOutput();
    steps.add(new MakeCleanDirectoryStep(pathToTestOutput));
    steps.add(new MakeCleanDirectoryStep(tmpDirectory));

    // If there are android resources, then compile the uber R.java files and add them to the
    // classpath used to run the test runner.
    ImmutableSet<String> classpathEntries;
    if (isAndroidRule()) {
      BuildTarget buildTarget = getBuildTarget();
      String rDotJavaClasspathEntry;
      UberRDotJavaUtil.createDummyRDotJavaFiles(androidResourceDeps, buildTarget, steps);
      rDotJavaClasspathEntry = UberRDotJavaUtil.getRDotJavaBinFolder(buildTarget);
      ImmutableSet.Builder<String> classpathEntriesBuilder = ImmutableSet.builder();
      classpathEntriesBuilder.add(rDotJavaClasspathEntry);
      classpathEntriesBuilder.addAll(getTransitiveClasspathEntries().values());
      classpathEntries = classpathEntriesBuilder.build();
    } else {
      classpathEntries = ImmutableSet.copyOf(getTransitiveClasspathEntries().values());
    }

    Step junit = new JUnitStep(
        classpathEntries,
        testClassNames,
        vmArgs,
        pathToTestOutput,
        tmpDirectory,
        executionContext.isCodeCoverageEnabled,
        executionContext.isDebugEnabled());
    steps.add(junit);

    return steps.build();
  }

  @Override
  public boolean isTestRunRequired(BuildContext buildContext, ExecutionContext executionContext) {
    // If this rule was cached, then no commands are necessary to run the tests. The results will be
    // read from the XML files in interpretTestResults(); If debug is enabled we should run the
    // tests as the user is expecting to hook up a debugger.
    if (executionContext.isDebugEnabled() || !isRuleBuiltFromCache()) {
      return true;
    }

    // The rule has been built from the cache. However, it's possible for the results file not to
    // have been written (eg. if a user runs with the --debug flag and then aborts the build) To
    // prevent a FileNotFoundException later on, check that the output files are present.

    // It is possible that this rule was not responsible for running any tests because all tests
    // were run by its deps. In this case, return an empty TestResults.
    Set<String> testClassNames = getClassNamesForSources();
    if (testClassNames.isEmpty()) {
      return false;
    }

    File outputDirectory = new File(getPathToTestOutput());
    for (String testClass : testClassNames) {
      File testResultFile = new File(outputDirectory, testClass + ".xml");
      if (!testResultFile.exists()) {
        return true;
      }
    }

    return false;
  }

  private String getPathToTestOutput() {
    return String.format("%s/%s/__java_test_%s_output__",
        BuckConstant.GEN_DIR,
        getBuildTarget().getBasePath(),
        getBuildTarget().getShortName());
  }

  @Override
  public Callable<TestResults> interpretTestResults() {
    return new Callable<TestResults>() {

      @Override
      public TestResults call() throws Exception {
        // It is possible that this rule was not responsible for running any tests because all tests
        // were run by its deps. In this case, return an empty TestResults.
        Set<String> testClassNames = getClassNamesForSources();
        if (testClassNames.isEmpty()) {
          return TestResults.getEmptyTestResults();
        }

        File outputDirectory = new File(getPathToTestOutput());
        List<TestCaseSummary> summaries = Lists.newArrayListWithCapacity(testClassNames.size());
        for (String testClass : testClassNames) {
          File testResultFile = new File(outputDirectory, testClass + ".xml");
          TestCaseSummary summary = XmlTestResultParser.parse(testResultFile);
          summaries.add(summary);
        }

        return new TestResults(summaries);
      }

    };
  }

  private Set<String> getClassNamesForSources() {
    if (compiledClassFileFinder == null) {
      compiledClassFileFinder = new CompiledClassFileFinder(this);
    }
    return compiledClassFileFinder.getClassNamesForSources();
  }

  @VisibleForTesting
  static class CompiledClassFileFinder {

    private final Set<String> classNamesForSources;

    CompiledClassFileFinder(JavaTestRule rule) {
      Preconditions.checkState(rule.isRuleBuilt(),
          "Rule must be built so that the classes folder is available");
      classNamesForSources = getClassNamesForSources(rule.getJavaSrcs(), rule.getOutput());
    }

    public Set<String> getClassNamesForSources() {
      return classNamesForSources;
    }

    /**
     * When a collection of .java files is compiled into a directory, that directory will have a
     * subfolder structure that matches the package structure of the input .java files. In general,
     * the .java files will be 1:1 with the .class files with two notable exceptions:
     * (1) There will be an additional .class file for each inner/anonymous class generated. These
     *     types of classes are easy to identify because they will contain a '$' in the name.
     * (2) A .java file that defines multiple top-level classes (yes, this can exist:
     *     http://stackoverflow.com/questions/2336692/java-multiple-class-declarations-in-one-file)
     *     will generate multiple .class files that do not have '$' in the name.
     * In this method, we perform a strict check for (1) and use a heuristic for (2). It is possible
     * to filter out the type (2) situation with a stricter check that aligns the package directories
     * of the .java files and the .class files, but it is a pain to implement. If this heuristic turns
     * out to be insufficient in practice, then we can fix it.
     *
     * @param sources paths to .java source files that were passed to javac
     * @param jarFile jar where the generated .class files were written
     */
    @VisibleForTesting
    static Set<String> getClassNamesForSources(Set<String> sources, @Nullable File jarFile) {
      if (jarFile == null) {
        return ImmutableSet.of();
      }

      final Set<String> sourceClassNames = Sets.newHashSetWithExpectedSize(sources.size());
      for (String source : sources) {
        int lastSlashIndex = source.lastIndexOf('/');
        if (lastSlashIndex >= 0) {
          source = source.substring(lastSlashIndex + 1);
        }
        source = source.substring(0, source.length() - ".java".length());
        sourceClassNames.add(source);
      }

      final ImmutableSet.Builder<String> testClassNames = ImmutableSet.builder();
      ZipFileTraversal traversal = new ZipFileTraversal(jarFile) {

        @Override
        public void visit(ZipFile zipFile, ZipEntry zipEntry) {
          final String name = new File(zipEntry.getName()).getName();

          // Ignore non-.class files.
          if (!name.endsWith(".class")) {
            return;
          }

          // As a heuristic for case (2) as described in the Javadoc, make sure the name of the .class
          // file matches the name of a .java file.
          String nameWithoutDotClass = name.substring(0, name.length() - ".class".length());
          if (!sourceClassNames.contains(nameWithoutDotClass)) {
            return;
          }

          // Make sure it is a .class file that corresponds to a top-level .class file and not an
          // inner class.
          if (!name.contains("$")) {
            String fullyQualifiedNameWithDotClassSuffix = zipEntry.getName().replace('/', '.');
            String className = fullyQualifiedNameWithDotClassSuffix
                .substring(0, fullyQualifiedNameWithDotClassSuffix.length() - ".class".length());
            testClassNames.add(className);
          }
        }
      };
      try {
        traversal.traverse();
      } catch (IOException e) {
        // There's nothing sane to do here. The jar file really should exist.
        throw Throwables.propagate(e);
      }

      return testClassNames.build();
    }
  }

  public static Builder newJavaTestRuleBuilder() {
    return new Builder();
  }

  public static class Builder extends DefaultJavaLibraryRule.Builder
      implements LabelsAttributeBuilder {

    @Nullable protected List<String> vmArgs = ImmutableList.of();
    protected ImmutableSet<String> sourceUnderTestNames = ImmutableSet.of();
    protected ImmutableSet<String> labels = ImmutableSet.of();
    protected Function<String, String> relativeToAbsolutePathFunction =
        Functions.RELATIVE_TO_ABSOLUTE_PATH;

    protected Builder() {}

    @Override
    public JavaTestRule build(Map<String, BuildRule> buildRuleIndex) {
      ImmutableSet<JavaLibraryRule> sourceUnderTest = generateSourceUnderTest(sourceUnderTestNames,
          buildRuleIndex);
      return new JavaTestRule(createCachingBuildRuleParams(buildRuleIndex),
          srcs,
          resources,
          labels,
          proguardConfig,
          getAnnotationProcessingBuilder().build(buildRuleIndex),
          vmArgs,
          sourceUnderTest,
          sourceLevel,
          targetLevel,
          relativeToAbsolutePathFunction);
    }

    @Override
    public Builder setBuildTarget(BuildTarget buildTarget) {
      super.setBuildTarget(buildTarget);
      return this;
    }

    @Override
    public Builder addDep(String dep) {
      super.addDep(dep);
      return this;
    }

    @Override
    public Builder addSrc(String src) {
      super.addSrc(src);
      return this;
    }

    @Override
    public Builder setArtifactCache(ArtifactCache artifactCache) {
      super.setArtifactCache(artifactCache);
      return this;
    }

    public Builder setVmArgs(List<String> vmArgs) {
      this.vmArgs = ImmutableList.copyOf(vmArgs);
      return this;
    }

    public Builder setSourceUnderTest(ImmutableSet<String> sourceUnderTestNames) {
      this.sourceUnderTestNames = sourceUnderTestNames;
      return this;
    }

    @Override
    public Builder setLabels(ImmutableSet<String> labels) {
      this.labels = labels;
      return this;
    }

    @VisibleForTesting
    Builder setRelativeToAbsolutePathFunction(
        Function<String, String> relativeToAbsolutePathFunction) {
      this.relativeToAbsolutePathFunction = relativeToAbsolutePathFunction;
      return this;
    }

    /**
     * Generates the set of build rules that contain the source that will be under test.
     */
    protected ImmutableSet<JavaLibraryRule> generateSourceUnderTest(
        ImmutableSet<String> sourceUnderTestNames, Map<String, BuildRule> buildRuleIndex) {
      ImmutableSet.Builder<JavaLibraryRule> sourceUnderTest = ImmutableSet.builder();
      for (String sourceUnderTestName : sourceUnderTestNames) {
        // Generates the set by matching its path with the full path names that are passed in.
        BuildRule rule = buildRuleIndex.get(sourceUnderTestName);
        if (rule instanceof JavaLibraryRule) {
          sourceUnderTest.add((JavaLibraryRule) rule);
        } else {
          // In this case, the source under test specified in the build file was not a Java library
          // rule. Since EMMA requires the sources to be in Java, we will throw this exception and
          // not continue with the tests.
          throw new HumanReadableException(
              "Specified source under test for %s is not a Java library: %s.",
              getBuildTarget().getFullyQualifiedName(), sourceUnderTestName);
        }
      }

      return sourceUnderTest.build();
    }
  }
}
