/*
 * Copyright 2008 Google Inc.
 * 
 * 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.gwt.tools.apichecker;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.dev.javac.impl.StaticJavaResource;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.util.log.AbstractTreeLogger;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;

import junit.framework.TestCase;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;

/**
 * 
 * Test 2 ApiContainers for compatibility
 * 
 * test compatibility output if returnType changes, parameters change, method
 * overload compatibility, exception compatibility; abstract added, final added
 * to both ApiClass, apiMethods.
 * 
 * test white-list support.
 * 
 * TODO(amitmanjhi): (1) Re-factor this code as much as possible into smaller
 * separate components similar to the ApiCompatibilityUnit class. (2) Use
 * MockApiElement instead of String comparisons.
 */
public class ApiCompatibilityTest extends TestCase {

  // These cups are slightly different from the cups in ApiContainerTest
  private static final boolean DEBUG = false;

  private static StaticJavaResource[] getScuArray() {
    return new StaticJavaResource[] {
        new StaticJavaResource("test.apicontainer.ApiClass", getSourceForApiClass()),
        new StaticJavaResource("test.apicontainer.NonApiClass",
            getSourceForNonApiClass()),
        new StaticJavaResource("test.nonapipackage.TestClass",
            getSourceForTestClass()),
        new StaticJavaResource("java.lang.Object", getSourceForObject()),
        new StaticJavaResource("java.lang.Throwable", getSourceForThrowable()),
        new StaticJavaResource("test.apicontainer.OneMoreApiClass",
            getSourceForOneMoreApiClass()),
        new StaticJavaResource("java.lang.RuntimeException",
            getSourceForRuntimeException()),};
  }

  private static String getSourceForApiClass() {
    StringBuffer sb = new StringBuffer();
    sb.append("package test.apicontainer;\n");
    sb.append("public class ApiClass extends NonApiClass {\n");
    sb.append("\tpublic void apiMethod() { };\n");
    sb.append("\tpublic void checkParametersAndReturnTypes(java.lang.Object x) throws java.lang.Throwable { };\n");
    sb.append("\tpublic final void checkParametersAndReturnTypesFinalVersion(java.lang.Object x) throws java.lang.Throwable { };\n");
    sb.append("};\n");
    return sb.toString();
  }

  private static String getSourceForNonApiClass() {
    StringBuffer sb = new StringBuffer();
    sb.append("package test.apicontainer;\n");
    sb.append("class NonApiClass extends java.lang.Object {\n");
    sb.append("\tpublic void methodInNonApiClass(ApiClassInNonApiClass o) { };\n");
    sb.append("\tpublic void methodInNonApiClass(NonApiClass t) { };\n");
    sb.append("\tpublic int fieldInNonApiClass = 3;\n");
    sb.append("\tprotected abstract class ApiClassInNonApiClass {\n");
    sb.append("\tprotected ApiClassInNonApiClass() { }\n");
    sb.append("\t}\n");
    sb.append("}\n");
    return sb.toString();
  }

  private static String getSourceForObject() {
    StringBuffer sb = new StringBuffer();
    sb.append("package java.lang;\n");
    sb.append("public class Object {\n");
    sb.append("\tpublic void apiMethod() { }\n");
    sb.append("\tprotected void checkOverloadedAndOverridableDetection(java.lang.Object b) { }\n");
    sb.append("\tprotected final void checkOverloadedMethodAccounted(java.lang.Object b) { }\n");
    sb.append("\tprivate void internalMethod() { }\n");
    sb.append("\tprotected final void protectedMethod() { }\n");
    sb.append("\tpublic final int apiField = 0;\n");
    sb.append("\tprivate int internalField = 0;\n");
    sb.append("\tprotected static int protectedField=2;\n");
    sb.append("}\n");
    return sb.toString();
  }

  private static String getSourceForOneMoreApiClass() {
    StringBuffer sb = new StringBuffer();
    sb.append("package test.apicontainer;\n");
    sb.append("public class OneMoreApiClass extends java.lang.Object {\n");
    sb.append("\tprotected void checkOverloadedAndOverridableDetection(test.apicontainer.OneMoreApiClass b) { }\n");
    sb.append("\tprotected final void checkOverloadedMethodAccounted(test.apicontainer.ApiClass b) throws java.lang.Throwable { }\n");
    sb.append("\tpublic void testUncheckedExceptions() throws RuntimeException { }\n");
    sb.append("};\n");
    return sb.toString();
  }

  private static String getSourceForRuntimeException() {
    StringBuffer sb = new StringBuffer();
    sb.append("package java.lang;\n");
    sb.append("public class RuntimeException extends Throwable {\n");
    sb.append("}\n");
    return sb.toString();
  }

  private static String getSourceForTestClass() {
    StringBuffer sb = new StringBuffer();
    sb.append("package test.nonapipackage;\n");
    sb.append("class TestClass extends java.lang.Object {\n");
    sb.append("\tpublic void method() { }\n");
    sb.append("}\n");
    return sb.toString();
  }

  private static String getSourceForThrowable() {
    StringBuffer sb = new StringBuffer();
    sb.append("package java.lang;\n");
    sb.append("public class Throwable extends Object {\n");
    sb.append("}\n");
    return sb.toString();
  }

  ApiContainer api1 = null;
  ApiContainer api2 = null;
  ApiContainer apiSameAs1 = null;

  @Override
  public void setUp() throws UnableToCompleteException {
    AbstractTreeLogger logger = new PrintWriterTreeLogger();
    logger.setMaxDetail(TreeLogger.ERROR);

    api1 = new ApiContainer("Api1", new HashSet<Resource>(
        Arrays.asList(ApiContainerTest.getScuArray())), new HashSet<String>(),
        logger);
    apiSameAs1 = new ApiContainer("ApiSameAs1", new HashSet<Resource>(
        Arrays.asList(ApiContainerTest.getScuArray())), new HashSet<String>(),
        logger);
    api2 = new ApiContainer("Api2", new HashSet<Resource>(
        Arrays.asList(getScuArray())), new HashSet<String>(), logger);
  }

  // setup is called before every test*. To avoid the overhead of setUp() each
  // time, test everything together.
  public void testEverything() throws NotFoundException {
    checkBasicStuff();
    checkWhiteList();
  }

  private void checkBasicStuff() throws NotFoundException {
    HashSet<String> hashSet = new HashSet<String>();
    assertEquals(0, ApiCompatibilityChecker.getApiDiff(api1, apiSameAs1,
        hashSet).size());
    ApiDiffGenerator apiDiff = new ApiDiffGenerator(api2, api1);
    String strWithDuplicates = getStringRepresentation(ApiCompatibilityChecker.getApiDiff(
        apiDiff, hashSet, !ApiCompatibilityChecker.FILTER_DUPLICATES));
    if (DEBUG) {
      System.out.println("computing apiDiff, now with duplicates");
      System.out.println(strWithDuplicates);
    }
    String strWithoutDuplicates = getStringRepresentation(ApiCompatibilityChecker.getApiDiff(
        apiDiff, hashSet, ApiCompatibilityChecker.FILTER_DUPLICATES));
    if (DEBUG) {
      System.out.println("computing apiDiff, now without duplicates");
      System.out.println(strWithoutDuplicates);
    }

    String delimiter = ApiDiffGenerator.DELIMITER;
    // test if missing packages are reported correctly
    String statusString = "java.newpackage" + delimiter
        + ApiChange.Status.MISSING;
    assertEquals(1, countPresence(statusString, strWithDuplicates));
    assertEquals(1, countPresence(statusString, strWithoutDuplicates));

    // test if missing classes are reported correctly
    assertEquals(1, countPresence(
        "test.apicontainer.NonApiClass.AnotherApiClassInNonApiClass"
            + delimiter + ApiChange.Status.MISSING, strWithoutDuplicates));

    // test if modifier changes of a class are reported
    assertEquals(1, countPresence(
        "test.apicontainer.NonApiClass.ApiClassInNonApiClass" + delimiter
            + ApiChange.Status.ABSTRACT_ADDED, strWithoutDuplicates));

    // test if methods are still reported even if class becomes abstract (as
    // long as it is sub-classable)
    assertEquals(0, countPresence(
        "test.apicontainer.NonApiClass.ApiClassInNonApiClass::ApiClassInNonApiClass()"
            + delimiter + ApiChange.Status.MISSING, strWithoutDuplicates));
    assertEquals(0, countPresence(
        "test.apicontainer.NonApiClass.ApiClassInNonApiClass::protectedMethod()"
            + delimiter + ApiChange.Status.MISSING, strWithoutDuplicates));

    // test if modifier changes of fields and methods are reported
    assertEquals(1, countPresence("java.lang.Object::apiField" + delimiter
        + ApiChange.Status.FINAL_ADDED, strWithoutDuplicates));
    assertEquals(1, countPresence("java.lang.Object::protectedMethod()"
        + delimiter + ApiChange.Status.FINAL_ADDED, strWithoutDuplicates));

    // test if duplicates are weeded out from intersecting methods
    assertEquals(4, countPresence("protectedMethod()" + delimiter
        + ApiChange.Status.FINAL_ADDED, strWithDuplicates));
    assertEquals(1, countPresence("protectedMethod()" + delimiter
        + ApiChange.Status.FINAL_ADDED, strWithoutDuplicates));

    // test if duplicates are weeded out from missing fields
    assertEquals(4, countPresence("apiFieldWillBeMissing" + delimiter
        + ApiChange.Status.MISSING, strWithDuplicates));
    assertEquals(1, countPresence("apiFieldWillBeMissing" + delimiter
        + ApiChange.Status.MISSING, strWithoutDuplicates));

    // test error in non-final version
    String nonFinalMethodSignature = "checkParametersAndReturnTypes(Ltest/apicontainer/ApiClass;)";
    for (ApiChange.Status status : new ApiChange.Status[] {
        ApiChange.Status.OVERRIDABLE_METHOD_ARGUMENT_TYPE_CHANGE,
        ApiChange.Status.OVERRIDABLE_METHOD_EXCEPTION_TYPE_CHANGE,
        ApiChange.Status.OVERRIDABLE_METHOD_RETURN_TYPE_CHANGE}) {
      assertEquals(1, countPresence(nonFinalMethodSignature + delimiter
          + status, strWithoutDuplicates));
    }
    // test return type and exception type error in final version
    String finalMethodSignature = "checkParametersAndReturnTypesFinalVersion(Ltest/apicontainer/ApiClass;)";
    assertEquals(1, countPresence(finalMethodSignature + delimiter
        + ApiChange.Status.RETURN_TYPE_ERROR, strWithoutDuplicates));
    assertEquals(1, countPresence(finalMethodSignature + delimiter
        + ApiChange.Status.EXCEPTION_TYPE_ERROR, strWithoutDuplicates));

    // checking if changes in parameter types were okay
    assertEquals(2, countPresence(finalMethodSignature, strWithoutDuplicates));

    // test method_overloading
    finalMethodSignature = "methodInNonApiClass(Ltest/apicontainer/NonApiClass;)";
    assertEquals(1, countPresence(finalMethodSignature + delimiter
        + ApiChange.Status.OVERLOADED_METHOD_CALL, strWithoutDuplicates));

    // test unchecked exceptions
    assertEquals(0, countPresence("testUncheckedExceptions",
        strWithoutDuplicates));

    // test overloaded and overridable detection
    String methodSignature = "test.apicontainer.OneMoreApiClass::checkOverloadedAndOverridableDetection(Ljava/lang/Object;)";
    for (ApiChange.Status status : new ApiChange.Status[] {
        ApiChange.Status.OVERRIDABLE_METHOD_ARGUMENT_TYPE_CHANGE,
        ApiChange.Status.OVERRIDABLE_METHOD_EXCEPTION_TYPE_CHANGE,
        ApiChange.Status.OVERRIDABLE_METHOD_RETURN_TYPE_CHANGE}) {
      assertEquals(0, countPresence(methodSignature + delimiter + status,
          strWithoutDuplicates));
    }

    // the method should be satisfied by the method in the super-class
    methodSignature = "test.apicontainer.OneMoreApiClass::checkOverloadedMethodAccounted(Ltest/apicontainer/OneMoreApiClass;)";
    assertEquals(0, countPresence(methodSignature + delimiter
        + ApiChange.Status.MISSING, strWithoutDuplicates));

    // the method should throw unchecked exceptions error
    methodSignature = "test.apicontainer.OneMoreApiClass::checkOverloadedMethodAccounted(Ljava/lang/Object;)";
    assertEquals(1, countPresence(methodSignature + delimiter
        + ApiChange.Status.EXCEPTION_TYPE_ERROR, strWithoutDuplicates));
  }

  private void checkWhiteList() throws NotFoundException {
    ApiDiffGenerator apiDiff = new ApiDiffGenerator(api2, api1);
    boolean removeDuplicates = false;
    String whiteList = "java.newpackage" + ApiDiffGenerator.DELIMITER
        + ApiChange.Status.MISSING;
    HashSet<String> hashSet = new HashSet<String>();
    hashSet.add(whiteList);
    String strWithoutDuplicates = getStringRepresentation(ApiCompatibilityChecker.getApiDiff(
        apiDiff, hashSet, !removeDuplicates));

    // test if missing packages are reported correctly
    assertEquals(0, countPresence(whiteList, strWithoutDuplicates));
  }

  private int countPresence(String needle, String hay) {
    int count = 0;
    int needleLength = needle.length();
    int index = -needleLength;
    while ((index = hay.indexOf(needle, index + needleLength)) != -1) {
      count++;
    }
    return count;
  }

  private String getStringRepresentation(Collection<ApiChange> collection) {
    StringBuffer sb = new StringBuffer();
    for (ApiChange apiChange : collection) {
      sb.append(apiChange);
      sb.append("\n");
    }
    return sb.toString();
  }

}

// abstract methods can't be static
class TestAA {
  static int j = 10;

  static void printX() {
    System.err.println("2");
  }

  int i = 5;

  private TestAA() {
  }
}

class TestAB {
  static void test() {
    TestAA.printX();
  }
}
