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