@Test public void uiField() throws Exception { compilationHelper .addSourceLines( "com/google/gwt/uibinder/client/UiField.java", "package com.google.gwt.uibinder.client;", "public @interface UiField {}") .addSourceLines("Box.java", "public class Box<T> {", " T get() { return null; }", "}") .addSourceLines( "Widget.java", "import com.google.gwt.uibinder.client.UiField;", "public class Widget {", " @UiField Box<Boolean> l;", "}") .addSourceLines( "Test.java", "import static org.mockito.Mockito.when;", "import static org.mockito.Answers.RETURNS_SMART_NULLS;", "class Test {", " Widget w;", " void m(Iterable<Boolean> xs) {", " // BUG: Diagnostic contains: when((Object) w.l.get()).thenReturn(null);", " when(w.l.get()).thenReturn(null);", " }", "}") .doTest(); }
@Test public void imported() throws Exception { compilationHelper .addSourceLines( "pkg/Bound.java", "package pkg;", "public class Bound {", " public static class Inner {}", " public static class Sub extends Inner {}", "}") .addSourceLines( "Foo.java", "import pkg.Bound;", "public class Foo {", " public <T extends Bound.Inner> T f(Iterable<T> xs) { return xs.iterator().next(); }", "}") .addSourceLines( "Test.java", "import static org.mockito.Mockito.when;", "import static org.mockito.Answers.RETURNS_SMART_NULLS;", "import org.mockito.Mock;", "class Test {", " final int ONE = 1;", " final int TWO = 1;", " @Mock(answer = RETURNS_SMART_NULLS) Foo l;", " void m(Iterable<pkg.Bound.Sub> xs) {", " // BUG: Diagnostic contains: when((Bound.Inner) l.f(xs)).thenReturn(null);", " when(l.f(xs)).thenReturn(null);", " }", "}") .doTest(); }
@Test public void testLocked() throws Exception { compilationHelper .addSourceLines( "threadsafety/Test.java", "package threadsafety;", "import javax.annotation.concurrent.GuardedBy;", "import java.util.concurrent.locks.Lock;", "class Test {", " final Lock mu = null;", " final Lock lock = null;", " @GuardedBy(\"lock\")", " int x;", " void m() {", " mu.lock();", " // BUG: Diagnostic contains: []", " x++;", " try {", " // BUG: Diagnostic contains:", " // [(SELECT (THIS) mu)]", " x++;", " } finally {", " mu.unlock();", " }", " // BUG: Diagnostic contains: []", " x++;", " }", "}") .doTest(); }
// regression test for #418 @Test public void typeParameter() { compilationHelper .addSourceLines( "Nullable.java", "import java.lang.annotation.ElementType;", "import java.lang.annotation.Retention;", "import java.lang.annotation.RetentionPolicy;", "import java.lang.annotation.Target;", "@Retention(RetentionPolicy.RUNTIME)", "@Target(ElementType.TYPE_USE)", "public @interface Nullable {}") .addSourceLines( "Test.java", "class Test {", " // BUG: Diagnostic contains:", " @Nullable int x;", " // BUG: Diagnostic contains:", " @Nullable int f() {", " return 42;", " }", " <@Nullable T> int g() {", " return 42;", " }", " int @Nullable [] y;", "}") .doTest(); }
@Test public void interfaceMethod() { compilationHelper .addSourceLines( "Test.java", // TODO(b/21633565): force line break "interface Test {", " void f(int y);", "}") .doTest(); }
@Test public void abstractMethod() { compilationHelper .addSourceLines( "Test.java", // TODO(b/21633565): force line break "abstract class Test {", " abstract void f(int y);", "}") .doTest(); }
@Test public void unnecessaryFinalNativeMethod() { compilationHelper .addSourceLines( "Test.java", "class Test {", " // BUG: Diagnostic contains: native void f(int y);", " native void f(final int y);", "}") .doTest(); }
@Test public void finalField() { compilationHelper .addSourceLines( "Test.java", // TODO(b/21633565): force line break "class Test {", " public final int x = 42;", "}") .doTest(); }
@Test public void negativeVoid() { compilationHelper .addSourceLines( "Test.java", "import javax.annotation.Nullable;", "class Test {", " @Nullable void f() {}", "}") .doTest(); }
@Test public void varField() { compilationHelper .addSourceLines( "Test.java", "import com.google.errorprone.annotations.Var;", "class Test {", " @Var public int x = 42;", "}") .doTest(); }
@Test public void negativeParam() { compilationHelper .addSourceLines( "Test.java", // TODO(b/21633565): force line break "class Test {", " public void x(int y) {", " }", "}") .doTest(); }
@Test public void enhancedFor() { compilationHelper .addSourceLines( "Test.java", "class Test {", " void f (Iterable<String> xs) {", " for (String x : xs) {", " }", " }", "}") .doTest(); }
@Test public void forLoop() { compilationHelper .addSourceLines( "Test.java", "class Test {", " {", " for (int i = 0; i < 10; i++) {", " }", " }", "}") .doTest(); }
@Test public void varParam() { compilationHelper .addSourceLines( "Test.java", "import com.google.errorprone.annotations.Var;", "class Test {", " public void x(@Var int y) {", " y++;", " }", "}") .doTest(); }
@Test public void positiveParam() { compilationHelper .addSourceLines( "Test.java", "class Test {", " // BUG: Diagnostic contains: public void x(@Var int y) {", " public void x(int y) {", " y++;", " }", "}") .doTest(); }
@Test public void finalLocal7() { compilationHelper .addSourceLines( "Test.java", // TODO(b/21633565): force line break "class Test {", " public void x() {", " final int y = 0;", " }", "}") .setArgs(Arrays.asList("-source", "7", "-target", "7")) .doTest(); }
@Test public void finalLocal8() { compilationHelper .addSourceLines( "Test.java", "class Test {", " public void x() {", " // BUG: Diagnostic contains: /*START*/ int y = 0;", " /*START*/ final int y = 0;", " }", "}") .setArgs(Arrays.asList("-source", "8", "-target", "8")) .doTest(); }
@Test public void varInitializedWithUnsupportedAnswer() throws Exception { compilationHelper .addSourceLines("Box.java", "public class Box<T> {", " T f() { return null; }", "}") .addSourceLines( "Test.java", "import org.mockito.Mockito;", "class Test {", " Box<Boolean> box = Mockito.mock(Box.class, Mockito.RETURNS_SMART_NULLS);", " void m() {", " // BUG: Diagnostic contains: when((Object) box.f()).thenReturn(false);", " Mockito.when(box.f()).thenReturn(false);", " }", "}") .doTest(); }
@Test public void testSynchronizedMethod() throws Exception { compilationHelper .addSourceLines( "threadsafety/Test.java", "package threadsafety;", "import javax.annotation.concurrent.GuardedBy;", "import java.util.concurrent.locks.Lock;", "class Test {", " @GuardedBy(\"this\")", " int x;", " synchronized void m() {", " // BUG: Diagnostic contains: [(THIS)]", " x++;", " }", "}") .doTest(); }
@Test public void mockedFieldInstantiationOfGenericType() throws Exception { compilationHelper .addSourceLines("Super.java", "public class Super<T> {", " T f() { return null; }", "}") .addSourceLines("Sub.java", "public class Sub extends Super<Boolean> {", "}") .addSourceLines( "Test.java", "import static org.mockito.Mockito.when;", "import static org.mockito.Answers.RETURNS_SMART_NULLS;", "import org.mockito.Mock;", "class Test {", " @Mock(answer = RETURNS_SMART_NULLS) Super<Boolean> s;", " void m() {", " // BUG: Diagnostic contains: when((Object) s.f()).thenReturn(false);", " when(s.f()).thenReturn(false);", " }", "}") .doTest(); }
@Test public void chainedCallOnUnsupportedMock() throws Exception { compilationHelper .addSourceLines( "Foo.java", "public class Foo {", " Bar<Boolean> bar() { return null; }", "}") .addSourceLines("Bar.java", "public class Bar<T> {", " T get() { return null; }", "}") .addSourceLines( "Test.java", "import static org.mockito.Mockito.when;", "import static org.mockito.Answers.RETURNS_SMART_NULLS;", "import org.mockito.Mock;", "class Test {", " @Mock(answer = RETURNS_SMART_NULLS) Foo f;", " void m() {", " // BUG: Diagnostic contains: when((Object) f.bar().get()).thenReturn(false);", " when(f.bar().get()).thenReturn(false);", " }", "}") .doTest(); }
@Test public void defaultAnswerOk() throws Exception { compilationHelper .addSourceLines( "Foo.java", "public class Foo {", " public <T> T f(Iterable<T> xs) { return xs.iterator().next(); }", "}") .addSourceLines( "Test.java", "import static org.mockito.Mockito.when;", "import static org.mockito.Answers.RETURNS_SMART_NULLS;", "import org.mockito.Mock;", "class Test {", " @Mock Foo l;", " void m(Iterable<Boolean> xs) {", " when(l.f(xs)).thenReturn(false);", " }", "}") .doTest(); }
@Test public void testSynchronizedClass() throws Exception { compilationHelper .addSourceLines( "threadsafety/Test.java", "package threadsafety;", "import javax.annotation.concurrent.GuardedBy;", "class Lock {}", "class Test {", " final Lock mu = new Lock();", " @GuardedBy(\"this\")", " int x;", " void m() {", " synchronized (Lock.class) {", " // BUG: Diagnostic contains: [(CLASS_LITERAL threadsafety.Lock)]", " x++;", " }", " }", "}") .doTest(); }
@Test public void testLockMethodEnclosingAccess() throws Exception { compilationHelper .addSourceLines( "threadsafety/Test.java", "package threadsafety;", "import javax.annotation.concurrent.GuardedBy;", "import com.google.errorprone.annotations.concurrent.LockMethod;", "import com.google.errorprone.annotations.concurrent.UnlockMethod;", "import java.util.concurrent.locks.Lock;", "class Outer {", " Lock lock;", " class Inner {", " @GuardedBy(\"lock\")", " int x;", " ", " @LockMethod(\"lock\")", " void lock() {", " lock.lock();", " }", " ", " @UnlockMethod(\"lock\")", " void unlock() {", " lock.unlock();", " }", " ", " void m(Inner i) {", " i.lock();", " try {", " // BUG: Diagnostic contains:", " // [(SELECT (SELECT (LOCAL_VARIABLE i) outer$threadsafety.Outer) lock)]", " i.x++;", " } finally {", " i.unlock();", " }", " }", " }", "}") .doTest(); }
@Test public void testSynchronizedField() throws Exception { compilationHelper .addSourceLines( "threadsafety/Test.java", "package threadsafety;", "import javax.annotation.concurrent.GuardedBy;", "class Lock { final Object lock = null; }", "class Test {", " final Lock mu = new Lock();", " @GuardedBy(\"this\")", " int x;", " void m() {", " synchronized (mu.lock) {", " // BUG: Diagnostic contains:", " // [(SELECT (SELECT (THIS) mu) lock)]", " x++;", " }", " }", "}") .doTest(); }
@Test public void mockAnnotationWithUnsupportedAnswer() throws Exception { compilationHelper .addSourceLines( "Foo.java", "public class Foo {", " public <T> T f(Iterable<T> xs) { return xs.iterator().next(); }", "}") .addSourceLines( "Test.java", "import static org.mockito.Mockito.when;", "import static org.mockito.Answers.RETURNS_SMART_NULLS;", "import org.mockito.Mock;", "class Test {", " @Mock(answer = RETURNS_SMART_NULLS) Foo l;", " void m(Iterable<Boolean> xs) {", " // BUG: Diagnostic contains: when((Object) l.f(xs)).thenReturn(false);", " when(l.f(xs)).thenReturn(false);", " }", "}") .doTest(); }
@Test public void erasureIsNotObject() throws Exception { compilationHelper .addSourceLines( "Super.java", "public class Super<T extends Boolean> {", " T f() { return null; }", "}") .addSourceLines("Sub.java", "public class Sub extends Super<Boolean> {", "}") .addSourceLines( "Test.java", "import static org.mockito.Mockito.when;", "import static org.mockito.Answers.RETURNS_SMART_NULLS;", "import org.mockito.Mock;", "class Test {", " @Mock(answer = RETURNS_SMART_NULLS) Super<Boolean> s;", " void m() {", " when(s.f()).thenReturn(false);", " }", "}") .doTest(); }
@Test public void testTwoInstances() throws Exception { compilationHelper .addSourceLines( "threadsafety/Test.java", "package threadsafety;", "import javax.annotation.concurrent.GuardedBy;", "import java.util.concurrent.locks.Lock;", "class Test {", " final Lock lock = null;", " @GuardedBy(\"lock\")", " int x;", " void m(Lock lock2) {", " lock.lock();", " lock2.lock();", " try {", " // BUG: Diagnostic contains:", " // [(LOCAL_VARIABLE lock2), (SELECT (THIS) lock)]", " x++;", " } finally { lock.unlock(); lock2.unlock(); }", " }", "}") .doTest(); }
// fields are ignored @Test public void nonFinalField() { compilationHelper .addSourceLines("Test.java", "class Test {", " public int x = 42;", "}") .doTest(); }