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