blob: 91112e8b2113eee9dc876e0910c40f48996de262 [file] [log] [blame]
Michael W. Hudson53d58bb2002-08-30 13:09:51 +00001# Testing the line trace facility.
2
3from test import test_support
4import unittest
5import sys
6import difflib
7
8# A very basic example. If this fails, we're in deep trouble.
9def basic():
10 return 1
11
12basic.events = [(0, 'call'),
13 (1, 'line'),
14 (1, 'return')]
15
16# Armin Rigo's failing example:
17def arigo_example():
18 x = 1
19 del x
20 while 0:
21 pass
22 x = 1
23
24arigo_example.events = [(0, 'call'),
25 (1, 'line'),
26 (2, 'line'),
27 (3, 'line'),
28 (5, 'line'),
29 (5, 'return')]
30
31# check that lines consisting of just one instruction get traced:
32def one_instr_line():
33 x = 1
34 del x
35 x = 1
36
37one_instr_line.events = [(0, 'call'),
38 (1, 'line'),
39 (2, 'line'),
40 (3, 'line'),
41 (3, 'return')]
42
43def no_pop_tops(): # 0
44 x = 1 # 1
45 for a in range(2): # 2
46 if a: # 3
47 x = 1 # 4
48 else: # 5
49 x = 1 # 6
50
51no_pop_tops.events = [(0, 'call'),
52 (1, 'line'),
53 (2, 'line'),
54 (3, 'line'),
55 (6, 'line'),
56 (2, 'line'),
57 (3, 'line'),
58 (4, 'line'),
59 (2, 'line'),
Michael W. Hudson02ff6a92002-09-11 15:36:32 +000060 (2, 'return')]
Michael W. Hudson53d58bb2002-08-30 13:09:51 +000061
62def no_pop_blocks():
63 while 0:
64 bla
65 x = 1
66
67no_pop_blocks.events = [(0, 'call'),
68 (1, 'line'),
69 (3, 'line'),
70 (3, 'return')]
71
Michael W. Hudson519a3422002-09-11 14:47:51 +000072def called(): # line -3
73 x = 1
74
75def call(): # line 0
76 called()
77
78call.events = [(0, 'call'),
79 (1, 'line'),
80 (-3, 'call'),
81 (-2, 'line'),
82 (-2, 'return'),
83 (1, 'return')]
84
85def raises():
86 raise Exception
87
88def test_raise():
89 try:
90 raises()
91 except Exception, exc:
92 x = 1
93
94test_raise.events = [(0, 'call'),
95 (1, 'line'),
96 (2, 'line'),
97 (-3, 'call'),
98 (-2, 'line'),
99 (-2, 'exception'),
100 (2, 'exception'),
101 (3, 'line'),
102 (4, 'line'),
103 (4, 'return')]
104
105def _settrace_and_return(tracefunc):
106 sys.settrace(tracefunc)
107 sys._getframe().f_back.f_trace = tracefunc
108def settrace_and_return(tracefunc):
109 _settrace_and_return(tracefunc)
110
111settrace_and_return.events = [(1, 'return')]
112
113def _settrace_and_raise(tracefunc):
114 sys.settrace(tracefunc)
115 sys._getframe().f_back.f_trace = tracefunc
116 raise RuntimeError
117def settrace_and_raise(tracefunc):
118 try:
119 _settrace_and_raise(tracefunc)
120 except RuntimeError, exc:
121 pass
122
123settrace_and_raise.events = [(2, 'exception'),
124 (3, 'line'),
125 (4, 'line'),
126 (4, 'return')]
127
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000128class Tracer:
129 def __init__(self):
130 self.events = []
131 def trace(self, frame, event, arg):
132 self.events.append((frame.f_lineno, event))
133 return self.trace
134
135class TraceTestCase(unittest.TestCase):
Michael W. Hudson519a3422002-09-11 14:47:51 +0000136 def compare_events(self, line_offset, events, expected_events):
137 events = [(l - line_offset, e) for (l, e) in events]
138 if events != expected_events:
139 self.fail(
140 "events did not match expectation:\n" +
141 "\n".join(difflib.ndiff(map(str, expected_events),
142 map(str, events))))
143
144
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000145 def run_test(self, func):
146 tracer = Tracer()
147 sys.settrace(tracer.trace)
148 func()
149 sys.settrace(None)
Michael W. Hudson519a3422002-09-11 14:47:51 +0000150 self.compare_events(func.func_code.co_firstlineno,
151 tracer.events, func.events)
152
153 def run_test2(self, func):
154 tracer = Tracer()
155 func(tracer.trace)
156 sys.settrace(None)
157 self.compare_events(func.func_code.co_firstlineno,
158 tracer.events, func.events)
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000159
160 def test_1_basic(self):
161 self.run_test(basic)
162 def test_2_arigo(self):
163 self.run_test(arigo_example)
164 def test_3_one_instr(self):
165 self.run_test(one_instr_line)
166 def test_4_no_pop_blocks(self):
167 self.run_test(no_pop_blocks)
168 def test_5_no_pop_tops(self):
169 self.run_test(no_pop_tops)
Michael W. Hudson519a3422002-09-11 14:47:51 +0000170 def test_6_call(self):
171 self.run_test(call)
172 def test_7_raise(self):
173 self.run_test(test_raise)
174
175 def test_8_settrace_and_return(self):
176 self.run_test2(settrace_and_return)
177 def test_9_settrace_and_raise(self):
178 self.run_test2(settrace_and_raise)
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000179
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000180class RaisingTraceFuncTestCase(unittest.TestCase):
181 def test_it(self):
182 def tr(frame, event, arg):
183 raise ValueError # just something that isn't RuntimeError
184 def f():
185 return 1
186 try:
187 for i in xrange(sys.getrecursionlimit() + 1):
188 sys.settrace(tr)
189 try:
190 f()
191 except ValueError:
192 pass
193 else:
194 self.fail("exception not thrown!")
195 except RuntimeError:
196 self.fail("recursion counter not reset")
197
198
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000199def test_main():
200 test_support.run_unittest(TraceTestCase)
Michael W. Hudsonfb4d6ec2002-10-02 13:13:45 +0000201 test_support.run_unittest(RaisingTraceFuncTestCase)
Michael W. Hudson53d58bb2002-08-30 13:09:51 +0000202
203if __name__ == "__main__":
204 test_main()