/*
 * 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.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.CompilationUnitTypeOracleUpdater.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 com.google.gwt.thirdparty.guava.common.io.BaseEncoding;

import junit.framework.TestCase;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
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 TypeOracleUpdater.
 *
 * 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 TypeOracleUpdaterTestBase extends TestCase {

  /**
   * A Java resource that provides a check() method.
   */
  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;
    }
  }

  /**
   * A mutable Java resource.
   */
  protected static abstract class MutableJavaResource extends MockJavaResource {
    private static byte[] getByteCode(Class<?> aClass) {
      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.
     */
    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() {
      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) {
        source = getSourceFromClasspath();
        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(".", "/"),
              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() {
      StringBuilder sb = new StringBuilder();
      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());
    }
  };

  /**
   * Not sourced off disk like the others since some build systems refuse files with $ in the name.
   */
  protected static final MutableJavaResource CU_PseudoInner = new MutableJavaResource(
      "com.google.gwt.dev.javac.mediatortest",
      "com.google.gwt.dev.javac.mediatortest.Pseudo$Inner") {

        @Override
        public CharSequence getContent() {
          StringBuilder code = new StringBuilder();
          code.append("package com.google.gwt.dev.javac.mediatortest;\n");
          code.append("public class Pseudo$Inner {}\n");
          return code;
        }

        @Override
        public TypeData[] getTypeData() {
          byte[] classBytes = BaseEncoding.base16().decode(
              "CAFEBABE000000330010070002010032636F6D2F676F6F676C652F6777742F6465762F6A617661632"
              + "F6D65646961746F72746573742F50736575646F24496E6E65720700040100106A6176612F6C616E672"
              + "F4F626A6563740100063C696E69743E010003282956010004436F64650A000300090C0005000601000"
              + "F4C696E654E756D6265725461626C650100124C6F63616C5661726961626C655461626C65010004746"
              + "869730100344C636F6D2F676F6F676C652F6777742F6465762F6A617661632F6D65646961746F72746"
              + "573742F50736575646F24496E6E65723B01000A536F7572636546696C6501001150736575646F24496"
              + "E6E65722E6A617661002100010003000000000001000100050006000100070000002F0001000100000"
              + "0052AB70008B100000002000A00000006000100000003000B0000000C000100000005000C000D00000"
              + "001000E00000002000F");
          TypeData classData = new TypeData("com.google.gwt.dev.javac.mediatortest", "Pseudo$Inner",
              "com/google/gwt/dev/javac/mediatortest/Pseudo$Inner", classBytes,
              System.currentTimeMillis());
          return new TypeData[] {classData};
        }
      };

  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() {
      StringBuilder sb = new StringBuilder();
      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() {
          StringBuilder sb = new StringBuilder();
          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 {
    // 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 {
    addTestResource(CU_Object);
    addTestResource(CU_BeforeAssimilate);
    buildTypeOracle();

    assertNotNull(typeOracle.findType(CU_Object.getTypeName()));
    assertNotNull(typeOracle.findType(CU_BeforeAssimilate.getTypeName()));
    assertEquals(2, typeOracle.getTypes().length);

    // Build onto an existing type oracle.
    addTestResource(CU_AfterAssimilate);
    buildTypeOracle();

    assertNotNull(typeOracle.findType(CU_Object.getTypeName()));
    assertNotNull(typeOracle.findType(CU_BeforeAssimilate.getTypeName()));
    assertNotNull(typeOracle.findType(CU_AfterAssimilate.getTypeName()));
    assertEquals(3, typeOracle.getTypes().length);
  }

  public void testBindToTypeScope() throws TypeOracleException {
    addTestResource(CU_Object);
    addTestResource(CU_BindToTypeScope);
    buildTypeOracle();

    assertNotNull(typeOracle.findType(CU_Object.getTypeName()));
    assertNotNull(typeOracle.findType("com.google.gwt.dev.javac.mediatortest.BindToTypeScope"));
    assertNotNull(
        typeOracle.findType("com.google.gwt.dev.javac.mediatortest.BindToTypeScope.DerivedObject"));
    assertNotNull(
        typeOracle.findType("com.google.gwt.dev.javac.mediatortest.BindToTypeScope.Object"));
    assertEquals(4, typeOracle.getTypes().length);
  }

  public void testConstrainedField() throws TypeOracleException {
    addTestResource(CU_Object);
    addTestResource(CU_ConstrainedList);
    addTestResource(CU_ConstrainedListAsField);
    addTestResource(CU_Throwable);
    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 {
    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 {
    addTestResource(CU_Object);
    buildTypeOracle();
    JClassType objectType = typeOracle.findType(CU_Object.getTypeName());
    assertNotNull(objectType);
    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();

    assertNotNull(typeOracle.findType(CU_Object.getTypeName()));
    assertNotNull(typeOracle.findType(CU_DefaultClass.getTypeName()));
    assertEquals(2, typeOracle.getTypes().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 {
    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();

    assertNotNull(typeOracle.findType(CU_Object.getTypeName()));
    assertNotNull(typeOracle.findType(CU_DefaultClass.getTypeName()));
    assertNotNull(typeOracle.findType(CU_FieldsAndTypes.getTypeName()));
    assertEquals(3, typeOracle.getTypes().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();

    assertNotNull(typeOracle.findType(CU_EnclosingLocalWithMember.getTypeName()));
    assertNotNull(typeOracle.findType(CU_Object.getTypeName()));
    assertEquals(2, typeOracle.getTypes().length);
  }

  public void testMethodsAndParams() throws TypeOracleException {
    addTestResource(CU_Object);
    addTestResource(CU_Throwable);
    addTestResource(CU_MethodsAndParams);
    buildTypeOracle();

    assertNotNull(typeOracle.findType(CU_Object.getTypeName()));
    assertNotNull(typeOracle.findType(CU_Throwable.getTypeName()));
    assertNotNull(typeOracle.findType(CU_MethodsAndParams.getTypeName()));
    // Can't make an assertion about the # of loaded types in this test since the results are
    // different for source versus bytecode.
  }

  public void testOuterInner() throws TypeOracleException {
    addTestResource(CU_Object);
    addTestResource(CU_OuterInner);
    buildTypeOracle();

    assertNotNull(typeOracle.findType(CU_Object.getTypeName()));
    assertNotNull(typeOracle.findType(CU_OuterInner.getTypeName()));
    JClassType outer = typeOracle.findType("com.google.gwt.dev.javac.mediatortest.Outer");
    assertEquals(3, typeOracle.getTypes().length);
    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()));
  }

  public void testPseudoInnerSourceName() throws TypeOracleException {
    addTestResource(CU_Object);
    resources.add(CU_PseudoInner);
    buildTypeOracle();

    JClassType pseudoInnerType = typeOracle.findType(CU_PseudoInner.getTypeName());
    assertNotNull(pseudoInnerType);
    assertEquals("Pseudo$Inner", pseudoInnerType.getSimpleSourceName());
    assertEquals(CU_PseudoInner.getTypeName(), pseudoInnerType.getQualifiedSourceName());
  }

  /**
   * Test that modifying a type will cause any types that depend on it to be
   * rebuilt by the TypeOracleUpdater during a refresh.
   *
   * @throws NotFoundException
   */
  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();

    assertNotNull(typeOracle.findType(CU_Object.getTypeName()));
    assertNotNull(typeOracle.findType(CU_NestedGenericInterfaces.getTypeName()));
    assertNotNull(typeOracle.findType("com.google.gwt.dev.javac.mediatortest.OuterInt"));
    assertNotNull(typeOracle.findType(CU_UnnestedImplementations.getTypeName()));
    assertNotNull(typeOracle.findType(CU_UnnestedImplementations.getTypeName() + ".OuterImpl"));

    JClassType innerImplType =
        typeOracle.findType(CU_UnnestedImplementations.getTypeName() + ".InnerImpl");
    assertNotNull(innerImplType);
    assertEquals(6, typeOracle.getTypes().length);
    JClassType[] interfaces = innerImplType.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.
   */
  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;
    }
  }

  protected 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 register(String qualifiedTypeName, CheckedJavaResource cup) {
    assertFalse(publicTypeNameToTestCupMap.containsKey(qualifiedTypeName));
    publicTypeNameToTestCupMap.put(qualifiedTypeName, cup);
  }
}
