blob: c9e20abf06e8604405741f20cc53e8800e7584f0 [file] [log] [blame]
/*
* 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);
}
}