Files
codeql/java/ql/lib/semmle/code/java/deadcode/TestEntryPoints.qll
Anders Schack-Mulligen 730eae9521 Java: Autoformat
2023-03-10 09:39:41 +01:00

160 lines
5.1 KiB
Plaintext

import java
import semmle.code.java.deadcode.DeadCode
import semmle.code.java.frameworks.Cucumber
import semmle.code.java.deadcode.frameworks.FitNesseEntryPoints
import semmle.code.java.frameworks.Mockito
import semmle.code.java.UnitTests
/**
* A test method, suite, or an associated setup/teardown method.
*/
class TestMethodEntry extends CallableEntryPoint {
TestMethodEntry() {
this instanceof TestMethod and
// Ignored tests are not run
not this instanceof JUnitIgnoredMethod
or
this instanceof JUnit3TestSuite
or
exists(AnnotationType a | a = this.getAnAnnotation().getType() |
a.hasQualifiedName("org.junit.runners", "Parameterized$Parameters") and
this.getDeclaringType() instanceof ParameterizedJUnitTest
)
}
}
/**
* Methods that are called before or after tests.
*/
class BeforeOrAfterEntry extends CallableEntryPoint {
BeforeOrAfterEntry() {
this.getAnAnnotation() instanceof TestNGBeforeAnnotation or
this.getAnAnnotation() instanceof TestNGAfterAnnotation or
this.getAnAnnotation() instanceof BeforeAnnotation or
this.getAnAnnotation() instanceof BeforeClassAnnotation or
this.getAnAnnotation() instanceof AfterAnnotation or
this.getAnAnnotation() instanceof AfterClassAnnotation
}
}
/**
* A method in a test class that is either a JUnit theory, or a method providing data points for a theory.
*/
class JUnitTheories extends CallableEntryPoint {
JUnitTheories() {
exists(AnnotationType a |
a = this.getAnAnnotation().getType() and
this.getDeclaringType() instanceof JUnitTheoryTest
|
a.hasQualifiedName("org.junit.experimental.theories", "Theory") or
a.hasQualifiedName("org.junit.experimental.theories", "DataPoint") or
a.hasQualifiedName("org.junit.experimental.theories", "DataPoints")
)
}
}
/**
* A field which provides a JUnit `DataPoint` for a theory.
*/
class JUnitDataPointField extends ReflectivelyReadField {
JUnitDataPointField() {
exists(AnnotationType a | a = this.getAnAnnotation().getType() |
(
a.hasQualifiedName("org.junit.experimental.theories", "DataPoint") or
a.hasQualifiedName("org.junit.experimental.theories", "DataPoints")
) and
this.getDeclaringType() instanceof JUnitTheoryTest
)
}
}
/**
* Any types used as a category in a JUnit `@Category` annotation should be considered live.
*/
class JUnitCategory extends WhitelistedLiveClass {
JUnitCategory() { exists(JUnitCategoryAnnotation ca | ca.getACategory() = this) }
}
/**
* A listener that will be reflectively constructed by TestNG.
*/
class TestNGReflectivelyConstructedListener extends ReflectivelyConstructedClass instanceof TestNGListenerImpl
{
// Consider any class that implements a TestNG listener interface to be live. Listeners can be
// specified on the command line, in `testng.xml` files and in Ant build files, so it is safest
// to assume that all such listeners are live.
}
/**
* A `@DataProvider` TestNG method which is live because it is accessed by at least one test.
*/
class TestNGDataProvidersEntryPoint extends CallableEntryPoint {
TestNGDataProvidersEntryPoint() {
exists(TestNGTestMethod method | this = method.getADataProvider())
}
}
/**
* A `@Factory` TestNG method or constructor which is live.
*/
class TestNGFactoryEntryPoint extends CallableEntryPoint instanceof TestNGFactoryCallable { }
class TestRefectivelyConstructedClass extends ReflectivelyConstructedClass {
TestRefectivelyConstructedClass() {
this.getAnAncestor().getACallable() instanceof TestMethodEntry
}
}
class RunWithReflectivelyConstructedClass extends ReflectivelyConstructedClass {
RunWithReflectivelyConstructedClass() {
exists(AnnotationType a | a = this.getAnAnnotation().getType() |
a.hasQualifiedName("org.junit.runner", "RunWith")
)
}
}
/**
* Callables called by Mockito when performing injection.
*/
class MockitoCalledByInjection extends CallableEntryPoint {
MockitoCalledByInjection() {
exists(MockitoInjectedField field | this = field.getAnInvokedCallable())
or
exists(MockitoSpiedField spyField |
spyField.isConstructed() and
this = spyField.getType().(RefType).getAConstructor() and
this.getNumberOfParameters() = 0
)
}
}
/**
* Mock fields that are read by Mockito when performing injection.
*/
class MockitoReadField extends ReflectivelyReadField {
MockitoReadField() { this.(MockitoMockedField).isReferencedByInjection() }
}
/**
* A class constructed by Cucumber.
*/
class CucumberConstructedClass extends ReflectivelyConstructedClass {
CucumberConstructedClass() {
this instanceof CucumberStepDefinitionClass or
this.getAnAncestor() instanceof CucumberJava8Language
}
override Callable getALiveCallable() {
// Consider any constructor to be live - Cucumber calls a runtime-specified dependency
// injection framework (possibly an in-built one) to construct these instances, so any
// constructor could be called.
result = this.getAConstructor()
}
}
/**
* A "step definition" that may be called by Cucumber when executing an acceptance test.
*/
class CucumberStepDefinitionEntryPoint extends CallableEntryPoint instanceof CucumberStepDefinition {
}