// Copyright 2018 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.python;

import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows;

import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.packages.StructImpl;
import com.google.devtools.build.lib.packages.StructProvider;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
import com.google.devtools.build.lib.testutil.MoreAsserts.ThrowingRunnable;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link PyProvider}. */
@RunWith(JUnit4.class)
public class PyProviderTest extends BuildViewTestCase {

  /**
   * Constructs a py provider struct with the given field values and with default values for any
   * field not specified.
   *
   * <p>The struct is constructed directly, rather than using {@link PyProvider.Builder}, so that
   * the resulting instance is suitable for asserting on {@code PyProvider}'s operations over
   * structs with known contents. {@code overrides} is applied directly without validating the
   * fields' names or types.
   */
  private StructImpl makeStruct(Map<String, Object> overrides) {
    Map<String, Object> fields = new LinkedHashMap<>();
    fields.put(
        PyProvider.TRANSITIVE_SOURCES,
        SkylarkNestedSet.of(Artifact.class, NestedSetBuilder.emptySet(Order.COMPILE_ORDER)));
    fields.put(PyProvider.USES_SHARED_LIBRARIES, false);
    fields.put(
        PyProvider.IMPORTS,
        SkylarkNestedSet.of(String.class, NestedSetBuilder.emptySet(Order.COMPILE_ORDER)));
    fields.put(PyProvider.HAS_PY2_ONLY_SOURCES, false);
    fields.put(PyProvider.HAS_PY3_ONLY_SOURCES, false);
    fields.putAll(overrides);
    return StructProvider.STRUCT.create(fields, "No such attribute '%s'");
  }

  /** Defines //pytarget, a target that returns a py provider with some arbitrary field values. */
  private void definePyTarget() throws IOException {
    scratch.file("rules/BUILD");
    scratch.file(
        "rules/pyrule.bzl",
        "def _pyrule_impl(ctx):",
        "    info = struct(",
        "        transitive_sources = depset(direct=ctx.files.transitive_sources),",
        "        uses_shared_libraries = ctx.attr.uses_shared_libraries,",
        "        imports = depset(direct=ctx.attr.imports),",
        "        has_py2_only_sources = ctx.attr.has_py2_only_sources,",
        "        has_py3_only_sources = ctx.attr.has_py3_only_sources,",
        "    )",
        "    return struct(py=info)",
        "",
        "pyrule = rule(",
        "    implementation = _pyrule_impl,",
        "    attrs = {",
        "        'transitive_sources': attr.label_list(allow_files=True),",
        "        'uses_shared_libraries': attr.bool(default=False),",
        "        'imports': attr.string_list(),",
        "        'has_py2_only_sources': attr.bool(),",
        "        'has_py3_only_sources': attr.bool(),",
        "    },",
        ")");
    scratch.file(
        "pytarget/BUILD",
        "load('//rules:pyrule.bzl', 'pyrule')",
        "",
        "pyrule(",
        "    name = 'pytarget',",
        "    transitive_sources = ['a.py'],",
        "    uses_shared_libraries = True,",
        "    imports = ['b'],",
        "    has_py2_only_sources = True,",
        "    has_py3_only_sources = True,",
        ")");
    scratch.file("pytarget/a.py");
  }

  /** Defines //dummytarget, a target that returns no py provider. */
  private void defineDummyTarget() throws IOException {
    scratch.file("rules/BUILD");
    scratch.file(
        "rules/dummytarget.bzl",
        "def _dummyrule_impl(ctx):",
        "    pass",
        "",
        "dummyrule = rule(",
        "    implementation = _dummyrule_impl,",
        ")");
    scratch.file(
        "dummytarget/BUILD",
        "load('//rules:dummytarget.bzl', 'dummyrule')",
        "",
        "dummyrule(",
        "    name = 'dummytarget',",
        ")");
  }

  @Test
  public void hasProvider_True() throws Exception {
    definePyTarget();
    assertThat(PyProvider.hasProvider(getConfiguredTarget("//pytarget"))).isTrue();
  }

  @Test
  public void hasProvider_False() throws Exception {
    defineDummyTarget();
    assertThat(PyProvider.hasProvider(getConfiguredTarget("//dummytarget"))).isFalse();
  }

  @Test
  public void getProvider_Present() throws Exception {
    definePyTarget();
    StructImpl info = PyProvider.getProvider(getConfiguredTarget("//pytarget"));
    // If we got this far, it's present. getProvider() should never be null, but check just in case.
    assertThat(info).isNotNull();
  }

  @Test
  public void getProvider_Absent() throws Exception {
    defineDummyTarget();
    EvalException ex =
        assertThrows(
            EvalException.class,
            () -> PyProvider.getProvider(getConfiguredTarget("//dummytarget")));
    assertThat(ex).hasMessageThat().contains("Target does not have 'py' provider");
  }

  @Test
  public void getProvider_WrongType() throws Exception {
    // badtyperule() returns a "py" provider that has the wrong type.
    scratch.file("rules/BUILD");
    scratch.file(
        "rules/badtyperule.bzl",
        "def _badtyperule_impl(ctx):",
        "    return struct(py='abc')",
        "",
        "badtyperule = rule(",
        "    implementation = _badtyperule_impl",
        ")");
    scratch.file(
        "badtypetarget/BUILD",
        "load('//rules:badtyperule.bzl', 'badtyperule')",
        "",
        "badtyperule(",
        "    name = 'badtypetarget',",
        ")");
    EvalException ex =
        assertThrows(
            EvalException.class,
            () -> PyProvider.getProvider(getConfiguredTarget("//badtypetarget")));
    assertThat(ex).hasMessageThat().contains("'py' provider should be a struct");
  }

  private static void assertThrowsEvalExceptionContaining(
      ThrowingRunnable runnable, String message) {
    assertThat(assertThrows(EvalException.class, runnable)).hasMessageThat().contains(message);
  }

  private static void assertHasMissingFieldMessage(ThrowingRunnable access, String fieldName) {
    assertThrowsEvalExceptionContaining(
        access, String.format("\'py' provider missing '%s' field", fieldName));
  }

  private static void assertHasWrongTypeMessage(
      ThrowingRunnable access, String fieldName, String expectedType) {
    assertThrowsEvalExceptionContaining(
        access,
        String.format(
            "\'py' provider's '%s' field should be a %s (got a 'int')", fieldName, expectedType));
  }

  /** We need this because {@code NestedSet}s don't have value equality. */
  private static void assertHasOrderAndContainsExactly(
      NestedSet<?> set, Order order, Object... values) {
    assertThat(set.getOrder()).isEqualTo(order);
    assertThat(set).containsExactly(values);
  }

  @Test
  public void getTransitiveSources_Good() throws Exception {
    NestedSet<Artifact> sources =
        NestedSetBuilder.create(Order.COMPILE_ORDER, getSourceArtifact("dummy"));
    StructImpl info =
        makeStruct(
            ImmutableMap.of(
                PyProvider.TRANSITIVE_SOURCES, SkylarkNestedSet.of(Artifact.class, sources)));
    assertThat(PyProvider.getTransitiveSources(info)).isSameAs(sources);
  }

  @Test
  public void getTransitiveSources_Missing() {
    StructImpl info = StructProvider.STRUCT.createEmpty(null);
    assertHasMissingFieldMessage(() -> PyProvider.getTransitiveSources(info), "transitive_sources");
  }

  @Test
  public void getTransitiveSources_WrongType() {
    StructImpl info = makeStruct(ImmutableMap.of(PyProvider.TRANSITIVE_SOURCES, 123));
    assertHasWrongTypeMessage(
        () -> PyProvider.getTransitiveSources(info), "transitive_sources", "depset of Files");
  }

  @Test
  public void getTransitiveSources_OrderMismatch() throws Exception {
    reporter.removeHandler(failFastHandler);
    // Depset order mismatches should be caught as rule errors.
    scratch.file("rules/BUILD");
    scratch.file(
        "rules/badorderrule.bzl",
        "def _badorderrule_impl(ctx):",
        // Native rules use "compile" / "postorder", so using "preorder" here creates a conflict.
        "    info = struct(transitive_sources=depset(direct=[], order='preorder'))",
        "    return struct(py=info)",
        "",
        "badorderrule = rule(",
        "    implementation = _badorderrule_impl",
        ")");
    scratch.file(
        "badordertarget/BUILD",
        "load('//rules:badorderrule.bzl', 'badorderrule')",
        "",
        "badorderrule(",
        "    name = 'badorderdep',",
        ")",
        "py_library(",
        "    name = 'pylib',",
        "    srcs = ['pylib.py'],",
        ")",
        "py_binary(",
        "    name = 'pybin',",
        "    srcs = ['pybin.py'],",
        "    deps = [':pylib', ':badorderdep'],",
        ")");
    getConfiguredTarget("//badordertarget:pybin");
    assertContainsEvent(
        "Incompatible order for transitive_sources: expected 'default' or 'postorder', got "
            + "'preorder'");
  }

  @Test
  public void getUsesSharedLibraries_Good() throws Exception {
    StructImpl info = makeStruct(ImmutableMap.of(PyProvider.USES_SHARED_LIBRARIES, true));
    assertThat(PyProvider.getUsesSharedLibraries(info)).isTrue();
  }

  @Test
  public void getUsesSharedLibraries_Missing() throws Exception {
    StructImpl info = StructProvider.STRUCT.createEmpty(null);
    assertThat(PyProvider.getUsesSharedLibraries(info)).isFalse();
  }

  @Test
  public void getUsesSharedLibraries_WrongType() {
    StructImpl info = makeStruct(ImmutableMap.of(PyProvider.USES_SHARED_LIBRARIES, 123));
    assertHasWrongTypeMessage(
        () -> PyProvider.getUsesSharedLibraries(info), "uses_shared_libraries", "boolean");
  }

  @Test
  public void getImports_Good() throws Exception {
    NestedSet<String> imports = NestedSetBuilder.create(Order.COMPILE_ORDER, "abc");
    StructImpl info =
        makeStruct(ImmutableMap.of(PyProvider.IMPORTS, SkylarkNestedSet.of(String.class, imports)));
    assertThat(PyProvider.getImports(info)).isSameAs(imports);
  }

  @Test
  public void getImports_Missing() throws Exception {
    StructImpl info = StructProvider.STRUCT.createEmpty(null);
    assertHasOrderAndContainsExactly(PyProvider.getImports(info), Order.COMPILE_ORDER);
  }

  @Test
  public void getImports_WrongType() {
    StructImpl info = makeStruct(ImmutableMap.of(PyProvider.IMPORTS, 123));
    assertHasWrongTypeMessage(() -> PyProvider.getImports(info), "imports", "depset of strings");
  }

  @Test
  public void getHasPy2OnlySources_Good() throws Exception {
    StructImpl info = makeStruct(ImmutableMap.of(PyProvider.HAS_PY2_ONLY_SOURCES, true));
    assertThat(PyProvider.getHasPy2OnlySources(info)).isTrue();
  }

  @Test
  public void getHasPy2OnlySources_Missing() throws Exception {
    StructImpl info = StructProvider.STRUCT.createEmpty(null);
    assertThat(PyProvider.getHasPy2OnlySources(info)).isFalse();
  }

  @Test
  public void getHasPy2OnlySources_WrongType() {
    StructImpl info = makeStruct(ImmutableMap.of(PyProvider.HAS_PY2_ONLY_SOURCES, 123));
    assertHasWrongTypeMessage(
        () -> PyProvider.getHasPy2OnlySources(info), "has_py2_only_sources", "boolean");
  }

  @Test
  public void getHasPy3OnlySources_Good() throws Exception {
    StructImpl info = makeStruct(ImmutableMap.of(PyProvider.HAS_PY3_ONLY_SOURCES, true));
    assertThat(PyProvider.getHasPy3OnlySources(info)).isTrue();
  }

  @Test
  public void getHasPy3OnlySources_Missing() throws Exception {
    StructImpl info = StructProvider.STRUCT.createEmpty(null);
    assertThat(PyProvider.getHasPy3OnlySources(info)).isFalse();
  }

  @Test
  public void getHasPy3OnlySources_WrongType() {
    StructImpl info = makeStruct(ImmutableMap.of(PyProvider.HAS_PY3_ONLY_SOURCES, 123));
    assertHasWrongTypeMessage(
        () -> PyProvider.getHasPy3OnlySources(info), "has_py3_only_sources", "boolean");
  }

  /** Checks values set by the builder. */
  @Test
  public void builder() throws Exception {
    NestedSet<Artifact> sources =
        NestedSetBuilder.create(Order.COMPILE_ORDER, getSourceArtifact("dummy"));
    NestedSet<String> imports = NestedSetBuilder.create(Order.COMPILE_ORDER, "abc");
    StructImpl info =
        PyProvider.builder()
            .setTransitiveSources(sources)
            .setUsesSharedLibraries(true)
            .setImports(imports)
            .setHasPy2OnlySources(true)
            .setHasPy3OnlySources(true)
            .build();
    // Assert using struct operations, not PyProvider accessors, which aren't necessarily trusted to
    // be correct.
    assertHasOrderAndContainsExactly(
        ((SkylarkNestedSet) info.getValue(PyProvider.TRANSITIVE_SOURCES)).getSet(Artifact.class),
        Order.COMPILE_ORDER,
        getSourceArtifact("dummy"));
    assertThat((Boolean) info.getValue(PyProvider.USES_SHARED_LIBRARIES)).isTrue();
    assertHasOrderAndContainsExactly(
        ((SkylarkNestedSet) info.getValue(PyProvider.IMPORTS)).getSet(String.class),
        Order.COMPILE_ORDER,
        "abc");
    assertThat((Boolean) info.getValue(PyProvider.HAS_PY2_ONLY_SOURCES)).isTrue();
    assertThat((Boolean) info.getValue(PyProvider.HAS_PY3_ONLY_SOURCES)).isTrue();
  }

  /** Checks the defaults set by the builder. */
  @Test
  public void builderDefaults() throws Exception {
    // transitive_sources is mandatory, so create a dummy value but no need to assert on it.
    NestedSet<Artifact> sources =
        NestedSetBuilder.create(Order.COMPILE_ORDER, getSourceArtifact("dummy"));
    StructImpl info = PyProvider.builder().setTransitiveSources(sources).build();
    // Assert using struct operations, not PyProvider accessors, which aren't necessarily trusted to
    // be correct.
    assertThat((Boolean) info.getValue(PyProvider.USES_SHARED_LIBRARIES)).isFalse();
    assertHasOrderAndContainsExactly(
        ((SkylarkNestedSet) info.getValue(PyProvider.IMPORTS)).getSet(String.class),
        Order.COMPILE_ORDER);
    assertThat((Boolean) info.getValue(PyProvider.HAS_PY2_ONLY_SOURCES)).isFalse();
    assertThat((Boolean) info.getValue(PyProvider.HAS_PY3_ONLY_SOURCES)).isFalse();
  }
}
