blob: d477a61c8adb8b05df7b33b8f820613268054845 [file] [log] [blame]
/*
* Copyright 2008 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.impl.JavaResourceBase;
import com.google.gwt.dev.javac.impl.MockJavaResource;
import com.google.gwt.dev.javac.impl.MockResourceOracle;
import com.google.gwt.dev.javac.impl.TweakedMockJavaResource;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Tests {@link CompilationState}.
*/
public class CompilationStateTest extends CompilationStateTestBase {
private static final MockJavaResource FOO_DIFF_API = new MockJavaResource(
"test.Foo") {
@Override
protected CharSequence getContent() {
StringBuffer code = new StringBuffer();
code.append("package test;\n");
code.append("public class Foo {\n");
code.append(" public String value() { return \"Foo\"; }\n");
code.append(" public String value2() { return \"Foo2\"; }\n");
code.append("}\n");
return code;
}
};
private static final MockJavaResource FOO_SAME_API = new MockJavaResource(
"test.Foo") {
@Override
protected CharSequence getContent() {
StringBuffer code = new StringBuffer();
code.append("package test;\n");
code.append("public class Foo {\n");
code.append(" public String value() { return \"Foo2\"; }\n");
code.append("}\n");
return code;
}
};
public void testAddGeneratedCompilationUnit() {
validateCompilationState();
// Add a unit and ensure it shows up.
addGeneratedUnits(JavaResourceBase.FOO);
validateCompilationState(Shared.getTypeName(JavaResourceBase.FOO));
rebuildCompilationState();
validateCompilationState();
}
/* test that a generated unit, if unchanged, is reused */
public void testCaching() {
testCaching(JavaResourceBase.FOO);
}
/* test that mutiple generated units, if unchanged, are reused */
public void testCachingOfMultipleUnits() {
testCaching(JavaResourceBase.BAR, JavaResourceBase.FOO);
}
public void testCompileError() {
oracle.add(JavaResourceBase.BAR);
rebuildCompilationState();
CompilationUnit badUnit = state.getCompilationUnitMap().get(
Shared.getTypeName(JavaResourceBase.BAR));
assertTrue(badUnit.isError());
Set<CompilationUnit> goodUnits = new HashSet<CompilationUnit>(
state.getCompilationUnits());
goodUnits.remove(badUnit);
assertUnitsChecked(goodUnits);
}
public void testCompileWithGeneratedUnits() {
assertUnitsChecked(state.getCompilationUnits());
addGeneratedUnits(JavaResourceBase.FOO);
assertUnitsChecked(state.getCompilationUnits());
}
public void testCompileWithGeneratedUnitsError() {
assertUnitsChecked(state.getCompilationUnits());
addGeneratedUnits(JavaResourceBase.BAR);
CompilationUnit badUnit = state.getCompilationUnitMap().get(
Shared.getTypeName(JavaResourceBase.BAR));
assertTrue(badUnit.isError());
Set<CompilationUnit> goodUnits = new HashSet<CompilationUnit>(
state.getCompilationUnits());
goodUnits.remove(badUnit);
assertUnitsChecked(goodUnits);
}
public void testCompileWithGeneratedUnitsErrorAndDepedentGeneratedUnit() {
assertUnitsChecked(state.getCompilationUnits());
MockJavaResource badFoo = new MockJavaResource(
Shared.getTypeName(JavaResourceBase.FOO)) {
@Override
protected CharSequence getContent() {
return "compilation error LOL!";
}
};
oracle.add(badFoo);
rebuildCompilationState();
addGeneratedUnits(JavaResourceBase.BAR);
CompilationUnit badUnit = state.getCompilationUnitMap().get(
Shared.getTypeName(badFoo));
assertTrue(badUnit.isError());
CompilationUnit invalidUnit = state.getCompilationUnitMap().get(
Shared.getTypeName(JavaResourceBase.BAR));
assertTrue(invalidUnit.isError());
Set<CompilationUnit> goodUnits = new HashSet<CompilationUnit>(
state.getCompilationUnits());
goodUnits.remove(badUnit);
goodUnits.remove(invalidUnit);
assertUnitsChecked(goodUnits);
}
/*
* test if things work correctly when a generated unit can't be reused, but
* another generated unit it depends on can be reused
*/
public void testComplexCacheInvalidation() {
testCachingOverMultipleRefreshes(new MockJavaResource[]{
JavaResourceBase.FOO, JavaResourceBase.BAR},
new MockJavaResource[]{
JavaResourceBase.FOO,
new TweakedMockJavaResource(JavaResourceBase.BAR)},
Collections.singleton(JavaResourceBase.FOO.getTypeName()));
}
public void testInitialization() {
assertUnitsChecked(state.getCompilationUnits());
}
public void testInvalidation() {
testCachingOverMultipleRefreshes(
new MockJavaResource[]{JavaResourceBase.FOO},
new MockJavaResource[]{new TweakedMockJavaResource(JavaResourceBase.FOO)},
Collections.<String> emptySet());
}
public void testInvalidationNonstructuralDep() {
testCachingOverMultipleRefreshes(new MockJavaResource[]{
JavaResourceBase.FOO, JavaResourceBase.BAR}, new MockJavaResource[]{
FOO_SAME_API, JavaResourceBase.BAR},
Collections.singleton(JavaResourceBase.BAR.getTypeName()));
}
public void testInvalidationOfMultipleUnits() {
testCachingOverMultipleRefreshes(new MockJavaResource[]{
JavaResourceBase.FOO, JavaResourceBase.BAR}, new MockJavaResource[]{
new TweakedMockJavaResource(JavaResourceBase.FOO),
new TweakedMockJavaResource(JavaResourceBase.BAR)},
Collections.<String> emptySet());
}
public void testInvalidationStructuralDep() {
testCachingOverMultipleRefreshes(new MockJavaResource[]{
JavaResourceBase.FOO, JavaResourceBase.BAR}, new MockJavaResource[]{
FOO_DIFF_API, JavaResourceBase.BAR}, Collections.<String> emptySet());
}
public void testInvalidationWhenSourceUnitsChange() {
/*
* Steps: (i) Check compilation state. (ii) Add generated units. (iii)
* Change unit in source oracle. (iv) Refresh oracle. (v) Add same generated
* units. (v) Check that there is no reuse.
*/
validateCompilationState();
oracle.add(JavaResourceBase.FOO);
rebuildCompilationState();
// add generated units
addGeneratedUnits(JavaResourceBase.BAR);
assertUnitsChecked(state.getCompilationUnits());
CompilationUnit oldBar = state.getCompilationUnitMap().get(
JavaResourceBase.BAR.getTypeName());
assertNotNull(oldBar);
// change unit in source oracle
oracle.replace(FOO_DIFF_API);
rebuildCompilationState();
/*
* Add same generated units. Verify that the original units are not used.
*/
addGeneratedUnits(JavaResourceBase.BAR);
assertUnitsChecked(state.getCompilationUnits());
CompilationUnit newBar = state.getCompilationUnitMap().get(
JavaResourceBase.BAR.getTypeName());
assertNotNull(newBar);
assertNotSame(oldBar, newBar);
}
public void testSourceOracleAdd() {
validateCompilationState();
int size = state.getCompilationUnits().size();
oracle.add(JavaResourceBase.FOO);
rebuildCompilationState();
assertEquals(size + 1, state.getCompilationUnits().size());
validateCompilationState();
}
public void testSourceOracleBasic() {
validateCompilationState();
}
public void testSourceOracleEmpty() {
oracle = new MockResourceOracle();
rebuildCompilationState();
validateCompilationState();
}
public void testSourceOracleRemove() {
validateCompilationState();
int size = state.getCompilationUnits().size();
oracle.remove(JavaResourceBase.MAP.getPath());
rebuildCompilationState();
assertEquals(size - 1, state.getCompilationUnits().size());
validateCompilationState();
}
public void testSourceOracleReplace() {
validateCompilationState();
int size = state.getCompilationUnits().size();
oracle.replace(new TweakedMockJavaResource(JavaResourceBase.OBJECT));
rebuildCompilationState();
assertEquals(size, state.getCompilationUnits().size());
validateCompilationState();
}
public void testSourceOracleReplaceWithSame() {
validateCompilationState();
int size = state.getCompilationUnits().size();
oracle.replace(JavaResourceBase.OBJECT);
rebuildCompilationState();
assertEquals(size, state.getCompilationUnits().size());
validateCompilationState();
}
private void testCaching(MockJavaResource... resources) {
Set<String> reusedTypes = new HashSet<String>();
for (MockJavaResource resource : resources) {
reusedTypes.add(resource.getTypeName());
}
testCachingOverMultipleRefreshes(resources, resources, reusedTypes);
}
/**
* Test caching logic for generated units during refreshes. Steps:
* <ol>
* <li>Verify that there were no generated units before</li>
* <li>Add 'initialSet' generatedUnits over a refresh cycle</li>
* <li>Add 'updatedSet' generatedUnits over a refresh cycle</li>
* <li>Add 'updatedSet' generatedUnits over the second refresh cycle</li>
* </ol>
*
* @param initialSet CompilationUnits that are generated the first time.
* @param updatedSet CompilationUnits that are generated the next time.
* @param reusedTypes Main type of the units that can be reused between the
* initialSet and updatedSet.
* @param numInvalidated Number of types invalidated from graveyardUnits.
*/
private void testCachingOverMultipleRefreshes(MockJavaResource[] initialSet,
MockJavaResource[] updatedSet, Set<String> reusedTypes) {
// Add 'initialSet' generatedUnits on the first cycle.
rebuildCompilationState();
assertEquals(oracle.getResources().size(),
state.getCompilationUnits().size());
addGeneratedUnits(initialSet);
Map<String, CompilationUnit> units1 = new HashMap<String, CompilationUnit>(
state.getCompilationUnitMap());
assertEquals(oracle.getResources().size() + initialSet.length,
units1.size());
assertUnitsChecked(units1.values());
// Add 'updatedSet' generatedUnits on the second cycle.
rebuildCompilationState();
assertEquals(oracle.getResources().size(),
state.getCompilationUnits().size());
addGeneratedUnits(updatedSet);
Map<String, CompilationUnit> units2 = new HashMap<String, CompilationUnit>(
state.getCompilationUnitMap());
assertEquals(oracle.getResources().size() + updatedSet.length,
units2.size());
assertUnitsChecked(units2.values());
// Validate that only 'reusedTypes' are reused.
for (MockJavaResource resource : updatedSet) {
String typeName = resource.getTypeName();
if (reusedTypes.contains(typeName)) {
assertSame(units1.get(typeName), units2.get(typeName));
} else {
assertNotSame(units1.get(typeName), units2.get(typeName));
}
}
// Add 'updatedSet' generatedUnits on the third cycle.
rebuildCompilationState();
assertEquals(oracle.getResources().size(),
state.getCompilationUnits().size());
addGeneratedUnits(updatedSet);
Map<String, CompilationUnit> units3 = new HashMap<String, CompilationUnit>(
state.getCompilationUnitMap());
assertEquals(oracle.getResources().size() + updatedSet.length,
units3.size());
assertUnitsChecked(units3.values());
// Validate that all generatedUnits are reused.
for (MockJavaResource resource : updatedSet) {
String typeName = resource.getTypeName();
assertSame(units2.get(typeName), units3.get(typeName));
}
}
}