// 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 java.util.stream.Collectors.toList;

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;

  @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;
  }
}
