// 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.assertWithMessage;

import com.google.common.collect.ImmutableList;
import com.google.common.testing.EqualsTester;
import com.google.devtools.common.options.Converter;
import com.google.devtools.common.options.OptionsParsingException;
import java.util.ArrayList;
import java.util.LinkedHashSet;

/**
 * A tester to confirm that {@link Converter} instances produce equal results on multiple calls with
 * the same input.
 */
public final class ConverterTester {

  private final Converter<?> converter;
  private final Class<? extends Converter<?>> converterClass;
  private final EqualsTester tester = new EqualsTester();
  private final LinkedHashSet<String> testedInputs = new LinkedHashSet<>();
  private final ArrayList<ImmutableList<String>> inputLists = new ArrayList<>();

  /** Creates a new ConverterTester which will test the given Converter class. */
  public ConverterTester(Class<? extends Converter<?>> converterClass) {
    this.converterClass = converterClass;
    this.converter = createConverter();
  }

  private Converter<?> createConverter() {
    try {
      return converterClass.getDeclaredConstructor().newInstance();
    } catch (ReflectiveOperationException ex) {
      throw new AssertionError("Failed to create converter", ex);
    }
  }

  /** Returns the class this ConverterTester is testing. */
  public Class<? extends Converter<?>> getConverterClass() {
    return converterClass;
  }

  /**
   * Returns whether this ConverterTester has a test for the given input, i.e., addEqualityGroup
   * was called with the given string.
   */
  public boolean hasTestForInput(String input) {
    return testedInputs.contains(input);
  }

  /**
   * Adds a set of valid inputs which are expected to convert to equal values.
   *
   * <p>The inputs added here will be converted to values using the Converter class passed to the
   * constructor of this instance; the resulting values must be equal (and have equal hashCodes):
   *
   * <ul>
   * <li>to themselves
   * <li>to another copy of themselves generated from the same Converter instance
   * <li>to another copy of themselves generated from a different Converter instance
   * <li>to the other values converted from inputs in the same addEqualityGroup call
   * </ul>
   *
   * <p>They must NOT be equal:
   *
   * <ul>
   * <li>to null
   * <li>to an instance of an arbitrary class
   * <li>to any values converted from inputs in a different addEqualityGroup call
   * </ul>
   *
   * @throws AssertionError if an {@link OptionsParsingException} is thrown from the
   *     {@link Converter#convert} method when converting any of the inputs.
   * @see EqualsTester#addEqualityGroup
   */
  public ConverterTester addEqualityGroup(String... inputs) {
    ImmutableList.Builder<WrappedItem> wrapped = ImmutableList.builder();
    ImmutableList<String> inputList = ImmutableList.copyOf(inputs);
    inputLists.add(inputList);
    for (String input : inputList) {
      testedInputs.add(input);
      try {
        wrapped.add(new WrappedItem(input, converter.convert(input)));
      } catch (OptionsParsingException ex) {
        throw new AssertionError("Failed to parse input: \"" + input + "\"", ex);
      }
    }
    tester.addEqualityGroup(wrapped.build().toArray());
    return this;
  }

  /**
   * Tests the convert method of the wrapped Converter class, verifying the properties listed in the
   * Javadoc listed for {@link #addEqualityGroup}.
   *
   * @throws AssertionError if one of the expected properties did not hold up
   * @see EqualsTester#testEquals
   */
  public ConverterTester testConvert() {
    tester.testEquals();
    testItems();
    return this;
  }

  private void testItems() {
    for (ImmutableList<String> inputList : inputLists) {
      for (String input : inputList) {
        Converter<?> converter = createConverter();
        Converter<?> converter2 = createConverter();

        Object converted;
        Object convertedAgain;
        Object convertedDifferentConverterInstance;
        try {
          converted = converter.convert(input);
          convertedAgain = converter.convert(input);
          convertedDifferentConverterInstance = converter2.convert(input);
        } catch (OptionsParsingException ex) {
          throw new AssertionError("Failed to parse input: \"" + input + "\"", ex);
        }

        assertWithMessage(
                "Input \""
                    + input
                    + "\" was not equal to itself when converted twice by the same Converter")
            .that(convertedAgain)
            .isEqualTo(converted);
        assertWithMessage(
                "Input \""
                    + input
                    + "\" did not have a consistent hashCode when converted twice "
                    + "by the same Converter")
            .that(convertedAgain.hashCode())
            .isEqualTo(converted.hashCode());
        assertWithMessage(
            "Input \""
                + input
                + "\" was not equal to itself when converted twice by a different Converter")
            .that(convertedDifferentConverterInstance)
            .isEqualTo(converted);
        assertWithMessage(
            "Input \""
                + input
                + "\" did not have a consistent hashCode when converted twice "
                + "by a different Converter")
            .that(convertedDifferentConverterInstance.hashCode())
            .isEqualTo(converted.hashCode());
      }
    }
  }

  /**
   * A wrapper around the objects passed to EqualsTester to give them a more useful toString() so
   * that the mapping between the input text which actually appears in the source file and the
   * object produced from parsing it is more obvious.
   */
  private static final class WrappedItem {
    private final String argument;
    private final Object wrapped;

    private WrappedItem(String argument, Object wrapped) {
      this.argument = argument;
      this.wrapped = wrapped;
    }

    @Override
    public String toString() {
      return String.format("Converted input \"%s\" => [%s]", argument, wrapped);
    }

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

    @Override
    public boolean equals(Object other) {
      if (other instanceof WrappedItem) {
        return this.wrapped.equals(((WrappedItem) other).wrapped);
      }
      return this.wrapped.equals(other);
    }
  }
}
