// Copyright 2019 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;

import static com.google.common.truth.Truth.assertWithMessage;
import static java.util.stream.Collectors.toList;
import static org.junit.Assume.assumeTrue;

import com.google.common.flogger.GoogleLogger;
import com.google.devtools.build.lib.util.Classpath;
import com.google.devtools.build.lib.util.Classpath.ClassPathException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

/**
 * Test to make sure all {@link Option}-annotated fields in <i>Prod</i> code have an {@link
 * Option#defaultValue()} that a corresponding {@link Option#converter()} can handle.<br>
 * {@link Option}-annotated field is considered to be in <i>Prod</i> code if its declaring class and
 * all its enclosing classes do not have {@link RunWith} annotation.
 *
 * @see OptionDefinition#getDefaultValue()
 */
@RunWith(Parameterized.class)
public class OptionDefaultValueConversionTest {

  private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();

  @Rule public ExpectedException thrown = ExpectedException.none();

  @Parameter public OptionDefinition optionDefinitionUnderTest;

  /**
   * Regression test for {@code allowMultiple = true} {@link Option#defaultValue()} switch from
   * {@code ""} to {@code "null"} as a part of enabling default values for {@code allowMultiple =
   * true} {@link Option}s.
   */
  @Test
  public void allowMultipleOptionsShouldNotHaveEmptyStringDefault() {
    // apply the test only to allowMultiple = true Options
    assumeTrue(optionDefinitionUnderTest.allowsMultiple());

    // arrange
    String assertionMessage =
        String.format(
            "\"%s\" option default value is an empty string - use a special \"null\" value for"
                + " empty multiple options",
            optionDefinitionUnderTest.getOptionName());

    // assert
    assertWithMessage(assertionMessage)
        .that(optionDefinitionUnderTest.getUnparsedDefaultValue())
        .isNotEmpty();
  }

  @Test
  public void shouldConvertDefaultValue() {
    // assert
    thrown = ExpectedException.none();

    // act
    optionDefinitionUnderTest.getDefaultValue();
  }

  @Parameters
  public static List<OptionDefinition> getAllProdOptionDefinitions() {
    try {
      Set<Class<?>> allClasses = Classpath.findClasses("com.google.devtools");

      List<OptionDefinition> optionDefinitions =
          allClasses.stream()
              .filter(c -> !isTestClass(c))
              .flatMap(c -> Arrays.stream(c.getFields()))
              .filter(f -> f.isAnnotationPresent(Option.class))
              .map(OptionDefinition::extractOptionDefinition)
              .collect(toList());
      logger.atFine().log(
          "Found %d Option-annotated fields in Prod code", optionDefinitions.size());

      return optionDefinitions;
    } catch (ClassPathException ex) {
      throw new RuntimeException("Unable to scan classpath", ex);
    }
  }

  private static boolean isTestClass(Class<?> initialClazz) {
    Class<?> clazz = initialClazz;
    do {
      if (clazz.isAnnotationPresent(RunWith.class)) {
        logger.atFiner().log("Filtered out %s: is a Test class", initialClazz);
        return true;
      }
      clazz = clazz.getEnclosingClass();
    } while (clazz != null);

    return false;
  }
}
