// 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.packages;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.fail;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.eventbus.EventBus;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelConstants;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.packages.RuleFactory.BuildLangTypedAttributeValuesMap;
import com.google.devtools.build.lib.packages.util.PackageLoadingTestCase;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.RootedPath;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class RuleFactoryTest extends PackageLoadingTestCase {

  private ConfiguredRuleClassProvider provider = TestRuleClassProvider.getRuleClassProvider();
  private RuleFactory ruleFactory = new RuleFactory(provider, AttributeContainer::new);

  public static final Location LOCATION_42 = Location.fromFileAndOffsets(null, 42, 42);

  @Test
  public void testCreateRule() throws Exception {
    Path myPkgPath = scratch.resolve("/workspace/mypkg/BUILD");
    Package.Builder pkgBuilder =
        packageFactory
            .newPackageBuilder(PackageIdentifier.createInMainRepo("mypkg"), "TESTING")
            .setFilename(RootedPath.toRootedPath(root, myPkgPath));

    Map<String, Object> attributeValues = new HashMap<>();
    attributeValues.put("name", "foo");
    attributeValues.put("alwayslink", true);

    RuleClass ruleClass = provider.getRuleClassMap().get("cc_library");
    Rule rule =
        RuleFactory.createAndAddRule(
            pkgBuilder,
            ruleClass,
            new BuildLangTypedAttributeValuesMap(attributeValues),
            new Reporter(new EventBus()),
            /*ast=*/ null,
            LOCATION_42,
            /*env=*/ null,
            new AttributeContainer(ruleClass));

    assertThat(rule.getAssociatedRule()).isSameAs(rule);

    // pkg.getRules() = [rule]
    Package pkg = pkgBuilder.build();
    assertThat(Sets.newHashSet(pkg.getTargets(Rule.class))).hasSize(1);
    assertThat(pkg.getTargets(Rule.class).iterator().next()).isEqualTo(rule);

    assertThat(pkg.getTarget("foo")).isSameAs(rule);

    assertThat(rule.getLabel()).isEqualTo(Label.parseAbsolute("//mypkg:foo", ImmutableMap.of()));
    assertThat(rule.getName()).isEqualTo("foo");

    assertThat(rule.getRuleClass()).isEqualTo("cc_library");
    assertThat(rule.getTargetKind()).isEqualTo("cc_library rule");
    assertThat(rule.getLocation().getStartOffset()).isEqualTo(42);
    assertThat(rule.containsErrors()).isFalse();

    // Attr with explicitly-supplied value:
    AttributeMap attributes = RawAttributeMapper.of(rule);
    assertThat(attributes.get("alwayslink", Type.BOOLEAN)).isTrue();
    try {
      attributes.get("alwayslink", Type.STRING); // type error: boolean, not string!
      fail();
    } catch (Exception e) {
      /* Class of exception and error message are not specified by API. */
    }
    try {
      attributes.get("nosuchattr", Type.STRING); // no such attribute
      fail();
    } catch (Exception e) {
      /* Class of exception and error message are not specified by API. */
    }

    // Attrs with default values:
    // cc_library linkstatic default=0 according to build encyc.
    assertThat(attributes.get("linkstatic", Type.BOOLEAN)).isFalse();
    assertThat(attributes.get("testonly", Type.BOOLEAN)).isFalse();
    assertThat(attributes.get("srcs", BuildType.LABEL_LIST)).isEmpty();
  }

  @Test
  public void testCreateWorkspaceRule() throws Exception {
    Path myPkgPath = scratch.resolve("/workspace/WORKSPACE");
    Package.Builder pkgBuilder =
        packageFactory.newExternalPackageBuilder(
            RootedPath.toRootedPath(root, myPkgPath), "TESTING");

    Map<String, Object> attributeValues = new HashMap<>();
    attributeValues.put("name", "foo");
    attributeValues.put("actual", "//foo:bar");

    RuleClass ruleClass = provider.getRuleClassMap().get("bind");
    Rule rule =
        RuleFactory.createAndAddRule(
            pkgBuilder,
            ruleClass,
            new BuildLangTypedAttributeValuesMap(attributeValues),
            new Reporter(new EventBus()),
            /*ast=*/ null,
            Location.fromFileAndOffsets(myPkgPath.asFragment(), 42, 42),
            /*env=*/ null,
            new AttributeContainer(ruleClass));
    assertThat(rule.containsErrors()).isFalse();
  }

  @Test
  public void testWorkspaceRuleFailsInBuildFile() throws Exception {
    Path myPkgPath = scratch.resolve("/workspace/mypkg/BUILD");
    Package.Builder pkgBuilder =
        packageFactory
            .newPackageBuilder(PackageIdentifier.createInMainRepo("mypkg"), "TESTING")
            .setFilename(RootedPath.toRootedPath(root, myPkgPath));

    Map<String, Object> attributeValues = new HashMap<>();
    attributeValues.put("name", "foo");
    attributeValues.put("actual", "//bar:baz");

    RuleClass ruleClass = provider.getRuleClassMap().get("bind");
    try {
      RuleFactory.createAndAddRule(
          pkgBuilder,
          ruleClass,
          new BuildLangTypedAttributeValuesMap(attributeValues),
          new Reporter(new EventBus()),
          /*ast=*/ null,
          LOCATION_42,
          /*env=*/ null,
          new AttributeContainer(ruleClass));
      fail();
    } catch (RuleFactory.InvalidRuleException e) {
      assertThat(e).hasMessageThat().contains("must be in the WORKSPACE file");
    }
  }

  @Test
  public void testBuildRuleFailsInWorkspaceFile() throws Exception {
    Path myPkgPath = scratch.resolve("/workspace/WORKSPACE");
    Package.Builder pkgBuilder =
        packageFactory
            .newPackageBuilder(LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER, "TESTING")
            .setFilename(RootedPath.toRootedPath(root, myPkgPath));

    Map<String, Object> attributeValues = new HashMap<>();
    attributeValues.put("name", "foo");
    attributeValues.put("alwayslink", true);

    RuleClass ruleClass = provider.getRuleClassMap().get("cc_library");
    try {
      RuleFactory.createAndAddRule(
          pkgBuilder,
          ruleClass,
          new BuildLangTypedAttributeValuesMap(attributeValues),
          new Reporter(new EventBus()),
          /*ast=*/ null,
          Location.fromFileAndOffsets(myPkgPath.asFragment(), 42, 42),
          /*env=*/ null,
          new AttributeContainer(ruleClass));
      fail();
    } catch (RuleFactory.InvalidRuleException e) {
      assertThat(e).hasMessageThat().contains("cannot be in the WORKSPACE file");
    }
  }

  private void assertAttr(RuleClass ruleClass, String attrName, Type<?> type) throws Exception {
    assertWithMessage(
            "Rule class '"
                + ruleClass.getName()
                + "' should have attribute '"
                + attrName
                + "' of type '"
                + type
                + "'")
        .that(ruleClass.hasAttr(attrName, type))
        .isTrue();
  }

  @Test
  public void testOutputFileNotEqualDot() throws Exception {
    Path myPkgPath = scratch.resolve("/workspace/mypkg");
    Package.Builder pkgBuilder =
        packageFactory
            .newPackageBuilder(PackageIdentifier.createInMainRepo("mypkg"), "TESTING")
            .setFilename(RootedPath.toRootedPath(root, myPkgPath));

    Map<String, Object> attributeValues = new HashMap<>();
    attributeValues.put("outs", Lists.newArrayList("."));
    attributeValues.put("name", "some");
    RuleClass ruleClass = provider.getRuleClassMap().get("genrule");
    try {
      RuleFactory.createAndAddRule(
          pkgBuilder,
          ruleClass,
          new BuildLangTypedAttributeValuesMap(attributeValues),
          new Reporter(new EventBus()),
          /*ast=*/ null,
          Location.fromFileAndOffsets(myPkgPath.asFragment(), 42, 42),
          /*env=*/ null,
          new AttributeContainer(ruleClass));
      fail();
    } catch (RuleFactory.InvalidRuleException e) {
      assertWithMessage(e.getMessage())
          .that(e.getMessage().contains("output file name can't be equal '.'"))
          .isTrue();
    }
  }

  /**
   * Tests mandatory attribute definitions for test rules.
   */
  // TODO(ulfjack): Remove this check when we switch over to the builder
  // pattern, which will always guarantee that these attributes are present.
  @Test
  public void testTestRules() throws Exception {
    Path myPkgPath = scratch.resolve("/workspace/mypkg/BUILD");
    Package pkg =
        packageFactory
            .newPackageBuilder(PackageIdentifier.createInMainRepo("mypkg"), "TESTING")
            .setFilename(RootedPath.toRootedPath(root, myPkgPath))
            .build();

    for (String name : ruleFactory.getRuleClassNames()) {
      // Create rule instance directly so we'll avoid mandatory attribute check yet will be able
      // to use TargetUtils.isTestRule() method to identify test rules.
      RuleClass ruleClass = ruleFactory.getRuleClass(name);
      Rule rule =
          new Rule(
              pkg,
              Label.create(pkg.getPackageIdentifier(), "myrule"),
              ruleClass,
              Location.fromFile(myPkgPath),
              new AttributeContainer(ruleClass));
      if (TargetUtils.isTestRule(rule)) {
        assertAttr(ruleClass, "tags", Type.STRING_LIST);
        assertAttr(ruleClass, "size", Type.STRING);
        assertAttr(ruleClass, "flaky", Type.BOOLEAN);
        assertAttr(ruleClass, "shard_count", Type.INTEGER);
        assertAttr(ruleClass, "local", Type.BOOLEAN);
      }
    }
  }
}
