/*
* Copyright 2015 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 com.google.errorprone.CompilationTestHelper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Tests for {@code ForOverrideChecker}.
*/
@RunWith(JUnit4.class)
public class ForOverrideCheckerTest {
private CompilationTestHelper compilationHelper;
@Before
public void setUp() throws Exception {
compilationHelper =
CompilationTestHelper.newInstance(ForOverrideChecker.class, getClass())
.addSourceLines(
"test/ExtendMe.java",
"package test;",
"import com.google.errorprone.annotations.ForOverride;",
"public class ExtendMe {",
" @ForOverride",
" protected int overrideMe() { return 1; }",
"",
" public final void callMe() {",
" overrideMe();",
" }",
"}");
}
@Test
public void testCanApplyForOverrideToProtectedMethod() throws Exception {
compilationHelper
.addSourceLines(
"test/Test.java",
"package test;",
"import com.google.errorprone.annotations.ForOverride;",
"public class Test {",
" @ForOverride protected void myMethod() {}",
"}")
.doTest();
}
@Test
public void testCanApplyForOverrideToPackagePrivateMethod() throws Exception {
compilationHelper
.addSourceLines(
"test/Test.java",
"package test;",
"import com.google.errorprone.annotations.ForOverride;",
"public class Test {",
" @ForOverride void myMethod() {}",
"}")
.doTest();
}
@Test
public void testCannotApplyForOverrideToPublicMethod() throws Exception {
compilationHelper
.addSourceLines(
"test/Test.java",
"package test;",
"import com.google.errorprone.annotations.ForOverride;",
"public class Test {",
" // BUG: Diagnostic contains: must have protected or package-private visibility",
" @ForOverride public void myMethod() {}",
"}")
.doTest();
}
@Test
public void testCannotApplyForOverrideToPrivateMethod() throws Exception {
compilationHelper
.addSourceLines(
"test/Test.java",
"package test;",
"import com.google.errorprone.annotations.ForOverride;",
"public class Test {",
" // BUG: Diagnostic contains: must have protected or package-private visibility",
" @ForOverride private void myMethod() {}",
"}")
.doTest();
}
@Test
public void testCannotApplyForOverrideToInterfaceMethod() throws Exception {
compilationHelper
.addSourceLines(
"test/Test.java",
"package test;",
"import com.google.errorprone.annotations.ForOverride;",
"public interface Test {",
" // BUG: Diagnostic contains: must have protected or package-private visibility",
" @ForOverride void myMethod();",
"}")
.doTest();
}
@Test
public void testUserCanCallAppropriateMethod() throws Exception {
compilationHelper
.addSourceLines(
"test/Test.java",
"package test;",
"public class Test extends test.ExtendMe {",
" public void googleyMethod() {",
" callMe();",
" }",
"}")
.doTest();
}
@Test
public void testUserInSamePackageCannotCallMethod() throws Exception {
compilationHelper
.addSourceLines(
"test/Test.java",
"package test;",
"public class Test {",
" public void tryCall() {",
" ExtendMe extendMe = new ExtendMe();",
" // BUG: Diagnostic contains: must not be invoked",
" extendMe.overrideMe();",
" }",
"}")
.doTest();
}
@Test
public void testUserCannotCallDefault() throws Exception {
compilationHelper
.addSourceLines(
"test/Test.java",
"package test;",
"public class Test extends test.ExtendMe {",
" public void circumventer() {",
" // BUG: Diagnostic contains: must not be invoked",
" overrideMe();",
" }",
"}")
.doTest();
}
@Test
public void testUserCannotCallOverridden() throws Exception {
compilationHelper
.addSourceLines(
"test/Test.java",
"package test2;",
"public class Test extends test.ExtendMe {",
" @Override",
" protected int overrideMe() {",
" System.err.println(\"Capybaras are semi-aquatic.\");",
" return 1;",
" }",
" public void circumventer() {",
" // BUG: Diagnostic contains: must not be invoked",
" overrideMe();",
" }",
"}")
.doTest();
}
@Test
public void testUserCanCallSuperFromOverridden() throws Exception {
compilationHelper
.addSourceLines(
"test/Test.java",
"package test2;",
"public class Test extends test.ExtendMe {",
" @Override",
" protected int overrideMe() {",
" return super.overrideMe();",
" }",
"}")
.doTest();
compilationHelper
.addSourceLines(
"test/Test.java",
"package test2;",
"public class Test extends test.ExtendMe {",
" @Override",
" protected int overrideMe() {",
// This is identical to the above, with a slightly less common explicit qualification
" return Test.super.overrideMe();",
" }",
"}")
.doTest();
}
@Test
public void testUserCannotCallSuperFromNonOverriddenMethod() throws Exception {
compilationHelper
.addSourceLines(
"test/Test.java",
"package test2;",
"public class Test extends test.ExtendMe {",
" protected void circumventer() {",
" // BUG: Diagnostic contains: must not be invoked",
" super.overrideMe();",
" }",
"}")
.doTest();
}
@Test
public void testUserCannotCallSuperFromFieldInitializer() throws Exception {
compilationHelper
.addSourceLines(
"test/Test.java",
"package test2;",
"public class Test extends test.ExtendMe {",
" // BUG: Diagnostic contains: must not be invoked",
" private final int k = super.overrideMe();",
"}")
.doTest();
}
@Test
public void testUserCannotCallSuperFromAnonymousInnerClassInOverride() throws Exception {
compilationHelper
.addSourceLines(
"test/Test.java",
"package test2;",
"public class Test extends test.ExtendMe {",
" @Override",
" protected int overrideMe() {",
" return new Object() {",
" // BUG: Diagnostic contains: must not be invoked",
" final int k = Test.super.overrideMe();",
"",
" int foo() {",
" // BUG: Diagnostic contains: must not be invoked",
" return Test.super.overrideMe();",
" }",
" }.foo();",
" }",
"}")
.doTest();
}
@Test
public void testUserCannotMakeMethodPublic() throws Exception {
compilationHelper
.addSourceLines(
"test/Test.java",
"package test2;",
"public class Test extends test.ExtendMe {",
" // BUG: Diagnostic contains: must have protected or package-private visibility",
" public int overrideMe() {",
" System.err.println(\"Capybaras are rodents.\");",
" return 1;",
" }",
"}")
.doTest();
}
@Test
public void testDefinerCanCallFromInnerClass() throws Exception {
compilationHelper
.addSourceLines(
"test/OuterClass.java",
"package test;",
"import com.google.errorprone.annotations.ForOverride;",
"public class OuterClass {",
" @ForOverride",
" protected void forOverride() { }",
" private class InnerClass {",
" void invoke() {",
" forOverride();",
" }",
" }",
"}")
.doTest();
}
@Test
public void testDefinerCanCallFromAnonymousInnerClass() throws Exception {
compilationHelper
.addSourceLines(
"test/OuterClass.java",
"package test;",
"import com.google.errorprone.annotations.ForOverride;",
"public class OuterClass {",
" @ForOverride",
" protected void forOverride() { }",
" public Runnable getRunner() {",
" return new Runnable() {",
" public void run() {",
" forOverride();",
" }",
" };",
" }",
"}")
.doTest();
}
}