/* * 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.javac; import com.google.gwt.dev.javac.Dependencies.Ref; import com.google.gwt.dev.javac.testing.impl.JavaResourceBase; import com.google.gwt.dev.javac.testing.impl.MockJavaResource; import com.google.gwt.dev.resource.Resource; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * Test if all fileReferences in a compilationUnit are recorded correctly. */ public class CompilationUnitFileReferenceTest extends CompilationStateTestBase { public static final MockJavaResource MEMBER_INNER_SUBCLASS = new MockJavaResource("test.OuterSubclass") { @Override public CharSequence getContent() { StringBuffer code = new StringBuffer(); code.append("package test;\n"); code.append("public class OuterSubclass extends Outer {\n"); code.append(" public String value() { return \"OuterSubclass\"; }\n"); code.append(" public class MemberInnerSubclass extends MemberInner {\n"); code.append(" public String value() { return \"MemberInnerSubclass\"; }\n"); code.append(" }\n"); code.append("}\n"); return code; } }; public static final MockJavaResource NOPACKAGE = new MockJavaResource("NoPackage") { @Override public CharSequence getContent() { StringBuffer code = new StringBuffer(); code.append("public class NoPackage extends test.Top {\n"); code.append(" public String value() { return \"NoPackage\"; }\n"); code.append("}\n"); return code; } }; public static final MockJavaResource NOPACKAGE2 = new MockJavaResource("NoPackage2") { @Override public CharSequence getContent() { StringBuffer code = new StringBuffer(); code.append("public class NoPackage2 extends NoPackage {\n"); code.append(" public String value() { return \"NoPackage2\"; }\n"); code.append("}\n"); return code; } }; public static final MockJavaResource OUTER = new MockJavaResource("test.Outer") { @Override public CharSequence getContent() { StringBuffer code = new StringBuffer(); code.append("package test;\n"); code.append("public class Outer {\n"); code.append(" public String value() { return \"Outer\"; }\n"); code.append(" public static class StaticInner {\n"); code.append(" public String value() { return \"StaticInner\"; }\n"); code.append(" }\n"); code.append(" public class MemberInner {\n"); code.append(" public String value() { return \"MemberInner\"; }\n"); code.append(" }\n"); code.append("}\n"); return code; } }; public static final MockJavaResource STATIC_INNER_SUBCLASS = new MockJavaResource("test.StaticInnerSubclass") { @Override public CharSequence getContent() { StringBuffer code = new StringBuffer(); code.append("package test;\n"); code.append("public class StaticInnerSubclass extends Outer.StaticInner {\n"); code.append(" public String value() { return \"StaticInnerSubclass\"; }\n"); code.append("}\n"); return code; } }; public static final MockJavaResource TOP = new MockJavaResource("test.Top") { @Override public CharSequence getContent() { StringBuffer code = new StringBuffer(); code.append("package test;\n"); code.append("public class Top {\n"); code.append(" public String value() { return \"Top\"; }\n"); code.append("}\n"); code.append("class Top2 extends Top {\n"); code.append(" public String value() { return \"Top2\"; }\n"); code.append("}\n"); return code; } }; public static final MockJavaResource TOP3 = new MockJavaResource("test.Top3") { @Override public CharSequence getContent() { StringBuffer code = new StringBuffer(); code.append("package test;\n"); code.append("public class Top3 extends Top2 {\n"); code.append(" public String value() { return \"Top3\"; }\n"); code.append("}\n"); return code; } }; /** * This map contains the hand-computed set of references we expect each of the * test compilation units to have. The actual set of references computed by * {@link CompilationState} will be checked against this set. */ private static final Map<String, Set<String>> EXPECTED_DEPENDENCIES = new HashMap<String, Set<String>>(); static { // Setup EXPECTED_DEPENDENCIES with hand-computed data. initializeExpectedDependency(JavaResourceBase.FOO, JavaResourceBase.STRING.getTypeName()); initializeExpectedDependency(JavaResourceBase.BAR, JavaResourceBase.STRING.getTypeName(), JavaResourceBase.FOO.getTypeName()); initializeExpectedDependency(NOPACKAGE, JavaResourceBase.STRING.getTypeName(), TOP .getTypeName()); initializeExpectedDependency(NOPACKAGE2, NOPACKAGE.getTypeName(), JavaResourceBase.STRING .getTypeName(), TOP.getTypeName()); initializeExpectedDependency(TOP, JavaResourceBase.STRING.getTypeName(), "test.Top2"); initializeExpectedDependency(TOP3, JavaResourceBase.STRING.getTypeName(), TOP.getTypeName(), "test.Top2"); initializeExpectedDependency(OUTER, JavaResourceBase.STRING.getTypeName(), "test.Outer$MemberInner"); initializeExpectedDependency(MEMBER_INNER_SUBCLASS, JavaResourceBase.STRING.getTypeName(), OUTER.getTypeName(), "test.Outer$MemberInner"); initializeExpectedDependency(OUTER, JavaResourceBase.STRING.getTypeName()); initializeExpectedDependency(STATIC_INNER_SUBCLASS, JavaResourceBase.STRING.getTypeName(), OUTER.getTypeName(), "test.Outer$StaticInner"); } private static void initializeExpectedDependency( MockJavaResource source, String... typeNames) { Set<String> targetSet = new HashSet<String>(); for (String typeName : typeNames) { targetSet.add(typeName); } EXPECTED_DEPENDENCIES.put(source.getTypeName(), targetSet); } public void testBinaryBindingsWithMemberInnerClass() { testBinaryBindings(OUTER, MEMBER_INNER_SUBCLASS); } public void testBinaryBindingsWithMultipleTopLevelClasses() { testBinaryBindings(TOP, TOP3); } public void testBinaryBindingsWithSimpleUnits() { testBinaryBindings(JavaResourceBase.FOO, JavaResourceBase.BAR); } public void testBinaryBindingsWithStaticInnerClass() { testBinaryBindings(OUTER, STATIC_INNER_SUBCLASS); } public void testBinaryNoPackage() { testBinaryBindings(TOP, NOPACKAGE, NOPACKAGE2); } public void testSourceBindingsWithMemberInnerClass() { testSourceBindings(OUTER, MEMBER_INNER_SUBCLASS); } public void testSourceBindingsWithMultipleTopLevelClasses() { testSourceBindings(TOP, TOP3); } public void testSourceBindingsWithSimpleUnits() { testSourceBindings(JavaResourceBase.FOO, JavaResourceBase.BAR); } public void testSourceBindingsWithStaticInnerClass() { testSourceBindings(OUTER, STATIC_INNER_SUBCLASS); } public void testSourceNoPackage() { testSourceBindings(TOP, NOPACKAGE, NOPACKAGE2); } public void testWithGeneratedUnits() { addGeneratedUnits(JavaResourceBase.FOO, JavaResourceBase.BAR); assertRefsMatchExpectedRefs(JavaResourceBase.FOO, JavaResourceBase.BAR); } public void testWithMixedUnits() { oracle.add(JavaResourceBase.FOO); rebuildCompilationState(); addGeneratedUnits(JavaResourceBase.BAR); assertRefsMatchExpectedRefs(JavaResourceBase.FOO, JavaResourceBase.BAR); } private void assertRefsMatchExpectedRefs(MockJavaResource... files) { Map<String, CompilationUnit> unitMap = state.getCompilationUnitMap(); for (MockJavaResource file : files) { String typeName = file.getTypeName(); Dependencies dependencies = unitMap.get(typeName).getDependencies(); Set<String> actualTypeNames = new HashSet<String>(); for (Ref ref : dependencies.qualified.values()) { if (ref != null) { actualTypeNames.add(ref.getInternalName().replace('/', '.')); } } for (Ref ref : dependencies.simple.values()) { if (ref != null) { actualTypeNames.add(ref.getInternalName().replace('/', '.')); } } actualTypeNames.remove(null); // Not tracking deps on Object. actualTypeNames.remove("java.lang.Object"); // Don't care about self dep. actualTypeNames.remove(typeName); Set<String> expectedTypeNames = EXPECTED_DEPENDENCIES.get(typeName); assertEquals("Resource: " + file, expectedTypeNames, actualTypeNames); } } /** * Independently compiles each file in order to force each subsequent unit to * have only binary references to the previous unit(s). This tests the binary * reference matching in {@link CompilationState}. */ private void testBinaryBindings(MockJavaResource... files) { for (Resource sourceFile : files) { oracle.add(sourceFile); rebuildCompilationState(); } assertRefsMatchExpectedRefs(files); } /** * Compiles all files together so that all units will have source references * to each other. This tests the source reference matching in * {@link CompilationState}. */ private void testSourceBindings(MockJavaResource... files) { for (Resource sourceFile : files) { oracle.add(sourceFile); } rebuildCompilationState(); assertRefsMatchExpectedRefs(files); } }