]> git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Python/Python-2.7.2/Lib/test/test_trace.py
AppPkg/Applications/Python: Add Python 2.7.2 sources since the release of Python...
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Lib / test / test_trace.py
1 import os
2 import sys
3 from test.test_support import (run_unittest, TESTFN, rmtree, unlink,
4 captured_stdout)
5 import unittest
6
7 import trace
8 from trace import CoverageResults, Trace
9
10 from test.tracedmodules import testmod
11
12
13 #------------------------------- Utilities -----------------------------------#
14
15 def fix_ext_py(filename):
16 """Given a .pyc/.pyo filename converts it to the appropriate .py"""
17 if filename.endswith(('.pyc', '.pyo')):
18 filename = filename[:-1]
19 return filename
20
21 def my_file_and_modname():
22 """The .py file and module name of this file (__file__)"""
23 modname = os.path.splitext(os.path.basename(__file__))[0]
24 return fix_ext_py(__file__), modname
25
26 def get_firstlineno(func):
27 return func.__code__.co_firstlineno
28
29 #-------------------- Target functions for tracing ---------------------------#
30 #
31 # The relative line numbers of lines in these functions matter for verifying
32 # tracing. Please modify the appropriate tests if you change one of the
33 # functions. Absolute line numbers don't matter.
34 #
35
36 def traced_func_linear(x, y):
37 a = x
38 b = y
39 c = a + b
40 return c
41
42 def traced_func_loop(x, y):
43 c = x
44 for i in range(5):
45 c += y
46 return c
47
48 def traced_func_importing(x, y):
49 return x + y + testmod.func(1)
50
51 def traced_func_simple_caller(x):
52 c = traced_func_linear(x, x)
53 return c + x
54
55 def traced_func_importing_caller(x):
56 k = traced_func_simple_caller(x)
57 k += traced_func_importing(k, x)
58 return k
59
60 def traced_func_generator(num):
61 c = 5 # executed once
62 for i in range(num):
63 yield i + c
64
65 def traced_func_calling_generator():
66 k = 0
67 for i in traced_func_generator(10):
68 k += i
69
70 def traced_doubler(num):
71 return num * 2
72
73 def traced_caller_list_comprehension():
74 k = 10
75 mylist = [traced_doubler(i) for i in range(k)]
76 return mylist
77
78
79 class TracedClass(object):
80 def __init__(self, x):
81 self.a = x
82
83 def inst_method_linear(self, y):
84 return self.a + y
85
86 def inst_method_calling(self, x):
87 c = self.inst_method_linear(x)
88 return c + traced_func_linear(x, c)
89
90 @classmethod
91 def class_method_linear(cls, y):
92 return y * 2
93
94 @staticmethod
95 def static_method_linear(y):
96 return y * 2
97
98
99 #------------------------------ Test cases -----------------------------------#
100
101
102 class TestLineCounts(unittest.TestCase):
103 """White-box testing of line-counting, via runfunc"""
104 def setUp(self):
105 self.tracer = Trace(count=1, trace=0, countfuncs=0, countcallers=0)
106 self.my_py_filename = fix_ext_py(__file__)
107
108 def test_traced_func_linear(self):
109 result = self.tracer.runfunc(traced_func_linear, 2, 5)
110 self.assertEqual(result, 7)
111
112 # all lines are executed once
113 expected = {}
114 firstlineno = get_firstlineno(traced_func_linear)
115 for i in range(1, 5):
116 expected[(self.my_py_filename, firstlineno + i)] = 1
117
118 self.assertEqual(self.tracer.results().counts, expected)
119
120 def test_traced_func_loop(self):
121 self.tracer.runfunc(traced_func_loop, 2, 3)
122
123 firstlineno = get_firstlineno(traced_func_loop)
124 expected = {
125 (self.my_py_filename, firstlineno + 1): 1,
126 (self.my_py_filename, firstlineno + 2): 6,
127 (self.my_py_filename, firstlineno + 3): 5,
128 (self.my_py_filename, firstlineno + 4): 1,
129 }
130 self.assertEqual(self.tracer.results().counts, expected)
131
132 def test_traced_func_importing(self):
133 self.tracer.runfunc(traced_func_importing, 2, 5)
134
135 firstlineno = get_firstlineno(traced_func_importing)
136 expected = {
137 (self.my_py_filename, firstlineno + 1): 1,
138 (fix_ext_py(testmod.__file__), 2): 1,
139 (fix_ext_py(testmod.__file__), 3): 1,
140 }
141
142 self.assertEqual(self.tracer.results().counts, expected)
143
144 def test_trace_func_generator(self):
145 self.tracer.runfunc(traced_func_calling_generator)
146
147 firstlineno_calling = get_firstlineno(traced_func_calling_generator)
148 firstlineno_gen = get_firstlineno(traced_func_generator)
149 expected = {
150 (self.my_py_filename, firstlineno_calling + 1): 1,
151 (self.my_py_filename, firstlineno_calling + 2): 11,
152 (self.my_py_filename, firstlineno_calling + 3): 10,
153 (self.my_py_filename, firstlineno_gen + 1): 1,
154 (self.my_py_filename, firstlineno_gen + 2): 11,
155 (self.my_py_filename, firstlineno_gen + 3): 10,
156 }
157 self.assertEqual(self.tracer.results().counts, expected)
158
159 def test_trace_list_comprehension(self):
160 self.tracer.runfunc(traced_caller_list_comprehension)
161
162 firstlineno_calling = get_firstlineno(traced_caller_list_comprehension)
163 firstlineno_called = get_firstlineno(traced_doubler)
164 expected = {
165 (self.my_py_filename, firstlineno_calling + 1): 1,
166 (self.my_py_filename, firstlineno_calling + 2): 11,
167 (self.my_py_filename, firstlineno_calling + 3): 1,
168 (self.my_py_filename, firstlineno_called + 1): 10,
169 }
170 self.assertEqual(self.tracer.results().counts, expected)
171
172
173 def test_linear_methods(self):
174 # XXX todo: later add 'static_method_linear' and 'class_method_linear'
175 # here, once issue1764286 is resolved
176 #
177 for methname in ['inst_method_linear',]:
178 tracer = Trace(count=1, trace=0, countfuncs=0, countcallers=0)
179 traced_obj = TracedClass(25)
180 method = getattr(traced_obj, methname)
181 tracer.runfunc(method, 20)
182
183 firstlineno = get_firstlineno(method)
184 expected = {
185 (self.my_py_filename, firstlineno + 1): 1,
186 }
187 self.assertEqual(tracer.results().counts, expected)
188
189 class TestRunExecCounts(unittest.TestCase):
190 """A simple sanity test of line-counting, via runctx (exec)"""
191 def setUp(self):
192 self.my_py_filename = fix_ext_py(__file__)
193
194 def test_exec_counts(self):
195 self.tracer = Trace(count=1, trace=0, countfuncs=0, countcallers=0)
196 code = r'''traced_func_loop(2, 5)'''
197 code = compile(code, __file__, 'exec')
198 self.tracer.runctx(code, globals(), vars())
199
200 firstlineno = get_firstlineno(traced_func_loop)
201 expected = {
202 (self.my_py_filename, firstlineno + 1): 1,
203 (self.my_py_filename, firstlineno + 2): 6,
204 (self.my_py_filename, firstlineno + 3): 5,
205 (self.my_py_filename, firstlineno + 4): 1,
206 }
207
208 # When used through 'run', some other spurious counts are produced, like
209 # the settrace of threading, which we ignore, just making sure that the
210 # counts fo traced_func_loop were right.
211 #
212 for k in expected.keys():
213 self.assertEqual(self.tracer.results().counts[k], expected[k])
214
215
216 class TestFuncs(unittest.TestCase):
217 """White-box testing of funcs tracing"""
218 def setUp(self):
219 self.tracer = Trace(count=0, trace=0, countfuncs=1)
220 self.filemod = my_file_and_modname()
221
222 def test_simple_caller(self):
223 self.tracer.runfunc(traced_func_simple_caller, 1)
224
225 expected = {
226 self.filemod + ('traced_func_simple_caller',): 1,
227 self.filemod + ('traced_func_linear',): 1,
228 }
229 self.assertEqual(self.tracer.results().calledfuncs, expected)
230
231 def test_loop_caller_importing(self):
232 self.tracer.runfunc(traced_func_importing_caller, 1)
233
234 expected = {
235 self.filemod + ('traced_func_simple_caller',): 1,
236 self.filemod + ('traced_func_linear',): 1,
237 self.filemod + ('traced_func_importing_caller',): 1,
238 self.filemod + ('traced_func_importing',): 1,
239 (fix_ext_py(testmod.__file__), 'testmod', 'func'): 1,
240 }
241 self.assertEqual(self.tracer.results().calledfuncs, expected)
242
243 def test_inst_method_calling(self):
244 obj = TracedClass(20)
245 self.tracer.runfunc(obj.inst_method_calling, 1)
246
247 expected = {
248 self.filemod + ('TracedClass.inst_method_calling',): 1,
249 self.filemod + ('TracedClass.inst_method_linear',): 1,
250 self.filemod + ('traced_func_linear',): 1,
251 }
252 self.assertEqual(self.tracer.results().calledfuncs, expected)
253
254
255 class TestCallers(unittest.TestCase):
256 """White-box testing of callers tracing"""
257 def setUp(self):
258 self.tracer = Trace(count=0, trace=0, countcallers=1)
259 self.filemod = my_file_and_modname()
260
261 def test_loop_caller_importing(self):
262 self.tracer.runfunc(traced_func_importing_caller, 1)
263
264 expected = {
265 ((os.path.splitext(trace.__file__)[0] + '.py', 'trace', 'Trace.runfunc'),
266 (self.filemod + ('traced_func_importing_caller',))): 1,
267 ((self.filemod + ('traced_func_simple_caller',)),
268 (self.filemod + ('traced_func_linear',))): 1,
269 ((self.filemod + ('traced_func_importing_caller',)),
270 (self.filemod + ('traced_func_simple_caller',))): 1,
271 ((self.filemod + ('traced_func_importing_caller',)),
272 (self.filemod + ('traced_func_importing',))): 1,
273 ((self.filemod + ('traced_func_importing',)),
274 (fix_ext_py(testmod.__file__), 'testmod', 'func')): 1,
275 }
276 self.assertEqual(self.tracer.results().callers, expected)
277
278
279 # Created separately for issue #3821
280 class TestCoverage(unittest.TestCase):
281 def tearDown(self):
282 rmtree(TESTFN)
283 unlink(TESTFN)
284
285 def _coverage(self, tracer,
286 cmd='from test import test_pprint; test_pprint.test_main()'):
287 tracer.run(cmd)
288 r = tracer.results()
289 r.write_results(show_missing=True, summary=True, coverdir=TESTFN)
290
291 def test_coverage(self):
292 tracer = trace.Trace(trace=0, count=1)
293 with captured_stdout() as stdout:
294 self._coverage(tracer)
295 stdout = stdout.getvalue()
296 self.assertTrue("pprint.py" in stdout)
297 self.assertTrue("case.py" in stdout) # from unittest
298 files = os.listdir(TESTFN)
299 self.assertTrue("pprint.cover" in files)
300 self.assertTrue("unittest.case.cover" in files)
301
302 def test_coverage_ignore(self):
303 # Ignore all files, nothing should be traced nor printed
304 libpath = os.path.normpath(os.path.dirname(os.__file__))
305 # sys.prefix does not work when running from a checkout
306 tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix, libpath],
307 trace=0, count=1)
308 with captured_stdout() as stdout:
309 self._coverage(tracer)
310 if os.path.exists(TESTFN):
311 files = os.listdir(TESTFN)
312 self.assertEqual(files, [])
313
314 def test_issue9936(self):
315 tracer = trace.Trace(trace=0, count=1)
316 modname = 'test.tracedmodules.testmod'
317 # Ensure that the module is executed in import
318 if modname in sys.modules:
319 del sys.modules[modname]
320 cmd = ("import test.tracedmodules.testmod as t;"
321 "t.func(0); t.func2();")
322 with captured_stdout() as stdout:
323 self._coverage(tracer, cmd)
324 stdout.seek(0)
325 stdout.readline()
326 coverage = {}
327 for line in stdout:
328 lines, cov, module = line.split()[:3]
329 coverage[module] = (int(lines), int(cov[:-1]))
330 # XXX This is needed to run regrtest.py as a script
331 modname = trace.fullmodname(sys.modules[modname].__file__)
332 self.assertIn(modname, coverage)
333 self.assertEqual(coverage[modname], (5, 100))
334
335
336 def test_main():
337 run_unittest(__name__)
338
339
340 if __name__ == '__main__':
341 test_main()