// 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.collect.ImmutableListMultimap;
import com.google.devtools.common.options.Converter;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionsBase;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

/**
 * A tester to validate certain useful properties of OptionsBase subclasses. These are not required
 * for parsing options in these classes, but can be helpful for e.g. ensuring that equality is not
 * violated.
 */
public final class OptionsTester {

  private final Class<? extends OptionsBase> optionsClass;

  public OptionsTester(Class<? extends OptionsBase> optionsClass) {
    this.optionsClass = optionsClass;
  }

  private static ImmutableList<Field> getAllFields(Class<? extends OptionsBase> optionsClass) {
    ImmutableList.Builder<Field> builder = ImmutableList.builder();
    Class<? extends OptionsBase> current = optionsClass;
    while (!OptionsBase.class.equals(current)) {
      builder.add(current.getDeclaredFields());
      // the input extends OptionsBase and we haven't seen OptionsBase yet, so this must also extend
      // (or be) OptionsBase
      @SuppressWarnings("unchecked")
      Class<? extends OptionsBase> superclass =
          (Class<? extends OptionsBase>) current.getSuperclass();
      current = superclass;
    }
    return builder.build();
  }

  /**
   * Tests that there are no non-Option instance fields. Fields not annotated with @Option will not
   * be considered for equality.
   */
  public OptionsTester testAllInstanceFieldsAnnotatedWithOption() {
    for (Field field : getAllFields(optionsClass)) {
      if (!Modifier.isStatic(field.getModifiers())) {
        assertWithMessage(
                field
                    + " is missing an @Option annotation; it will not be considered for equality.")
            .that(field.getAnnotation(Option.class))
            .isNotNull();
      }
    }
    return this;
  }

  /**
   * Tests that the default values of this class were part of the test data for the appropriate
   * ConverterTester, ensuring that the defaults at least obey proper equality semantics.
   *
   * <p>The default converters are not tested in this way.
   *
   * <p>Note that testConvert is not actually run on the ConverterTesters; it is expected that they
   * are run elsewhere.
   */
  public OptionsTester testAllDefaultValuesTestedBy(ConverterTesterMap testers) {
    ImmutableListMultimap.Builder<Class<? extends Converter<?>>, Field> converterClassesBuilder =
        ImmutableListMultimap.builder();
    for (Field field : getAllFields(optionsClass)) {
      Option option = field.getAnnotation(Option.class);
      if (option != null && !Converter.class.equals(option.converter())) {
        @SuppressWarnings("unchecked") // converter is rawtyped; see comment on Option.converter()
        Class<? extends Converter<?>> converter =
            (Class<? extends Converter<?>>) option.converter();
        converterClassesBuilder.put(converter, field);
      }
    }
    ImmutableListMultimap<Class<? extends Converter<?>>, Field> converterClasses =
        converterClassesBuilder.build();
    for (Class<? extends Converter<?>> converter : converterClasses.keySet()) {
      assertWithMessage(
              "Converter " + converter.getCanonicalName() + " has no corresponding ConverterTester")
          .that(testers)
          .containsKey(converter);
      for (Field field : converterClasses.get(converter)) {
        Option option = field.getAnnotation(Option.class);
        if (!option.allowMultiple() && !"null".equals(option.defaultValue())) {
          assertWithMessage(
                  "Default value \""
                      + option.defaultValue()
                      + "\" on "
                      + field
                      + " is not tested in the corresponding ConverterTester for "
                      + converter.getCanonicalName())
              .that(testers.get(converter).hasTestForInput(option.defaultValue()))
              .isTrue();
        }
      }
    }
    return this;
  }
}
