|
9 | 9 | * assertEquals(actual, "expected");
|
10 | 10 | * ```
|
11 | 11 | * SonarSource rule: [RSPEC-3415](https://rules.sonarsource.com/java/RSPEC-3415)
|
| 12 | + * |
| 13 | + * @kind problem |
| 14 | + * @id TODO |
12 | 15 | */
|
13 | 16 |
|
14 |
| - import java |
15 |
| - import lib.AssertLib |
| 17 | +import java |
| 18 | +import lib.AssertLib |
16 | 19 |
|
17 |
| - from MethodAccess assertCall, AssertTwoArgumentsMethod assertMethod |
| 20 | +/** |
| 21 | + * Expression which seems to be intended as 'expected' argument for an assertion. |
| 22 | + */ |
| 23 | +class ExpectedValueExpr extends Expr { |
| 24 | + ExpectedValueExpr() { |
| 25 | + // Note: Can cause false positives if the value of a constant (= 'actual') defined in the same |
| 26 | + // project is being checked, but on the other hand there are also cases where the constant is |
| 27 | + // is intended as 'expected' value |
| 28 | + this instanceof ConstantExpr |
| 29 | + or |
| 30 | + exists(MethodAccess call, Method m | |
| 31 | + call = this and |
| 32 | + m = call.getMethod() and |
| 33 | + m.isStatic() and |
| 34 | + forall(Expr arg | arg = call.getAnArgument() | arg instanceof ExpectedValueExpr) and |
| 35 | + // Only consider methods from third-party libraries or JDK, otherwise intention might be to |
| 36 | + // test result of method |
| 37 | + not m.getSourceDeclaration().fromSource() |
| 38 | + ) |
| 39 | + or |
| 40 | + exists(ClassInstanceExpr newExpr | |
| 41 | + newExpr = this and |
| 42 | + forall(Expr arg | arg = newExpr.getAnArgument() | arg instanceof ExpectedValueExpr) |
| 43 | + // Do not exclude types declared in same project, assume that `newExpr` is always the 'expected' value |
| 44 | + // If `newExpr` is intended as 'actual' then this might be misuse of `assertEquals` for `equals` |
| 45 | + // implementation check (which is discouraged) |
| 46 | + ) |
| 47 | + or |
| 48 | + exists(ArrayCreationExpr newArray | newArray = this | |
| 49 | + // Either creates array with constant dimensions |
| 50 | + forex(Expr dimExpr | dimExpr = newArray.getADimension() | |
| 51 | + dimExpr instanceof ExpectedValueExpr |
| 52 | + ) |
| 53 | + or |
| 54 | + // Or with init containing constants (checked transitively) |
| 55 | + forex(Expr initValue | initValue = newArray.getInit().getAnInit+() | |
| 56 | + initValue instanceof ArrayInit or initValue instanceof ExpectedValueExpr |
| 57 | + ) |
| 58 | + ) |
| 59 | + } |
| 60 | +} |
| 61 | + |
| 62 | +from MethodAccess assertCall, AssertTwoArgumentsMethod assertMethod |
18 | 63 | where
|
19 |
| - assertMethod = assertCall.getMethod() |
20 |
| - and assertCall.getArgument(assertMethod.getAssertionParamIndex()) instanceof CompileTimeConstantOrLiteral |
21 |
| - // Ignore if both arguments are constant, that is already detected by separate query |
22 |
| - and not assertCall.getArgument(assertMethod.getFixedParamIndex()) instanceof CompileTimeConstantOrLiteral |
| 64 | + assertMethod = assertCall.getMethod() and |
| 65 | + assertCall.getArgument(assertMethod.getAssertionParamIndex()) instanceof ExpectedValueExpr and |
| 66 | + // Ignore if both arguments are constant, that is already detected by separate query |
| 67 | + not assertCall.getArgument(assertMethod.getFixedParamIndex()) instanceof ExpectedValueExpr |
23 | 68 | select assertCall, "Assertion arguments are switched"
|
0 commit comments