Skip to content

Commit 86caf74

Browse files
committed
Go: Sync InlineExpectationsTest
1 parent 7214990 commit 86caf74

File tree

2 files changed

+35
-20
lines changed

2 files changed

+35
-20
lines changed

config/identical-files.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,8 @@
390390
"java/ql/test/TestUtilities/InlineExpectationsTest.qll",
391391
"python/ql/test/TestUtilities/InlineExpectationsTest.qll",
392392
"ruby/ql/test/TestUtilities/InlineExpectationsTest.qll",
393-
"ql/ql/test/TestUtilities/InlineExpectationsTest.qll"
393+
"ql/ql/test/TestUtilities/InlineExpectationsTest.qll",
394+
"go/ql/test/TestUtilities/InlineExpectationsTest.qll"
394395
],
395396
"C++ ExternalAPIs": [
396397
"cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll",

go/ql/test/TestUtilities/InlineExpectationsTest.qll

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393
private import InlineExpectationsTestPrivate
9494

9595
/**
96-
* Base class for tests with inline expectations. The test extends this class to provide the actual
96+
* The base class for tests with inline expectations. The test extends this class to provide the actual
9797
* results of the query, which are then compared with the expected results in comments to produce a
9898
* list of failure messages that point out where the actual results differ from the expected
9999
* results.
@@ -121,11 +121,17 @@ abstract class InlineExpectationsTest extends string {
121121
* - `value` - The value of the result, which will be matched against the value associated with
122122
* `tag` in any expected result comment on that line.
123123
*/
124-
abstract predicate hasActualResult(string file, int line, string element, string tag, string value);
124+
abstract predicate hasActualResult(Location location, string element, string tag, string value);
125125

126-
predicate hasActualResult(Location location, string element, string tag, string value) {
127-
this.hasActualResult(location.getFile().getAbsolutePath(), location.getStartLine(), element,
128-
tag, value)
126+
/**
127+
* Holds if there is an optional result on the specified location.
128+
*
129+
* This is similar to `hasActualResult`, but returns results that do not require a matching annotation.
130+
* A failure will still arise if there is an annotation that does not match any results, but not vice versa.
131+
* Override this predicate to specify optional results.
132+
*/
133+
predicate hasOptionalResult(Location location, string element, string tag, string value) {
134+
none()
129135
}
130136

131137
final predicate hasFailureMessage(FailureLocatable element, string message) {
@@ -139,13 +145,14 @@ abstract class InlineExpectationsTest extends string {
139145
)
140146
or
141147
not exists(ValidExpectation expectation | expectation.matchesActualResult(actualResult)) and
142-
message = "Unexpected result: " + actualResult.getExpectationText()
148+
message = "Unexpected result: " + actualResult.getExpectationText() and
149+
not actualResult.isOptional()
143150
)
144151
)
145152
or
146153
exists(ValidExpectation expectation |
147154
not exists(ActualResult actualResult | expectation.matchesActualResult(actualResult)) and
148-
expectation.getTag() = this.getARelevantTag() and
155+
expectation.getTag() = getARelevantTag() and
149156
element = expectation and
150157
(
151158
expectation instanceof GoodExpectation and
@@ -174,7 +181,7 @@ private string expectationCommentPattern() { result = "\\s*\\$((?:[^/]|/[^/])*)(
174181
/**
175182
* The possible columns in an expectation comment. The `TDefaultColumn` branch represents the first
176183
* column in a comment. This column is not precedeeded by a name. `TNamedColumn(name)` represents a
177-
* column containing expected results preceeded by the string `name:`.
184+
* column containing expected results preceded by the string `name:`.
178185
*/
179186
private newtype TColumn =
180187
TDefaultColumn() or
@@ -248,9 +255,13 @@ private string expectationPattern() {
248255

249256
private newtype TFailureLocatable =
250257
TActualResult(
251-
InlineExpectationsTest test, Location location, string element, string tag, string value
258+
InlineExpectationsTest test, Location location, string element, string tag, string value,
259+
boolean optional
252260
) {
253-
test.hasActualResult(location, element, tag, value)
261+
test.hasActualResult(location, element, tag, value) and
262+
optional = false
263+
or
264+
test.hasOptionalResult(location, element, tag, value) and optional = true
254265
} or
255266
TValidExpectation(ExpectationComment comment, string tag, string value, string knownFailure) {
256267
exists(TColumn column, string tags |
@@ -269,7 +280,7 @@ class FailureLocatable extends TFailureLocatable {
269280

270281
Location getLocation() { none() }
271282

272-
final string getExpectationText() { result = this.getTag() + "=" + this.getValue() }
283+
final string getExpectationText() { result = getTag() + "=" + getValue() }
273284

274285
string getTag() { none() }
275286

@@ -282,8 +293,9 @@ class ActualResult extends FailureLocatable, TActualResult {
282293
string element;
283294
string tag;
284295
string value;
296+
boolean optional;
285297

286-
ActualResult() { this = TActualResult(test, location, element, tag, value) }
298+
ActualResult() { this = TActualResult(test, location, element, tag, value, optional) }
287299

288300
override string toString() { result = element }
289301

@@ -294,6 +306,8 @@ class ActualResult extends FailureLocatable, TActualResult {
294306
override string getTag() { result = tag }
295307

296308
override string getValue() { result = value }
309+
310+
predicate isOptional() { optional = true }
297311
}
298312

299313
abstract private class Expectation extends FailureLocatable {
@@ -318,24 +332,24 @@ private class ValidExpectation extends Expectation, TValidExpectation {
318332
string getKnownFailure() { result = knownFailure }
319333

320334
predicate matchesActualResult(ActualResult actualResult) {
321-
this.getLocation().getStartLine() = actualResult.getLocation().getStartLine() and
322-
this.getLocation().getFile() = actualResult.getLocation().getFile() and
323-
this.getTag() = actualResult.getTag() and
324-
this.getValue() = actualResult.getValue()
335+
getLocation().getStartLine() = actualResult.getLocation().getStartLine() and
336+
getLocation().getFile() = actualResult.getLocation().getFile() and
337+
getTag() = actualResult.getTag() and
338+
getValue() = actualResult.getValue()
325339
}
326340
}
327341

328342
/* Note: These next three classes correspond to all the possible values of type `TColumn`. */
329343
class GoodExpectation extends ValidExpectation {
330-
GoodExpectation() { this.getKnownFailure() = "" }
344+
GoodExpectation() { getKnownFailure() = "" }
331345
}
332346

333347
class FalsePositiveExpectation extends ValidExpectation {
334-
FalsePositiveExpectation() { this.getKnownFailure() = "SPURIOUS" }
348+
FalsePositiveExpectation() { getKnownFailure() = "SPURIOUS" }
335349
}
336350

337351
class FalseNegativeExpectation extends ValidExpectation {
338-
FalseNegativeExpectation() { this.getKnownFailure() = "MISSING" }
352+
FalseNegativeExpectation() { getKnownFailure() = "MISSING" }
339353
}
340354

341355
class InvalidExpectation extends Expectation, TInvalidExpectation {

0 commit comments

Comments
 (0)