mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Add optional results to InlineExpectationsTest
The idea behind optional results is that there may be instances where each line of source code has many results and you don't want to annotate all of them, but you still want to ensure that any annotations you do have are correct. This change makes that possible by exposing a new predicate `hasOptionalResult`, which has the same signature as `hasResult`. Results produced by `hasOptionalResult` will be matched against any annotations, but the lack of a matching annotation will not cause a failure. We will use this in the inline tests for the API edge getASubclass, because for each API path that uses getASubclass there is always a shorter path that does not use it, and thus we can't use the normal shortest-path matching approach that works for other API Graph tests.
This commit is contained in:
@@ -123,6 +123,15 @@ abstract class InlineExpectationsTest extends string {
|
||||
*/
|
||||
abstract predicate hasActualResult(Location location, string element, string tag, string value);
|
||||
|
||||
/**
|
||||
* Like `hasActualResult`, but returns results that do not require a matching annotation.
|
||||
* A failure will still arise if there is an annotation that does not match any results, but not vice versa.
|
||||
* Override this predicate to specify optional results.
|
||||
*/
|
||||
predicate hasOptionalResult(Location location, string element, string tag, string value) {
|
||||
none()
|
||||
}
|
||||
|
||||
final predicate hasFailureMessage(FailureLocatable element, string message) {
|
||||
exists(ActualResult actualResult |
|
||||
actualResult.getTest() = this and
|
||||
@@ -134,7 +143,8 @@ abstract class InlineExpectationsTest extends string {
|
||||
)
|
||||
or
|
||||
not exists(ValidExpectation expectation | expectation.matchesActualResult(actualResult)) and
|
||||
message = "Unexpected result: " + actualResult.getExpectationText()
|
||||
message = "Unexpected result: " + actualResult.getExpectationText() and
|
||||
not actualResult.isOptional()
|
||||
)
|
||||
)
|
||||
or
|
||||
@@ -243,9 +253,13 @@ private string expectationPattern() {
|
||||
|
||||
private newtype TFailureLocatable =
|
||||
TActualResult(
|
||||
InlineExpectationsTest test, Location location, string element, string tag, string value
|
||||
InlineExpectationsTest test, Location location, string element, string tag, string value,
|
||||
boolean optional
|
||||
) {
|
||||
test.hasActualResult(location, element, tag, value)
|
||||
test.hasActualResult(location, element, tag, value) and
|
||||
optional = false
|
||||
or
|
||||
test.hasOptionalResult(location, element, tag, value) and optional = true
|
||||
} or
|
||||
TValidExpectation(ExpectationComment comment, string tag, string value, string knownFailure) {
|
||||
exists(TColumn column, string tags |
|
||||
@@ -277,8 +291,9 @@ class ActualResult extends FailureLocatable, TActualResult {
|
||||
string element;
|
||||
string tag;
|
||||
string value;
|
||||
boolean optional;
|
||||
|
||||
ActualResult() { this = TActualResult(test, location, element, tag, value) }
|
||||
ActualResult() { this = TActualResult(test, location, element, tag, value, optional) }
|
||||
|
||||
override string toString() { result = element }
|
||||
|
||||
@@ -289,6 +304,8 @@ class ActualResult extends FailureLocatable, TActualResult {
|
||||
override string getTag() { result = tag }
|
||||
|
||||
override string getValue() { result = value }
|
||||
|
||||
predicate isOptional() { optional = true }
|
||||
}
|
||||
|
||||
abstract private class Expectation extends FailureLocatable {
|
||||
|
||||
Reference in New Issue
Block a user