/*
* 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.common.css.compiler.ast.testing;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.css.SourceCode;
import com.google.common.css.compiler.ast.BasicErrorManager;
import com.google.common.css.compiler.ast.CssTree;
import com.google.common.css.compiler.ast.ErrorManager;
import com.google.common.css.compiler.ast.GssError;
import com.google.common.css.compiler.ast.GssParser;
import com.google.common.css.compiler.ast.GssParserException;
import com.google.common.css.compiler.passes.PrettyPrinter;
import java.util.List;
import java.util.Map;
/**
* Base class for testing the passes which use an {@link ErrorManager}.
*
*/
public class NewFunctionalTestBase extends FunctionalTestCommonBase {
protected static final String TEST_FILENAME = "test";
protected ErrorManager errorManager;
@Override
public void parseAndBuildTree(String sourceCode) {
parseAndBuildTree(ImmutableMap.of(TEST_FILENAME, sourceCode));
}
/**
* Parses GSS style sheets and calls fail if an exception is thrown.
*
* @param fileNameToGss a map connecting names to GSS style sheets
*/
public void parseAndBuildTree(ImmutableMap<String, String> fileNameToGss) {
try {
parseAndRun(fileNameToGss);
} catch (GssParserException e) {
fail(e.getMessage());
}
}
/**
* Parses a GSS style sheet and returns the tree. In addition, it checks
* whether the actual error messages exactly match the expected ones.
*
* @param gss the GSS style sheet
* @param expectedMessages the expected error messages in the right order
* @return the CSS tree created by the parser
* @throws GssParserException
*/
protected CssTree parseAndRun(String gss, String ... expectedMessages)
throws GssParserException {
return parseAndRun(
ImmutableMap.of(TEST_FILENAME, gss), true /* exactMatch */,
expectedMessages);
}
/**
* Parses a GSS style sheet and returns the tree. In addition, it checks
* whether the actual error messages match the expected ones.
*
* @param gss the GSS style sheet
* @param exactMatch Determines if the actual error messages have to exactly
* match the expected ones or only have to contain them.
* @param expectedMessages the expected error messages or parts of the
* messages in the right order
* @return the CSS tree created by the parser
* @throws GssParserException
*/
protected CssTree parseAndRun(String gss, boolean exactMatch,
String... expectedMessages) throws GssParserException {
return parseAndRun(
ImmutableMap.of(TEST_FILENAME, gss), exactMatch, expectedMessages);
}
/**
* Parses GSS style sheets and returns one tree containing everything.
* In addition, it checks whether the actual error messages exactly match
* the expected ones.
*
* @param fileNameToGss a map connecting names to GSS style sheets
* @param expectedMessages the expected error messages in the right order
* @return the CSS tree created by the parser
* @throws GssParserException
*/
protected CssTree parseAndRun(
ImmutableMap<String, String> fileNameToGss,
String... expectedMessages) throws GssParserException {
return parseAndRun(fileNameToGss, true /* exactMatch */, expectedMessages);
}
/**
* Parses GSS style sheets and returns one tree containing everything.
* In addition, it checks whether the actual error messages exactly match
* the expected ones.
*
* @param fileNameToGss a map connecting names to GSS style sheets
* @param exactMatch Determines if the actual error messages have to exactly
* match the expected ones or only have to contain them.
* @param expectedMessages the expected error messages or parts of the
* messages in the right order
* @return the CSS tree created by the parser
* @throws GssParserException
*/
protected CssTree parseAndRun(
ImmutableMap<String, String> fileNameToGss, boolean exactMatch,
String... expectedMessages) throws GssParserException {
tree = parse(fileNameToGss);
errorManager = new TestErrorManager(exactMatch, expectedMessages);
runPass();
errorManager.generateReport();
assertTrue("Encountered all errors.",
((TestErrorManager)errorManager).hasEncounteredAllErrors());
return tree;
}
/**
* Parses GSS style sheets and returns one tree containing everything.
*
* @param fileNameToGss a map connecting names to GSS style sheets
* @return the CSS tree created by the parser
* @throws GssParserException
*/
protected CssTree parse(ImmutableMap<String, String> fileNameToGss)
throws GssParserException {
ImmutableList.Builder<SourceCode> builder = ImmutableList.builder();
for (Map.Entry<String, String> entry : fileNameToGss.entrySet()) {
builder.add(new SourceCode(entry.getKey(), entry.getValue()));
}
return new GssParser(builder.build()).parse();
}
public ErrorManager getErrorManager() {
return errorManager;
}
public CssTree getTree() {
return tree;
}
/**
* Normalizes the compiled CSS to a pretty-printed form that can be compared
* with the result of {@link #normalizeExpectedCss(String)}.
*/
private String getCompiledCss() {
PrettyPrinter prettyPrinterPass = new PrettyPrinter(tree
.getVisitController());
prettyPrinterPass.runPass();
return prettyPrinterPass.getPrettyPrintedString();
}
/**
* Normalizes the expected CSS to a pretty-printed form that can be compared
* with the result of {@link #getCompiledCss()}.
*/
private static String normalizeExpectedCss(String expectedCss)
throws GssParserException {
List<SourceCode> inputs = ImmutableList.of(
new SourceCode("expectedCss", expectedCss));
CssTree tree = new GssParser(inputs).parse();
PrettyPrinter prettyPrinterPass = new PrettyPrinter(tree
.getVisitController());
prettyPrinterPass.runPass();
return prettyPrinterPass.getPrettyPrintedString();
}
/**
* Takes a string of GSS to compile and the CSS that should be produced as a
* result of compilation. The compiled GSS and expected CSS will be normalized
* to a pretty-printed format for comparison, so it is not necessary to format
* either by hand.
*/
protected void test(String inputGss, String expectedCss)
throws GssParserException {
parseAndRun(inputGss);
assertEquals(normalizeExpectedCss(expectedCss), getCompiledCss());
}
/**
* Used to check whether the actual error messages match the expected ones.
*/
public static class TestErrorManager extends BasicErrorManager {
private final String[] expectedMessages;
private int currentIndex = 0;
private boolean exactMatch;
public TestErrorManager(String[] expectedMessages) {
this(true, expectedMessages);
}
/**
* Used to check whether the actual error messages match the expected ones.
*
* @param exactMatch Determines if the actual error messages have to exactly
* match the expected ones or only have to contain them.
* @param expectedMessages the expected error messages or parts of the
* messages in the right order
*/
public TestErrorManager(boolean exactMatch, String[] expectedMessages) {
this.exactMatch = exactMatch;
this.expectedMessages = expectedMessages;
}
@Override
public void generateReport() {
for (GssError error : errors) {
print(error);
}
for (GssError warning : warnings) {
print(warning);
}
}
public void print(GssError error) {
assertTrue("Unexpected extra error: " + error.format(),
currentIndex < expectedMessages.length);
print(error.getMessage());
}
@Override
public void print(String message) {
assertTrue("Unexpected extra error: " + message,
currentIndex < expectedMessages.length);
if (exactMatch) {
assertEquals(expectedMessages[currentIndex], message);
} else {
assertTrue("Expected error '" + message + "' to contain '"
+ expectedMessages[currentIndex] + "'.",
message.contains(expectedMessages[currentIndex]));
}
currentIndex++;
}
public boolean hasEncounteredAllErrors() {
return currentIndex == expectedMessages.length;
}
}
}