Skip to content

Commit 07c22a8

Browse files
authored
Merge pull request github#9420 from RasmusWL/sync-go-inline
Go: Sync InlineExpectationsTest
2 parents aa78ce3 + 0b486ad commit 07c22a8

File tree

39 files changed

+185
-117
lines changed

39 files changed

+185
-117
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 {

go/ql/test/TestUtilities/InlineFlowTest.qll

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,11 @@ class InlineFlowTest extends InlineExpectationsTest {
7676

7777
override string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] }
7878

79-
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
79+
override predicate hasActualResult(Location location, string element, string tag, string value) {
8080
tag = "hasValueFlow" and
8181
exists(DataFlow::Node src, DataFlow::Node sink | getValueFlowConfig().hasFlow(src, sink) |
82-
sink.hasLocationInfo(file, line, _, _, _) and
82+
sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
83+
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
8384
element = sink.toString() and
8485
value = "\"" + sink.toString() + "\""
8586
)
@@ -88,7 +89,8 @@ class InlineFlowTest extends InlineExpectationsTest {
8889
exists(DataFlow::Node src, DataFlow::Node sink |
8990
getTaintFlowConfig().hasFlow(src, sink) and not getValueFlowConfig().hasFlow(src, sink)
9091
|
91-
sink.hasLocationInfo(file, line, _, _, _) and
92+
sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
93+
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
9294
element = sink.toString() and
9395
value = "\"" + sink.toString() + "\""
9496
)

go/ql/test/experimental/frameworks/CleverGo/HeaderWrite.ql

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ class HttpHeaderWriteTest extends InlineExpectationsTest {
99
result = ["headerKeyNode", "headerValNode", "headerKey", "headerVal"]
1010
}
1111

12-
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
12+
override predicate hasActualResult(Location location, string element, string tag, string value) {
1313
// Dynamic key-value header:
1414
exists(HTTP::HeaderWrite hw |
15-
hw.hasLocationInfo(file, line, _, _, _) and
15+
hw.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
16+
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
1617
(
1718
element = hw.getName().toString() and
1819
value = hw.getName().toString() and
@@ -26,7 +27,8 @@ class HttpHeaderWriteTest extends InlineExpectationsTest {
2627
or
2728
// Static key, dynamic value header:
2829
exists(HTTP::HeaderWrite hw |
29-
hw.hasLocationInfo(file, line, _, _, _) and
30+
hw.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
31+
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
3032
(
3133
element = hw.getHeaderName().toString() and
3234
value = hw.getHeaderName() and
@@ -40,7 +42,8 @@ class HttpHeaderWriteTest extends InlineExpectationsTest {
4042
or
4143
// Static key, static value header:
4244
exists(HTTP::HeaderWrite hw |
43-
hw.hasLocationInfo(file, line, _, _, _) and
45+
hw.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
46+
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
4447
(
4548
element = hw.getHeaderName().toString() and
4649
value = hw.getHeaderName() and

go/ql/test/experimental/frameworks/CleverGo/HttpRedirect.ql

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ class HttpRedirectTest extends InlineExpectationsTest {
77

88
override string getARelevantTag() { result = "redirectUrl" }
99

10-
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
10+
override predicate hasActualResult(Location location, string element, string tag, string value) {
1111
tag = "redirectUrl" and
1212
exists(HTTP::Redirect rd |
13-
rd.hasLocationInfo(file, line, _, _, _) and
13+
rd.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
14+
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
1415
element = rd.getUrl().toString() and
1516
value = rd.getUrl().toString()
1617
)

go/ql/test/experimental/frameworks/CleverGo/HttpResponseBody.ql

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ class HttpResponseBodyTest extends InlineExpectationsTest {
77

88
override string getARelevantTag() { result = ["contentType", "responseBody"] }
99

10-
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
10+
override predicate hasActualResult(Location location, string element, string tag, string value) {
1111
exists(HTTP::ResponseBody rd |
12-
rd.hasLocationInfo(file, line, _, _, _) and
12+
rd.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
13+
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
1314
(
1415
element = rd.getAContentType().toString() and
1516
value = rd.getAContentType().toString() and

go/ql/test/experimental/frameworks/CleverGo/TaintTracking.ql

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ class TaintTrackingTest extends InlineExpectationsTest {
1919

2020
override string getARelevantTag() { result = "taintSink" }
2121

22-
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
22+
override predicate hasActualResult(Location location, string element, string tag, string value) {
2323
tag = "taintSink" and
2424
exists(DataFlow::Node sink | any(Configuration c).hasFlow(_, sink) |
2525
element = sink.toString() and
2626
value = "" and
27-
sink.hasLocationInfo(file, line, _, _, _)
27+
sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
28+
location.getStartColumn(), location.getEndLine(), location.getEndColumn())
2829
)
2930
}
3031
}

go/ql/test/experimental/frameworks/CleverGo/UntrustedSources.ql

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class UntrustedFlowSourceTest extends InlineExpectationsTest {
77

88
override string getARelevantTag() { result = "untrustedFlowSource" }
99

10-
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
10+
override predicate hasActualResult(Location location, string element, string tag, string value) {
1111
tag = "untrustedFlowSource" and
1212
exists(DataFlow::CallNode sinkCall, DataFlow::ArgumentNode arg |
1313
sinkCall.getCalleeName() = "sink" and
@@ -16,7 +16,8 @@ class UntrustedFlowSourceTest extends InlineExpectationsTest {
1616
|
1717
element = arg.toString() and
1818
value = "" and
19-
arg.hasLocationInfo(file, line, _, _, _)
19+
arg.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
20+
location.getStartColumn(), location.getEndLine(), location.getEndColumn())
2021
)
2122
}
2223
}

go/ql/test/experimental/frameworks/Fiber/HeaderWrite.ql

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ class HttpHeaderWriteTest extends InlineExpectationsTest {
99
result = ["headerKeyNode", "headerValNode", "headerKey", "headerVal"]
1010
}
1111

12-
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
12+
override predicate hasActualResult(Location location, string element, string tag, string value) {
1313
// Dynamic key-value header:
1414
exists(HTTP::HeaderWrite hw |
15-
hw.hasLocationInfo(file, line, _, _, _) and
15+
hw.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
16+
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
1617
(
1718
element = hw.getName().toString() and
1819
value = hw.getName().toString() and
@@ -26,7 +27,8 @@ class HttpHeaderWriteTest extends InlineExpectationsTest {
2627
or
2728
// Static key, dynamic value header:
2829
exists(HTTP::HeaderWrite hw |
29-
hw.hasLocationInfo(file, line, _, _, _) and
30+
hw.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
31+
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
3032
(
3133
element = hw.getHeaderName().toString() and
3234
value = hw.getHeaderName() and
@@ -40,7 +42,8 @@ class HttpHeaderWriteTest extends InlineExpectationsTest {
4042
or
4143
// Static key, static value header:
4244
exists(HTTP::HeaderWrite hw |
43-
hw.hasLocationInfo(file, line, _, _, _) and
45+
hw.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
46+
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
4447
(
4548
element = hw.getHeaderName().toString() and
4649
value = hw.getHeaderName() and

go/ql/test/experimental/frameworks/Fiber/Redirect.ql

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ class HttpRedirectTest extends InlineExpectationsTest {
77

88
override string getARelevantTag() { result = "redirectUrl" }
99

10-
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
10+
override predicate hasActualResult(Location location, string element, string tag, string value) {
1111
tag = "redirectUrl" and
1212
exists(HTTP::Redirect rd |
13-
rd.hasLocationInfo(file, line, _, _, _) and
13+
rd.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
14+
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
1415
element = rd.getUrl().toString() and
1516
value = rd.getUrl().toString()
1617
)

0 commit comments

Comments
 (0)