mirror of
https://github.com/github/codeql.git
synced 2025-12-21 19:26:31 +01:00
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.
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
failures
|
||||
debug_callableNotUnique
|
||||
| code/class_advanced.py:18:5:18:18 | Function arg | Qualified function name 'B.arg' is not unique. Please fix. |
|
||||
| code/class_advanced.py:23:5:23:25 | Function arg | Qualified function name 'B.arg' is not unique. Please fix. |
|
||||
@@ -0,0 +1,49 @@
|
||||
import python
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
/** Holds when `call` is resolved to `callable` using points-to based call-graph. */
|
||||
predicate pointsToCallEdge(CallNode call, Function callable) {
|
||||
exists(PythonFunctionValue funcValue |
|
||||
funcValue.getScope() = callable and
|
||||
call = funcValue.getACall()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds when `call` is resolved to `callable` using type-tracking based call-graph. */
|
||||
predicate typeTrackerCallEdge(CallNode call, Function callable) { none() }
|
||||
|
||||
class CallGraphTest extends InlineExpectationsTest {
|
||||
CallGraphTest() { this = "CallGraphTest" }
|
||||
|
||||
override string getARelevantTag() { result in ["pt", "tt"] }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(location.getFile().getRelativePath()) and
|
||||
exists(CallNode call, Function target |
|
||||
tag = "tt" and
|
||||
typeTrackerCallEdge(call, target)
|
||||
or
|
||||
tag = "pt" and
|
||||
pointsToCallEdge(call, target)
|
||||
|
|
||||
location = call.getLocation() and
|
||||
element = call.toString() and
|
||||
(
|
||||
// note: `target.getQualifiedName` for Lambdas is just "lambda", so is not very useful :|
|
||||
not target.isLambda() and
|
||||
value = target.getQualifiedName()
|
||||
or
|
||||
target.isLambda() and
|
||||
value =
|
||||
"lambda[" + target.getLocation().getFile().getShortName() + ":" +
|
||||
target.getLocation().getStartLine() + ":" + target.getLocation().getStartColumn() + "]"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
query predicate debug_callableNotUnique(Function callable, string message) {
|
||||
exists(Function f | f != callable and f.getQualifiedName() = callable.getQualifiedName()) and
|
||||
message =
|
||||
"Qualified function name '" + callable.getQualifiedName() + "' is not unique. Please fix."
|
||||
}
|
||||
@@ -25,13 +25,13 @@ class A(object):
|
||||
a = A(42)
|
||||
|
||||
# calls:A.some_method
|
||||
a.some_method()
|
||||
a.some_method() # $ pt=A.some_method
|
||||
# calls:A.some_staticmethod
|
||||
a.some_staticmethod()
|
||||
a.some_staticmethod() # $ pt=A.some_staticmethod
|
||||
# calls:A.some_classmethod
|
||||
a.some_classmethod()
|
||||
a.some_classmethod() # $ pt=A.some_classmethod
|
||||
|
||||
# calls:A.some_staticmethod
|
||||
A.some_staticmethod()
|
||||
A.some_staticmethod() # $ pt=A.some_staticmethod
|
||||
# calls:A.some_classmethod
|
||||
A.some_classmethod()
|
||||
A.some_classmethod() # $ pt=A.some_classmethod
|
||||
|
||||
@@ -18,7 +18,7 @@ else:
|
||||
func = rd_bar
|
||||
|
||||
# calls:rd_foo calls:rd_bar
|
||||
func()
|
||||
func() # $ pt=rd_foo pt=rd_bar
|
||||
|
||||
# Random doesn't work with points-to :O
|
||||
if random.random() < 0.5:
|
||||
@@ -27,4 +27,4 @@ else:
|
||||
func2 = rd_bar
|
||||
|
||||
# calls:rd_foo calls:rd_bar
|
||||
func2()
|
||||
func2() # $ pt=rd_foo pt=rd_bar
|
||||
|
||||
@@ -16,12 +16,12 @@ lam = lambda: print("lambda called")
|
||||
|
||||
|
||||
# calls:foo
|
||||
foo()
|
||||
foo() # $ pt=foo
|
||||
# calls:foo
|
||||
indirect_foo()
|
||||
indirect_foo() # $ pt=foo
|
||||
# calls:bar
|
||||
bar()
|
||||
bar() # $ pt=bar
|
||||
# calls:lam
|
||||
lam()
|
||||
lam() # $ pt=lambda[simple.py:15:7]
|
||||
|
||||
# python -m trace --trackcalls simple.py
|
||||
|
||||
@@ -18,11 +18,11 @@ def _ignored():
|
||||
def _works_since_called():
|
||||
print('_works_since_called')
|
||||
# calls:some_function
|
||||
some_function()
|
||||
some_function() # $ pt=some_function
|
||||
|
||||
def works_even_though_not_called():
|
||||
# calls:some_function
|
||||
some_function()
|
||||
some_function() # $ pt=some_function
|
||||
|
||||
globals()['_ignored']()
|
||||
_works_since_called()
|
||||
_works_since_called() # $ pt=_works_since_called
|
||||
|
||||
Reference in New Issue
Block a user