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

Python code coverage for Lib/test/test_sys_setprofile.py

#countcontent
1n/aimport gc
2n/aimport pprint
3n/aimport sys
4n/aimport unittest
5n/a
6n/a
7n/aclass TestGetProfile(unittest.TestCase):
8n/a def setUp(self):
9n/a sys.setprofile(None)
10n/a
11n/a def tearDown(self):
12n/a sys.setprofile(None)
13n/a
14n/a def test_empty(self):
15n/a self.assertIsNone(sys.getprofile())
16n/a
17n/a def test_setget(self):
18n/a def fn(*args):
19n/a pass
20n/a
21n/a sys.setprofile(fn)
22n/a self.assertIs(sys.getprofile(), fn)
23n/a
24n/aclass HookWatcher:
25n/a def __init__(self):
26n/a self.frames = []
27n/a self.events = []
28n/a
29n/a def callback(self, frame, event, arg):
30n/a if (event == "call"
31n/a or event == "return"
32n/a or event == "exception"):
33n/a self.add_event(event, frame)
34n/a
35n/a def add_event(self, event, frame=None):
36n/a """Add an event to the log."""
37n/a if frame is None:
38n/a frame = sys._getframe(1)
39n/a
40n/a try:
41n/a frameno = self.frames.index(frame)
42n/a except ValueError:
43n/a frameno = len(self.frames)
44n/a self.frames.append(frame)
45n/a
46n/a self.events.append((frameno, event, ident(frame)))
47n/a
48n/a def get_events(self):
49n/a """Remove calls to add_event()."""
50n/a disallowed = [ident(self.add_event.__func__), ident(ident)]
51n/a self.frames = None
52n/a
53n/a return [item for item in self.events if item[2] not in disallowed]
54n/a
55n/a
56n/aclass ProfileSimulator(HookWatcher):
57n/a def __init__(self, testcase):
58n/a self.testcase = testcase
59n/a self.stack = []
60n/a HookWatcher.__init__(self)
61n/a
62n/a def callback(self, frame, event, arg):
63n/a # Callback registered with sys.setprofile()/sys.settrace()
64n/a self.dispatch[event](self, frame)
65n/a
66n/a def trace_call(self, frame):
67n/a self.add_event('call', frame)
68n/a self.stack.append(frame)
69n/a
70n/a def trace_return(self, frame):
71n/a self.add_event('return', frame)
72n/a self.stack.pop()
73n/a
74n/a def trace_exception(self, frame):
75n/a self.testcase.fail(
76n/a "the profiler should never receive exception events")
77n/a
78n/a def trace_pass(self, frame):
79n/a pass
80n/a
81n/a dispatch = {
82n/a 'call': trace_call,
83n/a 'exception': trace_exception,
84n/a 'return': trace_return,
85n/a 'c_call': trace_pass,
86n/a 'c_return': trace_pass,
87n/a 'c_exception': trace_pass,
88n/a }
89n/a
90n/a
91n/aclass TestCaseBase(unittest.TestCase):
92n/a def check_events(self, callable, expected):
93n/a events = capture_events(callable, self.new_watcher())
94n/a if events != expected:
95n/a self.fail("Expected events:\n%s\nReceived events:\n%s"
96n/a % (pprint.pformat(expected), pprint.pformat(events)))
97n/a
98n/a
99n/aclass ProfileHookTestCase(TestCaseBase):
100n/a def new_watcher(self):
101n/a return HookWatcher()
102n/a
103n/a def test_simple(self):
104n/a def f(p):
105n/a pass
106n/a f_ident = ident(f)
107n/a self.check_events(f, [(1, 'call', f_ident),
108n/a (1, 'return', f_ident),
109n/a ])
110n/a
111n/a def test_exception(self):
112n/a def f(p):
113n/a 1/0
114n/a f_ident = ident(f)
115n/a self.check_events(f, [(1, 'call', f_ident),
116n/a (1, 'return', f_ident),
117n/a ])
118n/a
119n/a def test_caught_exception(self):
120n/a def f(p):
121n/a try: 1/0
122n/a except: pass
123n/a f_ident = ident(f)
124n/a self.check_events(f, [(1, 'call', f_ident),
125n/a (1, 'return', f_ident),
126n/a ])
127n/a
128n/a def test_caught_nested_exception(self):
129n/a def f(p):
130n/a try: 1/0
131n/a except: pass
132n/a f_ident = ident(f)
133n/a self.check_events(f, [(1, 'call', f_ident),
134n/a (1, 'return', f_ident),
135n/a ])
136n/a
137n/a def test_nested_exception(self):
138n/a def f(p):
139n/a 1/0
140n/a f_ident = ident(f)
141n/a self.check_events(f, [(1, 'call', f_ident),
142n/a # This isn't what I expected:
143n/a # (0, 'exception', protect_ident),
144n/a # I expected this again:
145n/a (1, 'return', f_ident),
146n/a ])
147n/a
148n/a def test_exception_in_except_clause(self):
149n/a def f(p):
150n/a 1/0
151n/a def g(p):
152n/a try:
153n/a f(p)
154n/a except:
155n/a try: f(p)
156n/a except: pass
157n/a f_ident = ident(f)
158n/a g_ident = ident(g)
159n/a self.check_events(g, [(1, 'call', g_ident),
160n/a (2, 'call', f_ident),
161n/a (2, 'return', f_ident),
162n/a (3, 'call', f_ident),
163n/a (3, 'return', f_ident),
164n/a (1, 'return', g_ident),
165n/a ])
166n/a
167n/a def test_exception_propagation(self):
168n/a def f(p):
169n/a 1/0
170n/a def g(p):
171n/a try: f(p)
172n/a finally: p.add_event("falling through")
173n/a f_ident = ident(f)
174n/a g_ident = ident(g)
175n/a self.check_events(g, [(1, 'call', g_ident),
176n/a (2, 'call', f_ident),
177n/a (2, 'return', f_ident),
178n/a (1, 'falling through', g_ident),
179n/a (1, 'return', g_ident),
180n/a ])
181n/a
182n/a def test_raise_twice(self):
183n/a def f(p):
184n/a try: 1/0
185n/a except: 1/0
186n/a f_ident = ident(f)
187n/a self.check_events(f, [(1, 'call', f_ident),
188n/a (1, 'return', f_ident),
189n/a ])
190n/a
191n/a def test_raise_reraise(self):
192n/a def f(p):
193n/a try: 1/0
194n/a except: raise
195n/a f_ident = ident(f)
196n/a self.check_events(f, [(1, 'call', f_ident),
197n/a (1, 'return', f_ident),
198n/a ])
199n/a
200n/a def test_raise(self):
201n/a def f(p):
202n/a raise Exception()
203n/a f_ident = ident(f)
204n/a self.check_events(f, [(1, 'call', f_ident),
205n/a (1, 'return', f_ident),
206n/a ])
207n/a
208n/a def test_distant_exception(self):
209n/a def f():
210n/a 1/0
211n/a def g():
212n/a f()
213n/a def h():
214n/a g()
215n/a def i():
216n/a h()
217n/a def j(p):
218n/a i()
219n/a f_ident = ident(f)
220n/a g_ident = ident(g)
221n/a h_ident = ident(h)
222n/a i_ident = ident(i)
223n/a j_ident = ident(j)
224n/a self.check_events(j, [(1, 'call', j_ident),
225n/a (2, 'call', i_ident),
226n/a (3, 'call', h_ident),
227n/a (4, 'call', g_ident),
228n/a (5, 'call', f_ident),
229n/a (5, 'return', f_ident),
230n/a (4, 'return', g_ident),
231n/a (3, 'return', h_ident),
232n/a (2, 'return', i_ident),
233n/a (1, 'return', j_ident),
234n/a ])
235n/a
236n/a def test_generator(self):
237n/a def f():
238n/a for i in range(2):
239n/a yield i
240n/a def g(p):
241n/a for i in f():
242n/a pass
243n/a f_ident = ident(f)
244n/a g_ident = ident(g)
245n/a self.check_events(g, [(1, 'call', g_ident),
246n/a # call the iterator twice to generate values
247n/a (2, 'call', f_ident),
248n/a (2, 'return', f_ident),
249n/a (2, 'call', f_ident),
250n/a (2, 'return', f_ident),
251n/a # once more; returns end-of-iteration with
252n/a # actually raising an exception
253n/a (2, 'call', f_ident),
254n/a (2, 'return', f_ident),
255n/a (1, 'return', g_ident),
256n/a ])
257n/a
258n/a def test_stop_iteration(self):
259n/a def f():
260n/a for i in range(2):
261n/a yield i
262n/a def g(p):
263n/a for i in f():
264n/a pass
265n/a f_ident = ident(f)
266n/a g_ident = ident(g)
267n/a self.check_events(g, [(1, 'call', g_ident),
268n/a # call the iterator twice to generate values
269n/a (2, 'call', f_ident),
270n/a (2, 'return', f_ident),
271n/a (2, 'call', f_ident),
272n/a (2, 'return', f_ident),
273n/a # once more to hit the raise:
274n/a (2, 'call', f_ident),
275n/a (2, 'return', f_ident),
276n/a (1, 'return', g_ident),
277n/a ])
278n/a
279n/a
280n/aclass ProfileSimulatorTestCase(TestCaseBase):
281n/a def new_watcher(self):
282n/a return ProfileSimulator(self)
283n/a
284n/a def test_simple(self):
285n/a def f(p):
286n/a pass
287n/a f_ident = ident(f)
288n/a self.check_events(f, [(1, 'call', f_ident),
289n/a (1, 'return', f_ident),
290n/a ])
291n/a
292n/a def test_basic_exception(self):
293n/a def f(p):
294n/a 1/0
295n/a f_ident = ident(f)
296n/a self.check_events(f, [(1, 'call', f_ident),
297n/a (1, 'return', f_ident),
298n/a ])
299n/a
300n/a def test_caught_exception(self):
301n/a def f(p):
302n/a try: 1/0
303n/a except: pass
304n/a f_ident = ident(f)
305n/a self.check_events(f, [(1, 'call', f_ident),
306n/a (1, 'return', f_ident),
307n/a ])
308n/a
309n/a def test_distant_exception(self):
310n/a def f():
311n/a 1/0
312n/a def g():
313n/a f()
314n/a def h():
315n/a g()
316n/a def i():
317n/a h()
318n/a def j(p):
319n/a i()
320n/a f_ident = ident(f)
321n/a g_ident = ident(g)
322n/a h_ident = ident(h)
323n/a i_ident = ident(i)
324n/a j_ident = ident(j)
325n/a self.check_events(j, [(1, 'call', j_ident),
326n/a (2, 'call', i_ident),
327n/a (3, 'call', h_ident),
328n/a (4, 'call', g_ident),
329n/a (5, 'call', f_ident),
330n/a (5, 'return', f_ident),
331n/a (4, 'return', g_ident),
332n/a (3, 'return', h_ident),
333n/a (2, 'return', i_ident),
334n/a (1, 'return', j_ident),
335n/a ])
336n/a
337n/a
338n/adef ident(function):
339n/a if hasattr(function, "f_code"):
340n/a code = function.f_code
341n/a else:
342n/a code = function.__code__
343n/a return code.co_firstlineno, code.co_name
344n/a
345n/a
346n/adef protect(f, p):
347n/a try: f(p)
348n/a except: pass
349n/a
350n/aprotect_ident = ident(protect)
351n/a
352n/a
353n/adef capture_events(callable, p=None):
354n/a if p is None:
355n/a p = HookWatcher()
356n/a # Disable the garbage collector. This prevents __del__s from showing up in
357n/a # traces.
358n/a old_gc = gc.isenabled()
359n/a gc.disable()
360n/a try:
361n/a sys.setprofile(p.callback)
362n/a protect(callable, p)
363n/a sys.setprofile(None)
364n/a finally:
365n/a if old_gc:
366n/a gc.enable()
367n/a return p.get_events()[1:-1]
368n/a
369n/a
370n/adef show_events(callable):
371n/a import pprint
372n/a pprint.pprint(capture_events(callable))
373n/a
374n/a
375n/aif __name__ == "__main__":
376n/a unittest.main()