/*
 * Copyright 2010 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.dev.javac;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JArrayType;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JConstructor;
import com.google.gwt.core.ext.typeinfo.JField;
import com.google.gwt.core.ext.typeinfo.JGenericType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.JTypeParameter;
import com.google.gwt.core.ext.typeinfo.JWildcardType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.core.ext.typeinfo.TypeOracleException;
import com.google.gwt.dev.javac.TypeOracleMediator.TypeData;
import com.google.gwt.dev.javac.mediatortest.AfterAssimilate;
import com.google.gwt.dev.javac.mediatortest.BaseInterface;
import com.google.gwt.dev.javac.mediatortest.BeforeAssimilate;
import com.google.gwt.dev.javac.mediatortest.BindToTypeScope;
import com.google.gwt.dev.javac.mediatortest.ConstrainedList;
import com.google.gwt.dev.javac.mediatortest.ConstrainedListAsField;
import com.google.gwt.dev.javac.mediatortest.DeclaresGenericInnerInterface;
import com.google.gwt.dev.javac.mediatortest.DeclaresGenericInnerType;
import com.google.gwt.dev.javac.mediatortest.DefaultClass;
import com.google.gwt.dev.javac.mediatortest.Derived;
import com.google.gwt.dev.javac.mediatortest.DerivedInterface;
import com.google.gwt.dev.javac.mediatortest.EnclosingLocal;
import com.google.gwt.dev.javac.mediatortest.EnclosingLocalWithMember;
import com.google.gwt.dev.javac.mediatortest.ExtendsGenericList;
import com.google.gwt.dev.javac.mediatortest.ExtendsGenericOuter;
import com.google.gwt.dev.javac.mediatortest.ExtendsParameterizedInterface;
import com.google.gwt.dev.javac.mediatortest.Fields;
import com.google.gwt.dev.javac.mediatortest.GenericList;
import com.google.gwt.dev.javac.mediatortest.GenericOuter;
import com.google.gwt.dev.javac.mediatortest.Implementations;
import com.google.gwt.dev.javac.mediatortest.ListAsField;
import com.google.gwt.dev.javac.mediatortest.Methods;
import com.google.gwt.dev.javac.mediatortest.Outer;
import com.google.gwt.dev.javac.mediatortest.OuterInt;
import com.google.gwt.dev.javac.mediatortest.ReferencesGenericListConstant;
import com.google.gwt.dev.javac.mediatortest.ReferencesParameterizedTypeBeforeItsGenericFormHasBeenProcessed;
import com.google.gwt.dev.javac.testing.impl.MockJavaResource;
import com.google.gwt.dev.javac.testing.impl.StaticJavaResource;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.log.AbstractTreeLogger;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
import com.google.gwt.thirdparty.guava.common.collect.MapMaker;

import junit.framework.TestCase;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Test TypeOracleMediator.
 * 
 * NOTE: These tests require the test source code to be on the classpath. In
 * Eclipse, make sure your launch configuration includes the 'core/test'
 * directory on the classpath tab.
 */
public abstract class TypeOracleMediatorTestBase extends TestCase {

  protected static abstract class CheckedJavaResource extends MutableJavaResource {
    private final String[] shortTypeNames;

    public CheckedJavaResource(Class<?> clazz, String... shortTypeNames) {
      super(clazz);
      this.shortTypeNames = shortTypeNames;
    }

    public CheckedJavaResource(String packageName, String shortMainTypeName,
        String... shortTypeNames) {
      super(packageName, Shared.makeTypeName(packageName, shortMainTypeName));
      this.shortTypeNames = shortTypeNames;
    }

    public abstract void check(JClassType type) throws NotFoundException;

    public List<String> getTypeNames() {
      List<String> typeNames = new ArrayList<String>();
      typeNames.add(getTypeName());
      for (String shortTypeName : shortTypeNames) {
        String typeName = Shared.makeTypeName(getPackageName(), shortTypeName);
        typeNames.add(typeName);
      }
      return typeNames;
    }
  }

  protected static abstract class MutableJavaResource extends MockJavaResource {
    private static byte[] getByteCode(Class<?> aClass) throws IOException {
      String resourcePath = aClass.getName().replace(".", "/") + ".class";
      ClassLoader loader = aClass.getClassLoader();
      if (loader == null && aClass.getName().startsWith("java.")) {
        loader = Thread.currentThread().getContextClassLoader();
      }
      InputStream istream = loader.getResourceAsStream(resourcePath);
      assertNotNull(istream);
      return Util.readStreamAsBytes(istream);
    }

    // For building the type oracle from bytecode
    private final Class<?> clazz;
    private String extraSource = "";
    private final String packageName;

    public MutableJavaResource(Class<?> clazz) {
      super(clazz.getName());
      this.clazz = clazz;
      this.packageName = clazz.getPackage().getName();
    }

    public MutableJavaResource(String packageName, String qualifiedTypeName) {
      super(qualifiedTypeName);
      this.clazz = null;
      this.packageName = packageName;
    }

    public String getPackageName() {
      return packageName;
    }

    /**
     * This method is used to pull sample source from inside the test case. By
     * default, return <code>null</code> to indicate that source should be on
     * the classpath.
     * 
     * @return
     */
    public String getSource() {
      return null;
    }

    /**
     * Pulls Java source from files in the mediatortest package. If source files
     * are on the classpath, prefer this data.
     */
    public String getSourceFromClasspath() throws IOException {
      if (clazz == null) {
        return null;
      }
      assertFalse(clazz.getName().startsWith("java."));
      ClassLoader loader = clazz.getClassLoader();
      String resourcePath = clazz.getName().replace(".", "/") + ".java";
      InputStream istream = loader.getResourceAsStream(resourcePath);
      if (istream == null) {
        fail("Could not read " + resourcePath + " from classloader.");
      }
      return Util.readStreamAsString(istream);
    }

    public TypeData[] getTypeData() throws IOException {
      return getTypeData(clazz);
    }

    @Override
    public void touch() {
      super.touch();
      extraSource += '\n';
    }

    /**
     * Looks for the source data on the classpath.
     */
    @Override
    public CharSequence getContent() {
      String source = getSource();
      if (source == null) {
        try {
          source = getSourceFromClasspath();
        } catch (IOException ex) {
          return null;
        }
        assertNotNull("Make sure your runtime environment includes the source "
            + "for the testcases on the classpath if this assertion fails", source);
      }
      return source + extraSource;
    }

    private TypeData[] getTypeData(Class<?> aClass) throws IOException {
      List<TypeData> results = new ArrayList<TypeData>();
      String packageName = Shared.getPackageName(aClass.getName());
      TypeData newData =
          new TypeData(packageName, aClass.getSimpleName(), aClass.getName().replace(".", "/"),
              null, getByteCode(aClass), System.currentTimeMillis());
      results.add(newData);
      Class<?>[] subclasses = aClass.getDeclaredClasses();
      for (Class<?> subclass : subclasses) {
        for (TypeData result : getTypeData(subclass)) {
          results.add(result);
        }
      }
      return results.toArray(new TypeData[results.size()]);
    }
  }

  protected static final CheckedJavaResource CU_AfterAssimilate = new CheckedJavaResource(
      AfterAssimilate.class) {
    @Override
    public void check(JClassType type) {
      assertNotNull(type);
      assertEquals("AfterAssimilate", type.getSimpleSourceName());
      assertNotNull(type.getSuperclass());
      assertEquals(getPackageName() + ".BeforeAssimilate", type.getSuperclass()
          .getQualifiedSourceName());
    }
  };

  protected static final CheckedJavaResource CU_BaseInterface = new CheckedJavaResource(
      BaseInterface.class) {

    @Override
    public void check(JClassType type) {
      assertEquals(getTypeName(), type.getQualifiedSourceName());
      assertNotNull(type.isInterface());
    }
  };

  protected static final CheckedJavaResource CU_BeforeAssimilate = new CheckedJavaResource(
      BeforeAssimilate.class) {
    @Override
    public void check(JClassType type) {
      assertEquals(getTypeName(), type.getQualifiedSourceName());
    }
  };

  protected static final CheckedJavaResource CU_BindToTypeScope = new CheckedJavaResource(
      BindToTypeScope.class, "BindToTypeScope.Object", "BindToTypeScope.DerivedObject") {

    @Override
    public void check(JClassType type) throws NotFoundException {
      if ("BindToTypeScope".equals(type.getSimpleSourceName())) {
        checkBindToTypeScope(type);
      } else if ("Object".equals(type.getSimpleSourceName())) {
        checkObject(type);
      } else {
        checkDerivedObject(type);
      }
    }

    public void checkBindToTypeScope(JClassType type) throws NotFoundException {
      assertEquals("BindToTypeScope", type.getSimpleSourceName());
      assertEquals(getTypeName(), type.getQualifiedSourceName());
      JClassType object = type.getNestedType("Object");
      assertNotNull(object);
      JClassType derivedObject = type.getNestedType("DerivedObject");
      assertNotNull(derivedObject);
    }

    public void checkObject(JClassType type) {
      assertEquals("Object", type.getSimpleSourceName());
      assertEquals(getTypeName() + ".Object", type.getQualifiedSourceName());
    }

    private void checkDerivedObject(JClassType type) throws NotFoundException {
      JClassType bindToTypeScope = type.getEnclosingType();
      assertNotNull(bindToTypeScope);

      JClassType object = bindToTypeScope.getNestedType("Object");
      assertNotNull(object);
      assertEquals(object.getSimpleSourceName(), "Object");

      JClassType derivedObject = bindToTypeScope.getNestedType("DerivedObject");
      assertNotNull(derivedObject);
      assertEquals(derivedObject.getSimpleSourceName(), "DerivedObject");

      assertEquals(object, derivedObject.getSuperclass());
    }
  };

  protected static final CheckedJavaResource CU_ConstrainedList = new CheckedJavaResource(
      ConstrainedList.class) {
    @Override
    public void check(JClassType type) throws NotFoundException {
      assertNotNull(type.isGenericType());
    }
  };

  protected static final CheckedJavaResource CU_ConstrainedListAsField = new CheckedJavaResource(
      ConstrainedListAsField.class) {
    @Override
    public void check(JClassType type) throws NotFoundException {
      assertNull(type.isGenericType());
      assertNull(type.getEnclosingType());
    }
  };

  protected static final CheckedJavaResource CU_DeclaresInnerGenericInterface =
      new CheckedJavaResource(DeclaresGenericInnerInterface.class,
          "DeclaresGenericInnerInterface.Inner") {
        @Override
        public void check(JClassType type) throws NotFoundException {
          assertNotNull(type.isGenericType());
        }
      };

  protected static final CheckedJavaResource CU_DeclaresInnerGenericType = new CheckedJavaResource(
      DeclaresGenericInnerType.class, "DeclaresGenericInnerType.Inner") {
    @Override
    public void check(JClassType type) throws NotFoundException {
      assertNotNull(type.isGenericType());
    }
  };

  protected static final CheckedJavaResource CU_DefaultClass = new CheckedJavaResource(
      DefaultClass.class) {
    @Override
    public void check(JClassType type) {
      assertEquals("DefaultClass", type.getSimpleSourceName());
      assertEquals(getTypeName(), type.getQualifiedSourceName());
      JClassType object = type.getOracle().findType("java.lang", "Object");
      assertNotNull(object);

      assertEquals(object, type.getSuperclass());
      assertNull(type.isInterface());
      assertEquals(0, type.getMethods().length);
      assertEquals(0, type.getFields().length);
    }
  };

  protected static final CheckedJavaResource CU_Derived = new CheckedJavaResource(Derived.class,
      "Derived.Nested") {
    @Override
    public void check(JClassType type) {
      if ("Derived".equals(type.getSimpleSourceName())) {
        checkDerived(type);
      } else if ("Nested".equals(type.getSimpleSourceName())) {
        checkNested(type);
      } else {
        assert (false);
      }
    }

    private void checkDerived(JClassType type) {
      assertEquals(getTypeName(), type.getQualifiedSourceName());
    }

    private void checkNested(JClassType type) {
      assertEquals(getTypeName() + ".Nested", type.getQualifiedSourceName());

    }
  };

  protected static final CheckedJavaResource CU_DerivedInterface = new CheckedJavaResource(
      DerivedInterface.class) {

    @Override
    public void check(JClassType type) {
      assertEquals(getTypeName(), type.getQualifiedSourceName());
      assertNotNull(type.isInterface());
    }
  };

  protected static final CheckedJavaResource CU_EnclosingLocalClass = new CheckedJavaResource(
      EnclosingLocal.class) {

    @Override
    public void check(JClassType type) {
      final String name = type.getSimpleSourceName();
      assertEquals("EnclosingLocal", name);
      checkEnclosing(type);
    }

    public void checkEnclosing(JClassType type) {
      assertEquals("EnclosingLocal", type.getSimpleSourceName());
      assertEquals(getTypeName(), type.getQualifiedSourceName());
      // verify the local class doesn't show up
      JClassType[] nested = type.getNestedTypes();
      assertEquals(0, nested.length);
    }
  };

  protected static final CheckedJavaResource CU_EnclosingLocalWithMember = new CheckedJavaResource(
      EnclosingLocalWithMember.class) {

    @Override
    public void check(JClassType type) {
      final String name = type.getSimpleSourceName();
      assertEquals("EnclosingLocalWithMember", name);
      checkEnclosing(type);
    }

    public void checkEnclosing(JClassType type) {
      assertEquals(getTypeName(), type.getQualifiedSourceName());
      // verify the local class doesn't show up
      JClassType[] nested = type.getNestedTypes();
      assertEquals(0, nested.length);
    }
  };

  protected static final CheckedJavaResource CU_ExtendsGenericList = new CheckedJavaResource(
      ExtendsGenericList.class) {

    @Override
    public void check(JClassType type) throws NotFoundException {
      assertNotNull(type.getSuperclass().isParameterized());
    }
  };

  protected static final CheckedJavaResource CU_ExtendsGenericOuterInner = new CheckedJavaResource(
      ExtendsGenericOuter.class, "ExtendsGenericOuter.ExtendsInner") {

    @Override
    public void check(JClassType type) {
      final String name = type.getSimpleSourceName();
      if ("ExtendsGenericOuter".equals(name)) {
        checkOuter(type);
      } else {
        checkInner(type);
      }
    }

    public void checkInner(JClassType type) {
      assertEquals("ExtendsInner", type.getSimpleSourceName());
      assertEquals(getTypeName() + ".ExtendsInner", type.getQualifiedSourceName());
      assertEquals(getTypeName(), type.getEnclosingType().getQualifiedSourceName());
    }

    public void checkOuter(JClassType type) {
      assertEquals("ExtendsGenericOuter", type.getSimpleSourceName());
      assertEquals(getTypeName(), type.getQualifiedSourceName());
      JClassType[] nested = type.getNestedTypes();
      assertEquals(1, nested.length);
      JClassType inner = nested[0];
      assertEquals(getTypeName() + ".ExtendsInner", inner.getQualifiedSourceName());
    }
  };

  protected static final CheckedJavaResource CU_ExtendsParameterizedInterface =
      new CheckedJavaResource(ExtendsParameterizedInterface.class) {
        @Override
        public void check(JClassType type) throws NotFoundException {
          assertNotNull(type.getSuperclass().isParameterized());
        }
      };

  protected static final CheckedJavaResource CU_FieldsAndTypes = new CheckedJavaResource(
      Fields.class) {
    @Override
    public void check(JClassType type) throws NotFoundException {
      if ("Fields".equals(type.getSimpleSourceName())) {
        assertEquals(getTypeName(), type.getQualifiedSourceName());

        TypeOracle tio = type.getOracle();

        JField[] fields = type.getFields();
        assertEquals(12, fields.length);

        JField field;
        JType fieldType;
        JArrayType arrayType;
        JType componentType;
        final JClassType someType = tio.getType(getPackageName(), "DefaultClass");
        final JArrayType intArrayType = tio.getArrayType(JPrimitiveType.INT);
        final JArrayType someTypeArrayType = tio.getArrayType(someType);
        final JArrayType intArrayArrayType = tio.getArrayType(intArrayType);

        field = type.getField("privateInt");
        assertTrue(field.isPrivate());
        assertEquals(JPrimitiveType.INT, field.getType());

        field = type.getField("privateSomeType");
        assertTrue(field.isPrivate());
        assertEquals(someType, field.getType());

        field = type.getField("protectedInt");
        assertTrue(field.isProtected());

        field = type.getField("publicInt");
        assertTrue(field.isPublic());

        field = type.getField("packageInt");
        assertTrue(field.isDefaultAccess());

        field = type.getField("staticInt");
        assertTrue(field.isStatic());

        field = type.getField("transientInt");
        assertTrue(field.isTransient());

        field = type.getField("volatileInt");
        assertTrue(field.isVolatile());

        field = type.getField("multiInt");
        assertTrue(field.isPublic());
        assertTrue(field.isStatic());
        assertTrue(field.isFinal());
        assertTrue(field.isTransient());

        field = type.getField("intArray");
        fieldType = field.getType();
        arrayType = fieldType.isArray();
        assertNotNull(arrayType);
        assertSame(intArrayType, arrayType);
        componentType = arrayType.getComponentType();
        assertNotNull(componentType);
        assertSame(JPrimitiveType.INT, componentType);
        assertEquals("int[]", fieldType.getQualifiedSourceName());

        field = type.getField("someTypeArray");
        fieldType = field.getType();
        arrayType = fieldType.isArray();
        assertNotNull(arrayType);
        assertSame(someTypeArrayType, arrayType);
        componentType = arrayType.getComponentType();
        assertNotNull(componentType);
        assertSame(someType, componentType);
        assertEquals(getPackageName() + ".DefaultClass[]", fieldType.getQualifiedSourceName());

        field = type.getField("intArrayArray");
        fieldType = field.getType();
        arrayType = fieldType.isArray();
        assertNotNull(arrayType);
        assertSame(intArrayArrayType, arrayType);
        componentType = arrayType.getComponentType();
        assertNotNull(componentType);
        assertSame(intArrayType, arrayType.getComponentType());
        arrayType = (JArrayType) arrayType.getComponentType();
        assertSame(JPrimitiveType.INT, arrayType.getComponentType());
        assertEquals("int[][]", fieldType.getQualifiedSourceName());

      } else {
        // No need to check SomeType since there's already a DefaultClass
        // test.
      }
    }
  };

  protected static final CheckedJavaResource CU_GenericList = new CheckedJavaResource(
      GenericList.class) {
    @Override
    public void check(JClassType type) throws NotFoundException {
      assertNotNull(type.isGenericType());
    }
  };

  protected static final CheckedJavaResource CU_GenericOuterInner = new CheckedJavaResource(
      GenericOuter.class, "GenericOuter.Inner") {

    @Override
    public void check(JClassType type) {
      final String name = type.getSimpleSourceName();
      if ("GenericOuter".equals(name)) {
        checkOuter(type);
      } else {
        checkInner(type);
      }
    }

    public void checkInner(JClassType type) {
      assertEquals("Inner", type.getSimpleSourceName());
      assertEquals(getTypeName() + ".Inner", type.getQualifiedSourceName());
      assertEquals(getTypeName(), type.getEnclosingType().getQualifiedSourceName());
    }

    public void checkOuter(JClassType type) {
      assertEquals("GenericOuter", type.getSimpleSourceName());
      assertEquals(getTypeName(), type.getQualifiedSourceName());
      JClassType[] nested = type.getNestedTypes();
      assertEquals(1, nested.length);
      JClassType inner = nested[0];
      assertEquals(getTypeName() + ".Inner", inner.getQualifiedSourceName());
    }
  };

  protected static final CheckedJavaResource CU_List = new CheckedJavaResource(List.class) {

    @Override
    public void check(JClassType type) throws NotFoundException {
      assertNotNull(type.isGenericType());
      assertNotNull(type.isInterface());
      // TODO(zundel): This is a bug when building from source: interfaces
      // should not be default instantiable
      // assertNull(type.isDefaultInstantiable());
    }

    @Override
    public String getSource() {
      StringBuilder sb = new StringBuilder();
      sb.append("package java.util;\n");
      sb.append("public interface List<E> {\n");
      sb.append("}");
      return sb.toString();
    }
  };

  protected static final CheckedJavaResource CU_Object = new CheckedJavaResource(Object.class) {
    @Override
    public void check(JClassType type) {
      assertEquals("Object", type.getSimpleSourceName());
      assertEquals("java.lang.Object", type.getQualifiedSourceName());
    }

    @Override
    public String getSource() {
      StringBuffer sb = new StringBuffer();
      sb.append("package java.lang;");
      sb.append("public class Object { }");
      return sb.toString();
    }
  };

  protected static final CheckedJavaResource CU_OuterInner = new CheckedJavaResource(Outer.class,
      "Outer.Inner") {

    @Override
    public void check(JClassType type) {
      final String name = type.getSimpleSourceName();
      if ("Outer".equals(name)) {
        checkOuter(type);
      } else {
        checkInner(type);
      }
    }

    public void checkInner(JClassType type) {
      assertEquals("Inner", type.getSimpleSourceName());
      assertEquals(CU_OuterInner.getTypeName() + ".Inner", type.getQualifiedSourceName());
      assertEquals(CU_OuterInner.getTypeName(), type.getEnclosingType().getQualifiedSourceName());
    }

    public void checkOuter(JClassType type) {
      assertEquals("Outer", type.getSimpleSourceName());
      assertEquals(CU_OuterInner.getTypeName(), type.getQualifiedSourceName());
      JClassType[] nested = type.getNestedTypes();
      assertEquals(1, nested.length);
      JClassType inner = nested[0];
      assertEquals(CU_OuterInner.getTypeName() + ".Inner", inner.getQualifiedSourceName());
    }
  };

  protected static final CheckedJavaResource CU_ReferencesGenericListConstant =
      new CheckedJavaResource(ReferencesGenericListConstant.class) {
        @Override
        public void check(JClassType type) throws NotFoundException {
          assertEquals(getTypeName(), type.getQualifiedSourceName());
        }
      };

  protected static final CheckedJavaResource CU_ReferencesParameterizedTypeBeforeItsGenericFormHasBeenProcessed =
      new CheckedJavaResource(ReferencesParameterizedTypeBeforeItsGenericFormHasBeenProcessed.class) {

        @Override
        public void check(JClassType type) throws NotFoundException {

          JClassType[] intfs = type.getImplementedInterfaces();
          assertEquals(1, intfs.length);
          assertNotNull(intfs[0].isParameterized());
        }
      };

  protected static final CheckedJavaResource CU_String = new CheckedJavaResource(String.class) {
    @Override
    public void check(JClassType type) {
      assertEquals("String", type.getSimpleSourceName());
      assertEquals("java.lang.String", type.getQualifiedSourceName());
    }

    @Override
    public String getSource() {
      StringBuffer sb = new StringBuffer();
      sb.append("package java.lang;");
      sb.append("public class String { }");
      return sb.toString();
    }
  };

  protected static final CheckedJavaResource CU_Throwable =
      new CheckedJavaResource(Throwable.class) {

        @Override
        public void check(JClassType type) {
          assertEquals("Throwable", type.getSimpleSourceName());
          assertEquals("java.lang.Throwable", type.getQualifiedSourceName());
        }

        @Override
        public String getSource() {
          StringBuffer sb = new StringBuffer();
          sb.append("package java.lang;");
          sb.append("public class Throwable { }");
          return sb.toString();
        }
      };

  protected static final CheckedJavaResource CU_UnnestedImplementations = new CheckedJavaResource(
      Implementations.class, "Implementations.OuterImpl", "Implementations.InnerImpl") {
    @Override
    public void check(JClassType type) {
      if (type.getSimpleSourceName().equals("Implementations")) {
        assertEquals(getTypeName(), type.getQualifiedSourceName());
      }
    }
  };

  protected static void assertIsAssignable(JClassType from, JClassType to) {
    assertTrue("'" + from + "' should be assignable to '" + to + "'", from.isAssignableTo(to));
    assertTrue("'" + to + "' should be assignable from '" + from + "'", to.isAssignableFrom(from));
  }

  protected static void assertIsNotAssignable(JClassType from, JClassType to) {
    assertFalse(from + " should not be assignable to " + to, from.isAssignableTo(to));
    assertFalse(to + " should not be assignable to " + from, to.isAssignableFrom(from));
  }

  protected static void recordAssignability(Map<JClassType, Set<JClassType>> assignabilityMap,
      JClassType from, JClassType to) {
    Set<JClassType> set = assignabilityMap.get(from);
    if (set == null) {
      set = new HashSet<JClassType>();
      assignabilityMap.put(from, set);
    }
    set.add(to);
  }

  /**
   * Public so that this will be initialized before the CUs.
   */
  public final Map<String, CheckedJavaResource> publicTypeNameToTestCupMap =
      new HashMap<String, CheckedJavaResource>();

  protected CheckedJavaResource CU_ListAsField = new CheckedJavaResource(ListAsField.class) {
    @Override
    public void check(JClassType type) throws NotFoundException {
      assertNull(type.isGenericType());
      assertNull(type.getEnclosingType());
    }
  };

  protected CheckedJavaResource CU_MethodsAndParams = new CheckedJavaResource(Methods.class) {

    @Override
    public void check(JClassType type) throws NotFoundException {
      TypeOracle tio = type.getOracle();
      JMethod[] methods = type.getMethods();
      assertEquals(6, methods.length);
      JMethod method;
      JType[] thrownTypes;
      final JClassType javaLangObject = tio.findType("java.lang", "Object");
      final JClassType javaLangThrowable = tio.findType("java.lang", "Throwable");
      final JType[] noParamTypes = new JType[0];

      method = type.getMethod("returnsInt", noParamTypes);
      assertSame(JPrimitiveType.INT, method.getReturnType());
      assertEquals(0, method.getParameters().length);

      method = type.getMethod("returnsSomeType", noParamTypes);
      assertSame(javaLangObject, method.getReturnType());
      assertEquals(0, method.getParameters().length);

      method = type.getMethod("staticMethod", noParamTypes);
      assertSame(JPrimitiveType.VOID, method.getReturnType());
      assertEquals(0, method.getParameters().length);
      assertTrue(method.isStatic());

      method = type.getMethod("finalMethod", noParamTypes);
      assertSame(JPrimitiveType.VOID, method.getReturnType());
      assertEquals(0, method.getParameters().length);
      assertTrue(method.isFinal());

      try {
        method = type.getMethod("overloaded", noParamTypes);
        fail("expected throw");
      } catch (NotFoundException e) {
      }

      methods = type.getOverloads("overloaded");
      assertEquals(2, methods.length);
      for (JMethod element : methods) {
        assertEquals("overloaded", element.getName());
      }

      method = type.getMethod("overloaded", new JType[]{JPrimitiveType.INT, javaLangObject});
      assertSame(JPrimitiveType.VOID, method.getReturnType());
      thrownTypes = method.getThrows();
      assertEquals(1, thrownTypes.length);
      assertSame(javaLangThrowable, thrownTypes[0]);

      method = type.getMethod("overloaded", new JType[]{JPrimitiveType.INT, JPrimitiveType.CHAR});
      assertSame(javaLangObject, method.getReturnType());
      thrownTypes = method.getThrows();
      assertEquals(0, thrownTypes.length);
    }
  };

  protected CheckedJavaResource CU_NestedGenericInterfaces = new CheckedJavaResource(
      OuterInt.class, "OuterInt.InnerInt") {

    @Override
    public void check(JClassType type) {
      final String name = type.getSimpleSourceName();
      if ("OuterInt".equals(name)) {
        checkOuter(type);
      } else {
        checkInner(type);
      }
    }

    public void checkInner(JClassType type) {
      assertEquals("InnerInt", type.getSimpleSourceName());
      assertEquals(getTypeName() + ".InnerInt", type.getQualifiedSourceName());
      assertEquals(getTypeName(), type.getEnclosingType().getQualifiedSourceName());
    }

    public void checkOuter(JClassType type) {
      assertEquals("OuterInt", type.getSimpleSourceName());
      assertEquals(getTypeName(), type.getQualifiedSourceName());
      JClassType[] nested = type.getNestedTypes();
      assertEquals(1, nested.length);
      JClassType inner = nested[0];
      assertEquals(getTypeName() + ".InnerInt", inner.getQualifiedSourceName());
    }
  };

  protected final Set<Resource> resources = new LinkedHashSet<Resource>();

  protected TypeOracle typeOracle;

  public void checkTypes(JClassType[] types) throws NotFoundException {
    for (JClassType type : types) {
      check(type);

      JClassType[] nestedTypes = type.getNestedTypes();
      checkTypes(nestedTypes);
    }
  }

  /**
   * Tests which variant of AbstractRefrenceMap we want to store the map for
   * parameterizedTypes, arrayTypes, and wildCardTypes in TypeOracle. Note: this
   * test is manual because gc can be unreliable.
   */
  public void manualTestAbstractRefrenceMap() {

    /*
     * with a HARD -> WEAK map, verify that the entry remains if there is no
     * reference to key, but is deleted when the reference to value is gone
     */
    Map<Integer, Integer> simpleMap = new MapMaker().weakValues().makeMap();
    Integer bar = new Integer(42);
    simpleMap.put(new Integer(32), bar);
    Runtime.getRuntime().gc();
    assertEquals(1, simpleMap.size());
    bar = null;
    Runtime.getRuntime().gc();
    assertEquals(0, simpleMap.size());

    /*
     * with a WEAK -> WEAK map, verify that the entry is gone if there are no
     * references to either the key or the value.
     */
    simpleMap = new MapMaker().weakKeys().weakValues().makeMap();
    Map<Integer, Integer> reverseMap = new MapMaker().weakKeys().weakValues().makeMap();
    Integer foo = new Integer(32);
    bar = new Integer(42);
    simpleMap.put(foo, bar);
    reverseMap.put(bar, foo);
    Runtime.getRuntime().gc();
    assertEquals(1, simpleMap.size());
    assertEquals(1, reverseMap.size());
    bar = null;
    Runtime.getRuntime().gc();
    assertEquals(0, simpleMap.size());
    assertEquals(0, reverseMap.size());
  }

  @Override
  public void setUp() {
    resources.clear();
  }

  public void testAssignable() throws TypeOracleException, IOException {

    // Note: The order of adding resources is important for testing from byte
    // code
    addTestResource(CU_Object);
    addTestResource(CU_BaseInterface);
    addTestResource(CU_DerivedInterface);
    addTestResource(CU_OuterInner);
    addTestResource(CU_Derived);

    buildTypeOracle();

    Map<JClassType, Set<JClassType>> assignabilityMap = new HashMap<JClassType, Set<JClassType>>();
    JClassType obj = typeOracle.findType(CU_Object.getTypeName());
    assertNotNull(obj);

    JClassType inner = typeOracle.findType(CU_OuterInner.getTypeName() + ".Inner");
    assertNotNull(inner);

    JClassType derived = typeOracle.findType(CU_Derived.getTypeName());
    assertNotNull(derived);

    JClassType nested = typeOracle.findType(CU_Derived.getTypeName() + ".Nested");
    assertNotNull(nested);

    JClassType baseIntf = typeOracle.findType(CU_Derived.getPackageName() + ".BaseInterface");
    assertNotNull(baseIntf);

    JClassType derivedIntf = typeOracle.findType(CU_Derived.getPackageName() + ".DerivedInterface");
    assertNotNull(derivedIntf);

    recordAssignability(assignabilityMap, derivedIntf, baseIntf);
    recordAssignability(assignabilityMap, derived, inner);
    recordAssignability(assignabilityMap, nested, inner);
    recordAssignability(assignabilityMap, nested, derivedIntf);
    recordAssignability(assignabilityMap, nested, baseIntf);

    JClassType[] allTypes = typeOracle.getTypes();
    assertEquals(7, allTypes.length);

    for (JClassType fromType : allTypes) {
      for (JClassType toType : allTypes) {
        if (fromType == toType || toType == typeOracle.getJavaLangObject()) {
          assertIsAssignable(fromType, toType);
        } else {
          Set<JClassType> set = assignabilityMap.get(fromType);
          if (set != null && set.contains(toType)) {
            assertIsAssignable(fromType, toType);
          } else {
            assertIsNotAssignable(fromType, toType);
          }
        }
      }
    }
  }

  public void testAssimilation() throws TypeOracleException, IOException {
    addTestResource(CU_Object);
    addTestResource(CU_BeforeAssimilate);
    buildTypeOracle();
    assertEquals(2, typeOracle.getTypes().length);

    // Build onto an existing type oracle.
    addTestResource(CU_AfterAssimilate);
    buildTypeOracle();
    assertEquals(3, typeOracle.getTypes().length);
  }

  public void testBindToTypeScope() throws TypeOracleException, IOException {
    addTestResource(CU_Object);
    addTestResource(CU_BindToTypeScope);
    buildTypeOracle();
    JClassType[] types = typeOracle.getTypes();
    assertEquals(4, types.length);
  }

  public void testConstrainedField() throws TypeOracleException, IOException {
    addTestResource(CU_Object);
    addTestResource(CU_Throwable);
    addTestResource(CU_ConstrainedList);
    addTestResource(CU_ConstrainedListAsField);
    buildTypeOracle();

    // Get the types produced by the TypeOracle
    JClassType type = typeOracle.getType(CU_ConstrainedListAsField.getTypeName());
    assertNull(type.isParameterized());
    JField[] fields = type.getFields();
    assert (fields.length == 1);
    JField field = type.getField("field");
    assertNotNull(field);
    JType fieldType = field.getType();
    JParameterizedType fieldParamType = fieldType.isParameterized();
    assertNotNull(fieldParamType);
    assertNull(fieldParamType.getEnclosingType());
    JGenericType baseType = fieldParamType.getBaseType();
    assertNotNull(baseType);
    assertEquals(CU_ConstrainedList.getTypeName(), baseType.getQualifiedSourceName());
    JClassType[] typeArgs = fieldParamType.getTypeArgs();
    assertEquals(1, typeArgs.length);
    JWildcardType wildcard = typeArgs[0].isWildcard();
    assertNotNull(wildcard);
    JClassType upperBound = wildcard.getUpperBound();
    assertEquals("Throwable", upperBound.getSimpleSourceName());
  }

  public void testConstrainedList() throws TypeOracleException, IOException, InterruptedException {
    addTestResource(CU_Object);
    addTestResource(CU_Throwable);
    addTestResource(CU_ConstrainedList);

    buildTypeOracle();

    JClassType type = typeOracle.getType(CU_ConstrainedList.getPackageName() + ".ConstrainedList");
    JClassType throwable = typeOracle.getType("java.lang.Throwable");
    assertNotNull(throwable);
    assertEquals("Throwable", throwable.getSimpleSourceName());

    assertNull(type.isParameterized());
    JGenericType genericType = type.isGenericType();
    assertNotNull(genericType);
    JTypeParameter[] typeParams = genericType.getTypeParameters();
    assertEquals(1, typeParams.length);
    assertEquals(throwable, typeParams[0].getBaseType());
    assertEquals(type, typeParams[0].getDeclaringClass());
    JClassType[] bounds = typeParams[0].getBounds();
    assertEquals(1, bounds.length);
    assertEquals(throwable, bounds[0]);
  }

  public void testConstructors() throws TypeOracleException, IOException {
    addTestResource(CU_Object);
    buildTypeOracle();
    JClassType[] types = typeOracle.getTypes();
    assertEquals(1, types.length);
    JClassType objectType = types[0];
    assertEquals("Object", objectType.getSimpleSourceName());
    JConstructor[] ctors = objectType.getConstructors();
    assertEquals(1, ctors.length);
    JConstructor defaultCtor = ctors[0];
    assertEquals("Object", defaultCtor.getName());
    assertEquals(0, defaultCtor.getParameters().length);
  }

  public void testDefaultClass() throws TypeOracleException {
    addTestResource(CU_Object);
    addTestResource(CU_DefaultClass);
    buildTypeOracle();
    JClassType[] types = typeOracle.getTypes();
    assertEquals(2, types.length);

  }

  public void testEnclosingGenericType() throws TypeOracleException {
    addTestResource(CU_Object);
    addTestResource(CU_String);
    addTestResource(CU_List);
    addTestResource(CU_GenericOuterInner);
    addTestResource(CU_ExtendsGenericOuterInner);

    buildTypeOracle();

    // Get the types produced by the TypeOracle
    JClassType outer = typeOracle.getType(CU_GenericOuterInner.getPackageName() + ".GenericOuter");
    JClassType inner =
        typeOracle.getType(CU_GenericOuterInner.getPackageName() + ".GenericOuter.Inner");

    assertNull(outer.getEnclosingType());
    assertEquals(outer, inner.getEnclosingType());
    assertNull(inner.isParameterized());
    assertNotNull(outer.isGenericType());
    assertNotNull(inner.isGenericType());
    JField[] fields = inner.getFields();
    assertEquals(fields.length, 2);
    JField field = inner.getField("field");
    assertNotNull(field);
    JType fieldType = field.getType();
    JTypeParameter typeParam = fieldType.isTypeParameter();
    assertNotNull(typeParam);
    assertEquals("V", typeParam.getName());
    JClassType[] bounds = typeParam.getBounds();
    assertEquals(1, bounds.length);
    assertEquals(typeOracle.getJavaLangObject(), bounds[0]);

    JClassType extendsOuter =
        typeOracle.getType(CU_GenericOuterInner.getPackageName() + ".ExtendsGenericOuter");
    JClassType extendsInner =
        typeOracle.getType(CU_GenericOuterInner.getPackageName()
            + ".ExtendsGenericOuter.ExtendsInner");
    assertNull(extendsOuter.getEnclosingType());
    assertEquals(extendsOuter, extendsInner.getEnclosingType());

    JClassType outerSuper = extendsOuter.getSuperclass();
    JParameterizedType outerSuperParam = outerSuper.isParameterized();
    assertNotNull(outerSuperParam);
    assertEquals(outer, outerSuperParam.getBaseType());
    JClassType innerSuper = extendsInner.getSuperclass();
    assertEquals("GenericOuter.Inner", innerSuper.getName());
    field = inner.getField("field");
    assertNotNull(field);

    /*
     * This test fails for OpenJDK compiled classes compared to JDT classes. The
     * reason is that the superclass of this type doesn't contain a type
     * signature for OpenJDK byte code.
     * 
     * Commenting out this code for the tests: I'm not sure any generators
     * depend on this subtle difference.
     */
    // assertEquals("java.lang.String",
    // field.getType().getQualifiedSourceName());
    // JParameterizedType innerSuperParam = innerSuper.isParameterized();
    // assertNotNull(innerSuperParam);
    // assertEquals(inner, innerSuperParam.getBaseType());
  }

  public void testEnclosingType() throws TypeOracleException, IOException {
    addTestResource(CU_Object);
    addTestResource(CU_List);
    addTestResource(CU_ListAsField);

    buildTypeOracle();

    JClassType listAsField = typeOracle.getType(CU_ListAsField.getTypeName());
    assertNotNull(listAsField);
    assertNull(listAsField.isParameterized());
    JField field = listAsField.getField("field");
    assertNotNull(field);
    JType fieldType = field.getType();
    JParameterizedType fieldParamType = fieldType.isParameterized();
    assertNotNull(fieldParamType);
    assertNull(fieldParamType.getEnclosingType());
    JGenericType baseType = fieldParamType.getBaseType();
    assertNotNull(baseType);
    assertEquals("java.util.List", baseType.getQualifiedSourceName());
  }

  public void testFieldsAndTypes() throws TypeOracleException {
    addTestResource(CU_Object);
    addTestResource(CU_DefaultClass);
    addTestResource(CU_FieldsAndTypes);
    buildTypeOracle();
    JClassType[] types = typeOracle.getTypes();
    assertEquals(3, types.length);
  }

  // Check that anonymous classes are not reflected in TypeOracle
  public void testLocal() throws TypeOracleException {
    addTestResource(CU_Object);
    addTestResource(CU_EnclosingLocalClass);
    buildTypeOracle();
    JClassType[] types = typeOracle.getTypes();
    assertEquals(2, types.length);
  }

  public void testLocalWithSynthetic() throws TypeOracleException {
    addTestResource(CU_Object);
    addTestResource(CU_EnclosingLocalWithMember);
    buildTypeOracle();
    JClassType[] types = typeOracle.getTypes();
    assertEquals(2, types.length);
  }

  public void testMethodsAndParams() throws TypeOracleException {
    addTestResource(CU_Object);
    addTestResource(CU_Throwable);
    addTestResource(CU_MethodsAndParams);
    buildTypeOracle();
    // Throwable has nested classes in JDK 7, so we need to ignore them
    checkGetTypes("Methods", "Object", "Throwable");
  }

  public void testOuterInner() throws TypeOracleException {
    addTestResource(CU_Object);
    addTestResource(CU_OuterInner);
    buildTypeOracle();
    JClassType[] types = typeOracle.getTypes();
    assertEquals(3, types.length);
    JClassType outer = null;
    for (JClassType type : types) {
      if ("Outer".equals(type.getSimpleSourceName())) {
        outer = type;
        break;
      }
    }
    assertNotNull(outer);
    assertEquals("Outer", outer.getSimpleSourceName());
    JClassType superclass = outer.getSuperclass();
    JType objectRef = typeOracle.getJavaLangObject();
    assertNotNull(objectRef);
    assertEquals(objectRef, superclass);
  }

  /**
   * Tests that we can build nested parameterized types even if that happens
   * while the type oracle is being built. This test assumes that
   * CU_ReferencesParameterizedTypeBeforeItsGenericFormHasBeenProcessed will
   * cause a parameterized form of CU_DeclaresInnerGenericInterface to be
   * created before the type oracle has had a chance to resolve
   * CU_DeclaresInnerGenericInterface.
   */
  public void testParameterizedTypeBuildDependencies() throws TypeOracleException {
    addTestResource(CU_ReferencesParameterizedTypeBeforeItsGenericFormHasBeenProcessed);
    // Intentionally omitting the ExtendsParameterizedInterface resource
    // addResource(CU_ExtendsParameterizedInterface);
    addTestResource(CU_DeclaresInnerGenericInterface);
    addTestResource(CU_Object);

    buildTypeOracle();

    assertNull(typeOracle.findType(CU_ExtendsParameterizedInterface.getTypeName()));
  }

  /**
   * Test that modifying a type will cause any types that depend on it to be
   * rebuilt by the TypeOracleBuilder during a refresh.
   * 
   * @throws UnableToCompleteException
   * @throws NotFoundException
   * @throws IOException
   */
  public void testRefresh() throws TypeOracleException {
    addTestResource(CU_Object);
    addTestResource(CU_ExtendsGenericList);
    addTestResource(CU_GenericList);
    addTestResource(CU_ReferencesGenericListConstant);

    buildTypeOracle();

    // Get the types produced by the TypeOracle
    JClassType extendsGenericListType = typeOracle.getType(CU_ExtendsGenericList.getTypeName());
    JClassType genericListType = typeOracle.getType(CU_GenericList.getTypeName());
    JClassType referencesGenericListConstantType =
        typeOracle.getType(CU_ReferencesGenericListConstant.getTypeName());

    /*
     * Invalidate CU_GenericList and simulate a refresh. This should cause
     * anything that depends on GenericList to be rebuilt by the type oracle.
     */
    CU_GenericList.touch();
    buildTypeOracle();

    assertNotSame(genericListType.getQualifiedSourceName() + "; ", typeOracle
        .getType(CU_GenericList.getTypeName()), genericListType);
    assertNotSame(extendsGenericListType.getQualifiedSourceName() + "; ", typeOracle
        .getType(CU_ExtendsGenericList.getTypeName()), extendsGenericListType);

    /*
     * Make sure that referencing a constant field will cause a type to be
     * rebuilt if the constant changes.
     */
    assertNotSame(referencesGenericListConstantType.getQualifiedSourceName(), typeOracle
        .getType(CU_ReferencesGenericListConstant.getTypeName()), referencesGenericListConstantType);
  }

  public void testTypeParams() throws TypeOracleException {
    addTestResource(CU_Object);
    addTestResource(CU_NestedGenericInterfaces);
    addTestResource(CU_UnnestedImplementations);
    buildTypeOracle();
    JClassType[] types = typeOracle.getTypes();
    assertEquals(6, types.length);
    JClassType type = typeOracle.findType(CU_UnnestedImplementations.getTypeName() + ".InnerImpl");
    assertNotNull(type);
    JClassType[] interfaces = type.getImplementedInterfaces();
    assertEquals(1, interfaces.length);
    JClassType intf = interfaces[0];
    JParameterizedType intfParam = intf.isParameterized();
    assertNotNull(intfParam);
    JClassType intfEnclosing = intf.getEnclosingType();
    assertNotNull(intfEnclosing.isRawType());
  }

  /**
   * Creates a {@link Resource} and adds it the set of resources.
   * 
   * @throws UnableToCompleteException
   */
  protected void addResource(String qualifiedTypeName, CharSequence source) {
    resources.add(new StaticJavaResource(qualifiedTypeName, source));
  }

  protected abstract void buildTypeOracle() throws TypeOracleException;

  /**
   * Tweak this if you want to see the log output.
   */
  protected TreeLogger createTreeLogger() {
    boolean reallyLog = false;
    if (reallyLog) {
      AbstractTreeLogger logger = new PrintWriterTreeLogger();
      logger.setMaxDetail(TreeLogger.ALL);
      return logger;
    } else {
      return TreeLogger.NULL;
    }
  }

  private void addTestResource(CheckedJavaResource checkedResource) {
    resources.add(checkedResource);
    for (String typeName : checkedResource.getTypeNames()) {
      register(typeName, checkedResource);
    }
  }

  private void check(JClassType classInfo) throws NotFoundException {
    final String qName = classInfo.getQualifiedSourceName();
    CheckedJavaResource cup = publicTypeNameToTestCupMap.get(qName);
    if (cup != null) {
      cup.check(classInfo);
    }
  }

  private void checkGetTypes(String... expectedOuterClassNames) {
    Set<String> expected = new HashSet<String>();
    expected.addAll(Arrays.asList(expectedOuterClassNames));

    Set<String> found = new HashSet<String>();

    for (JClassType type : typeOracle.getTypes()) {
      String name = type.getName();
      if (name.indexOf('.') > 0) {
        name = name.substring(0, name.indexOf('.'));
      }
      if (!expected.contains(name)) {
        fail("getTypes() returned an unexpected class: " + type.getName());
      }
      found.add(name);
    }

    assertEquals(expected, found);
  }

  private void register(String qualifiedTypeName, CheckedJavaResource cup) {
    assertFalse(publicTypeNameToTestCupMap.containsKey(qualifiedTypeName));
    publicTypeNameToTestCupMap.put(qualifiedTypeName, cup);
  }
}
