Skip to content

Commit 4caaa3a

Browse files
committed
Python: Rewrite call-graph tests to be inline expectation (1/2)
This adds inline expectations, next commit will remove old annotations code... but I thought it would be easier to review like this.
1 parent e8fdff7 commit 4caaa3a

File tree

6 files changed

+67
-14
lines changed

6 files changed

+67
-14
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
failures
2+
debug_callableNotUnique
3+
| code/class_advanced.py:18:5:18:18 | Function arg | Qualified function name 'B.arg' is not unique. Please fix. |
4+
| code/class_advanced.py:23:5:23:25 | Function arg | Qualified function name 'B.arg' is not unique. Please fix. |
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import python
2+
import TestUtilities.InlineExpectationsTest
3+
4+
/** Holds when `call` is resolved to `callable` using points-to based call-graph. */
5+
predicate pointsToCallEdge(CallNode call, Function callable) {
6+
exists(PythonFunctionValue funcValue |
7+
funcValue.getScope() = callable and
8+
call = funcValue.getACall()
9+
)
10+
}
11+
12+
/** Holds when `call` is resolved to `callable` using type-tracking based call-graph. */
13+
predicate typeTrackerCallEdge(CallNode call, Function callable) { none() }
14+
15+
class CallGraphTest extends InlineExpectationsTest {
16+
CallGraphTest() { this = "CallGraphTest" }
17+
18+
override string getARelevantTag() { result in ["pt", "tt"] }
19+
20+
override predicate hasActualResult(Location location, string element, string tag, string value) {
21+
exists(location.getFile().getRelativePath()) and
22+
exists(CallNode call, Function target |
23+
tag = "tt" and
24+
typeTrackerCallEdge(call, target)
25+
or
26+
tag = "pt" and
27+
pointsToCallEdge(call, target)
28+
|
29+
location = call.getLocation() and
30+
element = call.toString() and
31+
(
32+
// note: `target.getQualifiedName` for Lambdas is just "lambda", so is not very useful :|
33+
not target.isLambda() and
34+
value = target.getQualifiedName()
35+
or
36+
target.isLambda() and
37+
value =
38+
"lambda[" + target.getLocation().getFile().getShortName() + ":" +
39+
target.getLocation().getStartLine() + ":" + target.getLocation().getStartColumn() + "]"
40+
)
41+
)
42+
}
43+
}
44+
45+
query predicate debug_callableNotUnique(Function callable, string message) {
46+
exists(Function f | f != callable and f.getQualifiedName() = callable.getQualifiedName()) and
47+
message =
48+
"Qualified function name '" + callable.getQualifiedName() + "' is not unique. Please fix."
49+
}

python/ql/test/experimental/library-tests/CallGraph/code/class_simple.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ def some_classmethod(cls):
2525
a = A(42)
2626

2727
# calls:A.some_method
28-
a.some_method()
28+
a.some_method() # $ pt=A.some_method
2929
# calls:A.some_staticmethod
30-
a.some_staticmethod()
30+
a.some_staticmethod() # $ pt=A.some_staticmethod
3131
# calls:A.some_classmethod
32-
a.some_classmethod()
32+
a.some_classmethod() # $ pt=A.some_classmethod
3333

3434
# calls:A.some_staticmethod
35-
A.some_staticmethod()
35+
A.some_staticmethod() # $ pt=A.some_staticmethod
3636
# calls:A.some_classmethod
37-
A.some_classmethod()
37+
A.some_classmethod() # $ pt=A.some_classmethod

python/ql/test/experimental/library-tests/CallGraph/code/runtime_decision.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def rd_bar():
1818
func = rd_bar
1919

2020
# calls:rd_foo calls:rd_bar
21-
func()
21+
func() # $ pt=rd_foo pt=rd_bar
2222

2323
# Random doesn't work with points-to :O
2424
if random.random() < 0.5:
@@ -27,4 +27,4 @@ def rd_bar():
2727
func2 = rd_bar
2828

2929
# calls:rd_foo calls:rd_bar
30-
func2()
30+
func2() # $ pt=rd_foo pt=rd_bar

python/ql/test/experimental/library-tests/CallGraph/code/simple.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ def bar():
1616

1717

1818
# calls:foo
19-
foo()
19+
foo() # $ pt=foo
2020
# calls:foo
21-
indirect_foo()
21+
indirect_foo() # $ pt=foo
2222
# calls:bar
23-
bar()
23+
bar() # $ pt=bar
2424
# calls:lam
25-
lam()
25+
lam() # $ pt=lambda[simple.py:15:7]
2626

2727
# python -m trace --trackcalls simple.py

python/ql/test/experimental/library-tests/CallGraph/code/underscore_prefix_func_name.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ def _ignored():
1818
def _works_since_called():
1919
print('_works_since_called')
2020
# calls:some_function
21-
some_function()
21+
some_function() # $ pt=some_function
2222

2323
def works_even_though_not_called():
2424
# calls:some_function
25-
some_function()
25+
some_function() # $ pt=some_function
2626

2727
globals()['_ignored']()
28-
_works_since_called()
28+
_works_since_called() # $ pt=_works_since_called

0 commit comments

Comments
 (0)