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