Skip to content

Commit dba4460

Browse files
committed
Python: Update more inline expectation tests to use the paramterized module
1 parent c53e529 commit dba4460

File tree

153 files changed

+549
-377
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

153 files changed

+549
-377
lines changed

python/ql/test/experimental/dataflow/TestUtil/DataflowQueryTest.qll

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@ import semmle.python.dataflow.new.DataFlow
33
import TestUtilities.InlineExpectationsTest
44
private import semmle.python.dataflow.new.internal.PrintNode
55

6-
class DataFlowQueryTest extends InlineExpectationsTest {
7-
DataFlowQueryTest() { this = "DataFlowQueryTest" }
6+
module DataFlowQueryTest implements TestSig {
7+
string getARelevantTag() { result = "result" }
88

9-
override string getARelevantTag() { result = "result" }
10-
11-
override predicate hasActualResult(Location location, string element, string tag, string value) {
9+
predicate hasActualResult(Location location, string element, string tag, string value) {
1210
exists(DataFlow::Configuration cfg, DataFlow::Node sink | cfg.hasFlowTo(sink) |
1311
location = sink.getLocation() and
1412
tag = "result" and
@@ -22,7 +20,7 @@ class DataFlowQueryTest extends InlineExpectationsTest {
2220
// Sometimes a line contains both an alert and a safe sink.
2321
// In this situation, the annotation form `OK(safe sink)`
2422
// can be useful.
25-
override predicate hasOptionalResult(Location location, string element, string tag, string value) {
23+
predicate hasOptionalResult(Location location, string element, string tag, string value) {
2624
exists(DataFlow::Configuration cfg, DataFlow::Node sink |
2725
cfg.isSink(sink) or cfg.isSink(sink, _)
2826
|
@@ -34,6 +32,8 @@ class DataFlowQueryTest extends InlineExpectationsTest {
3432
}
3533
}
3634

35+
import MakeTest<DataFlowQueryTest>
36+
3737
query predicate missingAnnotationOnSink(Location location, string error, string element) {
3838
error = "ERROR, you should add `# $ MISSING: result=BAD` or `result=OK` annotation" and
3939
exists(DataFlow::Node sink |
@@ -42,13 +42,13 @@ query predicate missingAnnotationOnSink(Location location, string error, string
4242
location = sink.getLocation() and
4343
element = prettyExpr(sink.asExpr()) and
4444
not exists(DataFlow::Configuration cfg | cfg.hasFlowTo(sink)) and
45-
not exists(FalseNegativeExpectation missingResult |
45+
not exists(FalseNegativeTestExpectation missingResult |
4646
missingResult.getTag() = "result" and
4747
missingResult.getValue() = "BAD" and
4848
missingResult.getLocation().getFile() = location.getFile() and
4949
missingResult.getLocation().getStartLine() = location.getStartLine()
5050
) and
51-
not exists(GoodExpectation okResult |
51+
not exists(GoodTestExpectation okResult |
5252
okResult.getTag() = "result" and
5353
okResult.getValue() in ["OK", "OK(" + prettyNode(sink) + ")"] and
5454
okResult.getLocation().getFile() = location.getFile() and

python/ql/test/experimental/dataflow/TestUtil/FlowTest.qll

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,21 @@ import semmle.python.dataflow.new.DataFlow
33
import TestUtilities.InlineExpectationsTest
44
private import semmle.python.dataflow.new.internal.PrintNode
55

6-
abstract class FlowTest extends InlineExpectationsTest {
7-
bindingset[this]
8-
FlowTest() { any() }
6+
signature module FlowTestSig {
7+
string flowTag();
98

10-
abstract string flowTag();
11-
12-
abstract predicate relevantFlow(DataFlow::Node fromNode, DataFlow::Node toNode);
9+
predicate relevantFlow(DataFlow::Node fromNode, DataFlow::Node toNode);
10+
}
1311

14-
override string getARelevantTag() { result = this.flowTag() }
12+
private module FlowTest<FlowTestSig Impl> implements TestSig {
13+
string getARelevantTag() { result = Impl::flowTag() }
1514

16-
override predicate hasActualResult(Location location, string element, string tag, string value) {
17-
exists(DataFlow::Node fromNode, DataFlow::Node toNode | this.relevantFlow(fromNode, toNode) |
15+
predicate hasActualResult(Location location, string element, string tag, string value) {
16+
exists(DataFlow::Node fromNode, DataFlow::Node toNode | Impl::relevantFlow(fromNode, toNode) |
1817
location = toNode.getLocation() and
19-
tag = this.flowTag() and
18+
tag = Impl::flowTag() and
2019
value =
21-
"\"" + prettyNode(fromNode).replaceAll("\"", "'") + this.lineStr(fromNode, toNode) + " -> " +
20+
"\"" + prettyNode(fromNode).replaceAll("\"", "'") + lineStr(fromNode, toNode) + " -> " +
2221
prettyNode(toNode).replaceAll("\"", "'") + "\"" and
2322
element = toNode.toString()
2423
)
@@ -38,3 +37,11 @@ abstract class FlowTest extends InlineExpectationsTest {
3837
)
3938
}
4039
}
40+
41+
module MakeFlowTest<FlowTestSig Impl> {
42+
import MakeTest<FlowTest<Impl>>
43+
}
44+
45+
module MakeFlowTest2<FlowTestSig Impl1, FlowTestSig Impl2> {
46+
import MakeTest<MergeTests<FlowTest<Impl1>, FlowTest<Impl2>>>
47+
}

python/ql/test/experimental/dataflow/TestUtil/LocalFlowStepTest.qll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ import python
22
import semmle.python.dataflow.new.DataFlow
33
import FlowTest
44

5-
class LocalFlowStepTest extends FlowTest {
6-
LocalFlowStepTest() { this = "LocalFlowStepTest" }
5+
module LocalFlowStepTest implements FlowTestSig {
6+
string flowTag() { result = "step" }
77

8-
override string flowTag() { result = "step" }
9-
10-
override predicate relevantFlow(DataFlow::Node fromNode, DataFlow::Node toNode) {
8+
predicate relevantFlow(DataFlow::Node fromNode, DataFlow::Node toNode) {
119
DataFlow::localFlowStep(fromNode, toNode)
1210
}
1311
}
12+
13+
import MakeFlowTest<LocalFlowStepTest>

python/ql/test/experimental/dataflow/TestUtil/MaximalFlowTest.qll

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,23 @@ import semmle.python.dataflow.new.DataFlow
33
private import semmle.python.dataflow.new.internal.DataFlowPrivate
44
import FlowTest
55

6-
class MaximalFlowTest extends FlowTest {
7-
MaximalFlowTest() { this = "MaximalFlowTest" }
6+
module MaximalFlowTest implements FlowTestSig {
7+
string flowTag() { result = "flow" }
88

9-
override string flowTag() { result = "flow" }
10-
11-
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
9+
predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
1210
source != sink and
13-
exists(MaximalFlowsConfig cfg | cfg.hasFlow(source, sink))
11+
MaximalFlows::flow(source, sink)
1412
}
1513
}
1614

15+
import MakeFlowTest<MaximalFlowTest>
16+
1717
/**
1818
* A configuration to find all "maximal" flows.
1919
* To be used on small programs.
2020
*/
21-
class MaximalFlowsConfig extends DataFlow::Configuration {
22-
MaximalFlowsConfig() { this = "MaximalFlowsConfig" }
23-
24-
override predicate isSource(DataFlow::Node node) {
21+
module MaximalFlowsConfig implements DataFlow::ConfigSig {
22+
predicate isSource(DataFlow::Node node) {
2523
exists(node.getLocation().getFile().getRelativePath()) and
2624
not node.asCfgNode() instanceof CallNode and
2725
not node.asCfgNode().getNode() instanceof Return and
@@ -32,11 +30,13 @@ class MaximalFlowsConfig extends DataFlow::Configuration {
3230
not DataFlow::localFlowStep(_, node)
3331
}
3432

35-
override predicate isSink(DataFlow::Node node) {
33+
predicate isSink(DataFlow::Node node) {
3634
exists(node.getLocation().getFile().getRelativePath()) and
3735
not any(CallNode c).getArg(_) = node.asCfgNode() and
3836
not node instanceof DataFlow::ArgumentNode and
3937
not node.asCfgNode().(NameNode).getId().matches("SINK%") and
4038
not DataFlow::localFlowStep(node, _)
4139
}
4240
}
41+
42+
module MaximalFlows = DataFlow::Global<MaximalFlowsConfig>;

python/ql/test/experimental/dataflow/TestUtil/NormalDataflowTest.qll

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,29 @@ import experimental.dataflow.TestUtil.FlowTest
33
import experimental.dataflow.testConfig
44
private import semmle.python.dataflow.new.internal.PrintNode
55

6-
class DataFlowTest extends FlowTest {
7-
DataFlowTest() { this = "DataFlowTest" }
6+
module DataFlowTest implements FlowTestSig {
7+
string flowTag() { result = "flow" }
88

9-
override string flowTag() { result = "flow" }
10-
11-
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
12-
exists(TestConfiguration cfg | cfg.hasFlow(source, sink))
9+
predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
10+
TestFlow::flow(source, sink)
1311
}
1412
}
1513

14+
import MakeFlowTest<DataFlowTest>
15+
1616
query predicate missingAnnotationOnSink(Location location, string error, string element) {
1717
error = "ERROR, you should add `# $ MISSING: flow` annotation" and
1818
exists(DataFlow::Node sink |
19-
any(TestConfiguration config).isSink(sink) and
19+
TestConfig::isSink(sink) and
2020
// note: we only care about `SINK` and not `SINK_F`, so we have to reconstruct manually.
2121
exists(DataFlow::CallCfgNode call |
2222
call.getFunction().asCfgNode().(NameNode).getId() = "SINK" and
2323
(sink = call.getArg(_) or sink = call.getArgByName(_))
2424
) and
2525
location = sink.getLocation() and
2626
element = prettyExpr(sink.asExpr()) and
27-
not any(TestConfiguration config).hasFlow(_, sink) and
28-
not exists(FalseNegativeExpectation missingResult |
27+
not TestFlow::flowTo(sink) and
28+
not exists(FalseNegativeTestExpectation missingResult |
2929
missingResult.getTag() = "flow" and
3030
missingResult.getLocation().getFile() = location.getFile() and
3131
missingResult.getLocation().getStartLine() = location.getStartLine()

python/ql/test/experimental/dataflow/TestUtil/NormalTaintTrackingTest.qll

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ import experimental.dataflow.TestUtil.FlowTest
33
import experimental.dataflow.testTaintConfig
44
private import semmle.python.dataflow.new.internal.PrintNode
55

6-
class DataFlowTest extends FlowTest {
7-
DataFlowTest() { this = "DataFlowTest" }
6+
module DataFlowTest implements FlowTestSig {
7+
string flowTag() { result = "flow" }
88

9-
override string flowTag() { result = "flow" }
10-
11-
override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
12-
exists(TestConfiguration cfg | cfg.hasFlow(source, sink))
9+
predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) {
10+
TestFlow::flow(source, sink)
1311
}
1412
}
1513

14+
import MakeFlowTest<DataFlowTest>
15+
1616
query predicate missingAnnotationOnSink(Location location, string error, string element) {
1717
error = "ERROR, you should add `# $ MISSING: flow` annotation" and
1818
exists(DataFlow::Node sink |
@@ -23,8 +23,8 @@ query predicate missingAnnotationOnSink(Location location, string error, string
2323
) and
2424
location = sink.getLocation() and
2525
element = prettyExpr(sink.asExpr()) and
26-
not any(TestConfiguration config).hasFlow(_, sink) and
27-
not exists(FalseNegativeExpectation missingResult |
26+
not TestFlow::flowTo(sink) and
27+
not exists(FalseNegativeTestExpectation missingResult |
2828
missingResult.getTag() = "flow" and
2929
missingResult.getLocation().getFile() = location.getFile() and
3030
missingResult.getLocation().getStartLine() = location.getStartLine()

python/ql/test/experimental/dataflow/TestUtil/UnresolvedCalls.qll

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,34 @@ private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPr
44
private import semmle.python.ApiGraphs
55
import TestUtilities.InlineExpectationsTest
66

7-
class UnresolvedCallExpectations extends InlineExpectationsTest {
8-
UnresolvedCallExpectations() { this = "UnresolvedCallExpectations" }
9-
10-
override string getARelevantTag() { result = "unresolved_call" }
7+
signature module UnresolvedCallExpectationsSig {
8+
predicate unresolvedCall(CallNode call);
9+
}
1110

11+
module DefaultUnresolvedCallExpectations implements UnresolvedCallExpectationsSig {
1212
predicate unresolvedCall(CallNode call) {
1313
not exists(DataFlowPrivate::DataFlowCall dfc |
1414
exists(dfc.getCallable()) and dfc.getNode() = call
1515
) and
1616
not DataFlowPrivate::resolveClassCall(call, _) and
1717
not call = API::builtin(_).getACall().asCfgNode()
1818
}
19+
}
1920

20-
override predicate hasActualResult(Location location, string element, string tag, string value) {
21-
exists(location.getFile().getRelativePath()) and
22-
exists(CallNode call | this.unresolvedCall(call) |
23-
location = call.getLocation() and
24-
tag = "unresolved_call" and
25-
value = prettyExpr(call.getNode()) and
26-
element = call.toString()
27-
)
21+
module MakeUnresolvedCallExpectations<UnresolvedCallExpectationsSig Impl> {
22+
private module UnresolvedCallExpectations implements TestSig {
23+
string getARelevantTag() { result = "unresolved_call" }
24+
25+
predicate hasActualResult(Location location, string element, string tag, string value) {
26+
exists(location.getFile().getRelativePath()) and
27+
exists(CallNode call | Impl::unresolvedCall(call) |
28+
location = call.getLocation() and
29+
tag = "unresolved_call" and
30+
value = prettyExpr(call.getNode()) and
31+
element = call.toString()
32+
)
33+
}
2834
}
35+
36+
import MakeTest<UnresolvedCallExpectations>
2937
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
failures
2+
testFailures
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
failures
2+
testFailures
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
missingAnnotationOnSink
22
failures
3+
testFailures

0 commit comments

Comments
 (0)