/*
 * Copyright (C) 2012 The Guava Authors
 *
 * 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.common.testing;

import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.not;
import static com.google.common.testing.AbstractPackageSanityTests.Chopper.suffix;

import com.google.common.annotations.Beta;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.reflect.ClassPath;
import com.google.common.testing.NullPointerTester.Visibility;

import junit.framework.AssertionFailedError;
import junit.framework.TestCase;

import org.junit.Test;

import java.io.IOException;
import java.io.Serializable;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Automatically runs sanity checks against top level classes in the same package of the test that
 * extends {@code AbstractPackageSanityTests}. Currently sanity checks include {@link
 * NullPointerTester}, {@link EqualsTester} and {@link SerializableTester}. For example: <pre>
 * public class PackageSanityTests extends AbstractPackageSanityTests {}
 * </pre>
 *
 * <p>Note that only top-level classes with either a non-private constructor or a non-private static
 * factory method to construct instances can have their instance methods checked. For example: <pre>
 * public class Address {
 *   private final String city;
 *   private final String state;
 *   private final String zipcode;
 *
 *   public Address(String city, String state, String zipcode) {...}
 *
 *   {@literal @Override} public boolean equals(Object obj) {...}
 *   {@literal @Override} public int hashCode() {...}
 *   ...
 * }
 * </pre>
 * <p>No cascading checks are performed against the return values of methods unless the method is a
 * static factory method. Neither are semantics of mutation methods such as {@code
 * someList.add(obj)} checked. For more detailed discussion of supported and unsupported cases, see
 * {@link #testEquals}, {@link #testNulls} and {@link #testSerializable}.
 *
 * <p>For testing against the returned instances from a static factory class, such as <pre>
 * interface Book {...}
 * public class Books {
 *   public static Book hardcover(String title) {...}
 *   public static Book paperback(String title) {...}
 * }
 * </pre>
 *
 * <p>please use {@link ClassSanityTester#forAllPublicStaticMethods}.
 *
 * <p>If not all classes on the classpath should be covered, {@link
 * #ignoreClasses} can be used to exclude certain classes.
 *
 * <p>{@link #setDefault} allows subclasses to specify default values for types.
 *
 * <p>This class incurs IO because it scans the classpath and reads classpath resources.
 *
 * @author Ben Yu
 * @since 14.0
 */
@Beta
// TODO: Switch to JUnit 4 and use @Parameterized and @BeforeClass
public abstract class AbstractPackageSanityTests extends TestCase {

  /* The names of the expected method that tests null checks. */
  private static final ImmutableList<String> NULL_TEST_METHOD_NAMES = ImmutableList.of(
      "testNulls", "testNull",
      "testNullPointers", "testNullPointer",
      "testNullPointerExceptions", "testNullPointerException");

  /* The names of the expected method that tests serializable. */
  private static final ImmutableList<String> SERIALIZABLE_TEST_METHOD_NAMES = ImmutableList.of(
      "testSerializable", "testSerialization",
      "testEqualsAndSerializable", "testEqualsAndSerialization");

  /* The names of the expected method that tests equals. */
  private static final ImmutableList<String> EQUALS_TEST_METHOD_NAMES = ImmutableList.of(
      "testEquals", "testEqualsAndHashCode",
      "testEqualsAndSerializable", "testEqualsAndSerialization",
      "testEquality");

  private static final Chopper TEST_SUFFIX =
      suffix("Test")
          .or(suffix("Tests"))
          .or(suffix("TestCase"))
          .or(suffix("TestSuite"));

  private final Logger logger = Logger.getLogger(getClass().getName());
  private final ClassSanityTester tester = new ClassSanityTester();
  private Visibility visibility = Visibility.PACKAGE;
  private Predicate<Class<?>> classFilter = new Predicate<Class<?>>() {
    @Override public boolean apply(Class<?> cls) {
      return visibility.isVisible(cls.getModifiers());
    }
  };

  /**
   * Restricts the sanity tests for public API only. By default, package-private API are also
   * covered.
   */
  protected final void publicApiOnly() {
    visibility = Visibility.PUBLIC;
  }

  /**
   * Tests all top-level {@link Serializable} classes in the package. For a serializable Class
   * {@code C}:
   * <ul>
   * <li>If {@code C} explicitly implements {@link Object#equals}, the deserialized instance will be
   *     checked to be equal to the instance before serialization.
   * <li>If {@code C} doesn't explicitly implement {@code equals} but instead inherits it from a
   *     superclass, no equality check is done on the deserialized instance because it's not clear
   *     whether the author intended for the class to be a value type.
   * <li>If a constructor or factory method takes a parameter whose type is interface, a dynamic
   *     proxy will be passed to the method. It's possible that the method body expects an instance
   *     method of the passed-in proxy to be of a certain value yet the proxy isn't aware of the
   *     assumption, in which case the equality check before and after serialization will fail.
   * <li>If the constructor or factory method takes a parameter that {@link
   *     AbstractPackageSanityTests} doesn't know how to construct, the test will fail.
   * <li>If there is no visible constructor or visible static factory method declared by {@code C},
   *     {@code C} is skipped for serialization test, even if it implements {@link Serializable}.
   * <li>Serialization test is not performed on method return values unless the method is a visible
   *     static factory method whose return type is {@code C} or {@code C}'s subtype.
   * </ul>
   *
   * <p>In all cases, if {@code C} needs custom logic for testing serialization, you can add an
   * explicit {@code testSerializable()} test in the corresponding {@code CTest} class, and {@code
   * C} will be excluded from automated serialization test performed by this method.
   */
  @Test
  public void testSerializable() throws Exception {
    // TODO: when we use @BeforeClass, we can pay the cost of class path scanning only once.
    for (Class<?> classToTest
        : findClassesToTest(loadClassesInPackage(), SERIALIZABLE_TEST_METHOD_NAMES)) {
      if (Serializable.class.isAssignableFrom(classToTest)) {
        try {
          Object instance = tester.instantiate(classToTest);
          if (instance != null) {
            if (isEqualsDefined(classToTest)) {
              SerializableTester.reserializeAndAssert(instance);
            } else {
              SerializableTester.reserialize(instance);
            }
          }
        } catch (Throwable e) {
          throw sanityError(classToTest, SERIALIZABLE_TEST_METHOD_NAMES, "serializable test", e);
        }
      }
    }
  }

  /**
   * Performs {@link NullPointerTester} checks for all top-level classes in the package. For a class
   * {@code C}
   * <ul>
   * <li>All visible static methods are checked such that passing null for any parameter that's not
   *     annotated with {@link javax.annotation.Nullable} should throw {@link NullPointerException}.
   * <li>If there is any visible constructor or visible static factory method declared by the class,
   *     all visible instance methods will be checked too using the instance created by invoking the
   *     constructor or static factory method.
   * <li>If the constructor or factory method used to construct instance takes a parameter that
   *     {@link AbstractPackageSanityTests} doesn't know how to construct, the test will fail.
   * <li>If there is no visible constructor or visible static factory method declared by {@code C},
   *     instance methods are skipped for nulls test.
   * <li>Nulls test is not performed on method return values unless the method is a visible static
   *     factory method whose return type is {@code C} or {@code C}'s subtype.
   * </ul>
   *
   * <p>In all cases, if {@code C} needs custom logic for testing nulls, you can add an explicit
   * {@code testNulls()} test in the corresponding {@code CTest} class, and {@code C} will be
   * excluded from the automated null tests performed by this method.
   */
  @Test
  public void testNulls() throws Exception {
    for (Class<?> classToTest
        : findClassesToTest(loadClassesInPackage(), NULL_TEST_METHOD_NAMES)) {
      try {
        tester.doTestNulls(classToTest, visibility);
      } catch (Throwable e) {
        throw sanityError(classToTest, NULL_TEST_METHOD_NAMES, "nulls test", e);
      }
    }
  }

  /**
   * Tests {@code equals()} and {@code hashCode()} implementations for every top-level class in the
   * package, that explicitly implements {@link Object#equals}. For a class {@code C}:
   * <ul>
   * <li>The visible constructor or visible static factory method with the most parameters is used
   *     to construct the sample instances. In case of tie, the candidate constructors or factories
   *     are tried one after another until one can be used to construct sample instances.
   * <li>For the constructor or static factory method used to construct instances, it's checked that
   *     when equal parameters are passed, the result instance should also be equal; and vice versa.
   * <li>Inequality check is not performed against state mutation methods such as {@link List#add},
   *     or functional update methods such as {@link com.google.common.base.Joiner#skipNulls}.
   * <li>If the constructor or factory method used to construct instance takes a parameter that
   *     {@link AbstractPackageSanityTests} doesn't know how to construct, the test will fail.
   * <li>If there is no visible constructor or visible static factory method declared by {@code C},
   *     {@code C} is skipped for equality test.
   * <li>Equality test is not performed on method return values unless the method is a visible
   *     static factory method whose return type is {@code C} or {@code C}'s subtype.
   * </ul>
   *
   * <p>In all cases, if {@code C} needs custom logic for testing {@code equals()}, you can add an
   * explicit {@code testEquals()} test in the corresponding {@code CTest} class, and {@code C} will
   * be excluded from the automated {@code equals} test performed by this method.
   */
  @Test
  public void testEquals() throws Exception {
    for (Class<?> classToTest
        : findClassesToTest(loadClassesInPackage(), EQUALS_TEST_METHOD_NAMES)) {
      if (!classToTest.isEnum() && isEqualsDefined(classToTest)) {
        try {
          tester.doTestEquals(classToTest);
        } catch (Throwable e) {
          throw sanityError(classToTest, EQUALS_TEST_METHOD_NAMES, "equals test", e);
        }
      }
    }
  }

  /**
   * Sets the default value for {@code type}, when dummy value for a parameter of the same type
   * needs to be created in order to invoke a method or constructor. The default value isn't used in
   * testing {@link Object#equals} because more than one sample instances are needed for testing
   * inequality.
   */
  protected final <T> void setDefault(Class<T> type, T value) {
    tester.setDefault(type, value);
  }

  /**
   * Sets two distinct values for {@code type}. These values can be used for both null pointer
   * testing and equals testing.
   *
   * @since 17.0
   */
  protected final <T> void setDistinctValues(Class<T> type, T value1, T value2) {
    tester.setDistinctValues(type, value1, value2);
  }

  /** Specifies that classes that satisfy the given predicate aren't tested for sanity. */
  protected final void ignoreClasses(Predicate<? super Class<?>> condition) {
    this.classFilter = and(this.classFilter, not(condition));
  }

  private static AssertionFailedError sanityError(
      Class<?> cls, List<String> explicitTestNames, String description, Throwable e) {
    String message = String.format(
        "Error in automated %s of %s\n"
            + "If the class is better tested explicitly, you can add %s() to %sTest",
        description, cls, explicitTestNames.get(0), cls.getName());
    AssertionFailedError error = new AssertionFailedError(message);
    error.initCause(e);
    return error;
  }

  /**
   * Finds the classes not ending with a test suffix and not covered by an explicit test
   * whose name is {@code explicitTestName}.
   */
  @VisibleForTesting List<Class<?>> findClassesToTest(
      Iterable<? extends Class<?>> classes, Iterable<String> explicitTestNames) {
    // "a.b.Foo" -> a.b.Foo.class
    TreeMap<String, Class<?>> classMap = Maps.newTreeMap();
    for (Class<?> cls : classes) {
      classMap.put(cls.getName(), cls);
    }
    // Foo.class -> [FooTest.class, FooTests.class, FooTestSuite.class, ...]
    Multimap<Class<?>, Class<?>> testClasses = HashMultimap.create();
    LinkedHashSet<Class<?>> candidateClasses = Sets.newLinkedHashSet();
    for (Class<?> cls : classes) {
      Optional<String> testedClassName = TEST_SUFFIX.chop(cls.getName());
      if (testedClassName.isPresent()) {
        Class<?> testedClass = classMap.get(testedClassName.get());
        if (testedClass != null) {
          testClasses.put(testedClass, cls);
        }
      } else {
        candidateClasses.add(cls);
      }
    }
    List<Class<?>> result = Lists.newArrayList();
    NEXT_CANDIDATE: for (Class<?> candidate : Iterables.filter(candidateClasses, classFilter)) {
      for (Class<?> testClass : testClasses.get(candidate)) {
        if (hasTest(testClass, explicitTestNames)) {
          // covered by explicit test
          continue NEXT_CANDIDATE;
        }
      }
      result.add(candidate);
    }
    return result;
  }

  private List<Class<?>> loadClassesInPackage() throws IOException {
    List<Class<?>> classes = Lists.newArrayList();
    String packageName = getClass().getPackage().getName();
    for (ClassPath.ClassInfo classInfo 
        : ClassPath.from(getClass().getClassLoader()).getTopLevelClasses(packageName)) {
      Class<?> cls;
      try {
        cls = classInfo.load();
      } catch (NoClassDefFoundError e) {
        // In case there were linking problems, this is probably not a class we care to test anyway.
        logger.log(Level.SEVERE, "Cannot load class " + classInfo + ", skipping...", e);
        continue;
      }
      if (!cls.isInterface()) {
        classes.add(cls);
      }
    }
    return classes;
  }

  private static boolean hasTest(Class<?> testClass, Iterable<String> testNames) {
    for (String testName : testNames) {
      try {
        testClass.getMethod(testName);
        return true;
      } catch (NoSuchMethodException e) {
        continue;
      }
    }
    return false;
  }

  private static boolean isEqualsDefined(Class<?> cls) {
    try {
      return !cls.getDeclaredMethod("equals", Object.class).isSynthetic();
    } catch (NoSuchMethodException e) {
      return false;
    }
  }

  static abstract class Chopper {

    final Chopper or(final Chopper you) {
      final Chopper i = this;
      return new Chopper() {
        @Override Optional<String> chop(String str) {
          return i.chop(str).or(you.chop(str));
        }
      };
    }

    abstract Optional<String> chop(String str);

    static Chopper suffix(final String suffix) {
      return new Chopper() {
        @Override Optional<String> chop(String str) {
          if (str.endsWith(suffix)) {
            return Optional.of(str.substring(0, str.length() - suffix.length()));
          } else {
            return Optional.absent();
          }
        }
      };
    }
  }
}
