Python: Add annotated call-graph tests

See the added README for in-depth details
This commit is contained in:
Rasmus Wriedt Larsen
2020-06-24 22:12:26 +02:00
parent 090a685d86
commit 155bbbdec9
21 changed files with 513 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
class B(object):
def __init__(self, arg):
print('B.__init__', arg)
self._arg = arg
def __str__(self):
print('B.__str__')
return 'B (arg={})'.format(self.arg)
def __add__(self, other):
print('B.__add__')
if isinstance(other, B):
return B(self.arg + other.arg)
return B(self.arg + other)
@property
def arg(self):
print('B.arg getter')
return self._arg
@arg.setter
def arg(self, value):
print('B.arg setter')
self._arg = value
b1 = B(1)
b2 = B(2)
b3 = b1 + b2
print('value printing:', str(b1))
print('value printing:', str(b2))
print('value printing:', str(b3))
b3.arg = 42
b4 = b3 + 100
# this calls `str(b4)` inside
print('value printing:', b4)

View File

@@ -0,0 +1,35 @@
class A(object):
# name:A.__init__
def __init__(self, arg):
print('A.__init__', arg)
self.arg = arg
# name:A.some_method
def some_method(self):
print('A.some_method', self)
@staticmethod
# name:A.some_staticmethod
def some_staticmethod():
print('A.some_staticmethod')
@classmethod
# name:A.some_classmethod
def some_classmethod(cls):
print('A.some_classmethod', cls)
# calls:A.__init__
a = A(42)
# calls:A.some_method
a.some_method()
# calls:A.some_staticmethod
a.some_staticmethod()
# calls:A.some_classmethod
a.some_classmethod()
# calls:A.some_staticmethod
A.some_staticmethod()
# calls:A.some_classmethod
A.some_classmethod()

View File

@@ -0,0 +1,30 @@
import sys
import random
# hmm, annoying that you have to keep names unique accross files :|
# since I like to use foo and bar ALL the time :D
# name:rd_foo
def rd_foo():
print('rd_foo')
# name:rd_bar
def rd_bar():
print('rd_bar')
if len(sys.argv) >= 2 and not sys.argv[1] in ['0', 'False', 'false']:
func = rd_foo
else:
func = rd_bar
# calls:rd_foo calls:rd_bar
func()
# Random doesn't work with points-to :O
if random.random() < 0.5:
func2 = rd_foo
else:
func2 = rd_bar
# calls:rd_foo calls:rd_bar
func2()

View File

@@ -0,0 +1,27 @@
# name:foo
def foo():
print("foo called")
indirect_foo = foo
# name:bar
def bar():
print("bar called")
# name:lam
lam = lambda: print("lambda called")
# calls:foo
foo()
# calls:foo
indirect_foo()
# calls:bar
bar()
# calls:lam
lam()
# python -m trace --trackcalls simple.py

View File

@@ -0,0 +1,28 @@
# Points-to information seems to be missing if our analysis thinks the enclosing function
# is never called. However, as illustrated by the code below, it's easy to fool our
# analysis :(
# This was inspired by a problem in real code, where our analysis doesn't have any
# points-to information about the `open` call in
# https://google-gruyere.appspot.com/code/gruyere.py on line 227
# name:some_function
def some_function():
print('some_function')
def _ignored():
print('_ignored')
# calls:some_function
some_function()
def _works_since_called():
print('_works_since_called')
# calls:some_function
some_function()
def works_even_though_not_called():
# calls:some_function
some_function()
globals()['_ignored']()
_works_since_called()