/* * Copyright 2009 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.jjs; import com.google.gwt.dev.MinimalRebuildCache; import com.google.gwt.dev.jjs.ast.JArrayType; import com.google.gwt.dev.jjs.ast.JClassType; import com.google.gwt.dev.jjs.ast.JDeclaredType; import com.google.gwt.dev.jjs.ast.JInterfaceType; import com.google.gwt.dev.jjs.ast.JProgram; import com.google.gwt.dev.jjs.ast.JReferenceType; import com.google.gwt.dev.jjs.ast.JTypeOracle; import com.google.gwt.dev.jjs.ast.JTypeOracle.ImmediateTypeRelations; import com.google.gwt.dev.jjs.ast.JTypeOracle.StandardTypes; import com.google.gwt.thirdparty.guava.common.base.Function; import com.google.gwt.thirdparty.guava.common.collect.Lists; import com.google.gwt.thirdparty.guava.common.collect.Sets; import junit.framework.TestCase; import org.junit.Assert; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; /** * Test basic operations on the types used by the JJS compiler. See * {@link com.google.gwt.dev.jjs.ast.JType}. */ public class JjsTypeTest extends TestCase { private JArrayType arrayOfA; private JArrayType arrayOfArrayOfB; private JReferenceType arrayOfArrayOfInt; private JArrayType arrayOfB; private JArrayType arrayOfBase; private JArrayType arrayOfBSub; private JArrayType arrayOfJso1; private JArrayType arrayOfJso2; private JArrayType arrayOfIntfJ; private JArrayType arrayOfIntfK; private JArrayType arrayOfJso; private JArrayType arrayOfC; private JArrayType arrayOfIntfSerializable; private JArrayType arrayOfIntfClonable; private JReferenceType arrayOfInt; private JArrayType arrayOfIntfI; private JArrayType arrayOfIntfIBase; private JArrayType arrayOfObject; private JClassType classA; private JClassType classArrayList; private JClassType classB; private JClassType classBase; private JReferenceType classBaseNn; private JReferenceType classBnn; private JClassType classBSub; private JClassType classC; private JClassType classJso; private JClassType classJso1; private JClassType classJso2; private JClassType classFinalJso1; private JClassType classFinalJso2; private JClassType classObject; private JClassType classString; private JReferenceType intfCloneable; private JInterfaceType intfCollection; private JInterfaceType intfI; private JInterfaceType intfIBase; private JInterfaceType intfIterable; private JInterfaceType intfJ; private JInterfaceType intfK; private JInterfaceType intfL; private JInterfaceType intfList; private JReferenceType intfSerializable; private JProgram program; private SourceInfo synthSource; private JReferenceType typeNull; private JTypeOracle typeOracle; private JArrayType arrayOfArrayOfBase; private JArrayType arrayOfArrayOfObject; private JArrayType arrayOfArrayOfIntfI; private JArrayType arrayOfArrayOfIntfIBase; private static final Collection<String> EMPTY_LIST = Collections.<String>emptySet(); public void testCrossCasts() { JClassType[] jsoClasses = new JClassType[] { classJso, classJso1, classJso2, classFinalJso1, classFinalJso2 }; for (JClassType thisJsoClass : jsoClasses) { for (JClassType thatJsoClass : jsoClasses) { assertCrossCasts(thisJsoClass, thatJsoClass); } } } public void testCastFailsTrivially() { assertShouldFailTrivially(classBnn, typeNull); assertShouldNotFailTrivially(classBSub, classB); assertShouldNotFailTrivially(classB, classBSub); assertShouldNotFailTrivially(classB, classBnn); assertShouldNotFailTrivially(classBnn, classB); assertShouldNotFailTrivially(classB, classB); assertShouldNotFailTrivially(classObject, arrayOfB); assertShouldFailTrivially(arrayOfA, arrayOfArrayOfB); assertShouldNotFailTrivially(arrayOfObject, arrayOfArrayOfB); assertShouldNotFailTrivially(arrayOfB, arrayOfBSub); assertShouldNotFailTrivially(classBase, intfI); assertShouldFailTrivially(classA, intfJ); assertShouldNotFailTrivially(intfIBase, intfI); assertShouldNotFailTrivially(intfIBase, classBase); assertShouldFailTrivially(intfJ, classA); assertShouldNotFailTrivially(arrayOfA, intfSerializable); assertShouldNotFailTrivially(intfSerializable, arrayOfA); assertShouldNotFailTrivially(arrayOfA, intfCloneable); assertShouldNotFailTrivially(intfCloneable, arrayOfA); assertShouldNotFailTrivially(intfList, intfIterable); assertShouldNotFailTrivially(classArrayList, intfIterable); assertShouldNotFailTrivially(classJso1, classJso2); assertShouldNotFailTrivially(classJso2, classJso1); assertShouldNotFailTrivially(classJso1, intfK); assertShouldNotFailTrivially(intfK, classJso1); assertShouldNotFailTrivially(intfJ, intfK); assertShouldNotFailTrivially(intfK, intfJ); assertShouldNotFailTrivially(classB, intfL); assertShouldFailTrivially(classB.strengthenToExact(), intfL); } public void testCastSucceedsTrivially() { assertShouldSucceedTrivially(classB, classB); assertShouldSucceedTrivially(classBSub, classB); assertShouldNotSucceedTrivially(classB, classBSub); assertShouldNotSucceedTrivially(classC, classA); assertShouldNotSucceedTrivially(classA, classC); assertShouldSucceedTrivially(classB, intfI); assertShouldNotSucceedTrivially(intfI, classB); assertShouldSucceedTrivially(classB, classObject); assertShouldNotSucceedTrivially(classObject, classB); assertShouldSucceedTrivially(classB, intfI); assertShouldNotSucceedTrivially(intfI, classB); assertShouldSucceedTrivially(classBnn, classB); assertShouldNotSucceedTrivially(classB, classBnn); assertShouldSucceedTrivially(typeNull, classB); assertShouldNotSucceedTrivially(classB, typeNull); assertShouldSucceedTrivially(arrayOfA, classObject); assertShouldSucceedTrivially(arrayOfBSub, arrayOfB); assertShouldNotSucceedTrivially(arrayOfB, arrayOfBSub); assertShouldNotSucceedTrivially(arrayOfA, arrayOfB); assertShouldNotSucceedTrivially(arrayOfB, arrayOfA); assertShouldNotSucceedTrivially(arrayOfArrayOfB, arrayOfB); assertShouldNotSucceedTrivially(arrayOfB, arrayOfArrayOfB); assertShouldSucceedTrivially(arrayOfArrayOfB, arrayOfObject); assertShouldNotSucceedTrivially(arrayOfObject, arrayOfArrayOfB); assertShouldSucceedTrivially(classJso1, classJso); assertShouldSucceedTrivially(arrayOfA, intfSerializable); assertShouldNotSucceedTrivially(intfSerializable, arrayOfA); assertShouldSucceedTrivially(arrayOfA, intfCloneable); assertShouldNotSucceedTrivially(intfCloneable, arrayOfA); /* * Test that two types cannot both be trivially castable to each other, * unless they are the same type. */ for (JReferenceType type1 : severalTypes()) { for (JReferenceType type2 : severalTypes()) { if (type1 != type2) { assertFalse(type1.toString() + " and " + type2 + " should not be castable to each other", typeOracle.castSucceedsTrivially(type1, type2) && typeOracle.castSucceedsTrivially(type2, type1)); } } } } public void testGeneralizeTypes() { assertSame(classA, generalizeTypes(classA, classA)); assertSame(classB, generalizeTypes(classB, classBnn)); assertSame(classB, generalizeTypes(classBnn, classB)); assertSame(classBaseNn, generalizeTypes(classBnn, classBaseNn)); assertSame(classB, generalizeTypes(classB, typeNull)); assertSame(classB, generalizeTypes(typeNull, classB)); assertSame(intfIBase, generalizeTypes(intfI, intfIBase)); assertSame(intfIBase, generalizeTypes(intfIBase, intfI)); assertSame(classObject, generalizeTypes(intfJ, intfI)); assertSame(classObject, generalizeTypes(arrayOfB, arrayOfInt)); assertSame(classObject, generalizeTypes(arrayOfC, arrayOfArrayOfB)); assertSame(arrayOfObject, generalizeTypes(arrayOfC, arrayOfB)); assertSame(arrayOfObject, generalizeTypes(arrayOfObject, arrayOfArrayOfInt)); assertSame(intfI, generalizeTypes(classB, intfI)); assertSame(classObject, generalizeTypes(classB, intfJ)); assertSame(classObject, generalizeTypes(intfI, arrayOfInt)); assertSame(intfSerializable, generalizeTypes(intfSerializable, arrayOfA)); assertSame(intfCloneable, generalizeTypes(intfCloneable, arrayOfA)); for (JReferenceType type1 : severalTypes()) { for (JReferenceType type2 : severalTypes()) { JReferenceType generalized = generalizeTypes(type1, type2); assertShouldSucceedTrivially(type1, generalized); assertShouldSucceedTrivially(type2, generalized); } } } public void testCastableDestinationTypes() { assertCastableDestinationTypes(classObject, classObject); assertCastableDestinationTypes(classString, classString, classObject); assertCastableDestinationTypes(classJso, classJso, classObject); assertCastableDestinationTypes(intfSerializable, intfSerializable, classObject); assertCastableDestinationTypes(intfCloneable, intfCloneable, classObject); assertCastableDestinationTypes(intfIBase, intfIBase, classObject); assertCastableDestinationTypes(intfI, intfI, intfIBase, classObject); assertCastableDestinationTypes(intfJ, intfJ, classObject); assertCastableDestinationTypes(intfK, intfK, classObject); assertCastableDestinationTypes(classBase, classBase, classObject); assertCastableDestinationTypes(classA, classA, classObject, classBase); assertCastableDestinationTypes(classB, classB, classObject, classBase, intfIBase, intfI); assertCastableDestinationTypes(classC, classC, classObject, intfIBase, intfI); assertCastableDestinationTypes(classBSub, classBSub, classObject, classBase, classB, intfIBase, intfI, intfL); assertCastableDestinationTypes(classJso1, classObject, classJso, intfJ); assertCastableDestinationTypes(classJso2, classObject, classJso, intfK); assertCastableDestinationTypes(arrayOfJso, classObject, intfCloneable, intfSerializable, arrayOfJso, arrayOfObject); assertCastableDestinationTypes(arrayOfJso1, classObject, intfCloneable, intfSerializable, arrayOfJso, arrayOfObject, arrayOfIntfJ); assertCastableDestinationTypes(arrayOfJso2, classObject, intfCloneable, intfSerializable, arrayOfJso, arrayOfObject, arrayOfIntfK); assertCastableDestinationTypes(intfIterable, intfIterable, classObject); assertCastableDestinationTypes(intfCollection, intfCollection, intfIterable, classObject); assertCastableDestinationTypes(intfList, intfList, intfIterable, intfCollection, classObject); assertCastableDestinationTypes(classArrayList, classArrayList, intfList, classObject, intfIterable, intfCollection); assertCastableDestinationTypes(arrayOfB, arrayOfB, arrayOfBase, arrayOfObject, arrayOfIntfI, arrayOfIntfIBase, classObject, arrayOfObject, intfCloneable, intfSerializable); assertCastableDestinationTypes(arrayOfArrayOfB, arrayOfArrayOfB, arrayOfArrayOfBase, arrayOfArrayOfObject, arrayOfArrayOfIntfI, arrayOfArrayOfIntfIBase, classObject, arrayOfObject, intfCloneable, arrayOfIntfClonable, intfSerializable, arrayOfIntfSerializable); assertCastableDestinationTypes(arrayOfInt, arrayOfInt, classObject, intfCloneable, intfSerializable); intfCollection = createInterface("java.util.Collection"); program.typeOracle.computeBeforeAST(StandardTypes.createFrom(program), program.getDeclaredTypes(), Sets.<JDeclaredType> newHashSet(classArrayList, intfList, intfCollection, classObject), Lists.newArrayList(intfIterable.getName())); assertCastableDestinationTypes(intfCollection, intfCollection, classObject); assertCastableDestinationTypes(intfList, intfList, intfCollection, classObject); assertCastableDestinationTypes(classArrayList, classArrayList, intfList, classObject, intfCollection); classA = createClass("A", classObject, false, false); program.typeOracle.computeBeforeAST(StandardTypes.createFrom(program), program.getDeclaredTypes(), Sets.<JDeclaredType> newHashSet(classA, classObject), Lists.newArrayList(classBase.getName())); assertCastableDestinationTypes(classA, classA, classObject); JClassType classASub = createClass("ASub", classA, false, false); program.typeOracle.computeBeforeAST(StandardTypes.createFrom(program), program.getDeclaredTypes(), Sets.<JDeclaredType> newHashSet(classASub, classA, classObject), EMPTY_LIST); assertCastableDestinationTypes(classASub, classASub, classA, classObject); } public void testJavahSignatures() { for (JReferenceType type : severalTypes()) { assertSignaturesMatch(type, new Function<JReferenceType, String>() { @Override public String apply(JReferenceType type) { return type.getJavahSignatureName(); } }); } } public void testJsniSignatures() { for (JReferenceType type : severalTypes()) { assertSignaturesMatch(type, new Function<JReferenceType, String>() { @Override public String apply(JReferenceType type) { return type.getJsniSignatureName(); } }); } } public void testStrongerType() { assertSame(classA, strongerType(classA, classA)); assertSame(classBnn, strongerType(classB, classBnn)); assertSame(classB, strongerType(classB, classBase)); assertSame(classB, strongerType(classBase, classB)); assertSame(intfI, strongerType(intfI, intfJ)); assertSame(arrayOfA, strongerType(intfSerializable, arrayOfA)); assertSame(arrayOfA, strongerType(intfCloneable, arrayOfA)); } public void testUpdateTypeInformation_JSODualImpl() { program.typeOracle.computeBeforeAST(StandardTypes.createFrom(program), program.getDeclaredTypes(), program.getModuleDeclaredTypes(), EMPTY_LIST); Assert.assertFalse(program.typeOracle.isDualJsoInterface(intfJ)); JClassType javaIntfImplementor = createClass("JavaImplementor", classObject, false, false); javaIntfImplementor.addImplements(intfJ); program.typeOracle.computeBeforeAST(StandardTypes.createFrom(program), program.getDeclaredTypes(), Sets.<JDeclaredType> newHashSet(javaIntfImplementor), EMPTY_LIST); Assert.assertTrue(program.typeOracle.isDualJsoInterface(intfJ)); program.typeOracle.computeBeforeAST(StandardTypes.createFrom(program), program.getDeclaredTypes(), Collections.<JDeclaredType> emptySet(), Lists.newArrayList(javaIntfImplementor.getName())); Assert.assertFalse(program.typeOracle.isDualJsoInterface(intfJ)); } public void testUpdateTypeInformation_SubClasses() { JClassType baseAll = createClass("IncrementalBaseAll", classObject, false, false); JClassType sub1 = createClass("IncrementalSub1", baseAll, false, false); JClassType sub2 = createClass("IncrementalSub2", baseAll, false, false); JClassType sub1_2 = createClass("IncrementalSub1_2", sub1, false, false); Assert.assertFalse(program.typeOracle.isSubClass(baseAll, sub1)); program.typeOracle.computeBeforeAST(StandardTypes.createFrom(program), program.getDeclaredTypes(), Sets.<JDeclaredType> newHashSet(baseAll, sub1, sub2, sub1_2), EMPTY_LIST); Assert.assertTrue(program.typeOracle.isSubClass(baseAll, sub1)); Assert.assertTrue(program.typeOracle.isSubClass(baseAll, sub2)); Assert.assertTrue(program.typeOracle.isSubClass(baseAll, sub1_2)); Assert.assertTrue(program.typeOracle.isSubClass(sub1, sub1_2)); sub1_2 = createClass("IncrementalSub1_2", baseAll, false, false); program.typeOracle.computeBeforeAST(StandardTypes.createFrom(program), program.getDeclaredTypes(), Sets.<JDeclaredType> newHashSet(baseAll, sub2, sub1_2), Lists.newArrayList(sub1.getName())); Assert.assertFalse(program.typeOracle.isSubClass(baseAll, sub1)); Assert.assertTrue(program.typeOracle.isSubClass(baseAll, sub2)); Assert.assertTrue(program.typeOracle.isSubClass(baseAll, sub1_2)); } public void testUpdateTypeInformation_SuperClasses() { JClassType baseAll = createClass("IncrementalBaseAll", classObject, false, false); JClassType sub1 = createClass("IncrementalSub1", baseAll, false, false); JClassType sub2 = createClass("IncrementalSub2", baseAll, false, false); JClassType sub1_2 = createClass("IncrementalSub1_2", sub1, false, false); Assert.assertFalse(program.typeOracle.isSuperClass(sub1, baseAll)); program.typeOracle.computeBeforeAST(StandardTypes.createFrom(program), program.getDeclaredTypes(), Sets.<JDeclaredType>newHashSet(baseAll, sub1, sub2, sub1_2), EMPTY_LIST); Assert.assertTrue(program.typeOracle.isSuperClass(sub1, baseAll)); Assert.assertTrue(program.typeOracle.isSuperClass(sub2, baseAll)); Assert.assertTrue(program.typeOracle.isSuperClass(sub1_2, baseAll)); Assert.assertTrue(program.typeOracle.isSuperClass(sub1_2, sub1)); sub1_2 = createClass("IncrementalSub1_2", baseAll, false, false); program.typeOracle.computeBeforeAST(StandardTypes.createFrom(program), program.getDeclaredTypes(), Sets.<JDeclaredType>newHashSet(baseAll, sub2, sub1_2), Lists.newArrayList(sub1.getName())); Assert.assertFalse(program.typeOracle.isSuperClass(sub1, baseAll)); Assert.assertTrue(program.typeOracle.isSuperClass(sub2, baseAll)); Assert.assertFalse(program.typeOracle.isSuperClass(sub1_2, sub1)); Assert.assertTrue(program.typeOracle.isSuperClass(sub1_2, baseAll)); } public void testTypeRelationsBeforeRecompute() { // Construct a JTypeOracle with some previously cached type relations, but do not recompute(); MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); ImmediateTypeRelations immediateTypeRelations = minimalRebuildCache.getImmediateTypeRelations(); immediateTypeRelations.getImmediateSuperclassesByClass().put("Foo", "java.lang.Object"); JTypeOracle typeOracle = new JTypeOracle(null, minimalRebuildCache); // Show that the typeOracle can already answer basic type relation questions. assertEquals("java.lang.Object", typeOracle.getSuperTypeName("Foo")); } @Override protected void setUp() { createSampleProgram(new MinimalRebuildCache()); } private void assertCastableDestinationTypes(JReferenceType type, JReferenceType... superHierarchyTypes) { assertEquals(Sets.<JReferenceType> newHashSet(superHierarchyTypes), typeOracle.getCastableDestinationTypes(type)); } private JClassType createClass(String className, JClassType superClass, boolean isAbstract, boolean isFinal) { JClassType x = new JClassType(synthSource, className, isAbstract, isFinal); program.addType(x); x.setSuperClass(superClass); return x; } private JInterfaceType createInterface(String className) { JInterfaceType x = new JInterfaceType(synthSource, className); program.addType(x); return x; } private void createSampleProgram(MinimalRebuildCache minimalRebuildCache) { // Make the program itself program = new JProgram(minimalRebuildCache); typeOracle = program.typeOracle; synthSource = SourceOrigin.UNKNOWN; classObject = createClass("java.lang.Object", null, false, false); classString = createClass("java.lang.String", classObject, false, true); createClass("com.google.gwt.lang.Array", classObject, false, true); classJso = createClass("com.google.gwt.core.client.JavaScriptObject", classObject, false, false); intfSerializable = createInterface("java.io.Serializable"); intfCloneable = createInterface("java.lang.Cloneable"); intfIBase = createInterface("IBase"); intfI = createInterface("I"); intfI.addImplements(intfIBase); intfJ = createInterface("J"); intfK = createInterface("K"); intfL = createInterface("L"); classBase = createClass("Base", classObject, false, false); classA = createClass("A", classBase, false, false); classB = createClass("B", classBase, false, false); classB.addImplements(intfI); classC = createClass("C", classObject, false, false); classC.addImplements(intfI); classBSub = createClass("BSub", classB, false, false); classBSub.addImplements(intfL); classJso1 = createClass("Jso1", classJso, false, false); classJso1.addImplements(intfJ); classJso2 = createClass("Jso2", classJso, false, false); classJso2.addImplements(intfK); classFinalJso1 = createClass("FinalJso1", classJso, false, true); classFinalJso2 = createClass("FinalJso2", classJso, false, true); intfIterable = createInterface("java.util.Iterable"); intfCollection = createInterface("java.util.Collection"); intfCollection.addImplements(intfIterable); intfList = createInterface("java.util.List"); intfList.addImplements(intfCollection); classArrayList = createClass("java.util.ArrayList", classObject, false, false); classArrayList.addImplements(intfList); classBnn = classB.strengthenToNonNull(); classBaseNn = classBase.strengthenToNonNull(); // 1 dimensional arrayOfObject = program.getTypeArray(classObject); arrayOfBase = program.getTypeArray(classBase); arrayOfA = program.getTypeArray(classA); arrayOfB = program.getTypeArray(classB); arrayOfBSub = program.getTypeArray(classBSub); arrayOfIntfIBase = program.getTypeArray(intfIBase); arrayOfIntfI = program.getTypeArray(intfI); arrayOfC = program.getTypeArray(classC); arrayOfInt = program.getTypeArray(program.getTypePrimitiveInt()); arrayOfJso = program.getTypeArray(classJso); arrayOfJso1 = program.getTypeArray(classJso1); arrayOfJso2 = program.getTypeArray(classJso2); arrayOfIntfJ = program.getTypeArray(intfJ); arrayOfIntfK = program.getTypeArray(intfK); arrayOfIntfClonable = program.getTypeArray(intfCloneable); arrayOfIntfSerializable = program.getTypeArray(intfSerializable); // 2 dimensional arrayOfArrayOfBase = program.getOrCreateArrayType(classBase, 2); arrayOfArrayOfObject = program.getOrCreateArrayType(classObject, 2); arrayOfArrayOfIntfI = program.getOrCreateArrayType(intfI, 2); arrayOfArrayOfIntfIBase = program.getOrCreateArrayType(intfIBase, 2); arrayOfArrayOfInt = program.getOrCreateArrayType(program.getTypePrimitiveInt(), 2); arrayOfArrayOfB = program.getOrCreateArrayType(classB, 2); program.typeOracle.computeBeforeAST(StandardTypes.createFrom(program), program.getDeclaredTypes(), program.getModuleDeclaredTypes(), EMPTY_LIST); // Save off some miscellaneous types to test against typeNull = JReferenceType.NULL_TYPE; } private JReferenceType strongerType(JReferenceType type1, JReferenceType type2) { return program.strengthenType(type1, program.generalizeTypes(Arrays.asList(type2))); } private JReferenceType generalizeTypes(JReferenceType type1, JReferenceType type2) { return program.strengthenType(program.getTypeJavaLangObject(), program.generalizeTypes(Arrays.asList(type1, type2))); } private void assertCrossCasts(JClassType thisType, JClassType thatType) { // Uncomment the following once the JSO/non-JSO semantics issue is sorted, Ideally // castXXXTrivially should be more precise and include casting JSO types; however in the current // architecture the results of these tests are used to remove casts and change return types // which in turn might affect the liveness computation for JSOs. // // assertShouldSucceedTrivially(thisType, thatType)); // assertShouldSucceedTrivially(thatType, thisType)); assertShouldNotFailTrivially(thisType, thatType); assertShouldNotFailTrivially(thatType, thisType); assertTrue(typeOracle.canBeJavaScriptObject(thisType)); assertTrue(typeOracle.canBeJavaScriptObject(thatType)); } private void assertShouldNotFailTrivially(JReferenceType thisType, JReferenceType thatType) { assertFalse("Casting " + thisType + " to " + thatType + " should not fail trivially", typeOracle.castFailsTrivially(thisType, thatType)); } private void assertShouldFailTrivially(JReferenceType thisType, JReferenceType thatType) { assertTrue("Casting " + thisType + " to " + thatType + " should fail trivially", typeOracle.castFailsTrivially(thisType, thatType)); } private void assertShouldNotSucceedTrivially(JReferenceType thisType, JReferenceType thatType) { assertFalse("Casting " + thisType + " to " + thatType + " should not succeed trivially", typeOracle.castSucceedsTrivially(thisType, thatType)); } private void assertShouldSucceedTrivially(JReferenceType thisType, JReferenceType thatType) { assertTrue("Casting " + thisType + " to " + thatType + " should succeed trivially", typeOracle.castSucceedsTrivially(thisType, thatType)); } private void assertSignaturesMatch( JReferenceType type, Function<JReferenceType, String> signatureForType) { if (type.isNullType()) { return; } assertEquals(signatureForType.apply(type), signatureForType.apply(type.strengthenToNonNull())); assertEquals(signatureForType.apply(type), signatureForType.apply(type.weakenToNullable())); } /** * Return several types, for exhaustively testing basic properties. */ private Collection<JReferenceType> severalTypes() { List<JReferenceType> types = new ArrayList<JReferenceType>(); types.add(arrayOfA); types.add(arrayOfB); types.add(arrayOfArrayOfB); types.add(arrayOfBSub); types.add(arrayOfObject); types.add(classA); types.add(classB); types.add(classBSub); types.add(classBnn); types.add(classBase); types.add(classC); types.add(classObject); types.add(classString); types.add(intfI); types.add(intfJ); types.add(intfK); types.add(intfIBase); types.add(classJso1); types.add(classJso2); types.add(classJso); types.add(typeNull); return types; } }