// Copyright 2006 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.collect.Lists;
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.syntax.StarlarkList;
import com.google.devtools.build.lib.syntax.Tuple;
import com.google.devtools.build.lib.testutil.MoreAsserts;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Test of type-conversions using Type.
 */
@RunWith(JUnit4.class)
public class TypeTest {

  private Label currentRule;

  @Before
  public final void setCurrentRule() throws Exception  {
    this.currentRule = Label.parseAbsolute("//quux:baz", ImmutableMap.of());
  }

  @Test
  public void testInteger() throws Exception {
    Object x = 3;
    assertThat(Type.INTEGER.convert(x, null)).isEqualTo(x);
    assertThat(collectLabels(Type.INTEGER, x)).isEmpty();
  }

  @Test
  public void testNonInteger() throws Exception {
    Type.ConversionException e =
        assertThrows(Type.ConversionException.class, () -> Type.INTEGER.convert("foo", null));
    assertThat(e)
        .hasMessageThat()
        .isEqualTo("expected value of type 'int', but got \"foo\" (string)");
  }

  // Ensure that types are reported correctly.
  @Test
  public void testTypeErrorMessage() throws Exception {
    Type.ConversionException e =
        assertThrows(
            Type.ConversionException.class,
            () -> Type.STRING_LIST.convert("[(1,2), 3, 4]", "myexpr", null));
    assertThat(e)
        .hasMessageThat()
        .isEqualTo(
            "expected value of type 'list(string)' for myexpr, "
                + "but got \"[(1,2), 3, 4]\" (string)");
  }

  @Test
  public void testString() throws Exception {
    Object s = "foo";
    assertThat(Type.STRING.convert(s, null)).isEqualTo(s);
    assertThat(collectLabels(Type.STRING, s)).isEmpty();
  }

  @Test
  public void testNonString() throws Exception {
    Type.ConversionException e =
        assertThrows(Type.ConversionException.class, () -> Type.STRING.convert(3, null));
    assertThat(e).hasMessageThat().isEqualTo("expected value of type 'string', but got 3 (int)");
  }

  @Test
  public void testBoolean() throws Exception {
    Object myTrue = true;
    Object myFalse = false;
    assertThat(Type.BOOLEAN.convert(1, null)).isEqualTo(Boolean.TRUE);
    assertThat(Type.BOOLEAN.convert(0, null)).isEqualTo(Boolean.FALSE);
    assertThat(Type.BOOLEAN.convert(true, null)).isTrue();
    assertThat(Type.BOOLEAN.convert(myTrue, null)).isTrue();
    assertThat(Type.BOOLEAN.convert(false, null)).isFalse();
    assertThat(Type.BOOLEAN.convert(myFalse, null)).isFalse();
    assertThat(collectLabels(Type.BOOLEAN, myTrue)).isEmpty();
  }

  @Test
  public void testNonBoolean() throws Exception {
    Type.ConversionException e =
        assertThrows(
            Type.ConversionException.class, () -> Type.BOOLEAN.convert("unexpected", null));
    assertThat(e)
        .hasMessageThat()
        .isEqualTo("expected value of type 'int', but got \"unexpected\" (string)");
    // Integers other than [0, 1] should fail.
    e = assertThrows(Type.ConversionException.class, () -> Type.BOOLEAN.convert(2, null));
    assertThat(e).hasMessageThat().isEqualTo("boolean is not one of [0, 1]");
    e = assertThrows(Type.ConversionException.class, () -> Type.BOOLEAN.convert(-1, null));
    assertThat(e).hasMessageThat().isEqualTo("boolean is not one of [0, 1]");
  }

  @Test
  public void testTriState() throws Exception {
    assertThat(BuildType.TRISTATE.convert(1, null)).isEqualTo(TriState.YES);
    assertThat(BuildType.TRISTATE.convert(0, null)).isEqualTo(TriState.NO);
    assertThat(BuildType.TRISTATE.convert(-1, null)).isEqualTo(TriState.AUTO);
    assertThat(BuildType.TRISTATE.convert(TriState.YES, null)).isEqualTo(TriState.YES);
    assertThat(BuildType.TRISTATE.convert(TriState.NO, null)).isEqualTo(TriState.NO);
    assertThat(BuildType.TRISTATE.convert(TriState.AUTO, null)).isEqualTo(TriState.AUTO);
    assertThat(collectLabels(BuildType.TRISTATE, TriState.YES)).isEmpty();

    // deprecated:
    assertThat(BuildType.TRISTATE.convert(true, null)).isEqualTo(TriState.YES);
    assertThat(BuildType.TRISTATE.convert(false, null)).isEqualTo(TriState.NO);
  }

  @Test
  public void testTriStateDoesNotAcceptArbitraryIntegers() throws Exception {
    List<Integer> listOfCases = Lists.newArrayList(2, 3, -5, -2, 20);
    for (Object entry : listOfCases) {
      assertThrows(Type.ConversionException.class, () -> BuildType.TRISTATE.convert(entry, null));
    }
  }

  @Test
  public void testTriStateDoesNotAcceptStrings() throws Exception {
    List<?> listOfCases = Lists.newArrayList("bad", "true", "auto", "false");
    // TODO(adonovan): add booleans true, false to this list; see b/116691720.
    for (Object entry : listOfCases) {
      assertThrows(Type.ConversionException.class, () -> BuildType.TRISTATE.convert(entry, null));
    }
  }

  @Test
  public void testTagConversion() throws Exception {
    assertThat(Type.BOOLEAN.toTagSet(true, "attribute"))
        .containsExactlyElementsIn(Sets.newHashSet("attribute"));
    assertThat(Type.BOOLEAN.toTagSet(false, "attribute"))
        .containsExactlyElementsIn(Sets.newHashSet("noattribute"));

    assertThat(Type.STRING.toTagSet("whiskey", "preferred_cocktail"))
        .containsExactlyElementsIn(Sets.newHashSet("whiskey"));

    assertThat(
            Type.STRING_LIST.toTagSet(
                Lists.newArrayList("cheddar", "ementaler", "gruyere"), "cheeses"))
        .containsExactlyElementsIn(Sets.newHashSet("cheddar", "ementaler", "gruyere"));
  }

  @Test
  public void testIllegalTagConversionByType() throws Exception {
    assertThrows(
        UnsupportedOperationException.class,
        () -> BuildType.TRISTATE.toTagSet(TriState.AUTO, "some_tristate"));
    assertThrows(
        UnsupportedOperationException.class,
        () -> BuildType.LICENSE.toTagSet(License.NO_LICENSE, "output_license"));
  }

  @Test
  public void testIllegalTagConversIonFromNullOnSupportedType() throws Exception {
    assertThrows(IllegalStateException.class, () -> Type.BOOLEAN.toTagSet(null, "a_boolean"));
  }

  @Test
  public void testLabel() throws Exception {
    Label label = Label.parseAbsolute("//foo:bar", ImmutableMap.of());
    assertThat(BuildType.LABEL.convert("//foo:bar", null, currentRule)).isEqualTo(label);
    assertThat(collectLabels(BuildType.LABEL, label)).containsExactly(label);
  }

  @Test
  public void testNodepLabel() throws Exception {
    Label label = Label.parseAbsolute("//foo:bar", ImmutableMap.of());
    assertThat(BuildType.NODEP_LABEL.convert("//foo:bar", null, currentRule)).isEqualTo(label);
    assertThat(collectLabels(BuildType.NODEP_LABEL, label)).containsExactly(label);
  }

  @Test
  public void testRelativeLabel() throws Exception {
    assertThat(BuildType.LABEL.convert(":wiz", null, currentRule))
        .isEqualTo(Label.parseAbsolute("//quux:wiz", ImmutableMap.of()));
    assertThat(BuildType.LABEL.convert("wiz", null, currentRule))
        .isEqualTo(Label.parseAbsolute("//quux:wiz", ImmutableMap.of()));
    assertThrows(Type.ConversionException.class, () -> BuildType.LABEL.convert("wiz", null));
  }

  @Test
  public void testInvalidLabel() throws Exception {
    Type.ConversionException e =
        assertThrows(
            Type.ConversionException.class,
            () -> BuildType.LABEL.convert("not//a label", null, currentRule));
    MoreAsserts.assertContainsWordsWithQuotes(e.getMessage(), "not//a label");
  }

  @Test
  public void testNonLabel() throws Exception {
    Type.ConversionException e =
        assertThrows(Type.ConversionException.class, () -> BuildType.LABEL.convert(3, null));
    assertThat(e).hasMessageThat().isEqualTo("expected value of type 'string', but got 3 (int)");
  }

  @Test
  public void testStringList() throws Exception {
    Object input = Arrays.asList("foo", "bar", "wiz");
    List<String> converted =
        Type.STRING_LIST.convert(input, null);
    assertThat(converted).isEqualTo(input);
    assertThat(converted).isNotSameInstanceAs(input);
    assertThat(collectLabels(Type.STRING_LIST, input)).isEmpty();
  }

  @Test
  public void testStringDict() throws Exception {
    Object input = ImmutableMap.of("foo", "bar",
                                   "wiz", "bang");
    Map<String, String> converted = Type.STRING_DICT.convert(input, null);
    assertThat(converted).isEqualTo(input);
    assertThat(converted).isNotSameInstanceAs(input);
    assertThat(collectLabels(Type.STRING_DICT, converted)).isEmpty();
  }

  @Test
  public void testStringDictBadElements() throws Exception {
    Object input = ImmutableMap.of("foo", StarlarkList.of(null, "bar", "baz"), "wiz", "bang");
    Type.ConversionException e =
        assertThrows(Type.ConversionException.class, () -> Type.STRING_DICT.convert(input, null));
    assertThat(e)
        .hasMessageThat()
        .isEqualTo(
            "expected value of type 'string' for dict value element, "
                + "but got [\"bar\", \"baz\"] (list)");
  }

  @Test
  public void testNonStringList() throws Exception {
    Type.ConversionException e =
        assertThrows(Type.ConversionException.class, () -> Type.STRING_LIST.convert(3, "blah"));
    assertThat(e)
        .hasMessageThat()
        .isEqualTo("expected value of type 'list(string)' for blah, but got 3 (int)");
  }

  @Test
  public void testStringListBadElements() throws Exception {
    Object input = Arrays.<Object>asList("foo", "bar", 1);
    Type.ConversionException e =
        assertThrows(
            Type.ConversionException.class, () -> Type.STRING_LIST.convert(input, "argument quux"));
    assertThat(e)
        .hasMessageThat()
        .isEqualTo(
            "expected value of type 'string' for element 2 of argument quux, but got 1 (int)");
  }

  @Test
  public void testListDepsetConversion() throws Exception {
    Object input =
        Depset.of(
            Depset.ElementType.STRING, NestedSetBuilder.create(Order.STABLE_ORDER, "a", "b", "c"));
    Type.STRING_LIST.convert(input, null);
  }

  @Test
  public void testLabelList() throws Exception {
    Object input = Arrays.asList("//foo:bar", ":wiz");
    List<Label> converted =
      BuildType.LABEL_LIST.convert(input , null, currentRule);
    List<Label> expected =
        Arrays.asList(
            Label.parseAbsolute("//foo:bar", ImmutableMap.of()),
            Label.parseAbsolute("//quux:wiz", ImmutableMap.of()));
    assertThat(converted).isEqualTo(expected);
    assertThat(converted).isNotSameInstanceAs(expected);
    assertThat(collectLabels(BuildType.LABEL_LIST, converted)).containsExactlyElementsIn(expected);
  }

  @Test
  public void testNonLabelList() throws Exception {
    Type.ConversionException e =
        assertThrows(
            Type.ConversionException.class,
            () -> BuildType.LABEL_LIST.convert(3, "foo", currentRule));
    assertThat(e)
        .hasMessageThat()
        .isEqualTo("expected value of type 'list(label)' for foo, but got 3 (int)");
  }

  @Test
  public void testLabelListBadElements() throws Exception {
    Object list = Arrays.<Object>asList("//foo:bar", 2, "foo");
    Type.ConversionException e =
        assertThrows(
            Type.ConversionException.class,
            () -> BuildType.LABEL_LIST.convert(list, null, currentRule));
    assertThat(e)
        .hasMessageThat()
        .isEqualTo("expected value of type 'string' for element 1 of null, but got 2 (int)");
  }

  @Test
  public void testLabelListSyntaxError() throws Exception {
    Object list = Arrays.<Object>asList("//foo:bar/..", "foo");
    Type.ConversionException e =
        assertThrows(
            Type.ConversionException.class,
            () -> BuildType.LABEL_LIST.convert(list, "myexpr", currentRule));
    assertThat(e)
        .hasMessageThat()
        .isEqualTo(
            "invalid label '//foo:bar/..' in element 0 of myexpr: "
                + "invalid target name 'bar/..': "
                + "target names may not contain up-level references '..'");
  }

  @Test
  public void testStringListDict() throws Exception {
    Object input = ImmutableMap.of("foo", Arrays.asList("foo", "bar"),
                                   "wiz", Arrays.asList("bang"));
    Map<String, List<String>> converted =
        Type.STRING_LIST_DICT.convert(input, null, currentRule);
    Map<?, ?> expected = ImmutableMap.<String, List<String>>of(
            "foo", Arrays.asList("foo", "bar"),
            "wiz", Arrays.asList("bang"));
    assertThat(converted).isEqualTo(expected);
    assertThat(converted).isNotSameInstanceAs(expected);
    assertThat(collectLabels(Type.STRING_LIST_DICT, converted)).isEmpty();
  }

  @Test
  public void testStringListDictBadFirstElement() throws Exception {
    Object input = ImmutableMap.of(2, Arrays.asList("foo", "bar"),
                                   "wiz", Arrays.asList("bang"));
    Type.ConversionException e =
        assertThrows(
            Type.ConversionException.class,
            () -> Type.STRING_LIST_DICT.convert(input, null, currentRule));
    assertThat(e)
        .hasMessageThat()
        .isEqualTo("expected value of type 'string' for dict key element, but got 2 (int)");
  }

  @Test
  public void testStringListDictBadSecondElement() throws Exception {
    Object input = ImmutableMap.of("foo", "bar",
                                   "wiz", Arrays.asList("bang"));
    Type.ConversionException e =
        assertThrows(
            Type.ConversionException.class,
            () -> Type.STRING_LIST_DICT.convert(input, null, currentRule));
    assertThat(e)
        .hasMessageThat()
        .isEqualTo(
            "expected value of type 'list(string)' for dict value element, "
                + "but got \"bar\" (string)");
  }

  @Test
  public void testStringListDictBadElements1() throws Exception {
    Object input = ImmutableMap.of(Tuple.of("foo"), Tuple.of("bang"), "wiz", Tuple.of("bang"));
    Type.ConversionException e =
        assertThrows(
            Type.ConversionException.class, () -> Type.STRING_LIST_DICT.convert(input, null));
    assertThat(e)
        .hasMessageThat()
        .isEqualTo(
            "expected value of type 'string' for dict key element, but got "
                + "(\"foo\",) (tuple)");
  }

  @Test
  public void testStringDictThrowsConversionException() throws Exception {
    Type.ConversionException e =
        assertThrows(
            Type.ConversionException.class, () -> Type.STRING_DICT.convert("some string", null));
    assertThat(e)
        .hasMessageThat()
        .isEqualTo(
            "expected value of type 'dict(string, string)', but got \"some string\" (string)");
  }

  private static ImmutableList<Label> collectLabels(Type<?> type, Object value) {
    final ImmutableList.Builder<Label> result = ImmutableList.builder();
    type.visitLabels((label, dummy) -> result.add(label), value, /*context=*/ null);
    return result.build();
  }
}
