Skip to content

Commit 56efdb7

Browse files
committed
Add some JUnit queries
1 parent c06bdb0 commit 56efdb7

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Finds usage of JUnit 5's `@CsvSource` where the values are not actually real CSV rows.
3+
* If none of the rows contains a delimiter character (`,` by default), then each 'row' is
4+
* passed as separate value to the test method. The `@ValueSource(strings = {...})`
5+
* annotation is exactly intended for that use case and should be preferred, because it
6+
* makes the intention clearer and is less error-prone in case a value happens to contain
7+
* a `,` (in which case it will not be split, unlike for `@CsvSource`).
8+
*
9+
* For example:
10+
* ```java
11+
* @CsvSource({"first", "second"})
12+
* // should be replaced with
13+
* @ValueSource(strings = {"first", "second"})
14+
* ```
15+
*
16+
* @id todo
17+
* @kind problem
18+
*/
19+
20+
import java
21+
22+
string getDelimiter(Annotation csvSource) {
23+
exists(string delimiterString, string delimiterChar |
24+
delimiterString = csvSource.getStringValue("delimiterString") and
25+
delimiterChar = csvSource.getValue("delimiter").(CharacterLiteral).getValue()
26+
|
27+
// Check default values of annotation elements
28+
if delimiterString != ""
29+
then result = delimiterString
30+
else
31+
if delimiterChar != 0.toUnicode()
32+
then result = delimiterChar
33+
else result = ","
34+
)
35+
}
36+
37+
from Annotation csvSource, string delimiter
38+
where
39+
csvSource.getType().hasQualifiedName("org.junit.jupiter.params.provider", "CsvSource") and
40+
delimiter = getDelimiter(csvSource) and
41+
// And none of the values contains the delimiter
42+
not (
43+
exists(csvSource.getAStringArrayValue("value").indexOf(delimiter)) or
44+
exists(csvSource.getStringValue("textBlock").indexOf(delimiter))
45+
)
46+
select csvSource, "Should use `@ValueSource(strings = {...})` instead"
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* Finds calls to `assertThrows` and `assertThrowsExactly` where a 'message' argument is provided which
3+
* seems to be intended as 'expected message'. The 'message' is actually what will be used in case the
4+
* assertion fails, it is _not_ the expected message for the thrown exception.
5+
*
6+
* For example this assertion will pass even though the exception has a different message:
7+
* ```java
8+
* assertThrows(
9+
* IllegalArgumentException.class,
10+
* () -> {
11+
* throw new IllegalArgumentException("argument 'actual' is invalid");
12+
* },
13+
* "argument 'expected' is invalid"
14+
* );
15+
* ```
16+
*
17+
* @id todo
18+
* @kind problem
19+
*/
20+
21+
import java
22+
23+
from
24+
MethodAccess assertThrowsCall, Method assertThrowsMethod, Class expectedException,
25+
CompileTimeConstantExpr messageArg
26+
where
27+
assertThrowsCall.getMethod() = assertThrowsMethod and
28+
// TODO: Use own assertion lib CodeQL classes?
29+
(
30+
// JUnit 4
31+
assertThrowsMethod.getDeclaringType().hasQualifiedName("org.junit", "Assert") and
32+
assertThrowsMethod.hasName("assertThrows") and
33+
expectedException = assertThrowsCall.getArgument(1).(TypeLiteral).getReferencedType() and
34+
messageArg = assertThrowsCall.getArgument(0)
35+
or
36+
// JUnit 5
37+
assertThrowsMethod.getDeclaringType().hasQualifiedName("org.junit.jupiter.api", "Assertions") and
38+
assertThrowsMethod.hasName(["assertThrows", "assertThrowsExactly"]) and
39+
expectedException = assertThrowsCall.getArgument(0).(TypeLiteral).getReferencedType() and
40+
messageArg = assertThrowsCall.getArgument(2)
41+
) and
42+
// Check if anywhere in the code an exception with the exact same message is created
43+
exists(ConstructorCall newExceptionCall |
44+
newExceptionCall.getConstructedType().getASourceSupertype*() = expectedException and
45+
newExceptionCall.getAnArgument().(CompileTimeConstantExpr).getStringValue() =
46+
messageArg.getStringValue()
47+
)
48+
select messageArg, "Message argument of `assertThrows` misunderstood as 'expected message'"

0 commit comments

Comments
 (0)