/*
 * 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.step.ExecutionContext;
import com.facebook.buck.shell.ShellStep;
import com.facebook.buck.util.AndroidPlatformTarget;
import com.facebook.buck.util.BuckConstant;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;

import java.io.File;
import java.util.List;
import java.util.Set;

public class JUnitStep extends ShellStep {

  public static final String EMMA_OUTPUT_DIR =
      String.format("%s/emma", BuckConstant.GEN_DIR);

  // Note that the default value is used when `buck test --all` is run on Buck itself.
  // TODO(mbolin): Change this so that pathToEmmaJar is injected. This is a non-trivial refactor
  // because a number of other classes currently reference this constant.
  public static final String PATH_TO_EMMA_JAR = System.getProperty("buck.path_to_emma_jar",
      "third-party/java/emma-2.0.5312/out/emma-2.0.5312.jar");

  @VisibleForTesting
  static final String JUNIT_TEST_RUNNER_CLASS_NAME =
      "com.facebook.buck.junit.JUnitRunner";

  private static final String EMMA_COVERAGE_OUT_FILE = "emma.coverage.out.file";

  private final Set<String> classpathEntries;

  private final Set<String> testClassNames;

  private final List<String> vmArgs;

  private final String directoryForTestResults;

  private final boolean isCodeCoverageEnabled;

  private final boolean isDebugEnabled;

  private final String tmpDirectory;

  private final String testRunnerClassesDirectory;

  /**
   * @param classpathEntries contains the entries that will be listed first in the classpath when
   *     running JUnit. Entries for the bootclasspath for Android will be appended to this list, as
   *     well as an entry for the test runner. classpathEntries must include entries for the tests
   *     that will be run, as well as an entry for JUnit.
   * @param testClassNames the fully qualified names of the Java tests to run
   * @param directoryForTestResults directory where test results should be written
   * @param tmpDirectory directory tests can use for local file scratch space.
   */
  public JUnitStep(
      Set<String> classpathEntries,
      Set<String> testClassNames,
      List<String> vmArgs,
      String directoryForTestResults,
      String tmpDirectory,
      boolean isCodeCoverageEnabled,
      boolean isDebugEnabled) {
    this(classpathEntries,
        testClassNames,
        vmArgs,
        directoryForTestResults,
        isCodeCoverageEnabled,
        isDebugEnabled,
        tmpDirectory,
        System.getProperty("buck.testrunner_classes"));
  }

  @VisibleForTesting
  JUnitStep(
      Set<String> classpathEntries,
      Set<String> testClassNames,
      List<String> vmArgs,
      String directoryForTestResults,
      boolean isCodeCoverageEnabled,
      boolean isDebugEnabled,
      String tmpDirectory,
      String testRunnerClassesDirectory) {
    this.classpathEntries = ImmutableSet.copyOf(classpathEntries);
    this.testClassNames = ImmutableSet.copyOf(testClassNames);
    this.vmArgs = ImmutableList.copyOf(vmArgs);
    this.directoryForTestResults = Preconditions.checkNotNull(directoryForTestResults);
    this.isCodeCoverageEnabled = isCodeCoverageEnabled;
    this.isDebugEnabled = isDebugEnabled;
    this.tmpDirectory = tmpDirectory;
    this.testRunnerClassesDirectory = Preconditions.checkNotNull(testRunnerClassesDirectory);
  }

  @Override
  public String getShortName(ExecutionContext context) {
    return "junit";
  }

  @Override
  protected ImmutableList<String> getShellCommandInternal(ExecutionContext context) {
    ImmutableList.Builder<String> args = ImmutableList.builder();
    args.add("java");
    args.add(String.format("-Djava.io.tmpdir=%s", tmpDirectory));

    // Add the output property for EMMA so if the classes are instrumented, coverage.ec will be
    // placed in the EMMA output folder.
    if (isCodeCoverageEnabled) {
      args.add(String.format("-D%s=%s/coverage.ec", EMMA_COVERAGE_OUT_FILE, EMMA_OUTPUT_DIR));
    }

    if (isDebugEnabled) {
      // This is the default config used by IntelliJ. By doing this, all a user
      // needs to do is create a new "Remote" debug config. Note that we start
      // suspended, so tests will not run until the user connects.
      args.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005");
      warnUser(context,
          "Debugging. Suspending JVM. Connect a JDWP debugger to port 5005 to proceed.");
    }

    // User-defined VM arguments, such as -D or -X.
    args.addAll(vmArgs);

    // verbose flag, if appropriate.
    if (context.getVerbosity().shouldUseVerbosityFlagIfAvailable()) {
      args.add("-verbose");
    }

    // Build up the -classpath argument, starting with the classpath entries the client specified.
    List<String> classpath = Lists.newArrayList(classpathEntries);

    // Add EMMA to the classpath.
    if (isCodeCoverageEnabled) {
      classpath.add(PATH_TO_EMMA_JAR);
    }

    // Next, add the bootclasspath entries specific to the Android platform being targeted.
    if (context.getAndroidPlatformTargetOptional().isPresent()) {
      AndroidPlatformTarget androidPlatformTarget = context.getAndroidPlatformTarget();
      for (File bootclasspathEntry : androidPlatformTarget.getBootclasspathEntries()) {
        classpath.add(bootclasspathEntry.getAbsolutePath());
      }
    }

    // Finally, include an entry for the test runner.
    classpath.add(testRunnerClassesDirectory);

    // Add the -classpath argument.
    args.add("-classpath").add(Joiner.on(':').join(classpath));

    // Specify the Java class whose main() method should be run. This is the class that is
    // responsible for running the tests.
    args.add(JUNIT_TEST_RUNNER_CLASS_NAME);

    // The first argument to the test runner is where the test results should be written. It is not
    // reliable to write test results to stdout or stderr because there may be output from the unit
    // tests written to those file descriptors, as well.
    args.add(directoryForTestResults);

    // List all of the tests to be run.
    for (String testClassName : testClassNames) {
      args.add(testClassName);
    }

    return args.build();
  }

  @Override
  public ImmutableMap<String, String> getEnvironmentVariables() {
	ImmutableMap.Builder<String, String> env = ImmutableMap.builder();
	env.put("TMP", tmpDirectory);
	return env.build();
  }

  private void warnUser(ExecutionContext context, String message) {
    context.getStdErr().println(context.getAnsi().asWarningText(message));
  }

}
