Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / tools / src / nas,5.n2.os.2 / lib / python / lib / python2.4 / test / test_trace.py
CommitLineData
86530b38
AT
1# 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'),
60 (2, 'return')]
61
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
72def 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, 'return'),
101 (2, 'exception'),
102 (3, 'line'),
103 (4, 'line'),
104 (4, 'return')]
105
106def _settrace_and_return(tracefunc):
107 sys.settrace(tracefunc)
108 sys._getframe().f_back.f_trace = tracefunc
109def settrace_and_return(tracefunc):
110 _settrace_and_return(tracefunc)
111
112settrace_and_return.events = [(1, 'return')]
113
114def _settrace_and_raise(tracefunc):
115 sys.settrace(tracefunc)
116 sys._getframe().f_back.f_trace = tracefunc
117 raise RuntimeError
118def settrace_and_raise(tracefunc):
119 try:
120 _settrace_and_raise(tracefunc)
121 except RuntimeError, exc:
122 pass
123
124settrace_and_raise.events = [(2, 'exception'),
125 (3, 'line'),
126 (4, 'line'),
127 (4, 'return')]
128
129# implicit return example
130def ireturn_example():
131 a = 5
132 b = 5
133 if a == b:
134 b = a+1
135 else:
136 pass
137
138ireturn_example.events = [(0, 'call'),
139 (1, 'line'),
140 (2, 'line'),
141 (3, 'line'),
142 (4, 'line'),
143 (4, 'return')]
144
145# Tight loop with while(1) example (SF #765624)
146def tightloop_example():
147 items = range(0, 3)
148 try:
149 i = 0
150 while 1:
151 b = items[i]; i+=1
152 except IndexError:
153 pass
154
155tightloop_example.events = [(0, 'call'),
156 (1, 'line'),
157 (2, 'line'),
158 (3, 'line'),
159 (4, 'line'),
160 (5, 'line'),
161 (5, 'line'),
162 (5, 'line'),
163 (5, 'line'),
164 (5, 'exception'),
165 (6, 'line'),
166 (7, 'line'),
167 (7, 'return')]
168
169def tighterloop_example():
170 items = range(1, 4)
171 try:
172 i = 0
173 while 1: i = items[i]
174 except IndexError:
175 pass
176
177tighterloop_example.events = [(0, 'call'),
178 (1, 'line'),
179 (2, 'line'),
180 (3, 'line'),
181 (4, 'line'),
182 (4, 'line'),
183 (4, 'line'),
184 (4, 'line'),
185 (4, 'exception'),
186 (5, 'line'),
187 (6, 'line'),
188 (6, 'return')]
189
190class Tracer:
191 def __init__(self):
192 self.events = []
193 def trace(self, frame, event, arg):
194 self.events.append((frame.f_lineno, event))
195 return self.trace
196
197class TraceTestCase(unittest.TestCase):
198 def compare_events(self, line_offset, events, expected_events):
199 events = [(l - line_offset, e) for (l, e) in events]
200 if events != expected_events:
201 self.fail(
202 "events did not match expectation:\n" +
203 "\n".join(difflib.ndiff(map(str, expected_events),
204 map(str, events))))
205
206
207 def run_test(self, func):
208 tracer = Tracer()
209 sys.settrace(tracer.trace)
210 func()
211 sys.settrace(None)
212 self.compare_events(func.func_code.co_firstlineno,
213 tracer.events, func.events)
214
215 def run_test2(self, func):
216 tracer = Tracer()
217 func(tracer.trace)
218 sys.settrace(None)
219 self.compare_events(func.func_code.co_firstlineno,
220 tracer.events, func.events)
221
222 def test_01_basic(self):
223 self.run_test(basic)
224 def test_02_arigo(self):
225 self.run_test(arigo_example)
226 def test_03_one_instr(self):
227 self.run_test(one_instr_line)
228 def test_04_no_pop_blocks(self):
229 self.run_test(no_pop_blocks)
230 def test_05_no_pop_tops(self):
231 self.run_test(no_pop_tops)
232 def test_06_call(self):
233 self.run_test(call)
234 def test_07_raise(self):
235 self.run_test(test_raise)
236
237 def test_08_settrace_and_return(self):
238 self.run_test2(settrace_and_return)
239 def test_09_settrace_and_raise(self):
240 self.run_test2(settrace_and_raise)
241 def test_10_ireturn(self):
242 self.run_test(ireturn_example)
243 def test_11_tightloop(self):
244 self.run_test(tightloop_example)
245 def test_12_tighterloop(self):
246 self.run_test(tighterloop_example)
247
248class RaisingTraceFuncTestCase(unittest.TestCase):
249 def trace(self, frame, event, arg):
250 """A trace function that raises an exception in response to a
251 specific trace event."""
252 if event == self.raiseOnEvent:
253 raise ValueError # just something that isn't RuntimeError
254 else:
255 return self.trace
256
257 def f(self):
258 """The function to trace; raises an exception if that's the case
259 we're testing, so that the 'exception' trace event fires."""
260 if self.raiseOnEvent == 'exception':
261 x = 0
262 y = 1/x
263 else:
264 return 1
265
266 def run_test_for_event(self, event):
267 """Tests that an exception raised in response to the given event is
268 handled OK."""
269 self.raiseOnEvent = event
270 try:
271 for i in xrange(sys.getrecursionlimit() + 1):
272 sys.settrace(self.trace)
273 try:
274 self.f()
275 except ValueError:
276 pass
277 else:
278 self.fail("exception not thrown!")
279 except RuntimeError:
280 self.fail("recursion counter not reset")
281
282 # Test the handling of exceptions raised by each kind of trace event.
283 def test_call(self):
284 self.run_test_for_event('call')
285 def test_line(self):
286 self.run_test_for_event('line')
287 def test_return(self):
288 self.run_test_for_event('return')
289 def test_exception(self):
290 self.run_test_for_event('exception')
291
292 def test_trash_stack(self):
293 def f():
294 for i in range(5):
295 print i # line tracing will raise an exception at this line
296
297 def g(frame, why, extra):
298 if (why == 'line' and
299 frame.f_lineno == f.func_code.co_firstlineno + 2):
300 raise RuntimeError, "i am crashing"
301 return g
302
303 sys.settrace(g)
304 try:
305 f()
306 except RuntimeError:
307 # the test is really that this doesn't segfault:
308 import gc
309 gc.collect()
310 else:
311 self.fail("exception not propagated")
312
313
314# 'Jump' tests: assigning to frame.f_lineno within a trace function
315# moves the execution position - it's how debuggers implement a Jump
316# command (aka. "Set next statement").
317
318class JumpTracer:
319 """Defines a trace function that jumps from one place to another,
320 with the source and destination lines of the jump being defined by
321 the 'jump' property of the function under test."""
322
323 def __init__(self, function):
324 self.function = function
325 self.jumpFrom = function.jump[0]
326 self.jumpTo = function.jump[1]
327 self.done = False
328
329 def trace(self, frame, event, arg):
330 if not self.done and frame.f_code == self.function.func_code:
331 firstLine = frame.f_code.co_firstlineno
332 if frame.f_lineno == firstLine + self.jumpFrom:
333 # Cope with non-integer self.jumpTo (because of
334 # no_jump_to_non_integers below).
335 try:
336 frame.f_lineno = firstLine + self.jumpTo
337 except TypeError:
338 frame.f_lineno = self.jumpTo
339 self.done = True
340 return self.trace
341
342# The first set of 'jump' tests are for things that are allowed:
343
344def jump_simple_forwards(output):
345 output.append(1)
346 output.append(2)
347 output.append(3)
348
349jump_simple_forwards.jump = (1, 3)
350jump_simple_forwards.output = [3]
351
352def jump_simple_backwards(output):
353 output.append(1)
354 output.append(2)
355
356jump_simple_backwards.jump = (2, 1)
357jump_simple_backwards.output = [1, 1, 2]
358
359def jump_out_of_block_forwards(output):
360 for i in 1, 2:
361 output.append(2)
362 for j in [3]: # Also tests jumping over a block
363 output.append(4)
364 output.append(5)
365
366jump_out_of_block_forwards.jump = (3, 5)
367jump_out_of_block_forwards.output = [2, 5]
368
369def jump_out_of_block_backwards(output):
370 output.append(1)
371 for i in [1]:
372 output.append(3)
373 for j in [2]: # Also tests jumping over a block
374 output.append(5)
375 output.append(6)
376 output.append(7)
377
378jump_out_of_block_backwards.jump = (6, 1)
379jump_out_of_block_backwards.output = [1, 3, 5, 1, 3, 5, 6, 7]
380
381def jump_to_codeless_line(output):
382 output.append(1)
383 # Jumping to this line should skip to the next one.
384 output.append(3)
385
386jump_to_codeless_line.jump = (1, 2)
387jump_to_codeless_line.output = [3]
388
389def jump_to_same_line(output):
390 output.append(1)
391 output.append(2)
392 output.append(3)
393
394jump_to_same_line.jump = (2, 2)
395jump_to_same_line.output = [1, 2, 3]
396
397# Tests jumping within a finally block, and over one.
398def jump_in_nested_finally(output):
399 try:
400 output.append(2)
401 finally:
402 output.append(4)
403 try:
404 output.append(6)
405 finally:
406 output.append(8)
407 output.append(9)
408
409jump_in_nested_finally.jump = (4, 9)
410jump_in_nested_finally.output = [2, 9]
411
412# The second set of 'jump' tests are for things that are not allowed:
413
414def no_jump_too_far_forwards(output):
415 try:
416 output.append(2)
417 output.append(3)
418 except ValueError, e:
419 output.append('after' in str(e))
420
421no_jump_too_far_forwards.jump = (3, 6)
422no_jump_too_far_forwards.output = [2, True]
423
424def no_jump_too_far_backwards(output):
425 try:
426 output.append(2)
427 output.append(3)
428 except ValueError, e:
429 output.append('before' in str(e))
430
431no_jump_too_far_backwards.jump = (3, -1)
432no_jump_too_far_backwards.output = [2, True]
433
434# Test each kind of 'except' line.
435def no_jump_to_except_1(output):
436 try:
437 output.append(2)
438 except:
439 e = sys.exc_info()[1]
440 output.append('except' in str(e))
441
442no_jump_to_except_1.jump = (2, 3)
443no_jump_to_except_1.output = [True]
444
445def no_jump_to_except_2(output):
446 try:
447 output.append(2)
448 except ValueError:
449 e = sys.exc_info()[1]
450 output.append('except' in str(e))
451
452no_jump_to_except_2.jump = (2, 3)
453no_jump_to_except_2.output = [True]
454
455def no_jump_to_except_3(output):
456 try:
457 output.append(2)
458 except ValueError, e:
459 output.append('except' in str(e))
460
461no_jump_to_except_3.jump = (2, 3)
462no_jump_to_except_3.output = [True]
463
464def no_jump_to_except_4(output):
465 try:
466 output.append(2)
467 except (ValueError, RuntimeError), e:
468 output.append('except' in str(e))
469
470no_jump_to_except_4.jump = (2, 3)
471no_jump_to_except_4.output = [True]
472
473def no_jump_forwards_into_block(output):
474 try:
475 output.append(2)
476 for i in 1, 2:
477 output.append(4)
478 except ValueError, e:
479 output.append('into' in str(e))
480
481no_jump_forwards_into_block.jump = (2, 4)
482no_jump_forwards_into_block.output = [True]
483
484def no_jump_backwards_into_block(output):
485 try:
486 for i in 1, 2:
487 output.append(3)
488 output.append(4)
489 except ValueError, e:
490 output.append('into' in str(e))
491
492no_jump_backwards_into_block.jump = (4, 3)
493no_jump_backwards_into_block.output = [3, 3, True]
494
495def no_jump_into_finally_block(output):
496 try:
497 try:
498 output.append(3)
499 x = 1
500 finally:
501 output.append(6)
502 except ValueError, e:
503 output.append('finally' in str(e))
504
505no_jump_into_finally_block.jump = (4, 6)
506no_jump_into_finally_block.output = [3, 6, True] # The 'finally' still runs
507
508def no_jump_out_of_finally_block(output):
509 try:
510 try:
511 output.append(3)
512 finally:
513 output.append(5)
514 output.append(6)
515 except ValueError, e:
516 output.append('finally' in str(e))
517
518no_jump_out_of_finally_block.jump = (5, 1)
519no_jump_out_of_finally_block.output = [3, True]
520
521# This verifies the line-numbers-must-be-integers rule.
522def no_jump_to_non_integers(output):
523 try:
524 output.append(2)
525 except ValueError, e:
526 output.append('integer' in str(e))
527
528no_jump_to_non_integers.jump = (2, "Spam")
529no_jump_to_non_integers.output = [True]
530
531# This verifies that you can't set f_lineno via _getframe or similar
532# trickery.
533def no_jump_without_trace_function():
534 try:
535 previous_frame = sys._getframe().f_back
536 previous_frame.f_lineno = previous_frame.f_lineno
537 except ValueError, e:
538 # This is the exception we wanted; make sure the error message
539 # talks about trace functions.
540 if 'trace' not in str(e):
541 raise
542 else:
543 # Something's wrong - the expected exception wasn't raised.
544 raise RuntimeError, "Trace-function-less jump failed to fail"
545
546
547class JumpTestCase(unittest.TestCase):
548 def compare_jump_output(self, expected, received):
549 if received != expected:
550 self.fail( "Outputs don't match:\n" +
551 "Expected: " + repr(expected) + "\n" +
552 "Received: " + repr(received))
553
554 def run_test(self, func):
555 tracer = JumpTracer(func)
556 sys.settrace(tracer.trace)
557 output = []
558 func(output)
559 sys.settrace(None)
560 self.compare_jump_output(func.output, output)
561
562 def test_01_jump_simple_forwards(self):
563 self.run_test(jump_simple_forwards)
564 def test_02_jump_simple_backwards(self):
565 self.run_test(jump_simple_backwards)
566 def test_03_jump_out_of_block_forwards(self):
567 self.run_test(jump_out_of_block_forwards)
568 def test_04_jump_out_of_block_backwards(self):
569 self.run_test(jump_out_of_block_backwards)
570 def test_05_jump_to_codeless_line(self):
571 self.run_test(jump_to_codeless_line)
572 def test_06_jump_to_same_line(self):
573 self.run_test(jump_to_same_line)
574 def test_07_jump_in_nested_finally(self):
575 self.run_test(jump_in_nested_finally)
576 def test_08_no_jump_too_far_forwards(self):
577 self.run_test(no_jump_too_far_forwards)
578 def test_09_no_jump_too_far_backwards(self):
579 self.run_test(no_jump_too_far_backwards)
580 def test_10_no_jump_to_except_1(self):
581 self.run_test(no_jump_to_except_1)
582 def test_11_no_jump_to_except_2(self):
583 self.run_test(no_jump_to_except_2)
584 def test_12_no_jump_to_except_3(self):
585 self.run_test(no_jump_to_except_3)
586 def test_13_no_jump_to_except_4(self):
587 self.run_test(no_jump_to_except_4)
588 def test_14_no_jump_forwards_into_block(self):
589 self.run_test(no_jump_forwards_into_block)
590 def test_15_no_jump_backwards_into_block(self):
591 self.run_test(no_jump_backwards_into_block)
592 def test_16_no_jump_into_finally_block(self):
593 self.run_test(no_jump_into_finally_block)
594 def test_17_no_jump_out_of_finally_block(self):
595 self.run_test(no_jump_out_of_finally_block)
596 def test_18_no_jump_to_non_integers(self):
597 self.run_test(no_jump_to_non_integers)
598 def test_19_no_jump_without_trace_function(self):
599 no_jump_without_trace_function()
600
601def test_main():
602 test_support.run_unittest(
603 TraceTestCase,
604 RaisingTraceFuncTestCase,
605 JumpTestCase
606 )
607
608if __name__ == "__main__":
609 test_main()