// 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.analysis.select;

import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.Type.STRING;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.AggregatingAttributeMapper;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
import com.google.devtools.build.lib.testutil.UnknownRuleConfiguredTarget;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Unit tests for {@link AggregatingAttributeMapper}.
 */
@RunWith(JUnit4.class)
public class AggregatingAttributeMapperTest extends AbstractAttributeMapperTest {

  @Before
  public final void createMapper() throws Exception {
    // Run AbstractAttributeMapper tests through an AggregatingAttributeMapper.
    mapper = AggregatingAttributeMapper.of(rule);
  }

  @Override
  protected ConfiguredRuleClassProvider createRuleClassProvider() {
    ConfiguredRuleClassProvider.Builder builder =
        new ConfiguredRuleClassProvider.Builder()
            .addRuleDefinition(new RuleWithDefaults())
            .addRuleDefinition(new RuleWithComputedDefaults());
    TestRuleClassProvider.addStandardRules(builder);
    return builder.build();
  }

  /**
   * Tests that {@link AggregatingAttributeMapper#visitAttribute} returns an
   * attribute's sole value when declared directly (i.e. not as a configurable dict).
   */
  @Test
  public void testGetPossibleValuesDirectAttribute() throws Exception {
    Rule rule = scratchRule("a", "myrule",
        "sh_binary(name = 'myrule',",
        "          srcs = ['a.sh'])");
    assertThat(AggregatingAttributeMapper.of(rule).visitAttribute("srcs", BuildType.LABEL_LIST))
        .containsExactly(ImmutableList.of(label("//a:a.sh")));
  }

  /**
   * Tests that {@link AggregatingAttributeMapper#visitAttribute} returns
   * every possible value that a configurable attribute can resolve to.
   */
  @Test
  public void testGetPossibleValuesConfigurableAttribute() throws Exception {
    Rule rule = scratchRule("a", "myrule",
        "sh_binary(name = 'myrule',",
        "          srcs = select({",
        "              '//conditions:a': ['a.sh'],",
        "              '//conditions:b': ['b.sh'],",
        "              '" + BuildType.Selector.DEFAULT_CONDITION_KEY + "': ['default.sh'],",
        "          }))");
    assertThat(AggregatingAttributeMapper.of(rule).visitAttribute("srcs", BuildType.LABEL_LIST))
        .containsExactly(
            ImmutableList.of(label("//a:a.sh")),
            ImmutableList.of(label("//a:b.sh")),
            ImmutableList.of(label("//a:default.sh")));
  }

  @Test
  public void testGetPossibleValuesWithConcatenatedSelects() throws Exception {
    Rule rule = scratchRule("a", "myrule",
        "sh_binary(name = 'myrule',",
        "          srcs = select({",
        "                  '//conditions:a1': ['a1.sh'],",
        "                  '//conditions:b1': ['b1.sh']})",
        "              + select({",
        "                  '//conditions:a2': ['a2.sh'],",
        "                  '//conditions:b2': ['b2.sh']})",
        "          )");
    assertThat(AggregatingAttributeMapper.of(rule).visitAttribute("srcs", BuildType.LABEL_LIST))
        .containsExactly(
            ImmutableList.of(label("//a:a1.sh"), label("//a:a2.sh")),
            ImmutableList.of(label("//a:a1.sh"), label("//a:b2.sh")),
            ImmutableList.of(label("//a:b1.sh"), label("//a:a2.sh")),
            ImmutableList.of(label("//a:b1.sh"), label("//a:b2.sh")));
  }

  /**
   * Given a large number of selects, we expect better than the naive
   * exponential performance from evaluating select1 x select2 x select3 x ...
   */
  @Test
  public void testGetPossibleValuesWithManySelects() throws Exception {
    String pattern = " + select({'//conditions:a1': '%c', '//conditions:a2': '%s'})";
    StringBuilder ruleDef = new StringBuilder();
    ruleDef.append("genrule(name = 'gen', srcs = [], outs = ['gen.out'], cmd = ''");
    for (char c : "abcdefghijklmnopqrstuvwxyz".toCharArray()) {
      ruleDef.append(String.format(pattern, c, Character.toUpperCase(c)));
    }
    ruleDef.append(")");
    Rule rule = scratchRule("a", "gen", ruleDef.toString());
    // Naive evaluation would visit 2^26 cases and either overflow memory or timeout the test.
    assertThat(AggregatingAttributeMapper.of(rule).visitAttribute("cmd", Type.STRING))
        .containsExactly("abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
  }

  @Test
  public void testGetPossibleValuesWithMultipleSelectsWithOverlappingConditions() throws Exception {
    Rule rule =
        scratchRule(
            "a",
            "myrule",
            "sh_binary(name = 'myrule',",
            // Even though this combination seems invalid it's allowed due to select specialization.
            "          srcs = select({'//conditions:x': ['x1.sh']})",
            "              + select({'//conditions:y': ['y1.sh']})",
            "              + select({",
            "                   '//conditions:x': ['x2.sh'],",
            "                   '//conditions:y': ['y2.sh'],",
            "                   '//conditions:z': ['z2.sh']})",
            "          )");
    assertThat(AggregatingAttributeMapper.of(rule).visitAttribute("srcs", BuildType.LABEL_LIST))
        .containsExactly(
            ImmutableList.of(label("//a:x1.sh"), label("//a:y1.sh"), label("//a:x2.sh")),
            ImmutableList.of(label("//a:x1.sh"), label("//a:y1.sh"), label("//a:y2.sh")),
            ImmutableList.of(label("//a:x1.sh"), label("//a:y1.sh"), label("//a:z2.sh")));
  }

  /**
   * Tests that, on rule visitation, {@link AggregatingAttributeMapper} visits *every* possible
   * value in a configurable attribute (including configuration key labels).
   */
  @Test
  public void testVisitationConfigurableAttribute() throws Exception {
    Rule rule = scratchRule("a", "myrule",
        "sh_binary(name = 'myrule',",
        "          srcs = select({",
        "              '//conditions:a': ['a.sh'],",
        "              '//conditions:b': ['b.sh'],",
        "              '" + BuildType.Selector.DEFAULT_CONDITION_KEY + "': ['default.sh'],",
        "          }))");

    assertThat(getLabelsForAttribute(AggregatingAttributeMapper.of(rule), "srcs"))
        .containsExactlyElementsIn(
            ImmutableList.of(
                "//a:a.sh", "//a:b.sh", "//a:default.sh", "//conditions:a", "//conditions:b"));
  }

  @Test
  public void testGetReachableLabels() throws Exception {
    Rule rule = scratchRule("x", "main",
        "cc_binary(",
        "    name = 'main',",
        "    srcs = select({",
        "        '//conditions:a': ['a.cc'],",
        "        '//conditions:b': ['b.cc']})",
        "    + ",
        "        ['always.cc']",
        "    + ",
        "         select({",
        "        '//conditions:c': ['c.cc'],",
        "        '//conditions:d': ['d.cc'],",
        "        '" + BuildType.Selector.DEFAULT_CONDITION_KEY + "': ['default.cc'],",
        "    }))");

    ImmutableList<Label> valueLabels =
        ImmutableList.of(
            label("//x:a.cc"), label("@//x:b.cc"),
            label("//x:always.cc"), label("@//x:c.cc"),
            label("//x:d.cc"), label("@//x:default.cc"));
    ImmutableList<Label> keyLabels =
        ImmutableList.of(
            label("@//conditions:a"), label("@//conditions:b"),
            label("@//conditions:c"), label("@//conditions:d"));

    AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule);
    assertThat(mapper.getReachableLabels("srcs", true))
        .containsExactlyElementsIn(Iterables.concat(valueLabels, keyLabels));
    assertThat(mapper.getReachableLabels("srcs", false)).containsExactlyElementsIn(valueLabels);
  }

  /** Custom rule to support testing over default values. */
  public static final class RuleWithDefaults
      implements RuleDefinition, RuleConfiguredTargetFactory {
    @Override
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      return builder
          .add(
              attr("attribute", BuildType.LABEL).value(label("//default:value")).allowedFileTypes())
          .build();
    }

    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("rule_with_default")
          .ancestors(BaseRuleClasses.NativeBuildRule.class)
          .factoryClass(UnknownRuleConfiguredTarget.class)
          .build();
    }

    @Override
    public ConfiguredTarget create(RuleContext ruleContext) {
      throw new UnsupportedOperationException();
    }
  }

  @Test
  public void testVisitationWithDefaultValues() throws Exception {
    Rule rule =
        scratchRule(
            "a",
            "myrule",
            "rule_with_default(name = 'myrule',",
            "    attribute = select({",
            "        '//conditions:a': None,",
            "    }))");

    assertThat(getLabelsForAttribute(AggregatingAttributeMapper.of(rule), "attribute"))
        .containsExactly("//conditions:a", "//default:value");
  }

  @Test
  public void testGetReachableLabelsWithDefaultValues() throws Exception {
    Rule rule =
        scratchRule(
            "a",
            "myrule",
            "rule_with_default(name = 'myrule',",
            "    attribute = select({",
            "        '//conditions:a': None,",
            "    }))");

    AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule);
    assertThat(mapper.getReachableLabels("attribute", true))
        .containsExactly(label("//default:value"), label("//conditions:a"));
  }

  /**
   * Custom rule to support testing over computed defaults.
   */
  public static final class RuleWithComputedDefaults
      implements RuleDefinition, RuleConfiguredTargetFactory {
    @Override
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      return builder
          .add(attr("configurable1", STRING))
          .add(attr("configurable2", STRING))
          .add(attr("nonconfigurable", STRING).nonconfigurable("that's the point"))
          .add(attr("$computed_default_with_configurable_deps", STRING).value(
              new Attribute.ComputedDefault("configurable1", "configurable2") {
                @Override
                public Object getDefault(AttributeMap rule) {
                  return Joiner.on(" ").join(
                      rule.get("configurable1", STRING),
                      rule.get("configurable2", STRING),
                      rule.get("nonconfigurable", STRING)
                  );
                }
              }))
          .add(attr("$computed_default_without_configurable_deps", STRING).value(
              new Attribute.ComputedDefault() {
                @Override
                public Object getDefault(AttributeMap rule) {
                  return rule.get("nonconfigurable", STRING);
                }
              }))
          .build();
    }

    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("rule_with_computed_defaults")
          .ancestors(BaseRuleClasses.NativeBuildRule.class)
          .factoryClass(UnknownRuleConfiguredTarget.class)
          .build();
    }

    @Override
    public ConfiguredTarget create(RuleContext ruleContext) {
      throw new UnsupportedOperationException();
    }
  }

  @Test
  public void testComputedDefaultWithConfigurableDeps() throws Exception {
    Rule rule = scratchRule("x", "bb",
        "rule_with_computed_defaults(",
        "    name = 'bb',",
        "    configurable1 = select({':a': 'of', ':b': 'from'}),",
        "    configurable2 = select({':a': 'this', ':b': 'the'}),",
        "    nonconfigurable = 'bottom')");
    assertThat(AggregatingAttributeMapper.of(rule)
        .visitAttribute("$computed_default_with_configurable_deps", STRING))
        .containsExactly("of this bottom", "from this bottom", "of the bottom", "from the bottom");
  }

  @Test
  public void testComputedDefaultWithoutConfigurableDeps() throws Exception {
    Rule rule = scratchRule("x", "bb",
        "rule_with_computed_defaults(",
        "    name = 'bb',",
        "    nonconfigurable = 'swim up')");
    assertThat(AggregatingAttributeMapper.of(rule)
        .visitAttribute("$computed_default_without_configurable_deps", STRING))
        .containsExactly("swim up");
  }

  private static Label label(String labelString) {
    return Label.parseCanonicalUnchecked(labelString);
  }
}
