// 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.rules.objc;

import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.PrerequisiteArtifacts;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.Runfiles.Builder;
import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction;
import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Substitution;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.test.InstrumentedFilesProvider;
import com.google.devtools.build.lib.analysis.test.TestEnvironmentInfo;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.Info;
import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
import com.google.devtools.build.lib.rules.apple.DottedVersion;
import com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.SimulatorRule;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.util.FileType;
import java.util.List;
import javax.annotation.Nullable;

/**
 * Support for running XcTests.
 */
public class TestSupport {
  private final RuleContext ruleContext;

  public TestSupport(RuleContext ruleContext) {
    this.ruleContext = ruleContext;
  }

  /**
   * Registers actions to create all files needed in order to actually run the test.
   *
   * @throws InterruptedException
   */
  public TestSupport registerTestRunnerActions() throws InterruptedException {
    registerTestScriptSubstitutionAction();
    return this;
  }

  /**
   * Returns the script which should be run in order to actually run the tests.
   */
  public Artifact generatedTestScript() {
    return ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, "_test_script");
  }

  private void registerTestScriptSubstitutionAction() throws InterruptedException {
    // testBundleIpa is the bundle actually containing the tests.
    Artifact testBundleIpa = testBundleIpa();

    String runMemleaks =
        ruleContext.getFragment(ObjcConfiguration.class).runMemleaks() ? "true" : "false";

    // TODO(ulfjack): This is missing the action environment, and the inherited parts from both. Is
    // that intentional? We should either fix it, or clearly document why we're doing that.
    ImmutableMap<String, String> testEnv =
        ruleContext.getConfiguration().getTestActionEnvironment().getFixedEnv();

    // The substitutions below are common for simulator and lab device.
    ImmutableList.Builder<Substitution> substitutions =
        new ImmutableList.Builder<Substitution>()
            .add(Substitution.of("%(memleaks)s", runMemleaks))
            .add(Substitution.of("%(test_app_ipa)s", testBundleIpa.getRootRelativePathString()))
            .add(Substitution.of("%(test_app_name)s", baseNameWithoutIpa(testBundleIpa)))
            .add(Substitution.of("%(test_bundle_path)s", testBundleIpa.getRootRelativePathString()))
            .add(
                Substitution.of("%(plugin_jars)s", Artifact.joinRootRelativePaths(":", plugins())));

    substitutions.add(Substitution.ofSpaceSeparatedMap("%(test_env)s", testEnv));

    // testHarnessIpa is the app being tested in the case where testBundleIpa is a .xctest bundle.
    Optional<Artifact> testHarnessIpa = testHarnessIpa();
    if (testHarnessIpa.isPresent()) {
      substitutions
          .add(Substitution.of("%(xctest_app_ipa)s",
              testHarnessIpa.get().getRootRelativePathString()))
          .add(Substitution.of("%(xctest_app_name)s", baseNameWithoutIpa(testHarnessIpa.get())))
          .add(Substitution.of("%(test_host_path)s",
              testHarnessIpa.get().getRootRelativePathString()));
    } else {
      substitutions
          .add(Substitution.of("%(xctest_app_ipa)s", ""))
          .add(Substitution.of("%(xctest_app_name)s", ""))
          .add(Substitution.of("%(test_host_path)s", ""));
    }

    if (ruleContext.attributes().get(IosTest.IS_XCTEST_ATTR, Type.BOOLEAN)) {
      substitutions.add(Substitution.of("%(test_type)s", "XCTEST"));
    } else {
      substitutions.add(Substitution.of("%(test_type)s", "KIF"));
    }

    Artifact template;
    if (!runWithLabDevice()) {
      substitutions.addAll(substitutionsForSimulator());
      template = ruleContext.getPrerequisiteArtifact(IosTest.TEST_TEMPLATE_ATTR, Mode.TARGET);
    } else {
      substitutions.addAll(substitutionsForLabDevice());
      template = testTemplateForLabDevice();
    }

    ruleContext.registerAction(
        new TemplateExpansionAction(
            ruleContext.getActionOwner(),
            template,
            generatedTestScript(),
            substitutions.build(),
            /* makeExecutable= */ true));
  }

  private boolean runWithLabDevice() {
    return iosLabDeviceSubstitutions() != null;
  }

  /**
   * Gets the substitutions for simulator.
   */
  private ImmutableList<Substitution> substitutionsForSimulator() {
    ImmutableList.Builder<Substitution> substitutions = new ImmutableList.Builder<Substitution>()
        .add(Substitution.of("%(std_redirect_dylib_path)s",
            stdRedirectDylib().getRunfilesPathString()))
        .addAll(deviceSubstitutions().getSubstitutionsForTestRunnerScript());

    Optional<Artifact> testRunner = testRunner();
    if (testRunner.isPresent()) {
      substitutions.add(
          Substitution.of("%(testrunner_binary)s", testRunner.get().getRunfilesPathString()));
    }
    return substitutions.build();
  }

  private IosTestSubstitutionProvider deviceSubstitutions() {
    return ruleContext.getPrerequisite(
        IosTest.TARGET_DEVICE, Mode.TARGET, IosTestSubstitutionProvider.class);
  }

  /*
   * The IPA of the bundle that contains the tests. Typically will be a .xctest bundle, but in the
   * case where the xctest attribute is false, it will be a .app bundle.
   */
  private Artifact testBundleIpa() throws InterruptedException {
    return ruleContext.getImplicitOutputArtifact(ReleaseBundlingSupport.IPA);
  }

  /*
   * The IPA of the testHarness in the case where the testBundleIpa is an .xctest bundle.
   */
  private Optional<Artifact> testHarnessIpa() {
    FileProvider fileProvider =
        ruleContext.getPrerequisite(IosTest.XCTEST_APP_ATTR, Mode.TARGET, FileProvider.class);
    if (fileProvider == null) {
      return Optional.absent();
    }
    List<Artifact> files =
        Artifact.filterFiles(fileProvider.getFilesToBuild(), FileType.of(".ipa"));
    if (files.size() == 0) {
      return Optional.absent();
    } else if (files.size() == 1) {
      return Optional.of(Iterables.getOnlyElement(files));
    } else {
      throw new IllegalStateException("Expected 0 or 1 files in xctest_app, got: " + files);
    }
  }

  private Artifact stdRedirectDylib() {
    return ruleContext.getPrerequisiteArtifact(SimulatorRule.STD_REDIRECT_DYLIB_ATTR, Mode.HOST);
  }

  /**
   * Gets the binary of the testrunner attribute, if there is one.
   */
  private Optional<Artifact> testRunner() {
    return Optional.fromNullable(
        ruleContext.getPrerequisiteArtifact(IosTest.TEST_RUNNER_ATTR, Mode.TARGET));
  }

  /**
   * Gets the substitutions for lab device.
   */
  private ImmutableList<Substitution> substitutionsForLabDevice() {
    return new ImmutableList.Builder<Substitution>()
        .addAll(iosLabDeviceSubstitutions().getSubstitutionsForTestRunnerScript())
        .add(Substitution.of("%(ios_device_arg)s", Joiner.on(" ").join(iosDeviceArgs()))).build();
  }

  /**
   * Gets the test template for lab devices.
   */
  private Artifact testTemplateForLabDevice() {
    return ruleContext
        .getPrerequisite(
            IosTest.TEST_TARGET_DEVICE_ATTR, Mode.TARGET, LabDeviceTemplateProvider.class)
        .getLabDeviceTemplate();
  }

  @Nullable
  private IosTestSubstitutionProvider iosLabDeviceSubstitutions() {
    return ruleContext.getPrerequisite(
        IosTest.TEST_TARGET_DEVICE_ATTR, Mode.TARGET, IosTestSubstitutionProvider.class);
  }

  private List<String> iosDeviceArgs() {
    return ruleContext.attributes().get(IosTest.DEVICE_ARG_ATTR, Type.STRING_LIST);
  }

  /**
   * Adds all files needed to run this test to the passed Runfiles builder.
   */
  public TestSupport addRunfiles(
      Builder runfilesBuilder, InstrumentedFilesProvider instrumentedFilesProvider)
      throws InterruptedException {
    runfilesBuilder
        .addArtifact(testBundleIpa())
        .addArtifacts(testHarnessIpa().asSet())
        .addArtifact(generatedTestScript())
        .addTransitiveArtifacts(plugins());
    if (!runWithLabDevice()) {
      runfilesBuilder
          .addArtifact(stdRedirectDylib())
          .addTransitiveArtifacts(deviceRunfiles())
          .addArtifacts(testRunner().asSet());
    } else {
      runfilesBuilder.addTransitiveArtifacts(labDeviceRunfiles());
    }

    if (ruleContext.getConfiguration().isCodeCoverageEnabled()) {
      runfilesBuilder.addArtifact(ruleContext.getHostPrerequisiteArtifact(IosTest.MCOV_TOOL_ATTR));
      runfilesBuilder.addTransitiveArtifacts(instrumentedFilesProvider.getInstrumentedFiles());
    }

    return this;
  }

  /**
   * Returns any additional providers that need to be exported to the rule context to the passed
   * builder.
   */
  public Iterable<Info> getExtraProviders() {
    IosDeviceProvider deviceProvider =
        ruleContext.getPrerequisite(
            IosTest.TARGET_DEVICE, Mode.TARGET, IosDeviceProvider.SKYLARK_CONSTRUCTOR);
    DottedVersion xcodeVersion = deviceProvider.getXcodeVersion();

    ImmutableMap.Builder<String, String> envBuilder = ImmutableMap.builder();

    if (xcodeVersion != null) {
      envBuilder.putAll(AppleConfiguration.getXcodeVersionEnv(xcodeVersion));
    }

    if (ruleContext.getConfiguration().isCodeCoverageEnabled()) {
      envBuilder.put("COVERAGE_GCOV_PATH",
          ruleContext.getHostPrerequisiteArtifact(IosTest.OBJC_GCOV_ATTR).getExecPathString());
      envBuilder.put("APPLE_COVERAGE", "1");
    }

    return ImmutableList.<Info>of(new TestEnvironmentInfo(envBuilder.build()));
  }

  /**
   * Jar files for plugins to the test runner. May be empty.
   */
  private NestedSet<Artifact> plugins() {
    NestedSetBuilder<Artifact> pluginArtifacts = NestedSetBuilder.stableOrder();
    pluginArtifacts.addTransitive(
        PrerequisiteArtifacts.nestedSet(ruleContext, IosTest.PLUGINS_ATTR, Mode.TARGET));
    if (ruleContext.getFragment(ObjcConfiguration.class).runMemleaks()) {
      pluginArtifacts.addTransitive(
          PrerequisiteArtifacts.nestedSet(ruleContext, IosTest.MEMLEAKS_PLUGIN_ATTR, Mode.TARGET));
    }
    return pluginArtifacts.build();
  }

  /**
   * Runfiles required in order to use the specified target device.
   */
  private NestedSet<Artifact> deviceRunfiles() {
    return ruleContext.getPrerequisite(IosTest.TARGET_DEVICE, Mode.TARGET, RunfilesProvider.class)
        .getDefaultRunfiles().getAllArtifacts();
  }

  /**
   * Runfiles required in order to use the specified target device.
   */
  private NestedSet<Artifact> labDeviceRunfiles() {
    return ruleContext
        .getPrerequisite(IosTest.TEST_TARGET_DEVICE_ATTR, Mode.TARGET, RunfilesProvider.class)
        .getDefaultRunfiles().getAllArtifacts();
  }

  /**
   * Adds files which must be built in order to run this test to builder.
   */
  public TestSupport addFilesToBuild(NestedSetBuilder<Artifact> builder)
      throws InterruptedException {
    builder.add(testBundleIpa()).addAll(testHarnessIpa().asSet());
    return this;
  }

  /**
   * Returns the base name of the artifact, with the .ipa stuffix stripped.
   */
  private static String baseNameWithoutIpa(Artifact artifact) {
    String baseName = artifact.getExecPath().getBaseName();
    Preconditions.checkState(baseName.endsWith(".ipa"),
        "%s should end in .ipa but doesn't", baseName);
    return baseName.substring(0, baseName.length() - 4);
  }
}
