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

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.testing.EqualsTester;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.SkylarkProvider.SkylarkKey;
import com.google.devtools.build.lib.syntax.Mutability;
import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.syntax.StarlarkThread;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link SkylarkProvider}. */
@RunWith(JUnit4.class)
public final class SkylarkProviderTest {

  @Test
  public void unexportedProvider_Accessors() {
    SkylarkProvider provider = SkylarkProvider.createUnexportedSchemaless(/*location=*/ null);
    assertThat(provider.isExported()).isFalse();
    assertThat(provider.getName()).isEqualTo("<no name>");
    assertThat(provider.getPrintableName()).isEqualTo("<no name>");
    assertThat(provider.getErrorMessageFormatForUnknownField())
        .isEqualTo("Object has no '%s' attribute.");
    assertThat(provider.isImmutable()).isFalse();
    assertThat(Starlark.repr(provider)).isEqualTo("<provider>");
    assertThrows(
        IllegalStateException.class,
        () -> provider.getKey());
  }

  @Test
  public void exportedProvider_Accessors() throws Exception {
    SkylarkKey key =
        new SkylarkKey(Label.parseAbsolute("//foo:bar.bzl", ImmutableMap.of()), "prov");
    SkylarkProvider provider = SkylarkProvider.createExportedSchemaless(key, /*location=*/ null);
    assertThat(provider.isExported()).isTrue();
    assertThat(provider.getName()).isEqualTo("prov");
    assertThat(provider.getPrintableName()).isEqualTo("prov");
    assertThat(provider.getErrorMessageFormatForUnknownField())
        .isEqualTo("'prov' value has no field or method '%s'");
    assertThat(provider.isImmutable()).isTrue();
    assertThat(Starlark.repr(provider)).isEqualTo("<provider>");
    assertThat(provider.getKey()).isEqualTo(key);
  }

  @Test
  public void schemalessProvider_Instantiation() throws Exception {
    SkylarkProvider provider = SkylarkProvider.createUnexportedSchemaless(/*location=*/ null);
    SkylarkInfo info = instantiateWithA1B2C3(provider);
    assertHasExactlyValuesA1B2C3(info);
  }

  @Test
  public void schemafulProvider_Instantiation() throws Exception {
    SkylarkProvider provider = SkylarkProvider.createUnexportedSchemaful(
        ImmutableList.of("a", "b", "c"), /*location=*/ null);
    SkylarkInfo info = instantiateWithA1B2C3(provider);
    assertHasExactlyValuesA1B2C3(info);
  }

  @Test
  public void schemalessProvider_GetFields() throws Exception {
    SkylarkProvider provider = SkylarkProvider.createUnexportedSchemaless(/*location=*/ null);
    assertThat(provider.getFields()).isNull();
  }

  @Test
  public void schemafulProvider_GetFields() throws Exception {
    SkylarkProvider provider = SkylarkProvider.createUnexportedSchemaful(
        ImmutableList.of("a", "b", "c"), /*location=*/ null);
    assertThat(provider.getFields()).containsExactly("a", "b", "c").inOrder();
  }

  @Test
  public void providerEquals() throws Exception {
    // All permutations of differing label and differing name.
    SkylarkKey keyFooA =
        new SkylarkKey(Label.parseAbsolute("//foo.bzl", ImmutableMap.of()), "provA");
    SkylarkKey keyFooB =
        new SkylarkKey(Label.parseAbsolute("//foo.bzl", ImmutableMap.of()), "provB");
    SkylarkKey keyBarA =
        new SkylarkKey(Label.parseAbsolute("//bar.bzl", ImmutableMap.of()), "provA");
    SkylarkKey keyBarB =
        new SkylarkKey(Label.parseAbsolute("//bar.bzl", ImmutableMap.of()), "provB");

    // 1 for each key, plus a duplicate for one of the keys, plus 2 that have no key.
    SkylarkProvider provFooA1 =
        SkylarkProvider.createExportedSchemaless(keyFooA, /*location=*/ null);
    SkylarkProvider provFooA2 =
        SkylarkProvider.createExportedSchemaless(keyFooA, /*location=*/ null);
    SkylarkProvider provFooB =
        SkylarkProvider.createExportedSchemaless(keyFooB, /*location=*/ null);
    SkylarkProvider provBarA =
        SkylarkProvider.createExportedSchemaless(keyBarA, /*location=*/ null);
    SkylarkProvider provBarB =
        SkylarkProvider.createExportedSchemaless(keyBarB, /*location=*/ null);
    SkylarkProvider provUnexported1 =
        SkylarkProvider.createUnexportedSchemaless(/*location=*/ null);
    SkylarkProvider provUnexported2 =
        SkylarkProvider.createUnexportedSchemaless(/*location=*/ null);

    // For exported providers, different keys -> unequal, same key -> equal. For unexported
    // providers it comes down to object identity.
    new EqualsTester()
        .addEqualityGroup(provFooA1, provFooA2)
        .addEqualityGroup(provFooB)
        .addEqualityGroup(provBarA, provBarA)  // reflexive equality (exported)
        .addEqualityGroup(provBarB)
        .addEqualityGroup(provUnexported1, provUnexported1)  // reflexive equality (unexported)
        .addEqualityGroup(provUnexported2)
        .testEquals();
  }

  /** Instantiates a {@link SkylarkInfo} with fields a=1, b=2, c=3 (and nothing else). */
  private static SkylarkInfo instantiateWithA1B2C3(SkylarkProvider provider) throws Exception{
    // Code under test begins with the entry point in BaseFunction.
    StarlarkThread thread =
        StarlarkThread.builder(Mutability.create("test")).useDefaultSemantics().build();
    Object result =
        Starlark.call(
            thread,
            provider,
            /*args=*/ ImmutableList.of(),
            /*kwargs=*/ ImmutableMap.of("a", 1, "b", 2, "c", 3));
    assertThat(result).isInstanceOf(SkylarkInfo.class);
    return (SkylarkInfo) result;
  }

  /** Asserts that a {@link SkylarkInfo} has fields a=1, b=2, c=3 (and nothing else). */
  private static void assertHasExactlyValuesA1B2C3(SkylarkInfo info) throws Exception {
    assertThat(info.getFieldNames()).containsExactly("a", "b", "c");
    assertThat(info.getValue("a")).isEqualTo(1);
    assertThat(info.getValue("b")).isEqualTo(2);
    assertThat(info.getValue("c")).isEqualTo(3);
  }
}
