/*
* Copyright 2014 Google Inc. All rights reserved.
*
* 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.errorprone.refaster;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assert_;
import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;
import com.google.common.base.CharMatcher;
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Iterables;
import com.google.errorprone.CodeTransformer;
import com.google.testing.compile.JavaFileObjects;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.Tree;
import java.io.IOException;
import javax.tools.JavaFileObject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Tests for Refaster templates.
*
* @author lowasser@google.com (Louis Wasserman)
*/
@RunWith(JUnit4.class)
public class TemplateIntegrationTest extends CompilerBasedTest {
private CodeTransformer extractRefasterRule(JavaFileObject object) {
compile(object);
ClassTree classTree =
Iterables.getOnlyElement(
FluentIterable.from(compilationUnits)
.transformAndConcat(
new Function<CompilationUnitTree, Iterable<? extends Tree>>() {
@Override
public Iterable<? extends Tree> apply(CompilationUnitTree input) {
return input.getTypeDecls();
}
})
.filter(ClassTree.class));
return Iterables.getOnlyElement(RefasterRuleBuilderScanner.extractRules(classTree, context));
}
private void expectTransforms(CodeTransformer transformer, JavaFileObject input,
JavaFileObject expectedOutput) throws IOException {
JavaFileObject transformedInput =
CodeTransformerTestHelper.create(transformer).transform(input);
// TODO(lowasser): modify compile-testing to enable direct tree comparison
assert_().about(javaSource()).that(transformedInput).compilesWithoutError();
String expectedSource = expectedOutput.getCharContent(false).toString();
String actualSource = transformedInput.getCharContent(false).toString();
assertThat(CharMatcher.whitespace().collapseFrom(actualSource, ' '))
.isEqualTo(CharMatcher.whitespace().collapseFrom(expectedSource, ' '));
}
private static final String TEMPLATE_DIR = "com/google/errorprone/refaster/testdata/template";
private static final String INPUT_DIR = "com/google/errorprone/refaster/testdata/input";
private static final String OUTPUT_DIR = "com/google/errorprone/refaster/testdata/output";
private void runTest(String testName) throws IOException {
CodeTransformer transformer = extractRefasterRule(
JavaFileObjects.forResource(String.format("%s/%s.java", TEMPLATE_DIR, testName)));
JavaFileObject input =
JavaFileObjects.forResource(String.format("%s/%sExample.java", INPUT_DIR, testName));
JavaFileObject output =
JavaFileObjects.forResource(String.format("%s/%sExample.java", OUTPUT_DIR, testName));
expectTransforms(transformer, input, output);
}
@Test
public void binary() throws IOException {
runTest("BinaryTemplate");
}
@Test
public void parenthesesOptional() throws IOException {
runTest("ParenthesesOptionalTemplate");
}
@Test
public void multipleReferencesToIdentifier() throws IOException {
runTest("MultipleReferencesToIdentifierTemplate");
}
@Test
public void methodInvocation() throws IOException {
runTest("MethodInvocationTemplate");
}
@Test
public void explicitTypesPreserved() throws IOException {
runTest("ExplicitTypesPreservedTemplate");
}
@Test
public void implicitTypesInlined() throws IOException {
runTest("ImplicitTypesInlinedTemplate");
}
@Test
public void autoboxing() throws IOException {
runTest("AutoboxingTemplate");
}
@Test
public void array() throws IOException {
runTest("ArrayTemplate");
}
@Test
public void precedenceSensitive() throws IOException {
runTest("PrecedenceSensitiveTemplate");
}
@Test
public void staticField() throws IOException {
runTest("StaticFieldTemplate");
}
@Test
public void isInstance() throws IOException {
runTest("IsInstanceTemplate");
}
@Test
public void anyOf() throws IOException {
runTest("AnyOfTemplate");
}
@Test
public void repeated() throws IOException {
runTest("VarargTemplate");
}
@Test
public void ifTemplate() throws IOException {
runTest("IfTemplate");
}
@Test
public void variableDecl() throws IOException {
runTest("VariableDeclTemplate");
}
@Test
public void inferredThis() throws IOException {
runTest("InferredThisTemplate");
}
@Test
public void twoLinesToOne() throws IOException {
runTest("TwoLinesToOneTemplate");
}
@Test
public void oneLineToTwo() throws IOException {
runTest("OneLineToTwoTemplate");
}
@Test
public void tryCatch() throws IOException {
runTest("TryTemplate");
}
@Test
public void tryMultiCatch() throws IOException {
runTest("TryMultiCatchTemplate");
}
@Test
public void wildcard() throws IOException {
runTest("WildcardTemplate");
}
@Test
public void freeIdentWildcardCapture() throws IOException {
runTest("WildcardUnificationTemplate");
}
@Test
public void labeledStatements() throws IOException {
runTest("LabelTemplate");
}
@Test
public void expressionPlaceholder() throws IOException {
runTest("PlaceholderTemplate");
}
@Test
public void expressionPlaceholderAllowsIdentity() throws IOException {
runTest("PlaceholderAllowsIdentityTemplate");
}
@Test
public void blockPlaceholder() throws IOException {
runTest("BlockPlaceholderTemplate");
}
@Test
public void genericPlaceholder() throws IOException {
runTest("GenericPlaceholderTemplate");
}
@Test
public void mayOptionallyUse() throws IOException {
runTest("MayOptionallyUseTemplate");
}
@Test
public void comparisonChain() throws IOException {
runTest("ComparisonChainTemplate");
}
@Test
public void multibound() throws IOException {
runTest("MultiBoundTemplate");
}
@Test
public void topLevel() throws IOException {
runTest("TopLevelTemplate");
}
@Test
public void diamond() throws IOException {
runTest("DiamondTemplate");
}
@Test
public void anonymousClass() throws IOException {
runTest("AnonymousClassTemplate");
}
@Test
public void returnPlaceholder() throws IOException {
runTest("ReturnPlaceholderTemplate");
}
@Test
public void literal() throws IOException {
runTest("LiteralTemplate");
}
@Test
public void importClassDirectly() throws IOException {
runTest("ImportClassDirectlyTemplate");
}
@Test
public void assertions() throws IOException {
runTest("AssertTemplate");
}
@Test
public void samePackageImports() throws IOException {
runTest("SamePackageImportsTemplate");
}
@Test
public void ifFallthrough() throws IOException {
runTest("IfFallthroughTemplate");
}
@Test
public void emitCommentBefore() throws IOException {
runTest("EmitCommentBeforeTemplate");
}
@Test
public void emitComment() throws IOException {
runTest("EmitCommentTemplate");
}
@Test
public void nestedClass() throws IOException {
runTest("NestedClassTemplate");
}
@Test
public void inferLambdaType() throws IOException {
runTest("InferLambdaType");
}
@Test
public void lambdaImplicitType() throws IOException {
runTest("LambdaImplicitType");
}
@Test
public void inferLambdaBodyType() throws IOException {
runTest("InferLambdaBodyType");
}
@Test
public void asVarargs() throws IOException {
runTest("AsVarargsTemplate");
}
}