mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +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)
|
a = A(42)
|
||||||
|
|
||||||
# calls:A.some_method
|
# calls:A.some_method
|
||||||
a.some_method()
|
a.some_method() # $ pt=A.some_method
|
||||||
# calls:A.some_staticmethod
|
# calls:A.some_staticmethod
|
||||||
a.some_staticmethod()
|
a.some_staticmethod() # $ pt=A.some_staticmethod
|
||||||
# calls:A.some_classmethod
|
# calls:A.some_classmethod
|
||||||
a.some_classmethod()
|
a.some_classmethod() # $ pt=A.some_classmethod
|
||||||
|
|
||||||
# calls:A.some_staticmethod
|
# calls:A.some_staticmethod
|
||||||
A.some_staticmethod()
|
A.some_staticmethod() # $ pt=A.some_staticmethod
|
||||||
# calls:A.some_classmethod
|
# calls:A.some_classmethod
|
||||||
A.some_classmethod()
|
A.some_classmethod() # $ pt=A.some_classmethod
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ else:
|
|||||||
func = rd_bar
|
func = rd_bar
|
||||||
|
|
||||||
# calls:rd_foo calls:rd_bar
|
# calls:rd_foo calls:rd_bar
|
||||||
func()
|
func() # $ pt=rd_foo pt=rd_bar
|
||||||
|
|
||||||
# Random doesn't work with points-to :O
|
# Random doesn't work with points-to :O
|
||||||
if random.random() < 0.5:
|
if random.random() < 0.5:
|
||||||
@@ -27,4 +27,4 @@ else:
|
|||||||
func2 = rd_bar
|
func2 = rd_bar
|
||||||
|
|
||||||
# calls:rd_foo calls: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
|
# calls:foo
|
||||||
foo()
|
foo() # $ pt=foo
|
||||||
# calls:foo
|
# calls:foo
|
||||||
indirect_foo()
|
indirect_foo() # $ pt=foo
|
||||||
# calls:bar
|
# calls:bar
|
||||||
bar()
|
bar() # $ pt=bar
|
||||||
# calls:lam
|
# calls:lam
|
||||||
lam()
|
lam() # $ pt=lambda[simple.py:15:7]
|
||||||
|
|
||||||
# python -m trace --trackcalls simple.py
|
# python -m trace --trackcalls simple.py
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ def _ignored():
|
|||||||
def _works_since_called():
|
def _works_since_called():
|
||||||
print('_works_since_called')
|
print('_works_since_called')
|
||||||
# calls:some_function
|
# calls:some_function
|
||||||
some_function()
|
some_function() # $ pt=some_function
|
||||||
|
|
||||||
def works_even_though_not_called():
|
def works_even_though_not_called():
|
||||||
# calls:some_function
|
# calls:some_function
|
||||||
some_function()
|
some_function() # $ pt=some_function
|
||||||
|
|
||||||
globals()['_ignored']()
|
globals()['_ignored']()
|
||||||
_works_since_called()
|
_works_since_called() # $ pt=_works_since_called
|
||||||
|
|||||||
Reference in New Issue
Block a user