// Copyright 2017 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.buildtool;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import java.util.SortedSet;

/**
 * Helper class to heuristically compute an instrumentation filter from a list of tests to run.
 */
public final class InstrumentationFilterSupport {
  public static final String INSTRUMENTATION_FILTER_FLAG = "instrumentation_filter";

  /**
   * Method implements a heuristic used to set default value of the --instrumentation_filter option.
   * The following algorithm is used:
   * 1) Identify all test targets on the command line.
   * 2) Expand all test suites into the individual test targets.
   * 3) Calculate list of package names containing all test targets above.
   * 4) Replace all "javatests" directories in packages with "java". Similarly, replace "test/java/"
   *    with "main/java". Also, strip trailing "/internal", "/public", and "/tests" from packages.
   *    (See getInstrumentedPrefix.)
   * 5) If two packages reside in the same directory, use filter based on the parent directory name
        instead. Doing so significantly simplifies instrumentation filter in majority of real-life
        scenarios (in particular when dealing with my/package/... wildcards).
   * 6) Set --instrumentation_filter default value to instrument everything in those packages.
   */
  @VisibleForTesting
  public static String computeInstrumentationFilter(
      EventHandler eventHandler, Collection<Target> testTargets) {
    SortedSet<String> packageFilters = Sets.newTreeSet();
    collectInstrumentedPackages(testTargets, packageFilters);
    optimizeFilterSet(packageFilters);

    String instrumentationFilter =
        Joiner.on("[/:],//")
            .appendTo(new StringBuilder("//"), packageFilters)
            .append("[/:]")
            .toString();
    // Fix up if one of the test targets is a top-level target. "//foo[/:]" matches everything
    // under //foo and subpackages, but "//[/:]" only matches targets directly under the top-level
    // package.
    if (instrumentationFilter.equals("//[/:]")) {
      instrumentationFilter = "//";
    }
    if (!packageFilters.isEmpty()) {
      eventHandler.handle(
          Event.info("Using default value for --instrumentation_filter: \""
              + instrumentationFilter + "\"."));
      eventHandler.handle(Event.info("Override the above default with --"
          + INSTRUMENTATION_FILTER_FLAG));
    }
    return instrumentationFilter;
  }

  private static void collectInstrumentedPackages(
      Collection<Target> targets, Set<String> packageFilters) {
    for (Target target : targets) {
      // Add package-based filters for every test target.
      packageFilters.add(getInstrumentedPrefix(target.getLabel().getPackageName()));
      if (TargetUtils.isTestSuiteRule(target)) {
        AttributeMap attributes = NonconfigurableAttributeMapper.of((Rule) target);
        // We don't need to handle $implicit_tests attribute since we already added
        // test_suite package to the set.
        for (Label label : attributes.get("tests", BuildType.LABEL_LIST)) {
          // Add package-based filters for all tests in the test suite.
          packageFilters.add(getInstrumentedPrefix(label.getPackageName()));
        }
      }
    }
  }

  /**
   * Returns prefix string that should be instrumented for a given package. Input string should
   * be formatted like the output of Label.getPackageName().
   * Generally, package name will be used as such string with two modifications.
   * - "javatests/ directories will be substituted with "java/", since we do
   * not want to instrument java test code. "java/" directories in "test/" will
   * be replaced by the same in "main/".
   * - "/internal", "/public", and "tests/" package suffix will be dropped, since usually we would
   * want to instrument code in the parent package as well
   */
  @VisibleForTesting
  public static String getInstrumentedPrefix(String packageName) {
    if (packageName.endsWith("/internal")) {
      packageName = packageName.substring(0, packageName.length() - "/internal".length());
    } else if (packageName.endsWith("/public")) {
      packageName = packageName.substring(0, packageName.length() - "/public".length());
    } else if (packageName.endsWith("/tests")) {
      packageName = packageName.substring(0, packageName.length() - "/tests".length());
    }
    return packageName
        .replaceFirst("(?<=^|/)javatests/", "java/")
        .replaceFirst("(?<=^|/)test/java/", "main/java/");
  }

  private static void optimizeFilterSet(SortedSet<String> packageFilters) {
    Iterator<String> iterator = packageFilters.iterator();
    if (iterator.hasNext()) {
      // Find common parent filters to reduce number of filter expressions. In practice this
      // still produces nicely constrained instrumentation filter while making final
      // filter value much more user-friendly - especially in case of /my/package/... wildcards.
      Set<String> parentFilters = Sets.newTreeSet();
      String filterString = iterator.next();
      PathFragment parent = PathFragment.create(filterString).getParentDirectory();
      String parentPath = (parent == null) ? "" : parent.getPathString();
      while (iterator.hasNext()) {
        String current = iterator.next();
        if (!current.startsWith(filterString) && current.startsWith(parentPath)) {
          parentFilters.add(parentPath);
        } else {
          filterString = current;
          parent = PathFragment.create(filterString).getParentDirectory();
          parentPath = (parent == null) ? "" : parent.getPathString();
        }
      }
      packageFilters.addAll(parentFilters);

      // Optimize away nested filters.
      iterator = packageFilters.iterator();
      String prev = iterator.next();
      while (iterator.hasNext()) {
        String current = iterator.next();
        if (current.startsWith(prev)) {
          iterator.remove();
        } else {
          prev = current;
        }
      }
    }
  }
}
