// 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 org.junit.Assert.assertThrows;

import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.collect.nestedset.Depset;
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.StarlarkInfo;
import com.google.devtools.build.lib.packages.StructImpl;
import com.google.devtools.build.lib.packages.StructProvider;
import com.google.devtools.build.lib.testutil.FoundationTestCase;
import com.google.devtools.build.lib.vfs.Root;
import java.util.LinkedHashMap;
import java.util.Map;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.StarlarkInt;
import org.junit.Before;
import org.junit.Test;
import org.junit.function.ThrowingRunnable;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link PyStructUtils}. */
@RunWith(JUnit4.class)
public class PyStructUtilsTest extends FoundationTestCase {

  private Artifact dummyArtifact;

  @Before
  public void setUp() {
    this.dummyArtifact =
        ActionsTestUtil.createArtifact(
            ArtifactRoot.asSourceRoot(Root.fromPath(rootDirectory)), "dummy");
  }

  /**
   * 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 PyStructUtils.Builder}, so that
   * the resulting instance is suitable for asserting on {@code PyStructUtils}'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(
        PyStructUtils.TRANSITIVE_SOURCES,
        Depset.of(Artifact.TYPE, NestedSetBuilder.emptySet(Order.COMPILE_ORDER)));
    fields.put(PyStructUtils.USES_SHARED_LIBRARIES, false);
    fields.put(
        PyStructUtils.IMPORTS,
        Depset.of(Depset.ElementType.STRING, NestedSetBuilder.emptySet(Order.COMPILE_ORDER)));
    fields.put(PyStructUtils.HAS_PY2_ONLY_SOURCES, false);
    fields.put(PyStructUtils.HAS_PY3_ONLY_SOURCES, false);
    fields.putAll(overrides);
    return StructProvider.STRUCT.create(fields, "No such attribute '%s'");
  }

  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 was int, want %s", 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.toList()).containsExactly(values);
  }

  @Test
  public void getTransitiveSources_Good() throws Exception {
    NestedSet<Artifact> sources = NestedSetBuilder.create(Order.COMPILE_ORDER, dummyArtifact);
    StructImpl info =
        makeStruct(
            ImmutableMap.of(PyStructUtils.TRANSITIVE_SOURCES, Depset.of(Artifact.TYPE, sources)));
    assertThat(PyStructUtils.getTransitiveSources(info)).isSameInstanceAs(sources);
  }

  private static final StructImpl emptyInfo =
      StarlarkInfo.create(StructProvider.STRUCT, ImmutableMap.of(), /* loc= */ null);

  @Test
  public void getTransitiveSources_Missing() {
    assertHasMissingFieldMessage(
        () -> PyStructUtils.getTransitiveSources(emptyInfo), "transitive_sources");
  }

  @Test
  public void getTransitiveSources_WrongType() {
    StructImpl info =
        makeStruct(ImmutableMap.of(PyStructUtils.TRANSITIVE_SOURCES, StarlarkInt.of(123)));
    assertThrowsEvalExceptionContaining(
        () -> PyStructUtils.getTransitiveSources(info),
        "for transitive_sources, got int, want a depset of File");
  }

  @Test
  public void getTransitiveSources_OrderMismatch() throws Exception {
    NestedSet<Artifact> sources = NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
    StructImpl info =
        makeStruct(
            ImmutableMap.of(PyStructUtils.TRANSITIVE_SOURCES, Depset.of(Artifact.TYPE, sources)));
    assertThrowsEvalExceptionContaining(
        () -> PyStructUtils.getTransitiveSources(info),
        "Incompatible depset order for 'transitive_sources': expected 'default' or 'postorder', "
            + "but got 'preorder'");
  }

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

  @Test
  public void getUsesSharedLibraries_Missing() throws Exception {
    assertThat(PyStructUtils.getUsesSharedLibraries(emptyInfo)).isFalse();
  }

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

  @Test
  public void getImports_Good() throws Exception {
    NestedSet<String> imports = NestedSetBuilder.create(Order.COMPILE_ORDER, "abc");
    StructImpl info =
        makeStruct(
            ImmutableMap.of(PyStructUtils.IMPORTS, Depset.of(Depset.ElementType.STRING, imports)));
    assertThat(PyStructUtils.getImports(info)).isSameInstanceAs(imports);
  }

  @Test
  public void getImports_Missing() throws Exception {
    assertHasOrderAndContainsExactly(PyStructUtils.getImports(emptyInfo), Order.COMPILE_ORDER);
  }

  @Test
  public void getImports_WrongType() {
    StructImpl info = makeStruct(ImmutableMap.of(PyStructUtils.IMPORTS, StarlarkInt.of(123)));
    assertThrowsEvalExceptionContaining(
        () -> PyStructUtils.getImports(info), "for imports, got int, want a depset of string");
  }

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

  @Test
  public void getHasPy2OnlySources_Missing() throws Exception {
    assertThat(PyStructUtils.getHasPy2OnlySources(emptyInfo)).isFalse();
  }

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

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

  @Test
  public void getHasPy3OnlySources_Missing() throws Exception {
    assertThat(PyStructUtils.getHasPy3OnlySources(emptyInfo)).isFalse();
  }

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

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