// 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.common.options.testing;

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

import com.google.devtools.common.options.Converter;
import com.google.devtools.common.options.Converters;
import com.google.devtools.common.options.OptionsParsingException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests to exercise the functionality of {@link ConverterTester}. */
@RunWith(JUnit4.class)
public final class ConverterTesterTest {

  @Test
  public void construction_throwsAssertionErrorIfConverterCreationFails() throws Exception {
    try {
      new ConverterTester(UnconstructableConverter.class, /*conversionContext=*/ null);
    } catch (AssertionError expected) {
      assertThat(expected) // AssertionError
          .hasCauseThat() // InvocationTargetException
          .hasCauseThat() // UnsupportedOperationException
          .hasMessageThat()
          .contains("YOU CAN'T MAKE ME!");
      return;
    }
    fail("expected tester creation to fail");
  }

  /** Test converter for construction_throwsAssertionErrorIfConverterCreationFails. */
  public static final class UnconstructableConverter extends Converter.Contextless<String> {
    public UnconstructableConverter() {
      throw new UnsupportedOperationException("YOU CAN'T MAKE ME!");
    }

    @Override
    public String convert(String input) throws OptionsParsingException {
      return input;
    }

    @Override
    public String getTypeDescription() {
      return "anything, if you can get an instance";
    }
  }

  @Test
  public void getConverterClass_returnsConstructorArg() throws Exception {
    ConverterTester tester =
        new ConverterTester(Converters.BooleanConverter.class, /*conversionContext=*/ null);
    assertThat(tester.getConverterClass()).isEqualTo(Converters.BooleanConverter.class);
  }

  @Test
  public void hasTestForInput_returnsTrueIffInputPassedToAddEqualityGroup() throws Exception {
    ConverterTester tester =
        new ConverterTester(Converters.DoubleConverter.class, /*conversionContext=*/ null)
            .addEqualityGroup("1.0", "1", "1.00")
            .addEqualityGroup("2");

    assertThat(tester.hasTestForInput("1.0")).isTrue();
    assertThat(tester.hasTestForInput("1")).isTrue();
    assertThat(tester.hasTestForInput("1.00")).isTrue();
    assertThat(tester.hasTestForInput("2")).isTrue();

    assertThat(tester.hasTestForInput("3")).isFalse();
    assertThat(tester.hasTestForInput("1.000")).isFalse();
    assertThat(tester.hasTestForInput("not a double")).isFalse();
  }

  @Test
  public void addEqualityGroup_throwsIfConversionFails() throws Exception {
    ConverterTester tester =
        new ConverterTester(ThrowingConverter.class, /*conversionContext=*/ null)
            .addEqualityGroup("okay")
            .addEqualityGroup("also okay", "pretty fine");
    try {
      tester.addEqualityGroup("wrong");
    } catch (AssertionError expected) {
      assertThat(expected).hasMessageThat().contains("\"wrong\"");
      assertThat(expected).hasCauseThat().hasMessageThat().contains("HOW DARE YOU");
      return;
    }
    fail("expected addEqualityGroup to fail");
  }

  /** Test converter for addEqualityGroup_throwsIfConversionFails. */
  public static final class ThrowingConverter extends Converter.Contextless<String> {
    @Override
    public String convert(String input) throws OptionsParsingException {
      if ("wrong".equals(input)) {
        throw new OptionsParsingException("HOW DARE YOU");
      }
      return input;
    }

    @Override
    public String getTypeDescription() {
      return "just don't give the wrong answer";
    }
  }

  @Test
  public void testConvert_passesWhenAllInstancesObeyEqualsAndItemsOnlyEqualToOthersInSameGroup() {
    new ConverterTester(Converters.DoubleConverter.class, /*conversionContext=*/ null)
        .addEqualityGroup("1.0", "1", "1.00")
        .addEqualityGroup("2", "2", "2.0000", "2.0", "+2")
        .addEqualityGroup("3")
        .addEqualityGroup("3.1415")
        .testConvert();
  }

  @Test
  public void testConvert_testsHashCodeConsistencyForConvertedInstance() {
    ConverterTester tester =
        new ConverterTester(InconsistentHashCodeConverter.class, /*conversionContext=*/ null)
            .addEqualityGroup("input doesn't matter");
    try {
      tester.testConvert();
    } catch (AssertionError expected) {
      assertThat(expected).hasMessageThat().contains("\"input doesn't matter\"");
      assertThat(expected).hasMessageThat().contains("hashCode");
      assertThat(expected).hasMessageThat().contains("must be consistent");
      return;
    }
    fail("expected the tester to notice the bad hash code implementation");
  }

  /** A class with a badly implemented hashCode which is not consistent across calls. */
  public static final class InconsistentHashCode {
    @Override
    public boolean equals(Object other) {
      return other instanceof InconsistentHashCode;
    }

    private int howManyTimesHaveIBeenHashedAlready = 0;

    @Override
    public int hashCode() {
      howManyTimesHaveIBeenHashedAlready += 1;
      return howManyTimesHaveIBeenHashedAlready;
    }
  }

  /** Test converter for testConvert_testsHashCodeConsistencyForConvertedInstance. */
  public static final class InconsistentHashCodeConverter
      extends Converter.Contextless<InconsistentHashCode> {
    @Override
    public InconsistentHashCode convert(String input) throws OptionsParsingException {
      return new InconsistentHashCode();
    }

    @Override
    public String getTypeDescription() {
      return "anything, I don't even look at it";
    }
  }

  @Test
  public void testConvert_testsHashCodeConsistencyForSameConverter() {
    ConverterTester tester =
        new ConverterTester(IncrementingHashCodeConverter.class, /*conversionContext=*/ null)
            .addEqualityGroup("meaningless input");
    try {
      tester.testConvert();
    } catch (AssertionError expected) {
      assertThat(expected).hasMessageThat().contains("\"meaningless input\"");
      assertThat(expected).hasMessageThat().contains("consistent hashCode");
      assertThat(expected).hasMessageThat().contains("same Converter");
      return;
    }
    fail("expected the tester to notice the mismatched hash codes");
  }

  /** A class with a configurable hashCode set in the constructor. */
  public static final class SettableHashCode {
    private final int hashCode;

    public SettableHashCode(int hashCode) {
      this.hashCode = hashCode;
    }

    @Override
    public boolean equals(Object other) {
      return other instanceof SettableHashCode;
    }

    @Override
    public int hashCode() {
      return hashCode;
    }
  }

  /** Test converter for testConvert_testsHashCodeConsistencyForSameConverter. */
  public static final class IncrementingHashCodeConverter
      extends Converter.Contextless<SettableHashCode> {
    private int howManyInstancesHaveIMadeAlready = 0;

    @Override
    public SettableHashCode convert(String input) throws OptionsParsingException {
      howManyInstancesHaveIMadeAlready += 1;
      return new SettableHashCode(howManyInstancesHaveIMadeAlready);
    }

    @Override
    public String getTypeDescription() {
      return "whatever, I'm pretty much just going to ignore it";
    }
  }

  @Test
  public void testConvert_testsHashCodeConsistencyForDifferentConverters() {
    ConverterTester tester =
        new ConverterTester(StaticIncrementingHashCodeConverter.class, /*conversionContext=*/ null)
            .addEqualityGroup("some kind of input");
    try {
      tester.testConvert();
    } catch (AssertionError expected) {
      assertThat(expected).hasMessageThat().contains("\"some kind of input\"");
      assertThat(expected).hasMessageThat().contains("consistent hashCode");
      assertThat(expected).hasMessageThat().contains("different Converter");
      return;
    }
    fail("expected the tester to notice the mismatched hash codes");
  }

  /** Test converter for testConvert_testsHashCodeConsistencyForDifferentConverters. */
  public static final class StaticIncrementingHashCodeConverter
      extends Converter.Contextless<SettableHashCode> {
    private static int howManyInstancesHaveIMadeAlready = 0;

    private final int hashCode;

    public StaticIncrementingHashCodeConverter() {
      howManyInstancesHaveIMadeAlready += 1;
      this.hashCode = howManyInstancesHaveIMadeAlready;
    }

    @Override
    public SettableHashCode convert(String input) throws OptionsParsingException {
      return new SettableHashCode(hashCode);
    }

    @Override
    public String getTypeDescription() {
      return "a string or null, I'm easy";
    }
  }


  @Test
  public void testConvert_testsSelfEqualityForConvertedInstance() {
    ConverterTester tester =
        new ConverterTester(SelfLoathingConverter.class, /*conversionContext=*/ null)
            .addEqualityGroup("self-loathing");
    try {
      tester.testConvert();
    } catch (AssertionError expected) {
      assertThat(expected).hasMessageThat().contains("\"self-loathing\"");
      assertThat(expected).hasMessageThat().contains("must be Object#equals to itself");
      return;
    }
    fail("expected the tester to notice the bad equals implementation");
  }

  /** A class which is equal to every instance of its class except itself. */
  public static final class SelfLoathingObject {
    @Override
    public boolean equals(Object other) {
      return other instanceof SelfLoathingObject && other != this;
    }

    @Override
    public int hashCode() {
      return 4; // chosen by fair hashing algorithm
    }
  }

  /** Test converter for testConvert_testsSelfEqualityForConvertedInstance. */
  public static final class SelfLoathingConverter
      extends Converter.Contextless<SelfLoathingObject> {
    @Override
    public SelfLoathingObject convert(String input) throws OptionsParsingException {
      return new SelfLoathingObject();
    }

    @Override
    public String getTypeDescription() {
      return "whatever... why even ask me to convert anything..............";
    }
  }

  @Test
  public void testConvert_testsEqualityForSameConverter() {
    ConverterTester tester =
        new ConverterTester(CountingConverter.class, /*conversionContext=*/ null)
            .addEqualityGroup("countables");
    try {
      tester.testConvert();
    } catch (AssertionError expected) {
      assertThat(expected).hasMessageThat().contains("\"countables\"");
      assertThat(expected).hasMessageThat().contains("equal to itself");
      assertThat(expected).hasMessageThat().contains("same Converter");
      return;
    }
    fail("expected the tester to notice the converter giving unequal objects");
  }

  /** Test converter for testConvert_testsEqualityForSameConverter. */
  public static final class CountingConverter extends Converter.Contextless<Integer> {
    private int howManyInstancesHaveIMadeAlready = 0;

    @Override
    public Integer convert(String input) throws OptionsParsingException {
      howManyInstancesHaveIMadeAlready += 1;
      return howManyInstancesHaveIMadeAlready;
    }

    @Override
    public String getTypeDescription() {
      return "I can count anything!";
    }
  }

  @Test
  public void testConvert_testsEqualityForDifferentConverters() {
    ConverterTester tester =
        new ConverterTester(StaticCountingConverter.class, /*conversionContext=*/ null)
            .addEqualityGroup("words I like");
    try {
      tester.testConvert();
    } catch (AssertionError expected) {
      assertThat(expected).hasMessageThat().contains("\"words I like\"");
      assertThat(expected).hasMessageThat().contains("equal to itself");
      assertThat(expected).hasMessageThat().contains("different Converter");
      return;
    }
    fail("expected the tester to notice the converters giving unequal objects");
  }

  /** Test converter for testConvert_testsEqualityForDifferentConverters. */
  public static final class StaticCountingConverter extends Converter.Contextless<Integer> {
    private static int howManyInstancesHaveIMadeAlready = 0;

    private final int output;

    public StaticCountingConverter() {
      howManyInstancesHaveIMadeAlready += 1;
      this.output = howManyInstancesHaveIMadeAlready;
    }

    @Override
    public Integer convert(String input) throws OptionsParsingException {
      return output;
    }

    @Override
    public String getTypeDescription() {
      return "your favorite text";
    }
  }

  @Test
  public void testConvert_testsEqualityForItemsInSameGroup() {
    ConverterTester tester =
        new ConverterTester(Converters.DoubleConverter.class, /*conversionContext=*/ null)
            .addEqualityGroup("+1.000", "2.30");
    try {
      tester.testConvert();
    } catch (AssertionError expected) {
      assertThat(expected).hasMessageThat().contains("\"+1.000\"");
      assertThat(expected).hasMessageThat().contains("\"2.30\"");
      return;
    }
    fail("expected the tester to notice the two non-equal conversion results in the same group");
  }

  @Test
  public void testConvert_testsNonEqualityForItemsInDifferentGroups() {
    ConverterTester tester =
        new ConverterTester(Converters.DoubleConverter.class, /*conversionContext=*/ null)
            .addEqualityGroup("+1.000")
            .addEqualityGroup("1.0");
    try {
      tester.testConvert();
    } catch (AssertionError expected) {
      assertThat(expected).hasMessageThat().contains("\"+1.000\"");
      assertThat(expected).hasMessageThat().contains("\"1.0\"");
      return;
    }
    fail("expected the tester to notice the two equal conversion results in different groups");
  }
}
