| /* |
| * 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.codeserver; |
| |
| import com.google.gwt.core.ext.TreeLogger; |
| import com.google.gwt.core.ext.UnableToCompleteException; |
| import com.google.gwt.dev.codeserver.Job.Result; |
| import com.google.gwt.dev.javac.UnitCacheSingleton; |
| import com.google.gwt.dev.javac.testing.impl.JavaResourceBase; |
| import com.google.gwt.dev.javac.testing.impl.MockJavaResource; |
| import com.google.gwt.dev.javac.testing.impl.MockResource; |
| import com.google.gwt.dev.util.log.PrintWriterTreeLogger; |
| import com.google.gwt.thirdparty.guava.common.base.Charsets; |
| import com.google.gwt.thirdparty.guava.common.collect.Lists; |
| import com.google.gwt.thirdparty.guava.common.io.Files; |
| |
| import junit.framework.TestCase; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * Tests for {@link Recompiler} |
| */ |
| public class RecompilerTest extends TestCase { |
| |
| private static void writeResourcesTo(List<MockResource> resources, File dir) throws IOException { |
| for (MockResource applicationResource : resources) { |
| File resourceFile = |
| new File(dir.getAbsolutePath() + File.separator + applicationResource.getPath()); |
| resourceFile.getParentFile().mkdirs(); |
| Files.write(applicationResource.getContent(), resourceFile, Charsets.UTF_8); |
| } |
| } |
| |
| private MockJavaResource barReferencesBazResource = |
| JavaResourceBase.createMockJavaResource("com.foo.Bar", |
| "package com.foo;", |
| "public class Bar {", |
| " Baz baz = new Baz();", |
| "}"); |
| |
| private MockJavaResource bazReferencesFooResource = |
| JavaResourceBase.createMockJavaResource("com.foo.Baz", |
| "package com.foo;", |
| "public class Baz {", |
| " Foo foo = new Foo();", |
| "}"); |
| |
| private MockJavaResource fooResource = |
| JavaResourceBase.createMockJavaResource("com.foo.Foo", |
| "package com.foo;", |
| "public class Foo {}"); |
| |
| private MockJavaResource nonCompilableFooResource = |
| JavaResourceBase.createMockJavaResource("com.foo.Foo", |
| "package com.foo;", |
| "import com.google.gwt.core.client.impl.SpecializeMethod;", |
| "public class Foo {", |
| " // This will throw an error in UnifyAst.", |
| " @SpecializeMethod()", |
| " public void run() {}", |
| "}"); |
| |
| private MockJavaResource referencesBarEntryPointResource = |
| JavaResourceBase.createMockJavaResource("com.foo.TestEntryPoint", |
| "package com.foo;", |
| "import com.google.gwt.core.client.EntryPoint;", |
| "public class TestEntryPoint implements EntryPoint {", |
| " @Override", |
| " public void onModuleLoad() {", |
| " Bar bar = new Bar();", |
| " }", |
| "}"); |
| |
| private MockResource simpleModuleResource = |
| JavaResourceBase.createMockResource("com/foo/SimpleModule.gwt.xml", |
| "<module>", |
| "<source path=''/>", |
| "<entry-point class='com.foo.TestEntryPoint'/>", |
| "</module>"); |
| |
| public void testIncrementalRecompile_compileErrorDoesntCorruptMinimalRebuildCache() |
| throws UnableToCompleteException, IOException, InterruptedException { |
| PrintWriterTreeLogger logger = new PrintWriterTreeLogger(); |
| logger.setMaxDetail(TreeLogger.ERROR); |
| |
| File sourcePath = Files.createTempDir(); |
| // Setup options to perform a per-file compile and compile the given module. |
| Options options = new Options(); |
| options.parseArgs(new String[] { |
| "-incremental", "-src", sourcePath.getAbsolutePath(), "com.foo.SimpleModule"}); |
| |
| // Prepare the basic resources in the test application. |
| List<MockResource> originalResources = Lists.newArrayList(simpleModuleResource, |
| referencesBarEntryPointResource, barReferencesBazResource, bazReferencesFooResource, |
| fooResource); |
| writeResourcesTo(originalResources, sourcePath); |
| |
| Recompiler recompiler = |
| new Recompiler(OutboxDir.create(Files.createTempDir(), logger), null, |
| "com.foo.SimpleModule", options); |
| Outbox outbox = new Outbox("Transactional Cache", recompiler, options, logger); |
| OutboxTable outboxes = new OutboxTable(); |
| outboxes.addOutbox(outbox); |
| JobRunner runner = new JobRunner(new JobEventTable(), outboxes); |
| |
| // Perform a first compile. This should pass since all resources are valid. |
| Result result = |
| compileWithChanges(logger, runner, outbox, sourcePath, Lists.<MockResource> newArrayList()); |
| assertTrue(result.isOk()); |
| |
| // Recompile should fail since the provided Foo is not compilable. |
| result = compileWithChanges(logger, runner, outbox, sourcePath, |
| Lists.<MockResource> newArrayList(nonCompilableFooResource)); |
| assertFalse(result.isOk()); |
| |
| // Recompile with a modified entry point. This should fail again since Foo is still |
| // bad, but if transactionality protection failed on the minimalRebuildCache this compile will |
| // succeed because it will think that it has "already processed" Foo. |
| result = compileWithChanges(logger, runner, outbox, sourcePath, |
| Lists.<MockResource> newArrayList(referencesBarEntryPointResource)); |
| assertFalse(result.isOk()); |
| } |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| // Make sure we're using a MemoryUnitCache. |
| System.setProperty(UnitCacheSingleton.GWT_PERSISTENTUNITCACHE, "false"); |
| } |
| |
| private Result compileWithChanges(TreeLogger logger, JobRunner runner, Outbox outbox, |
| File sourcePath, List<MockResource> changedResources) throws InterruptedException, |
| IOException { |
| // Wait 1 second so that any new file modification times are actually different. |
| Thread.sleep(1001); |
| |
| // Write the Java/XML/etc resources that make up the test application. |
| writeResourcesTo(changedResources, sourcePath); |
| |
| // Compile and return success status. |
| Map<String, String> bindingProperties = new HashMap<String, String>(); |
| Job job = outbox.makeJob(bindingProperties, logger); |
| runner.submit(job); |
| return job.waitForResult(); |
| } |
| } |