/*
* Copyright 2012 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.bugpatterns;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.errorprone.CompilationTestHelper;
import com.google.errorprone.VisitorState;
import com.google.errorprone.matchers.CompilerBasedAbstractTest;
import com.google.errorprone.scanner.Scanner;
import com.sun.source.tree.ExpressionStatementTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.IdentifierTree;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* @author eaftan@google.com (Eddie Aftandilian)
*/
@RunWith(JUnit4.class)
public class PreconditionsCheckNotNullPrimitiveTest extends CompilerBasedAbstractTest {
private CompilationTestHelper compilationHelper;
@Before
public void setUp() {
compilationHelper =
CompilationTestHelper.newInstance(PreconditionsCheckNotNullPrimitive.class, getClass());
}
@Test
public void testPositiveCases() throws Exception {
compilationHelper.addSourceFile("PreconditionsCheckNotNullPrimitivePositiveCases.java")
.doTest();
}
@Test
public void testNegativeCase1() throws Exception {
compilationHelper.addSourceFile("PreconditionsCheckNotNullPrimitiveNegativeCases.java")
.doTest();
}
@Test
public void testGetVariableUses() {
writeFile("A.java",
"public class A {",
" public String b;",
" void foo() {}",
"}");
writeFile("B.java",
"public class B {",
" A my;",
" B bar() { return null; }",
" void foo(String x, A a) {",
" x.trim().intern();",
" a.b.trim().intern();",
" this.my.foo();",
" my.foo();",
" this.bar();",
" String.valueOf(0);",
" java.lang.String.valueOf(1);",
" bar().bar();",
" System.out.println();",
" a.b.indexOf(x.substring(1));",
" }",
"}");
TestScanner scanner = new TestScanner.Builder()
.add("x.trim().intern()", "x")
.add("a.b.trim().intern()", "a")
.add("this.my.foo()", "this")
.add("my.foo()", "my")
.add("this.bar()", "this")
.add("String.valueOf(0)")
.add("java.lang.String.valueOf(1)")
.add("bar().bar()")
.add("System.out.println()")
.add("a.b.indexOf(x.substring(1))", "a", "x")
.build();
assertCompiles(scanner);
scanner.assertFoundAll();
}
// TODO(mdempsky): Make this more reusable.
private static class TestScanner extends Scanner {
private static class Match {
private final ImmutableList<String> expected;
private boolean found = false;
private Match(String... expected) {
this.expected = ImmutableList.copyOf(expected);
}
}
private static class Builder {
private final ImmutableMap.Builder<String, Match> builder = ImmutableMap.builder();
public Builder add(String expression, String... expected) {
builder.put(expression, new Match(expected));
return this;
}
public TestScanner build() {
return new TestScanner(builder.build());
}
}
private final ImmutableMap<String, Match> matches;
private TestScanner(ImmutableMap<String, Match> matches) {
this.matches = matches;
}
@Override
public Void visitExpressionStatement(ExpressionStatementTree node, VisitorState state) {
ExpressionTree expression = node.getExpression();
Match match = matches.get(expression.toString());
if (match != null) {
assertMatch(expression, match.expected);
match.found = true;
}
return super.visitExpressionStatement(node, state);
}
private void assertMatch(ExpressionTree node, List<String> expected) {
List<IdentifierTree> uses = PreconditionsCheckNotNullPrimitive.getVariableUses(node);
assertEquals("variables used in " + node, expected,
Lists.transform(uses, new Function<IdentifierTree, String>() {
@Override
public String apply(IdentifierTree ident) {
return ident.toString();
}
}));
}
public void assertFoundAll() {
for (Map.Entry<String, Match> entry : matches.entrySet()) {
assertTrue("found " + entry.getKey(), entry.getValue().found);
}
}
}
}