diff --git a/python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.expected b/python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.expected index e748746b01a..d095fc73dbb 100644 --- a/python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.expected +++ b/python/ql/test/experimental/library-tests/CallGraph/InlineCallGraphTest.expected @@ -39,5 +39,18 @@ typeTracker_found_pointsTo_notFound | code/class_super.py:101:1:101:7 | ControlFlowNode for Attribute() | Z.foo | | code/class_super.py:108:1:108:8 | ControlFlowNode for Attribute() | Z.foo | | code/def_in_function.py:22:5:22:11 | ControlFlowNode for Attribute() | test.A.foo | +| code/isinstance.py:9:13:9:22 | ControlFlowNode for Attribute() | A.foo | +| code/isinstance.py:9:13:9:22 | ControlFlowNode for Attribute() | ASub.foo | +| code/isinstance.py:9:13:9:22 | ControlFlowNode for Attribute() | B.foo | +| code/isinstance.py:9:13:9:22 | ControlFlowNode for Attribute() | Base.foo | +| code/isinstance.py:14:13:14:22 | ControlFlowNode for Attribute() | A.foo | +| code/isinstance.py:14:13:14:22 | ControlFlowNode for Attribute() | ASub.foo | +| code/isinstance.py:14:13:14:22 | ControlFlowNode for Attribute() | B.foo | +| code/isinstance.py:14:13:14:22 | ControlFlowNode for Attribute() | Base.foo | +| code/isinstance.py:17:13:17:22 | ControlFlowNode for Attribute() | A.foo | +| code/isinstance.py:17:13:17:22 | ControlFlowNode for Attribute() | ASub.foo | +| code/isinstance.py:17:13:17:22 | ControlFlowNode for Attribute() | B.foo | +| code/isinstance.py:17:13:17:22 | ControlFlowNode for Attribute() | Base.foo | +| code/isinstance.py:40:5:40:11 | ControlFlowNode for Attribute() | B.foo | | code/nested_class.py:83:9:83:16 | ControlFlowNode for Attribute() | X.class_def_in_func.Y.meth | | code/underscore_prefix_func_name.py:14:5:14:19 | ControlFlowNode for some_function() | some_function | diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/isinstance.py b/python/ql/test/experimental/library-tests/CallGraph/code/isinstance.py new file mode 100644 index 00000000000..a8fbcc32d43 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph/code/isinstance.py @@ -0,0 +1,40 @@ +import os + +class Base: + def foo(self): + print("Base.foo") + + def call(self): + if isinstance(self, A): + self.foo() # $ tt=A.foo tt=ASub.foo SPURIOUS: tt=B.foo tt=Base.foo + + # This is a silly test, but just to show that second argument of isinstance as + # tuple is handled + if isinstance(self, (A, B)): + self.foo() # $ tt=A.foo tt=ASub.foo tt=B.foo SPURIOUS: tt=Base.foo + + if isinstance(self, ASubNoDef): + self.foo() # $ tt=A.foo SPURIOUS: tt=ASub.foo tt=B.foo tt=Base.foo + + +class A(Base): + def foo(self): + print("A.foo") + +class ASub(A): + def foo(self): + print("ASub.foo") + +class ASubNoDef(A): pass + +class B(Base): + def foo(self): + print("B.foo") + +cond = os.urandom(1)[0] > 128 + +x = A() if cond else B() +x.foo() # $ pt,tt=A.foo pt,tt=B.foo + +if isinstance(x, A): + x.foo() # $ pt,tt=A.foo SPURIOUS: tt=B.foo