Skip to content

Commit a5c2341

Browse files
committed
Python: Add simple test of DataFlowCall
Notice the strange thing with treating `mypkg.foo(42)` as a ClassCall, but completely ignoring `mypkg.subpkg.bar(43)` -- due to having the two `ClassValue`s: - `Missing module attribute mypkg.foo` - `Missing module attribute mypkg.subpkg` But not `Missing module attribute mypkg.subpkg` with the current import structure.
1 parent 48aa07d commit a5c2341

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

python/ql/test/experimental/dataflow/calls/DataFlowCallTest.expected

Whitespace-only changes.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import python
2+
import semmle.python.dataflow.new.DataFlow
3+
import semmle.python.dataflow.new.internal.DataFlowPrivate
4+
import TestUtilities.InlineExpectationsTest
5+
private import semmle.python.dataflow.new.internal.PrintNode
6+
7+
class DataFlowCallTest extends InlineExpectationsTest {
8+
DataFlowCallTest() { this = "DataFlowCallTest" }
9+
10+
override string getARelevantTag() {
11+
result in ["call", "qlclass"]
12+
or
13+
result = "arg_" + [0 .. 10]
14+
}
15+
16+
override predicate hasActualResult(Location location, string element, string tag, string value) {
17+
exists(location.getFile().getRelativePath()) and
18+
exists(DataFlowCall call |
19+
location = call.getLocation() and
20+
element = call.toString()
21+
|
22+
value = prettyExpr(call.getNode().getNode()) and
23+
tag = "call"
24+
or
25+
value = call.getAQlClass() and
26+
tag = "qlclass"
27+
or
28+
exists(int n, DataFlow::Node arg | arg = call.getArg(n) |
29+
value = prettyNodeForInlineTest(arg) and
30+
tag = "arg_" + n
31+
)
32+
)
33+
}
34+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# A very basic test of DataFlowCall
2+
#
3+
# see `coverage/argumentRoutingTest.ql` for a more in depth test of argument routing
4+
# handling.
5+
6+
def func(arg):
7+
pass
8+
9+
10+
class MyClass(object):
11+
def __init__(self, arg):
12+
pass
13+
14+
def my_method(self, arg):
15+
pass
16+
17+
def __getitem__(self, key):
18+
pass
19+
20+
21+
func("foo") # $ call=func(..) qlclass=FunctionCall arg_0="foo"
22+
x = MyClass(1) # $ call=MyClass(..) qlclass=ClassCall arg_0=[pre]MyClass(..) arg_1=1
23+
x.my_method(2) # $ call=x.my_method(..) qlclass=MethodCall arg_0=x arg_1=2
24+
mm = x.my_method
25+
mm(2) # $ call=mm(..) qlclass=MethodCall arg_1=2 MISSING: arg_0=x
26+
x[3] # $ call=x[3] qlclass=SpecialCall arg_0=x arg_1=3
27+
28+
29+
try:
30+
# These are included to show how we handle absent things with points-to where
31+
# `mypkg.foo` is a `missing module variable`, but `mypkg.subpkg.bar` is compeltely
32+
# ignored.
33+
import mypkg
34+
mypkg.foo(42) # $ call=mypkg.foo(..) qlclass=ClassCall arg_0=[pre]mypkg.foo(..)
35+
mypkg.subpkg.bar(43)
36+
except:
37+
pass

0 commit comments

Comments
 (0)