Coverage for tests/test_call_graph/test_parser.py: 100%

1"""Tests for call graph parser."""

2

3 from __future__ import annotations

4

5 from pathlib import Path

6

7 from call_graph.parsers.python import PythonCallParser

8 from parsers.python import parse

9

10

11 def test_extract_function_definitions():

12 code = """

13 def foo(x, y):

14 return x + y

15

16 class Bar:

17 def method_a(self):

18 pass

19

20 def method_b(self):

21 pass

22

23 def baz():

24 pass

25"""

26 parser = PythonCallParser()

27 root = parse(code)

28 defs = parser.extract_function_definitions(root, code, "/tmp/test.py")

29

30 assert len(defs) == 4

31 def_names = [d.name for d in defs]

32 assert "foo" in def_names

33 assert "method_a" in def_names

34 assert "method_b" in def_names

35 assert "baz" in def_names

36

37 func_def = next(d for d in defs if d.name == "foo")

38 assert func_def.def_type == "function"

39 assert len(func_def.params) == 2

40

41 method_def = next(d for d in defs if d.name == "method_a")

42 assert method_def.def_type == "method"

43 assert method_def.class_name == "Bar"

44

45

46 def test_extract_simple_calls():

47 code = """

48 def foo():

49 bar()

50

51 def bar():

52 baz()

53

54 def baz():

55 pass

56"""

57 parser = PythonCallParser()

58 root = parse(code)

59 defs = parser.extract_function_definitions(root, code, "/tmp/test.py")

60 calls = parser.extract_calls(root, code, "/tmp/test.py", defs)

61

62 assert len(calls) == 2

63

64 call_names = [c.callee_function for c in calls]

65 assert "bar" in call_names

66 assert "baz" in call_names

67

68 foo_to_bar = next(c for c in calls if c.caller_function == "foo")

69 assert foo_to_bar.callee_function == "bar"

70 assert foo_to_bar.call_type == "local"

71

72

73 def test_extract_method_calls():

74 code = """

75 class MyClass:

76 def foo(self):

77 self.bar()

78

79 def bar(self):

80 pass

81"""

82 parser = PythonCallParser()

83 root = parse(code)

84 defs = parser.extract_function_definitions(root, code, "/tmp/test.py")

85 calls = parser.extract_calls(root, code, "/tmp/test.py", defs)

86

87 assert len(calls) == 1

88 assert calls[0].callee_function == "bar"

89 assert calls[0].call_type == "method"

90 assert calls[0].receiver_object == "self"

91

92

93 def test_extract_external_calls():

94 code = """

95 def foo():

96 print("hello")

97 len([1, 2, 3])

98"""

99 parser = PythonCallParser()

100 root = parse(code)

101 defs = parser.extract_function_definitions(root, code, "/tmp/test.py")

102 calls = parser.extract_calls(root, code, "/tmp/test.py", defs)

103

104 assert len(calls) == 2

105 external_calls = [c for c in calls if c.call_type == "external"]

106 assert len(external_calls) == 2