Bump version number to 2.4.2 to pick up the latest minor bug fixes.
[python/dscho.git] / Lib / test / test_trace.py
blob91112e8b2113eee9dc876e0910c40f48996de262
1 # Testing the line trace facility.
3 from test import test_support
4 import unittest
5 import sys
6 import difflib
8 # A very basic example. If this fails, we're in deep trouble.
9 def basic():
10 return 1
12 basic.events = [(0, 'call'),
13 (1, 'line'),
14 (1, 'return')]
16 # Armin Rigo's failing example:
17 def arigo_example():
18 x = 1
19 del x
20 while 0:
21 pass
22 x = 1
24 arigo_example.events = [(0, 'call'),
25 (1, 'line'),
26 (2, 'line'),
27 (3, 'line'),
28 (5, 'line'),
29 (5, 'return')]
31 # check that lines consisting of just one instruction get traced:
32 def one_instr_line():
33 x = 1
34 del x
35 x = 1
37 one_instr_line.events = [(0, 'call'),
38 (1, 'line'),
39 (2, 'line'),
40 (3, 'line'),
41 (3, 'return')]
43 def 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
51 no_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'),
60 (2, 'return')]
62 def no_pop_blocks():
63 while 0:
64 bla
65 x = 1
67 no_pop_blocks.events = [(0, 'call'),
68 (1, 'line'),
69 (3, 'line'),
70 (3, 'return')]
72 def called(): # line -3
73 x = 1
75 def call(): # line 0
76 called()
78 call.events = [(0, 'call'),
79 (1, 'line'),
80 (-3, 'call'),
81 (-2, 'line'),
82 (-2, 'return'),
83 (1, 'return')]
85 def raises():
86 raise Exception
88 def test_raise():
89 try:
90 raises()
91 except Exception, exc:
92 x = 1
94 test_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')]
105 def _settrace_and_return(tracefunc):
106 sys.settrace(tracefunc)
107 sys._getframe().f_back.f_trace = tracefunc
108 def settrace_and_return(tracefunc):
109 _settrace_and_return(tracefunc)
111 settrace_and_return.events = [(1, 'return')]
113 def _settrace_and_raise(tracefunc):
114 sys.settrace(tracefunc)
115 sys._getframe().f_back.f_trace = tracefunc
116 raise RuntimeError
117 def settrace_and_raise(tracefunc):
118 try:
119 _settrace_and_raise(tracefunc)
120 except RuntimeError, exc:
121 pass
123 settrace_and_raise.events = [(2, 'exception'),
124 (3, 'line'),
125 (4, 'line'),
126 (4, 'return')]
128 class 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
135 class TraceTestCase(unittest.TestCase):
136 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))))
145 def run_test(self, func):
146 tracer = Tracer()
147 sys.settrace(tracer.trace)
148 func()
149 sys.settrace(None)
150 self.compare_events(func.func_code.co_firstlineno,
151 tracer.events, func.events)
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)
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)
170 def test_6_call(self):
171 self.run_test(call)
172 def test_7_raise(self):
173 self.run_test(test_raise)
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)
180 class 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:
191 except ValueError:
192 pass
193 else:
194 self.fail("exception not thrown!")
195 except RuntimeError:
196 self.fail("recursion counter not reset")
199 def test_main():
200 test_support.run_unittest(TraceTestCase)
201 test_support.run_unittest(RaisingTraceFuncTestCase)
203 if __name__ == "__main__":
204 test_main()