blob: f41f404894fbe92c69166323183cf33b8471b40a [file] [log] [blame]
Armin Rigoa871ef22006-02-08 12:53:56 +00001"""Test suite for the cProfile module."""
Brett Cannon70f1192d2008-09-29 03:57:24 +00002import cProfile, pstats, sys, test.test_support
Armin Rigoa871ef22006-02-08 12:53:56 +00003
4# In order to have reproducible time, we simulate a timer in the global
5# variable 'ticks', which represents simulated time in milliseconds.
6# (We can't use a helper function increment the timer since it would be
7# included in the profile and would appear to consume all the time.)
8ticks = 0
9
10# IMPORTANT: this is an output test. *ALL* NUMBERS in the expected
11# output are relevant. If you change the formatting of pstats,
12# please don't just regenerate output/test_cProfile without checking
13# very carefully that not a single number has changed.
14
15def test_main():
16 global ticks
17 ticks = 42000
18 prof = cProfile.Profile(timer, 0.001)
19 prof.runctx("testfunc()", globals(), locals())
20 assert ticks == 43000, ticks
21 st = pstats.Stats(prof)
22 st.strip_dirs().sort_stats('stdname').print_stats()
23 st.print_callees()
24 st.print_callers()
Brett Cannon70f1192d2008-09-29 03:57:24 +000025 test_bad_counter_during_dealloc()
Armin Rigoa871ef22006-02-08 12:53:56 +000026
27def timer():
28 return ticks
29
30def testfunc():
31 # 1 call
32 # 1000 ticks total: 270 ticks local, 730 ticks in subfunctions
33 global ticks
34 ticks += 99
35 helper() # 300
36 helper() # 300
37 ticks += 171
38 factorial(14) # 130
39
40def factorial(n):
41 # 23 calls total
42 # 170 ticks total, 150 ticks local
43 # 3 primitive calls, 130, 20 and 20 ticks total
44 # including 116, 17, 17 ticks local
45 global ticks
46 if n > 0:
47 ticks += n
48 return mul(n, factorial(n-1))
49 else:
50 ticks += 11
51 return 1
52
53def mul(a, b):
54 # 20 calls
55 # 1 tick, local
56 global ticks
57 ticks += 1
58 return a * b
59
60def helper():
61 # 2 calls
62 # 300 ticks total: 20 ticks local, 260 ticks in subfunctions
63 global ticks
64 ticks += 1
65 helper1() # 30
66 ticks += 2
67 helper1() # 30
68 ticks += 6
69 helper2() # 50
70 ticks += 3
71 helper2() # 50
72 ticks += 2
73 helper2() # 50
74 ticks += 5
75 helper2_indirect() # 70
76 ticks += 1
77
78def helper1():
79 # 4 calls
80 # 30 ticks total: 29 ticks local, 1 tick in subfunctions
81 global ticks
82 ticks += 10
83 hasattr(C(), "foo") # 1
84 ticks += 19
85 lst = []
86 lst.append(42) # 0
87 sys.exc_info() # 0
88
89def helper2_indirect():
90 helper2() # 50
91 factorial(3) # 20
92
93def helper2():
94 # 8 calls
95 # 50 ticks local: 39 ticks local, 11 ticks in subfunctions
96 global ticks
97 ticks += 11
98 hasattr(C(), "bar") # 1
99 ticks += 13
100 subhelper() # 10
101 ticks += 15
102
103def subhelper():
104 # 8 calls
105 # 10 ticks total: 8 ticks local, 2 ticks in subfunctions
106 global ticks
107 ticks += 2
108 for i in range(2): # 0
109 try:
110 C().foo # 1 x 2
111 except AttributeError:
112 ticks += 3 # 3 x 2
113
114class C:
115 def __getattr__(self, name):
116 # 28 calls
117 # 1 tick, local
118 global ticks
119 ticks += 1
120 raise AttributeError
121
Brett Cannon70f1192d2008-09-29 03:57:24 +0000122# Issue 3895.
123def test_bad_counter_during_dealloc():
124 import _lsprof
125 # Must use a file as StringIO doesn't trigger the bug.
126 sys.stderr = open(test.test_support.TESTFN, 'w')
127 try:
128 obj = _lsprof.Profiler(lambda: int)
129 obj.enable()
130 obj = _lsprof.Profiler(1)
131 obj.disable()
132 finally:
133 sys.stderr = sys.__stderr__
134 test.test_support.unlink(test.test_support.TESTFN)
135
136
Armin Rigoa871ef22006-02-08 12:53:56 +0000137if __name__ == "__main__":
138 test_main()