blob: db4fb653bc20492b816e41a7f65663373b1994cc [file] [log] [blame]
/*
* Copyright 2009 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.resources.rg;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.resources.css.GenerateCssAst;
import com.google.gwt.resources.css.ast.CssNode;
import com.google.gwt.resources.css.ast.CssStylesheet;
import com.google.gwt.resources.css.ast.CssVisitor;
import com.google.gwt.resources.css.ast.HasNodes;
import com.google.gwt.resources.ext.ClientBundleRequirements;
import com.google.gwt.resources.ext.ResourceContext;
import junit.framework.TestCase;
import java.net.URL;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
/**
* Contains functions for golden-output tests that are concerned with structural
* modifications to the CSS AST.
*/
public class CssTestCase extends TestCase {
/*
* NB: This class is in the resources.rg package so that it can access
* package-protected methods in CssResourceGenerator.
*/
/**
* Triggers an assertion if a CssNode is traversed more than once.
*
* @see CssTestCase#assertNoAliasing(CssNode)
*/
public static class AliasDetector extends CssVisitor {
private final Map<CssNode, Void> seen = new IdentityHashMap<CssNode, Void>();
@Override
protected void doAccept(List<? extends CssNode> list) {
for (CssNode node : list) {
doAccept(node);
}
}
@Override
protected <T extends CssNode> T doAccept(T node) {
assertFalse("Found repeated node " + node.toString(),
seen.containsKey(node));
seen.put(node, null);
return super.doAccept(node);
}
@Override
protected void doAcceptWithInsertRemove(List<? extends CssNode> list) {
for (CssNode node : list) {
doAccept(node);
}
}
}
/**
* Total fake, no implementations.
*/
private static class FakeContext implements ResourceContext {
@Override
public String deploy(String suggestedFileName, String mimeType,
byte[] data, boolean forceExternal) throws UnableToCompleteException {
return null;
}
@Override
@Deprecated
public String deploy(URL resource, boolean forceExternal)
throws UnableToCompleteException {
return null;
}
@Override
public String deploy(URL resource, String mimeType, boolean forceExternal)
throws UnableToCompleteException {
return null;
}
@Override
public <T> T getCachedData(String key, Class<T> clazz) {
return null;
}
@Override
public JClassType getClientBundleType() {
return null;
}
@Override
public GeneratorContext getGeneratorContext() {
return null;
}
@Override
public String getImplementationSimpleSourceName()
throws IllegalStateException {
return null;
}
@Override
public ClientBundleRequirements getRequirements() {
return null;
}
@Override
public <T> boolean putCachedData(String key, T value) {
return false;
}
@Override
public boolean supportsDataUrls() {
return true;
}
}
/**
* Asserts that two CssNodes are identical.
*/
protected static <T extends CssNode & HasNodes> void assertEquals(
TreeLogger logger, T expected, T test) throws UnableToCompleteException {
String expectedCss = CssResourceGenerator.makeExpression(logger,
new FakeContext(), expected, false);
String testCss = CssResourceGenerator.makeExpression(logger,
new FakeContext(), test, false);
assertEquals(expectedCss, testCss);
}
/**
* Ensure that no CssNode is traversed more than once due to AST errors.
*/
protected static void assertNoAliasing(CssNode node) {
(new AliasDetector()).accept(node);
}
/**
* Compares the generated Java expressions for an input file, transformed in
* order by the specified visitors, and a golden-output file.
*/
private static void test(TreeLogger logger, URL test, URL expected,
CssVisitor... visitors) throws UnableToCompleteException {
CssStylesheet expectedSheet = null;
CssStylesheet testSheet = null;
try {
expectedSheet = GenerateCssAst.exec(logger, expected);
testSheet = GenerateCssAst.exec(logger, test);
} catch (UnableToCompleteException e) {
fail("Unable to parse stylesheet");
}
for (CssVisitor v : visitors) {
v.accept(testSheet);
}
assertEquals(logger, expectedSheet, testSheet);
}
/**
* Runs a test.
*
* @param testName is used to compute the test and expected resource paths.
* @param reversible if <code>true</code>, the test will attempt to transform
* the expected css into the test css
*/
protected void test(TreeLogger logger, String testName, boolean reversible,
CssVisitor... visitors) throws UnableToCompleteException {
String packagePath = getClass().getPackage().getName().replace('.', '/')
+ "/";
URL testUrl = getClass().getClassLoader().getResource(
packagePath + testName + "_test.css");
assertNotNull("Could not find testUrl", testUrl);
URL expectedUrl = getClass().getClassLoader().getResource(
packagePath + testName + "_expected.css");
assertNotNull("Could not find testUrl", expectedUrl);
test(logger, testUrl, expectedUrl, visitors);
if (reversible) {
test(logger, expectedUrl, testUrl, visitors);
}
}
}