| /* |
| * Copyright 2014 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; |
| |
| import com.google.gwt.core.ext.TreeLogger; |
| import com.google.gwt.dev.jjs.ast.JTypeOracle; |
| import com.google.gwt.thirdparty.guava.common.collect.ImmutableMap; |
| import com.google.gwt.thirdparty.guava.common.collect.Lists; |
| import com.google.gwt.thirdparty.guava.common.collect.Sets; |
| |
| import junit.framework.TestCase; |
| |
| import java.util.Map; |
| |
| /** |
| * Tests for {@link MinimalRebuildCache}. |
| */ |
| public class MinimalRebuildCacheTest extends TestCase { |
| |
| private MinimalRebuildCache minimalRebuildCache; |
| |
| public void testComputeAndClearStale() { |
| // These three compilation units exist. |
| Map<String, Long> currentModifiedBySourcePath = new ImmutableMap.Builder<String, Long>().put( |
| "Foo.java", 0L).put("Bar.java", 0L).put("Baz.java", 0L).build(); |
| minimalRebuildCache.recordDiskSourceResources(currentModifiedBySourcePath); |
| |
| // They each contain a type and nested type. |
| StringAnalyzableTypeEnvironment typeEnvironment = minimalRebuildCache.getTypeEnvironment(); |
| minimalRebuildCache.recordNestedTypeName("Foo", "Foo"); |
| typeEnvironment.recordTypeEnclosesMethod("Foo", "Foo::$clinit()V"); |
| minimalRebuildCache.recordNestedTypeName("Foo", "Foo$Inner"); |
| typeEnvironment.recordTypeEnclosesMethod("Foo$Inner", "Foo$Inner::$clinit()V"); |
| minimalRebuildCache.recordNestedTypeName("Bar", "Bar"); |
| typeEnvironment.recordTypeEnclosesMethod("Bar", "Bar::$clinit()V"); |
| minimalRebuildCache.recordNestedTypeName("Bar", "Bar$Inner"); |
| typeEnvironment.recordTypeEnclosesMethod("Bar$Inner", "Bar$Inner::$clinit()V"); |
| minimalRebuildCache.recordNestedTypeName("Baz", "Baz"); |
| typeEnvironment.recordTypeEnclosesMethod("Baz", "Baz::$clinit()V"); |
| minimalRebuildCache.recordNestedTypeName("Baz", "Baz$Inner"); |
| typeEnvironment.recordTypeEnclosesMethod("Baz$Inner", "Baz$Inner::$clinit()V"); |
| |
| // There's some JS for each type. |
| minimalRebuildCache.setJsForType(TreeLogger.NULL, "Foo", "Some Js for Foo"); |
| minimalRebuildCache.setJsForType(TreeLogger.NULL, "Foo$Inner", "Some Js for Foo"); |
| minimalRebuildCache.setJsForType(TreeLogger.NULL, "Bar", "Some Js for Bar"); |
| minimalRebuildCache.setJsForType(TreeLogger.NULL, "Bar$Inner", "Some Js for Bar"); |
| minimalRebuildCache.setJsForType(TreeLogger.NULL, "Baz", "Some Js for Baz"); |
| minimalRebuildCache.setJsForType(TreeLogger.NULL, "Baz$Inner", "Some Js for Baz"); |
| |
| // Record that Bar references Foo and Baz subclasses Foo. |
| minimalRebuildCache.addTypeReference("Bar", "Foo"); |
| typeEnvironment.recordMethodCallsMethod("Bar::start()", "Foo::run()"); |
| typeEnvironment.recordStaticReferenceInMethod("Foo", "Bar::start()"); |
| typeEnvironment.recordTypeEnclosesMethod("Bar", "Bar::start()"); |
| typeEnvironment.recordTypeEnclosesMethod("Foo", "Foo::run()"); |
| minimalRebuildCache.getImmediateTypeRelations().getImmediateSuperclassesByClass().put("Baz", |
| "Foo"); |
| typeEnvironment.recordMethodCallsMethod("Foo::run()", "Baz::run()"); |
| typeEnvironment.recordStaticReferenceInMethod("Baz", "Foo::run()"); |
| typeEnvironment.recordTypeEnclosesMethod("Baz", "Baz::run()"); |
| |
| // Record that these types reference their inner classes. |
| minimalRebuildCache.addTypeReference("Foo", "Foo$Inner"); |
| minimalRebuildCache.addTypeReference("Bar", "Bar$Inner"); |
| minimalRebuildCache.addTypeReference("Baz", "Baz$Inner"); |
| typeEnvironment.recordStaticReferenceInMethod("Bar$Inner", "Bar::start()"); |
| typeEnvironment.recordStaticReferenceInMethod("Foo$Inner", "Foo::run()"); |
| typeEnvironment.recordStaticReferenceInMethod("Baz$Inner", "Baz::run()"); |
| |
| // In the next compile only Foo is modified. |
| Map<String, Long> laterModifiedBySourcePath = new ImmutableMap.Builder<String, Long>().put( |
| "Foo.java", 9999L).put("Bar.java", 0L).put("Baz.java", 0L).build(); |
| minimalRebuildCache.recordDiskSourceResources(laterModifiedBySourcePath); |
| |
| // Ensure the types are known to be reachable. |
| minimalRebuildCache.setRootTypeNames(Sets.newHashSet("Foo", "Bar", "Baz")); |
| minimalRebuildCache.setEntryMethodNames(Lists.newArrayList("Bar::start()")); |
| minimalRebuildCache.computeReachableTypeNames(); |
| |
| // Request clearing of cache related to stale types. |
| minimalRebuildCache.computeAndClearStaleTypesCache(TreeLogger.NULL, |
| new JTypeOracle(null, minimalRebuildCache)); |
| |
| // Has the expected JS been cleared? |
| assertNull(minimalRebuildCache.getJs("Foo")); |
| assertNull(minimalRebuildCache.getJs("Foo$Inner")); |
| assertNull(minimalRebuildCache.getJs("Bar")); |
| assertNull(minimalRebuildCache.getJs("Baz")); |
| assertNotNull(minimalRebuildCache.getJs("Bar$Inner")); |
| assertNotNull(minimalRebuildCache.getJs("Baz$Inner")); |
| } |
| |
| public void testComputeDeletedTypes() { |
| // These three compilation units exist. |
| Map<String, Long> currentModifiedBySourcePath = new ImmutableMap.Builder<String, Long>().put( |
| "Foo.java", 0L).put("Bar.java", 0L).put("Baz.java", 0L).build(); |
| minimalRebuildCache.recordDiskSourceResources(currentModifiedBySourcePath); |
| |
| // They each contain a type and nested type. |
| minimalRebuildCache.recordNestedTypeName("Foo", "Foo"); |
| minimalRebuildCache.recordNestedTypeName("Foo", "Foo$Inner"); |
| minimalRebuildCache.recordNestedTypeName("Bar", "Bar"); |
| minimalRebuildCache.recordNestedTypeName("Bar", "Bar$Inner"); |
| minimalRebuildCache.recordNestedTypeName("Baz", "Baz"); |
| minimalRebuildCache.recordNestedTypeName("Baz", "Baz$Inner"); |
| |
| // In the next compile it turns out there are fewer compilation units, Baz is gone. |
| Map<String, Long> laterModifiedBySourcePath = |
| new ImmutableMap.Builder<String, Long>().put("Foo.java", 0L).put("Bar.java", 0L).build(); |
| minimalRebuildCache.recordDiskSourceResources(laterModifiedBySourcePath); |
| |
| // Is the correct deleted type set calculated? |
| assertEquals(Sets.newHashSet("Baz", "Baz$Inner"), |
| minimalRebuildCache.computeDeletedTypeNames()); |
| } |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| |
| minimalRebuildCache = new MinimalRebuildCache(); |
| } |
| } |