ยปCore Development>Code coverage>Lib/test/test_sys_settrace.py

Python code coverage for Lib/test/test_sys_settrace.py

#countcontent
1n/a# Testing the line trace facility.
2n/a
3n/afrom test import support
4n/aimport unittest
5n/aimport sys
6n/aimport difflib
7n/aimport gc
8n/a
9n/a# A very basic example. If this fails, we're in deep trouble.
10n/adef basic():
11n/a return 1
12n/a
13n/abasic.events = [(0, 'call'),
14n/a (1, 'line'),
15n/a (1, 'return')]
16n/a
17n/a# Many of the tests below are tricky because they involve pass statements.
18n/a# If there is implicit control flow around a pass statement (in an except
19n/a# clause or else caluse) under what conditions do you set a line number
20n/a# following that clause?
21n/a
22n/a
23n/a# The entire "while 0:" statement is optimized away. No code
24n/a# exists for it, so the line numbers skip directly from "del x"
25n/a# to "x = 1".
26n/adef arigo_example():
27n/a x = 1
28n/a del x
29n/a while 0:
30n/a pass
31n/a x = 1
32n/a
33n/aarigo_example.events = [(0, 'call'),
34n/a (1, 'line'),
35n/a (2, 'line'),
36n/a (5, 'line'),
37n/a (5, 'return')]
38n/a
39n/a# check that lines consisting of just one instruction get traced:
40n/adef one_instr_line():
41n/a x = 1
42n/a del x
43n/a x = 1
44n/a
45n/aone_instr_line.events = [(0, 'call'),
46n/a (1, 'line'),
47n/a (2, 'line'),
48n/a (3, 'line'),
49n/a (3, 'return')]
50n/a
51n/adef no_pop_tops(): # 0
52n/a x = 1 # 1
53n/a for a in range(2): # 2
54n/a if a: # 3
55n/a x = 1 # 4
56n/a else: # 5
57n/a x = 1 # 6
58n/a
59n/ano_pop_tops.events = [(0, 'call'),
60n/a (1, 'line'),
61n/a (2, 'line'),
62n/a (3, 'line'),
63n/a (6, 'line'),
64n/a (2, 'line'),
65n/a (3, 'line'),
66n/a (4, 'line'),
67n/a (2, 'line'),
68n/a (2, 'return')]
69n/a
70n/adef no_pop_blocks():
71n/a y = 1
72n/a while not y:
73n/a bla
74n/a x = 1
75n/a
76n/ano_pop_blocks.events = [(0, 'call'),
77n/a (1, 'line'),
78n/a (2, 'line'),
79n/a (4, 'line'),
80n/a (4, 'return')]
81n/a
82n/adef called(): # line -3
83n/a x = 1
84n/a
85n/adef call(): # line 0
86n/a called()
87n/a
88n/acall.events = [(0, 'call'),
89n/a (1, 'line'),
90n/a (-3, 'call'),
91n/a (-2, 'line'),
92n/a (-2, 'return'),
93n/a (1, 'return')]
94n/a
95n/adef raises():
96n/a raise Exception
97n/a
98n/adef test_raise():
99n/a try:
100n/a raises()
101n/a except Exception as exc:
102n/a x = 1
103n/a
104n/atest_raise.events = [(0, 'call'),
105n/a (1, 'line'),
106n/a (2, 'line'),
107n/a (-3, 'call'),
108n/a (-2, 'line'),
109n/a (-2, 'exception'),
110n/a (-2, 'return'),
111n/a (2, 'exception'),
112n/a (3, 'line'),
113n/a (4, 'line'),
114n/a (4, 'return')]
115n/a
116n/adef _settrace_and_return(tracefunc):
117n/a sys.settrace(tracefunc)
118n/a sys._getframe().f_back.f_trace = tracefunc
119n/adef settrace_and_return(tracefunc):
120n/a _settrace_and_return(tracefunc)
121n/a
122n/asettrace_and_return.events = [(1, 'return')]
123n/a
124n/adef _settrace_and_raise(tracefunc):
125n/a sys.settrace(tracefunc)
126n/a sys._getframe().f_back.f_trace = tracefunc
127n/a raise RuntimeError
128n/adef settrace_and_raise(tracefunc):
129n/a try:
130n/a _settrace_and_raise(tracefunc)
131n/a except RuntimeError as exc:
132n/a pass
133n/a
134n/asettrace_and_raise.events = [(2, 'exception'),
135n/a (3, 'line'),
136n/a (4, 'line'),
137n/a (4, 'return')]
138n/a
139n/a# implicit return example
140n/a# This test is interesting because of the else: pass
141n/a# part of the code. The code generate for the true
142n/a# part of the if contains a jump past the else branch.
143n/a# The compiler then generates an implicit "return None"
144n/a# Internally, the compiler visits the pass statement
145n/a# and stores its line number for use on the next instruction.
146n/a# The next instruction is the implicit return None.
147n/adef ireturn_example():
148n/a a = 5
149n/a b = 5
150n/a if a == b:
151n/a b = a+1
152n/a else:
153n/a pass
154n/a
155n/aireturn_example.events = [(0, 'call'),
156n/a (1, 'line'),
157n/a (2, 'line'),
158n/a (3, 'line'),
159n/a (4, 'line'),
160n/a (6, 'line'),
161n/a (6, 'return')]
162n/a
163n/a# Tight loop with while(1) example (SF #765624)
164n/adef tightloop_example():
165n/a items = range(0, 3)
166n/a try:
167n/a i = 0
168n/a while 1:
169n/a b = items[i]; i+=1
170n/a except IndexError:
171n/a pass
172n/a
173n/atightloop_example.events = [(0, 'call'),
174n/a (1, 'line'),
175n/a (2, 'line'),
176n/a (3, 'line'),
177n/a (4, 'line'),
178n/a (5, 'line'),
179n/a (5, 'line'),
180n/a (5, 'line'),
181n/a (5, 'line'),
182n/a (5, 'exception'),
183n/a (6, 'line'),
184n/a (7, 'line'),
185n/a (7, 'return')]
186n/a
187n/adef tighterloop_example():
188n/a items = range(1, 4)
189n/a try:
190n/a i = 0
191n/a while 1: i = items[i]
192n/a except IndexError:
193n/a pass
194n/a
195n/atighterloop_example.events = [(0, 'call'),
196n/a (1, 'line'),
197n/a (2, 'line'),
198n/a (3, 'line'),
199n/a (4, 'line'),
200n/a (4, 'line'),
201n/a (4, 'line'),
202n/a (4, 'line'),
203n/a (4, 'exception'),
204n/a (5, 'line'),
205n/a (6, 'line'),
206n/a (6, 'return')]
207n/a
208n/adef generator_function():
209n/a try:
210n/a yield True
211n/a "continued"
212n/a finally:
213n/a "finally"
214n/adef generator_example():
215n/a # any() will leave the generator before its end
216n/a x = any(generator_function())
217n/a
218n/a # the following lines were not traced
219n/a for x in range(10):
220n/a y = x
221n/a
222n/agenerator_example.events = ([(0, 'call'),
223n/a (2, 'line'),
224n/a (-6, 'call'),
225n/a (-5, 'line'),
226n/a (-4, 'line'),
227n/a (-4, 'return'),
228n/a (-4, 'call'),
229n/a (-4, 'exception'),
230n/a (-1, 'line'),
231n/a (-1, 'return')] +
232n/a [(5, 'line'), (6, 'line')] * 10 +
233n/a [(5, 'line'), (5, 'return')])
234n/a
235n/a
236n/aclass Tracer:
237n/a def __init__(self):
238n/a self.events = []
239n/a def trace(self, frame, event, arg):
240n/a self.events.append((frame.f_lineno, event))
241n/a return self.trace
242n/a def traceWithGenexp(self, frame, event, arg):
243n/a (o for o in [1])
244n/a self.events.append((frame.f_lineno, event))
245n/a return self.trace
246n/a
247n/aclass TraceTestCase(unittest.TestCase):
248n/a
249n/a # Disable gc collection when tracing, otherwise the
250n/a # deallocators may be traced as well.
251n/a def setUp(self):
252n/a self.using_gc = gc.isenabled()
253n/a gc.disable()
254n/a self.addCleanup(sys.settrace, sys.gettrace())
255n/a
256n/a def tearDown(self):
257n/a if self.using_gc:
258n/a gc.enable()
259n/a
260n/a def compare_events(self, line_offset, events, expected_events):
261n/a events = [(l - line_offset, e) for (l, e) in events]
262n/a if events != expected_events:
263n/a self.fail(
264n/a "events did not match expectation:\n" +
265n/a "\n".join(difflib.ndiff([str(x) for x in expected_events],
266n/a [str(x) for x in events])))
267n/a
268n/a def run_and_compare(self, func, events):
269n/a tracer = Tracer()
270n/a sys.settrace(tracer.trace)
271n/a func()
272n/a sys.settrace(None)
273n/a self.compare_events(func.__code__.co_firstlineno,
274n/a tracer.events, events)
275n/a
276n/a def run_test(self, func):
277n/a self.run_and_compare(func, func.events)
278n/a
279n/a def run_test2(self, func):
280n/a tracer = Tracer()
281n/a func(tracer.trace)
282n/a sys.settrace(None)
283n/a self.compare_events(func.__code__.co_firstlineno,
284n/a tracer.events, func.events)
285n/a
286n/a def test_set_and_retrieve_none(self):
287n/a sys.settrace(None)
288n/a assert sys.gettrace() is None
289n/a
290n/a def test_set_and_retrieve_func(self):
291n/a def fn(*args):
292n/a pass
293n/a
294n/a sys.settrace(fn)
295n/a try:
296n/a assert sys.gettrace() is fn
297n/a finally:
298n/a sys.settrace(None)
299n/a
300n/a def test_01_basic(self):
301n/a self.run_test(basic)
302n/a def test_02_arigo(self):
303n/a self.run_test(arigo_example)
304n/a def test_03_one_instr(self):
305n/a self.run_test(one_instr_line)
306n/a def test_04_no_pop_blocks(self):
307n/a self.run_test(no_pop_blocks)
308n/a def test_05_no_pop_tops(self):
309n/a self.run_test(no_pop_tops)
310n/a def test_06_call(self):
311n/a self.run_test(call)
312n/a def test_07_raise(self):
313n/a self.run_test(test_raise)
314n/a
315n/a def test_08_settrace_and_return(self):
316n/a self.run_test2(settrace_and_return)
317n/a def test_09_settrace_and_raise(self):
318n/a self.run_test2(settrace_and_raise)
319n/a def test_10_ireturn(self):
320n/a self.run_test(ireturn_example)
321n/a def test_11_tightloop(self):
322n/a self.run_test(tightloop_example)
323n/a def test_12_tighterloop(self):
324n/a self.run_test(tighterloop_example)
325n/a
326n/a def test_13_genexp(self):
327n/a self.run_test(generator_example)
328n/a # issue1265: if the trace function contains a generator,
329n/a # and if the traced function contains another generator
330n/a # that is not completely exhausted, the trace stopped.
331n/a # Worse: the 'finally' clause was not invoked.
332n/a tracer = Tracer()
333n/a sys.settrace(tracer.traceWithGenexp)
334n/a generator_example()
335n/a sys.settrace(None)
336n/a self.compare_events(generator_example.__code__.co_firstlineno,
337n/a tracer.events, generator_example.events)
338n/a
339n/a def test_14_onliner_if(self):
340n/a def onliners():
341n/a if True: x=False
342n/a else: x=True
343n/a return 0
344n/a self.run_and_compare(
345n/a onliners,
346n/a [(0, 'call'),
347n/a (1, 'line'),
348n/a (3, 'line'),
349n/a (3, 'return')])
350n/a
351n/a def test_15_loops(self):
352n/a # issue1750076: "while" expression is skipped by debugger
353n/a def for_example():
354n/a for x in range(2):
355n/a pass
356n/a self.run_and_compare(
357n/a for_example,
358n/a [(0, 'call'),
359n/a (1, 'line'),
360n/a (2, 'line'),
361n/a (1, 'line'),
362n/a (2, 'line'),
363n/a (1, 'line'),
364n/a (1, 'return')])
365n/a
366n/a def while_example():
367n/a # While expression should be traced on every loop
368n/a x = 2
369n/a while x > 0:
370n/a x -= 1
371n/a self.run_and_compare(
372n/a while_example,
373n/a [(0, 'call'),
374n/a (2, 'line'),
375n/a (3, 'line'),
376n/a (4, 'line'),
377n/a (3, 'line'),
378n/a (4, 'line'),
379n/a (3, 'line'),
380n/a (3, 'return')])
381n/a
382n/a def test_16_blank_lines(self):
383n/a namespace = {}
384n/a exec("def f():\n" + "\n" * 256 + " pass", namespace)
385n/a self.run_and_compare(
386n/a namespace["f"],
387n/a [(0, 'call'),
388n/a (257, 'line'),
389n/a (257, 'return')])
390n/a
391n/a def test_17_none_f_trace(self):
392n/a # Issue 20041: fix TypeError when f_trace is set to None.
393n/a def func():
394n/a sys._getframe().f_trace = None
395n/a lineno = 2
396n/a self.run_and_compare(func,
397n/a [(0, 'call'),
398n/a (1, 'line')])
399n/a
400n/a
401n/aclass RaisingTraceFuncTestCase(unittest.TestCase):
402n/a def setUp(self):
403n/a self.addCleanup(sys.settrace, sys.gettrace())
404n/a
405n/a def trace(self, frame, event, arg):
406n/a """A trace function that raises an exception in response to a
407n/a specific trace event."""
408n/a if event == self.raiseOnEvent:
409n/a raise ValueError # just something that isn't RuntimeError
410n/a else:
411n/a return self.trace
412n/a
413n/a def f(self):
414n/a """The function to trace; raises an exception if that's the case
415n/a we're testing, so that the 'exception' trace event fires."""
416n/a if self.raiseOnEvent == 'exception':
417n/a x = 0
418n/a y = 1/x
419n/a else:
420n/a return 1
421n/a
422n/a def run_test_for_event(self, event):
423n/a """Tests that an exception raised in response to the given event is
424n/a handled OK."""
425n/a self.raiseOnEvent = event
426n/a try:
427n/a for i in range(sys.getrecursionlimit() + 1):
428n/a sys.settrace(self.trace)
429n/a try:
430n/a self.f()
431n/a except ValueError:
432n/a pass
433n/a else:
434n/a self.fail("exception not raised!")
435n/a except RuntimeError:
436n/a self.fail("recursion counter not reset")
437n/a
438n/a # Test the handling of exceptions raised by each kind of trace event.
439n/a def test_call(self):
440n/a self.run_test_for_event('call')
441n/a def test_line(self):
442n/a self.run_test_for_event('line')
443n/a def test_return(self):
444n/a self.run_test_for_event('return')
445n/a def test_exception(self):
446n/a self.run_test_for_event('exception')
447n/a
448n/a def test_trash_stack(self):
449n/a def f():
450n/a for i in range(5):
451n/a print(i) # line tracing will raise an exception at this line
452n/a
453n/a def g(frame, why, extra):
454n/a if (why == 'line' and
455n/a frame.f_lineno == f.__code__.co_firstlineno + 2):
456n/a raise RuntimeError("i am crashing")
457n/a return g
458n/a
459n/a sys.settrace(g)
460n/a try:
461n/a f()
462n/a except RuntimeError:
463n/a # the test is really that this doesn't segfault:
464n/a import gc
465n/a gc.collect()
466n/a else:
467n/a self.fail("exception not propagated")
468n/a
469n/a
470n/a def test_exception_arguments(self):
471n/a def f():
472n/a x = 0
473n/a # this should raise an error
474n/a x.no_such_attr
475n/a def g(frame, event, arg):
476n/a if (event == 'exception'):
477n/a type, exception, trace = arg
478n/a self.assertIsInstance(exception, Exception)
479n/a return g
480n/a
481n/a existing = sys.gettrace()
482n/a try:
483n/a sys.settrace(g)
484n/a try:
485n/a f()
486n/a except AttributeError:
487n/a # this is expected
488n/a pass
489n/a finally:
490n/a sys.settrace(existing)
491n/a
492n/a
493n/a# 'Jump' tests: assigning to frame.f_lineno within a trace function
494n/a# moves the execution position - it's how debuggers implement a Jump
495n/a# command (aka. "Set next statement").
496n/a
497n/aclass JumpTracer:
498n/a """Defines a trace function that jumps from one place to another,
499n/a with the source and destination lines of the jump being defined by
500n/a the 'jump' property of the function under test."""
501n/a
502n/a def __init__(self, function):
503n/a self.function = function
504n/a self.jumpFrom = function.jump[0]
505n/a self.jumpTo = function.jump[1]
506n/a self.done = False
507n/a
508n/a def trace(self, frame, event, arg):
509n/a if not self.done and frame.f_code == self.function.__code__:
510n/a firstLine = frame.f_code.co_firstlineno
511n/a if event == 'line' and frame.f_lineno == firstLine + self.jumpFrom:
512n/a # Cope with non-integer self.jumpTo (because of
513n/a # no_jump_to_non_integers below).
514n/a try:
515n/a frame.f_lineno = firstLine + self.jumpTo
516n/a except TypeError:
517n/a frame.f_lineno = self.jumpTo
518n/a self.done = True
519n/a return self.trace
520n/a
521n/a# The first set of 'jump' tests are for things that are allowed:
522n/a
523n/adef jump_simple_forwards(output):
524n/a output.append(1)
525n/a output.append(2)
526n/a output.append(3)
527n/a
528n/ajump_simple_forwards.jump = (1, 3)
529n/ajump_simple_forwards.output = [3]
530n/a
531n/adef jump_simple_backwards(output):
532n/a output.append(1)
533n/a output.append(2)
534n/a
535n/ajump_simple_backwards.jump = (2, 1)
536n/ajump_simple_backwards.output = [1, 1, 2]
537n/a
538n/adef jump_out_of_block_forwards(output):
539n/a for i in 1, 2:
540n/a output.append(2)
541n/a for j in [3]: # Also tests jumping over a block
542n/a output.append(4)
543n/a output.append(5)
544n/a
545n/ajump_out_of_block_forwards.jump = (3, 5)
546n/ajump_out_of_block_forwards.output = [2, 5]
547n/a
548n/adef jump_out_of_block_backwards(output):
549n/a output.append(1)
550n/a for i in [1]:
551n/a output.append(3)
552n/a for j in [2]: # Also tests jumping over a block
553n/a output.append(5)
554n/a output.append(6)
555n/a output.append(7)
556n/a
557n/ajump_out_of_block_backwards.jump = (6, 1)
558n/ajump_out_of_block_backwards.output = [1, 3, 5, 1, 3, 5, 6, 7]
559n/a
560n/adef jump_to_codeless_line(output):
561n/a output.append(1)
562n/a # Jumping to this line should skip to the next one.
563n/a output.append(3)
564n/a
565n/ajump_to_codeless_line.jump = (1, 2)
566n/ajump_to_codeless_line.output = [3]
567n/a
568n/adef jump_to_same_line(output):
569n/a output.append(1)
570n/a output.append(2)
571n/a output.append(3)
572n/a
573n/ajump_to_same_line.jump = (2, 2)
574n/ajump_to_same_line.output = [1, 2, 3]
575n/a
576n/a# Tests jumping within a finally block, and over one.
577n/adef jump_in_nested_finally(output):
578n/a try:
579n/a output.append(2)
580n/a finally:
581n/a output.append(4)
582n/a try:
583n/a output.append(6)
584n/a finally:
585n/a output.append(8)
586n/a output.append(9)
587n/a
588n/ajump_in_nested_finally.jump = (4, 9)
589n/ajump_in_nested_finally.output = [2, 9]
590n/a
591n/adef jump_infinite_while_loop(output):
592n/a output.append(1)
593n/a while 1:
594n/a output.append(2)
595n/a output.append(3)
596n/a
597n/ajump_infinite_while_loop.jump = (3, 4)
598n/ajump_infinite_while_loop.output = [1, 3]
599n/a
600n/a# The second set of 'jump' tests are for things that are not allowed:
601n/a
602n/adef no_jump_too_far_forwards(output):
603n/a try:
604n/a output.append(2)
605n/a output.append(3)
606n/a except ValueError as e:
607n/a output.append('after' in str(e))
608n/a
609n/ano_jump_too_far_forwards.jump = (3, 6)
610n/ano_jump_too_far_forwards.output = [2, True]
611n/a
612n/adef no_jump_too_far_backwards(output):
613n/a try:
614n/a output.append(2)
615n/a output.append(3)
616n/a except ValueError as e:
617n/a output.append('before' in str(e))
618n/a
619n/ano_jump_too_far_backwards.jump = (3, -1)
620n/ano_jump_too_far_backwards.output = [2, True]
621n/a
622n/a# Test each kind of 'except' line.
623n/adef no_jump_to_except_1(output):
624n/a try:
625n/a output.append(2)
626n/a except:
627n/a e = sys.exc_info()[1]
628n/a output.append('except' in str(e))
629n/a
630n/ano_jump_to_except_1.jump = (2, 3)
631n/ano_jump_to_except_1.output = [True]
632n/a
633n/adef no_jump_to_except_2(output):
634n/a try:
635n/a output.append(2)
636n/a except ValueError:
637n/a e = sys.exc_info()[1]
638n/a output.append('except' in str(e))
639n/a
640n/ano_jump_to_except_2.jump = (2, 3)
641n/ano_jump_to_except_2.output = [True]
642n/a
643n/adef no_jump_to_except_3(output):
644n/a try:
645n/a output.append(2)
646n/a except ValueError as e:
647n/a output.append('except' in str(e))
648n/a
649n/ano_jump_to_except_3.jump = (2, 3)
650n/ano_jump_to_except_3.output = [True]
651n/a
652n/adef no_jump_to_except_4(output):
653n/a try:
654n/a output.append(2)
655n/a except (ValueError, RuntimeError) as e:
656n/a output.append('except' in str(e))
657n/a
658n/ano_jump_to_except_4.jump = (2, 3)
659n/ano_jump_to_except_4.output = [True]
660n/a
661n/adef no_jump_forwards_into_block(output):
662n/a try:
663n/a output.append(2)
664n/a for i in 1, 2:
665n/a output.append(4)
666n/a except ValueError as e:
667n/a output.append('into' in str(e))
668n/a
669n/ano_jump_forwards_into_block.jump = (2, 4)
670n/ano_jump_forwards_into_block.output = [True]
671n/a
672n/adef no_jump_backwards_into_block(output):
673n/a try:
674n/a for i in 1, 2:
675n/a output.append(3)
676n/a output.append(4)
677n/a except ValueError as e:
678n/a output.append('into' in str(e))
679n/a
680n/ano_jump_backwards_into_block.jump = (4, 3)
681n/ano_jump_backwards_into_block.output = [3, 3, True]
682n/a
683n/adef no_jump_into_finally_block(output):
684n/a try:
685n/a try:
686n/a output.append(3)
687n/a x = 1
688n/a finally:
689n/a output.append(6)
690n/a except ValueError as e:
691n/a output.append('finally' in str(e))
692n/a
693n/ano_jump_into_finally_block.jump = (4, 6)
694n/ano_jump_into_finally_block.output = [3, 6, True] # The 'finally' still runs
695n/a
696n/adef no_jump_out_of_finally_block(output):
697n/a try:
698n/a try:
699n/a output.append(3)
700n/a finally:
701n/a output.append(5)
702n/a output.append(6)
703n/a except ValueError as e:
704n/a output.append('finally' in str(e))
705n/a
706n/ano_jump_out_of_finally_block.jump = (5, 1)
707n/ano_jump_out_of_finally_block.output = [3, True]
708n/a
709n/a# This verifies the line-numbers-must-be-integers rule.
710n/adef no_jump_to_non_integers(output):
711n/a try:
712n/a output.append(2)
713n/a except ValueError as e:
714n/a output.append('integer' in str(e))
715n/a
716n/ano_jump_to_non_integers.jump = (2, "Spam")
717n/ano_jump_to_non_integers.output = [True]
718n/a
719n/adef jump_across_with(output):
720n/a with open(support.TESTFN, "wb") as fp:
721n/a pass
722n/a with open(support.TESTFN, "wb") as fp:
723n/a pass
724n/ajump_across_with.jump = (1, 3)
725n/ajump_across_with.output = []
726n/a
727n/a# This verifies that you can't set f_lineno via _getframe or similar
728n/a# trickery.
729n/adef no_jump_without_trace_function():
730n/a try:
731n/a previous_frame = sys._getframe().f_back
732n/a previous_frame.f_lineno = previous_frame.f_lineno
733n/a except ValueError as e:
734n/a # This is the exception we wanted; make sure the error message
735n/a # talks about trace functions.
736n/a if 'trace' not in str(e):
737n/a raise
738n/a else:
739n/a # Something's wrong - the expected exception wasn't raised.
740n/a raise RuntimeError("Trace-function-less jump failed to fail")
741n/a
742n/a
743n/aclass JumpTestCase(unittest.TestCase):
744n/a def setUp(self):
745n/a self.addCleanup(sys.settrace, sys.gettrace())
746n/a sys.settrace(None)
747n/a
748n/a def compare_jump_output(self, expected, received):
749n/a if received != expected:
750n/a self.fail( "Outputs don't match:\n" +
751n/a "Expected: " + repr(expected) + "\n" +
752n/a "Received: " + repr(received))
753n/a
754n/a def run_test(self, func):
755n/a tracer = JumpTracer(func)
756n/a sys.settrace(tracer.trace)
757n/a output = []
758n/a func(output)
759n/a sys.settrace(None)
760n/a self.compare_jump_output(func.output, output)
761n/a
762n/a def test_01_jump_simple_forwards(self):
763n/a self.run_test(jump_simple_forwards)
764n/a def test_02_jump_simple_backwards(self):
765n/a self.run_test(jump_simple_backwards)
766n/a def test_03_jump_out_of_block_forwards(self):
767n/a self.run_test(jump_out_of_block_forwards)
768n/a def test_04_jump_out_of_block_backwards(self):
769n/a self.run_test(jump_out_of_block_backwards)
770n/a def test_05_jump_to_codeless_line(self):
771n/a self.run_test(jump_to_codeless_line)
772n/a def test_06_jump_to_same_line(self):
773n/a self.run_test(jump_to_same_line)
774n/a def test_07_jump_in_nested_finally(self):
775n/a self.run_test(jump_in_nested_finally)
776n/a def test_jump_infinite_while_loop(self):
777n/a self.run_test(jump_infinite_while_loop)
778n/a def test_08_no_jump_too_far_forwards(self):
779n/a self.run_test(no_jump_too_far_forwards)
780n/a def test_09_no_jump_too_far_backwards(self):
781n/a self.run_test(no_jump_too_far_backwards)
782n/a def test_10_no_jump_to_except_1(self):
783n/a self.run_test(no_jump_to_except_1)
784n/a def test_11_no_jump_to_except_2(self):
785n/a self.run_test(no_jump_to_except_2)
786n/a def test_12_no_jump_to_except_3(self):
787n/a self.run_test(no_jump_to_except_3)
788n/a def test_13_no_jump_to_except_4(self):
789n/a self.run_test(no_jump_to_except_4)
790n/a def test_14_no_jump_forwards_into_block(self):
791n/a self.run_test(no_jump_forwards_into_block)
792n/a def test_15_no_jump_backwards_into_block(self):
793n/a self.run_test(no_jump_backwards_into_block)
794n/a def test_16_no_jump_into_finally_block(self):
795n/a self.run_test(no_jump_into_finally_block)
796n/a def test_17_no_jump_out_of_finally_block(self):
797n/a self.run_test(no_jump_out_of_finally_block)
798n/a def test_18_no_jump_to_non_integers(self):
799n/a self.run_test(no_jump_to_non_integers)
800n/a def test_19_no_jump_without_trace_function(self):
801n/a # Must set sys.settrace(None) in setUp(), else condition is not
802n/a # triggered.
803n/a no_jump_without_trace_function()
804n/a def test_jump_across_with(self):
805n/a self.addCleanup(support.unlink, support.TESTFN)
806n/a self.run_test(jump_across_with)
807n/a
808n/a def test_20_large_function(self):
809n/a d = {}
810n/a exec("""def f(output): # line 0
811n/a x = 0 # line 1
812n/a y = 1 # line 2
813n/a ''' # line 3
814n/a %s # lines 4-1004
815n/a ''' # line 1005
816n/a x += 1 # line 1006
817n/a output.append(x) # line 1007
818n/a return""" % ('\n' * 1000,), d)
819n/a f = d['f']
820n/a
821n/a f.jump = (2, 1007)
822n/a f.output = [0]
823n/a self.run_test(f)
824n/a
825n/a def test_jump_to_firstlineno(self):
826n/a # This tests that PDB can jump back to the first line in a
827n/a # file. See issue #1689458. It can only be triggered in a
828n/a # function call if the function is defined on a single line.
829n/a code = compile("""
830n/a# Comments don't count.
831n/aoutput.append(2) # firstlineno is here.
832n/aoutput.append(3)
833n/aoutput.append(4)
834n/a""", "<fake module>", "exec")
835n/a class fake_function:
836n/a __code__ = code
837n/a jump = (2, 0)
838n/a tracer = JumpTracer(fake_function)
839n/a sys.settrace(tracer.trace)
840n/a namespace = {"output": []}
841n/a exec(code, namespace)
842n/a sys.settrace(None)
843n/a self.compare_jump_output([2, 3, 2, 3, 4], namespace["output"])
844n/a
845n/a
846n/adef test_main():
847n/a support.run_unittest(
848n/a TraceTestCase,
849n/a RaisingTraceFuncTestCase,
850n/a JumpTestCase
851n/a )
852n/a
853n/aif __name__ == "__main__":
854n/a test_main()