| /* |
| * Copyright 2007 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.shell; |
| |
| import com.google.gwt.core.ext.BadPropertyValueException; |
| import com.google.gwt.core.ext.ConfigurationProperty; |
| import com.google.gwt.core.ext.Generator; |
| import com.google.gwt.core.ext.GeneratorContext; |
| import com.google.gwt.core.ext.PropertyOracle; |
| import com.google.gwt.core.ext.SelectionProperty; |
| import com.google.gwt.core.ext.TreeLogger; |
| import com.google.gwt.core.ext.UnableToCompleteException; |
| import com.google.gwt.core.ext.linker.ArtifactSet; |
| import com.google.gwt.core.ext.linker.GeneratedResource; |
| import com.google.gwt.dev.cfg.MockModuleDef; |
| import com.google.gwt.dev.javac.CompilationState; |
| import com.google.gwt.dev.javac.CompilationStateBuilder; |
| import com.google.gwt.dev.javac.StandardGeneratorContext; |
| import com.google.gwt.dev.resource.Resource; |
| import com.google.gwt.dev.util.Util; |
| |
| import junit.framework.TestCase; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.io.UnsupportedEncodingException; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.List; |
| |
| /** |
| * A wide variety of tests on {@link StandardGeneratorContext}. |
| */ |
| public class StandardGeneratorContextTest extends TestCase { |
| |
| private static class MockGenerator extends Generator { |
| @Override |
| public String generate(TreeLogger logger, GeneratorContext context, |
| String typeName) throws UnableToCompleteException { |
| return typeName; |
| } |
| } |
| |
| private static class MockPropertyOracle implements PropertyOracle { |
| public ConfigurationProperty getConfigurationProperty(String name) { |
| return null; |
| } |
| |
| public String getPropertyValue(TreeLogger logger, String propertyName) |
| throws BadPropertyValueException { |
| return ""; |
| } |
| |
| public String[] getPropertyValueSet(TreeLogger logger, String propertyName) |
| throws BadPropertyValueException { |
| return new String[] {}; |
| } |
| |
| public SelectionProperty getSelectionProperty(TreeLogger logger, String name) { |
| return null; |
| } |
| } |
| |
| private final ArtifactSet artifactSet = new ArtifactSet(); |
| private final StandardGeneratorContext genCtx; |
| private final CompilationState mockCompilationState = CompilationStateBuilder.buildFrom( |
| TreeLogger.NULL, Collections.<Resource> emptySet()); |
| private final TreeLogger mockLogger = TreeLogger.NULL; |
| private final PropertyOracle mockPropOracle = new MockPropertyOracle(); |
| /** |
| * Stores the File objects to delete in the order they were created. Delete |
| * them in reverse order. |
| */ |
| private final List<File> toDelete = new ArrayList<File>(); |
| |
| public StandardGeneratorContextTest() { |
| genCtx = new StandardGeneratorContext(mockCompilationState, |
| new MockModuleDef(), null, artifactSet, false); |
| genCtx.setPropertyOracle(mockPropOracle); |
| genCtx.setCurrentGenerator(Generator.class); |
| } |
| |
| public void testTryCreateResource_badFileName() { |
| try { |
| genCtx.tryCreateResource(mockLogger, null); |
| fail("The null filename in the previous statement should have caused an exception"); |
| } catch (UnableToCompleteException e) { |
| // Success |
| } |
| |
| try { |
| genCtx.tryCreateResource(mockLogger, ""); |
| fail("The empty filename in the previous statement should have caused an exception"); |
| } catch (UnableToCompleteException e) { |
| // Success |
| } |
| |
| try { |
| genCtx.tryCreateResource(mockLogger, " "); |
| fail("The whitespace-only filename in the previous statement should have caused an exception"); |
| } catch (UnableToCompleteException e) { |
| // Success |
| } |
| |
| try { |
| File absFile = new File("stuff.bin"); |
| String asbPath = absFile.getAbsolutePath(); |
| genCtx.tryCreateResource(mockLogger, asbPath); |
| fail("The absolute path in the previous statement should have caused an exception"); |
| } catch (UnableToCompleteException e) { |
| // Success |
| } |
| |
| try { |
| genCtx.tryCreateResource(mockLogger, "asdf\\stuff.bin"); |
| fail("The backslash in the path in the previous statement should have caused an exception"); |
| } catch (UnableToCompleteException e) { |
| // Success |
| } |
| } |
| |
| /** |
| * Tests that calling commit a second time on the same OutputStream throws an |
| * exception. Note that this behavior should follow the same basic code path |
| * attempting to commit an unknown OutputStream, as in |
| * {@link #testTryCreateResource_commitWithUnknownStream()}. |
| */ |
| public void testTryCreateResource_commitCalledTwice() |
| throws UnableToCompleteException, IOException { |
| String path = "testTryCreateResource/commitCalledTwice"; |
| OutputStream os = genCtx.tryCreateResource(mockLogger, path); |
| os.write("going to call commit twice after this...".getBytes(Util.DEFAULT_ENCODING)); |
| genCtx.setCurrentGenerator(MockGenerator.class); |
| GeneratedResource res = genCtx.commitResource(mockLogger, os); |
| assertEquals(path, res.getPartialPath()); |
| assertEquals(MockGenerator.class, res.getGenerator()); |
| assertEquals(1, artifactSet.size()); |
| assertTrue(artifactSet.contains(res)); |
| try { |
| genCtx.commitResource(mockLogger, os); |
| fail("Calling commit() again on the same stream object should have caused an exception"); |
| } catch (UnableToCompleteException e) { |
| // Success |
| } |
| // Didn't change the artifactSet |
| assertEquals(1, artifactSet.size()); |
| } |
| |
| public void testTryCreateResource_commitNotCalled() |
| throws UnableToCompleteException, IOException { |
| String path = "testTryCreateResource/commitNotCalled"; |
| OutputStream os = genCtx.tryCreateResource(mockLogger, path); |
| byte[] arrayWritten = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; |
| os.write(arrayWritten); |
| |
| // Note that we're *not* committing before calling finish(). |
| genCtx.finish(mockLogger); |
| assertEquals(0, artifactSet.size()); |
| try { |
| os.write(arrayWritten); |
| fail("Expected IOException for writing after abort"); |
| } catch (IOException expected) { |
| } |
| } |
| |
| public void testTryCreateResource_commitWithBadStream() { |
| try { |
| genCtx.commitResource(mockLogger, (OutputStream) null); |
| fail("Calling commit() on a null stream should have caused an exception"); |
| } catch (UnableToCompleteException e) { |
| // Success |
| } |
| assertEquals(0, artifactSet.size()); |
| |
| try { |
| OutputStream os = new ByteArrayOutputStream(); |
| genCtx.commitResource(mockLogger, os); |
| fail("Calling commit() on a stream not returned from tryCreateResource() should have caused an exception"); |
| } catch (UnableToCompleteException e) { |
| // Success |
| } |
| assertEquals(0, artifactSet.size()); |
| } |
| |
| /** |
| * Tests that finish() can be called before and after output file creation. |
| * |
| * @throws UnableToCompleteException |
| * @throws IOException |
| * |
| */ |
| public void testTryCreateResource_creationWorksBetweenFinishes() |
| throws UnableToCompleteException, IOException { |
| genCtx.finish(mockLogger); |
| testTryCreateResource_normalCompletion("creationWorksBetweenFinishes1"); |
| genCtx.finish(mockLogger); |
| testTryCreateResource_normalCompletion("creationWorksBetweenFinishes2"); |
| genCtx.finish(mockLogger); |
| } |
| |
| public void testTryCreateResource_duplicateCreationAfterCommit() |
| throws UnableToCompleteException, UnsupportedEncodingException, |
| IOException { |
| String path = "testTryCreateResource/duplicateCreationAfterCommit"; |
| OutputStream os1 = genCtx.tryCreateResource(mockLogger, path); |
| os1.write("going to call commit twice after this...".getBytes(Util.DEFAULT_ENCODING)); |
| genCtx.commitResource(mockLogger, os1); |
| assertEquals(1, artifactSet.size()); |
| |
| OutputStream os2 = genCtx.tryCreateResource(mockLogger, path); |
| assertNull(os2); |
| } |
| |
| public void testTryCreateResource_duplicateCreationAttempt() |
| throws UnableToCompleteException { |
| String path = "testTryCreateResource/duplicateCreationAttempt"; |
| OutputStream os1 = genCtx.tryCreateResource(mockLogger, path); |
| assertNotNull(os1); |
| OutputStream os2 = genCtx.tryCreateResource(mockLogger, path); |
| assertNull(os2); |
| } |
| |
| public void testTryCreateResource_finishCalledTwice() |
| throws UnableToCompleteException, IOException { |
| // Borrow impl. |
| testTryCreateResource_commitNotCalled(); |
| |
| // Now call finish() again to make sure nothing blows up. |
| genCtx.finish(mockLogger); |
| } |
| |
| public void testTryCreateResource_normalCompletionWithoutSubDir() |
| throws UnableToCompleteException, IOException { |
| String path = "normalCompletionWithoutSubDir"; |
| testTryCreateResource_normalCompletion(path); |
| } |
| |
| public void testTryCreateResource_normalCompletionWithSubDir() |
| throws UnableToCompleteException, IOException { |
| String filename = "testTryCreateResource/normalCompletionWithSubDir"; |
| testTryCreateResource_normalCompletion(filename); |
| } |
| |
| /** |
| * Tests that tryCreateResource() returns <code>null</code> when the specified |
| * file is already on the public path. |
| * |
| * @throws UnableToCompleteException |
| * @throws IOException |
| */ |
| public void testTryCreateResource_outputFileOnPublicPath() |
| throws UnableToCompleteException { |
| OutputStream os = genCtx.tryCreateResource(mockLogger, "onPublicPath.txt"); |
| assertNull( |
| "tryCreateResource() should return null when the target file is already on the public path", |
| os); |
| assertEquals(0, artifactSet.size()); |
| } |
| |
| public void testTryCreateResource_writeAfterCommit() |
| throws UnableToCompleteException, IOException { |
| String path = "normalCompletionWithoutSubDir"; |
| OutputStream os = genCtx.tryCreateResource(mockLogger, path); |
| assertNotNull(os); |
| byte[] arrayWritten = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; |
| os.write(arrayWritten); |
| genCtx.commitResource(mockLogger, os); |
| try { |
| os.write(arrayWritten); |
| fail("Expected IOException for writing after commit"); |
| } catch (IOException expected) { |
| } |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| for (int i = toDelete.size() - 1; i >= 0; --i) { |
| File f = toDelete.get(i); |
| Util.recursiveDelete(f, false); |
| assertFalse("Unable to delete " + f.getAbsolutePath(), f.exists()); |
| } |
| } |
| |
| private void testTryCreateResource_normalCompletion(String name) |
| throws UnableToCompleteException, IOException { |
| OutputStream os = genCtx.tryCreateResource(mockLogger, name); |
| assertNotNull(os); |
| byte[] arrayWritten = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; |
| os.write(arrayWritten); |
| GeneratedResource res = genCtx.commitResource(mockLogger, os); |
| assertEquals(name, res.getPartialPath()); |
| assertTrue(artifactSet.contains(res)); |
| |
| // Read the file. |
| byte[] arrayRead = Util.readStreamAsBytes(res.getContents(mockLogger)); |
| assertTrue(Arrays.equals(arrayWritten, arrayRead)); |
| } |
| |
| } |