// Copyright 2014 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;

import com.google.devtools.build.lib.util.Pair;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Utility functions over test Targets that don't really belong in the base {@link Target}
 * interface.
 */
public final class TestTargetUtils {

  /**
   * Returns whether a test with the specified tags matches a filter (as specified by the set
   * of its positive and its negative filters).
   */
  public static boolean testMatchesFilters(
      Collection<String> testTags,
      Collection<String> requiredTags,
      Collection<String> excludedTags,
      boolean mustMatchAllPositive) {
    for (String tag : excludedTags) {
      if (testTags.contains(tag)) {
        return false;
      }
    }

    // Check required tags, if there are any.
    if (requiredTags.isEmpty()) {
      return true;
    } else if (mustMatchAllPositive) {
      // Require all tags to be present.
      for (String tag : requiredTags) {
        if (!testTags.contains(tag)) {
          return false;
        }
      }
      return true;
    } else {
      // Require at least one positive tag. If the two collections are not disjoint, then they have
      // at least one element in common.
      return !Collections.disjoint(requiredTags, testTags);
    }
  }

  /**
   * Decides whether to include a test in a test_suite or not.
   * @param testTags Collection of all tags exhibited by a given test.
   * @param requiredTags Tags declared by the suite. A Test must match ALL of these.
   * @param excludedTags Tags declared by the suite. A Test must match NONE of these.
   * @return false is the test is to be removed.
   */
  public static boolean testMatchesFilters(
      Collection<String> testTags,
      Collection<String> requiredTags,
      Collection<String> excludedTags) {
    return testMatchesFilters(
        testTags, requiredTags, excludedTags, /* mustMatchAllPositive= */ true);
  }

  /**
   * Decides whether to include a test in a test_suite or not.
   * @param testTarget A given test target.
   * @param requiredTags Tags declared by the suite. A Test must match ALL of these.
   * @param excludedTags Tags declared by the suite. A Test must match NONE of these.
   * @return false is the test is to be removed.
   */
  private static boolean testMatchesFilters(
      Rule testTarget,
      Collection<String> requiredTags,
      Collection<String> excludedTags) {
    AttributeMap nonConfigurableAttrs = NonconfigurableAttributeMapper.of(testTarget);
    Set<String> testTags = new HashSet<>(nonConfigurableAttrs.get("tags", Type.STRING_LIST));
    testTags.add(nonConfigurableAttrs.get("size", Type.STRING));
    return testMatchesFilters(testTags, requiredTags, excludedTags);
  }

  /**
   * Filters 'tests' (by mutation) according to the 'tags' attribute, specifically those that
   * match ALL of the tags in tagsAttribute.
   *
   * @precondition {@code env.getAccessor().isTestSuite(testSuite)}
   * @precondition {@code env.getAccessor().isTestRule(test)} for all test in tests
   */
  public static void filterTests(Rule testSuite, Set<Target> tests) {
    List<String> tagsAttribute =
        NonconfigurableAttributeMapper.of(testSuite).get("tags", Type.STRING_LIST);
    // Split the tags list into positive and negative tags
    Pair<Collection<String>, Collection<String>> tagLists = sortTagsBySense(tagsAttribute);
    Collection<String> positiveTags = tagLists.first;
    Collection<String> negativeTags = tagLists.second;
    tests.removeIf((Target t) -> !testMatchesFilters((Rule) t, positiveTags, negativeTags));
  }

  /**
   * Separates a list of text "tags" into a Pair of Collections, where
   * the first element are the required or positive tags and the second element
   * are the excluded or negative tags.
   * This should work on tag list provided from the command line
   * --test_tags_filters flag or on tag filters explicitly declared in the
   * suite.
   *
   * @param tagList A collection of text targets to separate.
   */
  public static Pair<Collection<String>, Collection<String>> sortTagsBySense(
      Iterable<String> tagList) {
    Collection<String> requiredTags = new HashSet<>();
    Collection<String> excludedTags = new HashSet<>();

    for (String tag : tagList) {
      if (tag.startsWith("-")) {
        excludedTags.add(tag.substring(1));
      } else if (tag.startsWith("+")) {
        requiredTags.add(tag.substring(1));
      } else if (tag.equals("manual")) {
        // Ignore manual attribute because it is an exception: it is not a filter
        // but a property of test_suite
        continue;
      } else {
        requiredTags.add(tag);
      }
    }
    return Pair.of(requiredTags, excludedTags);
  }
}
