17db96d56Sopenharmony_ciimport os 27db96d56Sopenharmony_cifrom pickle import dump 37db96d56Sopenharmony_ciimport sys 47db96d56Sopenharmony_cifrom test.support import captured_stdout 57db96d56Sopenharmony_cifrom test.support.os_helper import (TESTFN, rmtree, unlink) 67db96d56Sopenharmony_cifrom test.support.script_helper import assert_python_ok, assert_python_failure 77db96d56Sopenharmony_ciimport textwrap 87db96d56Sopenharmony_ciimport unittest 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ciimport trace 117db96d56Sopenharmony_cifrom trace import Trace 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_cifrom test.tracedmodules import testmod 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_ci## 167db96d56Sopenharmony_ci## See also test_sys_settrace.py, which contains tests that cover 177db96d56Sopenharmony_ci## tracing of many more code blocks. 187db96d56Sopenharmony_ci## 197db96d56Sopenharmony_ci 207db96d56Sopenharmony_ci#------------------------------- Utilities -----------------------------------# 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_cidef fix_ext_py(filename): 237db96d56Sopenharmony_ci """Given a .pyc filename converts it to the appropriate .py""" 247db96d56Sopenharmony_ci if filename.endswith('.pyc'): 257db96d56Sopenharmony_ci filename = filename[:-1] 267db96d56Sopenharmony_ci return filename 277db96d56Sopenharmony_ci 287db96d56Sopenharmony_cidef my_file_and_modname(): 297db96d56Sopenharmony_ci """The .py file and module name of this file (__file__)""" 307db96d56Sopenharmony_ci modname = os.path.splitext(os.path.basename(__file__))[0] 317db96d56Sopenharmony_ci return fix_ext_py(__file__), modname 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_cidef get_firstlineno(func): 347db96d56Sopenharmony_ci return func.__code__.co_firstlineno 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_ci#-------------------- Target functions for tracing ---------------------------# 377db96d56Sopenharmony_ci# 387db96d56Sopenharmony_ci# The relative line numbers of lines in these functions matter for verifying 397db96d56Sopenharmony_ci# tracing. Please modify the appropriate tests if you change one of the 407db96d56Sopenharmony_ci# functions. Absolute line numbers don't matter. 417db96d56Sopenharmony_ci# 427db96d56Sopenharmony_ci 437db96d56Sopenharmony_cidef traced_func_linear(x, y): 447db96d56Sopenharmony_ci a = x 457db96d56Sopenharmony_ci b = y 467db96d56Sopenharmony_ci c = a + b 477db96d56Sopenharmony_ci return c 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_cidef traced_func_loop(x, y): 507db96d56Sopenharmony_ci c = x 517db96d56Sopenharmony_ci for i in range(5): 527db96d56Sopenharmony_ci c += y 537db96d56Sopenharmony_ci return c 547db96d56Sopenharmony_ci 557db96d56Sopenharmony_cidef traced_func_importing(x, y): 567db96d56Sopenharmony_ci return x + y + testmod.func(1) 577db96d56Sopenharmony_ci 587db96d56Sopenharmony_cidef traced_func_simple_caller(x): 597db96d56Sopenharmony_ci c = traced_func_linear(x, x) 607db96d56Sopenharmony_ci return c + x 617db96d56Sopenharmony_ci 627db96d56Sopenharmony_cidef traced_func_importing_caller(x): 637db96d56Sopenharmony_ci k = traced_func_simple_caller(x) 647db96d56Sopenharmony_ci k += traced_func_importing(k, x) 657db96d56Sopenharmony_ci return k 667db96d56Sopenharmony_ci 677db96d56Sopenharmony_cidef traced_func_generator(num): 687db96d56Sopenharmony_ci c = 5 # executed once 697db96d56Sopenharmony_ci for i in range(num): 707db96d56Sopenharmony_ci yield i + c 717db96d56Sopenharmony_ci 727db96d56Sopenharmony_cidef traced_func_calling_generator(): 737db96d56Sopenharmony_ci k = 0 747db96d56Sopenharmony_ci for i in traced_func_generator(10): 757db96d56Sopenharmony_ci k += i 767db96d56Sopenharmony_ci 777db96d56Sopenharmony_cidef traced_doubler(num): 787db96d56Sopenharmony_ci return num * 2 797db96d56Sopenharmony_ci 807db96d56Sopenharmony_cidef traced_capturer(*args, **kwargs): 817db96d56Sopenharmony_ci return args, kwargs 827db96d56Sopenharmony_ci 837db96d56Sopenharmony_cidef traced_caller_list_comprehension(): 847db96d56Sopenharmony_ci k = 10 857db96d56Sopenharmony_ci mylist = [traced_doubler(i) for i in range(k)] 867db96d56Sopenharmony_ci return mylist 877db96d56Sopenharmony_ci 887db96d56Sopenharmony_cidef traced_decorated_function(): 897db96d56Sopenharmony_ci def decorator1(f): 907db96d56Sopenharmony_ci return f 917db96d56Sopenharmony_ci def decorator_fabric(): 927db96d56Sopenharmony_ci def decorator2(f): 937db96d56Sopenharmony_ci return f 947db96d56Sopenharmony_ci return decorator2 957db96d56Sopenharmony_ci @decorator1 967db96d56Sopenharmony_ci @decorator_fabric() 977db96d56Sopenharmony_ci def func(): 987db96d56Sopenharmony_ci pass 997db96d56Sopenharmony_ci func() 1007db96d56Sopenharmony_ci 1017db96d56Sopenharmony_ci 1027db96d56Sopenharmony_ciclass TracedClass(object): 1037db96d56Sopenharmony_ci def __init__(self, x): 1047db96d56Sopenharmony_ci self.a = x 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_ci def inst_method_linear(self, y): 1077db96d56Sopenharmony_ci return self.a + y 1087db96d56Sopenharmony_ci 1097db96d56Sopenharmony_ci def inst_method_calling(self, x): 1107db96d56Sopenharmony_ci c = self.inst_method_linear(x) 1117db96d56Sopenharmony_ci return c + traced_func_linear(x, c) 1127db96d56Sopenharmony_ci 1137db96d56Sopenharmony_ci @classmethod 1147db96d56Sopenharmony_ci def class_method_linear(cls, y): 1157db96d56Sopenharmony_ci return y * 2 1167db96d56Sopenharmony_ci 1177db96d56Sopenharmony_ci @staticmethod 1187db96d56Sopenharmony_ci def static_method_linear(y): 1197db96d56Sopenharmony_ci return y * 2 1207db96d56Sopenharmony_ci 1217db96d56Sopenharmony_ci 1227db96d56Sopenharmony_ci#------------------------------ Test cases -----------------------------------# 1237db96d56Sopenharmony_ci 1247db96d56Sopenharmony_ci 1257db96d56Sopenharmony_ciclass TestLineCounts(unittest.TestCase): 1267db96d56Sopenharmony_ci """White-box testing of line-counting, via runfunc""" 1277db96d56Sopenharmony_ci def setUp(self): 1287db96d56Sopenharmony_ci self.addCleanup(sys.settrace, sys.gettrace()) 1297db96d56Sopenharmony_ci self.tracer = Trace(count=1, trace=0, countfuncs=0, countcallers=0) 1307db96d56Sopenharmony_ci self.my_py_filename = fix_ext_py(__file__) 1317db96d56Sopenharmony_ci 1327db96d56Sopenharmony_ci def test_traced_func_linear(self): 1337db96d56Sopenharmony_ci result = self.tracer.runfunc(traced_func_linear, 2, 5) 1347db96d56Sopenharmony_ci self.assertEqual(result, 7) 1357db96d56Sopenharmony_ci 1367db96d56Sopenharmony_ci # all lines are executed once 1377db96d56Sopenharmony_ci expected = {} 1387db96d56Sopenharmony_ci firstlineno = get_firstlineno(traced_func_linear) 1397db96d56Sopenharmony_ci for i in range(1, 5): 1407db96d56Sopenharmony_ci expected[(self.my_py_filename, firstlineno + i)] = 1 1417db96d56Sopenharmony_ci 1427db96d56Sopenharmony_ci self.assertEqual(self.tracer.results().counts, expected) 1437db96d56Sopenharmony_ci 1447db96d56Sopenharmony_ci def test_traced_func_loop(self): 1457db96d56Sopenharmony_ci self.tracer.runfunc(traced_func_loop, 2, 3) 1467db96d56Sopenharmony_ci 1477db96d56Sopenharmony_ci firstlineno = get_firstlineno(traced_func_loop) 1487db96d56Sopenharmony_ci expected = { 1497db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 1): 1, 1507db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 2): 6, 1517db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 3): 5, 1527db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 4): 1, 1537db96d56Sopenharmony_ci } 1547db96d56Sopenharmony_ci self.assertEqual(self.tracer.results().counts, expected) 1557db96d56Sopenharmony_ci 1567db96d56Sopenharmony_ci def test_traced_func_importing(self): 1577db96d56Sopenharmony_ci self.tracer.runfunc(traced_func_importing, 2, 5) 1587db96d56Sopenharmony_ci 1597db96d56Sopenharmony_ci firstlineno = get_firstlineno(traced_func_importing) 1607db96d56Sopenharmony_ci expected = { 1617db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 1): 1, 1627db96d56Sopenharmony_ci (fix_ext_py(testmod.__file__), 2): 1, 1637db96d56Sopenharmony_ci (fix_ext_py(testmod.__file__), 3): 1, 1647db96d56Sopenharmony_ci } 1657db96d56Sopenharmony_ci 1667db96d56Sopenharmony_ci self.assertEqual(self.tracer.results().counts, expected) 1677db96d56Sopenharmony_ci 1687db96d56Sopenharmony_ci def test_trace_func_generator(self): 1697db96d56Sopenharmony_ci self.tracer.runfunc(traced_func_calling_generator) 1707db96d56Sopenharmony_ci 1717db96d56Sopenharmony_ci firstlineno_calling = get_firstlineno(traced_func_calling_generator) 1727db96d56Sopenharmony_ci firstlineno_gen = get_firstlineno(traced_func_generator) 1737db96d56Sopenharmony_ci expected = { 1747db96d56Sopenharmony_ci (self.my_py_filename, firstlineno_calling + 1): 1, 1757db96d56Sopenharmony_ci (self.my_py_filename, firstlineno_calling + 2): 11, 1767db96d56Sopenharmony_ci (self.my_py_filename, firstlineno_calling + 3): 10, 1777db96d56Sopenharmony_ci (self.my_py_filename, firstlineno_gen + 1): 1, 1787db96d56Sopenharmony_ci (self.my_py_filename, firstlineno_gen + 2): 11, 1797db96d56Sopenharmony_ci (self.my_py_filename, firstlineno_gen + 3): 10, 1807db96d56Sopenharmony_ci } 1817db96d56Sopenharmony_ci self.assertEqual(self.tracer.results().counts, expected) 1827db96d56Sopenharmony_ci 1837db96d56Sopenharmony_ci def test_trace_list_comprehension(self): 1847db96d56Sopenharmony_ci self.tracer.runfunc(traced_caller_list_comprehension) 1857db96d56Sopenharmony_ci 1867db96d56Sopenharmony_ci firstlineno_calling = get_firstlineno(traced_caller_list_comprehension) 1877db96d56Sopenharmony_ci firstlineno_called = get_firstlineno(traced_doubler) 1887db96d56Sopenharmony_ci expected = { 1897db96d56Sopenharmony_ci (self.my_py_filename, firstlineno_calling + 1): 1, 1907db96d56Sopenharmony_ci # List comprehensions work differently in 3.x, so the count 1917db96d56Sopenharmony_ci # below changed compared to 2.x. 1927db96d56Sopenharmony_ci (self.my_py_filename, firstlineno_calling + 2): 12, 1937db96d56Sopenharmony_ci (self.my_py_filename, firstlineno_calling + 3): 1, 1947db96d56Sopenharmony_ci (self.my_py_filename, firstlineno_called + 1): 10, 1957db96d56Sopenharmony_ci } 1967db96d56Sopenharmony_ci self.assertEqual(self.tracer.results().counts, expected) 1977db96d56Sopenharmony_ci 1987db96d56Sopenharmony_ci def test_traced_decorated_function(self): 1997db96d56Sopenharmony_ci self.tracer.runfunc(traced_decorated_function) 2007db96d56Sopenharmony_ci 2017db96d56Sopenharmony_ci firstlineno = get_firstlineno(traced_decorated_function) 2027db96d56Sopenharmony_ci expected = { 2037db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 1): 1, 2047db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 2): 1, 2057db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 3): 1, 2067db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 4): 1, 2077db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 5): 1, 2087db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 6): 1, 2097db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 7): 2, 2107db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 8): 2, 2117db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 9): 2, 2127db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 10): 1, 2137db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 11): 1, 2147db96d56Sopenharmony_ci } 2157db96d56Sopenharmony_ci self.assertEqual(self.tracer.results().counts, expected) 2167db96d56Sopenharmony_ci 2177db96d56Sopenharmony_ci def test_linear_methods(self): 2187db96d56Sopenharmony_ci # XXX todo: later add 'static_method_linear' and 'class_method_linear' 2197db96d56Sopenharmony_ci # here, once issue1764286 is resolved 2207db96d56Sopenharmony_ci # 2217db96d56Sopenharmony_ci for methname in ['inst_method_linear',]: 2227db96d56Sopenharmony_ci tracer = Trace(count=1, trace=0, countfuncs=0, countcallers=0) 2237db96d56Sopenharmony_ci traced_obj = TracedClass(25) 2247db96d56Sopenharmony_ci method = getattr(traced_obj, methname) 2257db96d56Sopenharmony_ci tracer.runfunc(method, 20) 2267db96d56Sopenharmony_ci 2277db96d56Sopenharmony_ci firstlineno = get_firstlineno(method) 2287db96d56Sopenharmony_ci expected = { 2297db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 1): 1, 2307db96d56Sopenharmony_ci } 2317db96d56Sopenharmony_ci self.assertEqual(tracer.results().counts, expected) 2327db96d56Sopenharmony_ci 2337db96d56Sopenharmony_ci 2347db96d56Sopenharmony_ciclass TestRunExecCounts(unittest.TestCase): 2357db96d56Sopenharmony_ci """A simple sanity test of line-counting, via runctx (exec)""" 2367db96d56Sopenharmony_ci def setUp(self): 2377db96d56Sopenharmony_ci self.my_py_filename = fix_ext_py(__file__) 2387db96d56Sopenharmony_ci self.addCleanup(sys.settrace, sys.gettrace()) 2397db96d56Sopenharmony_ci 2407db96d56Sopenharmony_ci def test_exec_counts(self): 2417db96d56Sopenharmony_ci self.tracer = Trace(count=1, trace=0, countfuncs=0, countcallers=0) 2427db96d56Sopenharmony_ci code = r'''traced_func_loop(2, 5)''' 2437db96d56Sopenharmony_ci code = compile(code, __file__, 'exec') 2447db96d56Sopenharmony_ci self.tracer.runctx(code, globals(), vars()) 2457db96d56Sopenharmony_ci 2467db96d56Sopenharmony_ci firstlineno = get_firstlineno(traced_func_loop) 2477db96d56Sopenharmony_ci expected = { 2487db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 1): 1, 2497db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 2): 6, 2507db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 3): 5, 2517db96d56Sopenharmony_ci (self.my_py_filename, firstlineno + 4): 1, 2527db96d56Sopenharmony_ci } 2537db96d56Sopenharmony_ci 2547db96d56Sopenharmony_ci # When used through 'run', some other spurious counts are produced, like 2557db96d56Sopenharmony_ci # the settrace of threading, which we ignore, just making sure that the 2567db96d56Sopenharmony_ci # counts fo traced_func_loop were right. 2577db96d56Sopenharmony_ci # 2587db96d56Sopenharmony_ci for k in expected.keys(): 2597db96d56Sopenharmony_ci self.assertEqual(self.tracer.results().counts[k], expected[k]) 2607db96d56Sopenharmony_ci 2617db96d56Sopenharmony_ci 2627db96d56Sopenharmony_ciclass TestFuncs(unittest.TestCase): 2637db96d56Sopenharmony_ci """White-box testing of funcs tracing""" 2647db96d56Sopenharmony_ci def setUp(self): 2657db96d56Sopenharmony_ci self.addCleanup(sys.settrace, sys.gettrace()) 2667db96d56Sopenharmony_ci self.tracer = Trace(count=0, trace=0, countfuncs=1) 2677db96d56Sopenharmony_ci self.filemod = my_file_and_modname() 2687db96d56Sopenharmony_ci self._saved_tracefunc = sys.gettrace() 2697db96d56Sopenharmony_ci 2707db96d56Sopenharmony_ci def tearDown(self): 2717db96d56Sopenharmony_ci if self._saved_tracefunc is not None: 2727db96d56Sopenharmony_ci sys.settrace(self._saved_tracefunc) 2737db96d56Sopenharmony_ci 2747db96d56Sopenharmony_ci def test_simple_caller(self): 2757db96d56Sopenharmony_ci self.tracer.runfunc(traced_func_simple_caller, 1) 2767db96d56Sopenharmony_ci 2777db96d56Sopenharmony_ci expected = { 2787db96d56Sopenharmony_ci self.filemod + ('traced_func_simple_caller',): 1, 2797db96d56Sopenharmony_ci self.filemod + ('traced_func_linear',): 1, 2807db96d56Sopenharmony_ci } 2817db96d56Sopenharmony_ci self.assertEqual(self.tracer.results().calledfuncs, expected) 2827db96d56Sopenharmony_ci 2837db96d56Sopenharmony_ci def test_arg_errors(self): 2847db96d56Sopenharmony_ci res = self.tracer.runfunc(traced_capturer, 1, 2, self=3, func=4) 2857db96d56Sopenharmony_ci self.assertEqual(res, ((1, 2), {'self': 3, 'func': 4})) 2867db96d56Sopenharmony_ci with self.assertRaises(TypeError): 2877db96d56Sopenharmony_ci self.tracer.runfunc(func=traced_capturer, arg=1) 2887db96d56Sopenharmony_ci with self.assertRaises(TypeError): 2897db96d56Sopenharmony_ci self.tracer.runfunc() 2907db96d56Sopenharmony_ci 2917db96d56Sopenharmony_ci def test_loop_caller_importing(self): 2927db96d56Sopenharmony_ci self.tracer.runfunc(traced_func_importing_caller, 1) 2937db96d56Sopenharmony_ci 2947db96d56Sopenharmony_ci expected = { 2957db96d56Sopenharmony_ci self.filemod + ('traced_func_simple_caller',): 1, 2967db96d56Sopenharmony_ci self.filemod + ('traced_func_linear',): 1, 2977db96d56Sopenharmony_ci self.filemod + ('traced_func_importing_caller',): 1, 2987db96d56Sopenharmony_ci self.filemod + ('traced_func_importing',): 1, 2997db96d56Sopenharmony_ci (fix_ext_py(testmod.__file__), 'testmod', 'func'): 1, 3007db96d56Sopenharmony_ci } 3017db96d56Sopenharmony_ci self.assertEqual(self.tracer.results().calledfuncs, expected) 3027db96d56Sopenharmony_ci 3037db96d56Sopenharmony_ci @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), 3047db96d56Sopenharmony_ci 'pre-existing trace function throws off measurements') 3057db96d56Sopenharmony_ci def test_inst_method_calling(self): 3067db96d56Sopenharmony_ci obj = TracedClass(20) 3077db96d56Sopenharmony_ci self.tracer.runfunc(obj.inst_method_calling, 1) 3087db96d56Sopenharmony_ci 3097db96d56Sopenharmony_ci expected = { 3107db96d56Sopenharmony_ci self.filemod + ('TracedClass.inst_method_calling',): 1, 3117db96d56Sopenharmony_ci self.filemod + ('TracedClass.inst_method_linear',): 1, 3127db96d56Sopenharmony_ci self.filemod + ('traced_func_linear',): 1, 3137db96d56Sopenharmony_ci } 3147db96d56Sopenharmony_ci self.assertEqual(self.tracer.results().calledfuncs, expected) 3157db96d56Sopenharmony_ci 3167db96d56Sopenharmony_ci def test_traced_decorated_function(self): 3177db96d56Sopenharmony_ci self.tracer.runfunc(traced_decorated_function) 3187db96d56Sopenharmony_ci 3197db96d56Sopenharmony_ci expected = { 3207db96d56Sopenharmony_ci self.filemod + ('traced_decorated_function',): 1, 3217db96d56Sopenharmony_ci self.filemod + ('decorator_fabric',): 1, 3227db96d56Sopenharmony_ci self.filemod + ('decorator2',): 1, 3237db96d56Sopenharmony_ci self.filemod + ('decorator1',): 1, 3247db96d56Sopenharmony_ci self.filemod + ('func',): 1, 3257db96d56Sopenharmony_ci } 3267db96d56Sopenharmony_ci self.assertEqual(self.tracer.results().calledfuncs, expected) 3277db96d56Sopenharmony_ci 3287db96d56Sopenharmony_ci 3297db96d56Sopenharmony_ciclass TestCallers(unittest.TestCase): 3307db96d56Sopenharmony_ci """White-box testing of callers tracing""" 3317db96d56Sopenharmony_ci def setUp(self): 3327db96d56Sopenharmony_ci self.addCleanup(sys.settrace, sys.gettrace()) 3337db96d56Sopenharmony_ci self.tracer = Trace(count=0, trace=0, countcallers=1) 3347db96d56Sopenharmony_ci self.filemod = my_file_and_modname() 3357db96d56Sopenharmony_ci 3367db96d56Sopenharmony_ci @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), 3377db96d56Sopenharmony_ci 'pre-existing trace function throws off measurements') 3387db96d56Sopenharmony_ci def test_loop_caller_importing(self): 3397db96d56Sopenharmony_ci self.tracer.runfunc(traced_func_importing_caller, 1) 3407db96d56Sopenharmony_ci 3417db96d56Sopenharmony_ci expected = { 3427db96d56Sopenharmony_ci ((os.path.splitext(trace.__file__)[0] + '.py', 'trace', 'Trace.runfunc'), 3437db96d56Sopenharmony_ci (self.filemod + ('traced_func_importing_caller',))): 1, 3447db96d56Sopenharmony_ci ((self.filemod + ('traced_func_simple_caller',)), 3457db96d56Sopenharmony_ci (self.filemod + ('traced_func_linear',))): 1, 3467db96d56Sopenharmony_ci ((self.filemod + ('traced_func_importing_caller',)), 3477db96d56Sopenharmony_ci (self.filemod + ('traced_func_simple_caller',))): 1, 3487db96d56Sopenharmony_ci ((self.filemod + ('traced_func_importing_caller',)), 3497db96d56Sopenharmony_ci (self.filemod + ('traced_func_importing',))): 1, 3507db96d56Sopenharmony_ci ((self.filemod + ('traced_func_importing',)), 3517db96d56Sopenharmony_ci (fix_ext_py(testmod.__file__), 'testmod', 'func')): 1, 3527db96d56Sopenharmony_ci } 3537db96d56Sopenharmony_ci self.assertEqual(self.tracer.results().callers, expected) 3547db96d56Sopenharmony_ci 3557db96d56Sopenharmony_ci 3567db96d56Sopenharmony_ci# Created separately for issue #3821 3577db96d56Sopenharmony_ciclass TestCoverage(unittest.TestCase): 3587db96d56Sopenharmony_ci def setUp(self): 3597db96d56Sopenharmony_ci self.addCleanup(sys.settrace, sys.gettrace()) 3607db96d56Sopenharmony_ci 3617db96d56Sopenharmony_ci def tearDown(self): 3627db96d56Sopenharmony_ci rmtree(TESTFN) 3637db96d56Sopenharmony_ci unlink(TESTFN) 3647db96d56Sopenharmony_ci 3657db96d56Sopenharmony_ci def _coverage(self, tracer, 3667db96d56Sopenharmony_ci cmd='import test.support, test.test_pprint;' 3677db96d56Sopenharmony_ci 'test.support.run_unittest(test.test_pprint.QueryTestCase)'): 3687db96d56Sopenharmony_ci tracer.run(cmd) 3697db96d56Sopenharmony_ci r = tracer.results() 3707db96d56Sopenharmony_ci r.write_results(show_missing=True, summary=True, coverdir=TESTFN) 3717db96d56Sopenharmony_ci 3727db96d56Sopenharmony_ci def test_coverage(self): 3737db96d56Sopenharmony_ci tracer = trace.Trace(trace=0, count=1) 3747db96d56Sopenharmony_ci with captured_stdout() as stdout: 3757db96d56Sopenharmony_ci self._coverage(tracer) 3767db96d56Sopenharmony_ci stdout = stdout.getvalue() 3777db96d56Sopenharmony_ci self.assertIn("pprint.py", stdout) 3787db96d56Sopenharmony_ci self.assertIn("case.py", stdout) # from unittest 3797db96d56Sopenharmony_ci files = os.listdir(TESTFN) 3807db96d56Sopenharmony_ci self.assertIn("pprint.cover", files) 3817db96d56Sopenharmony_ci self.assertIn("unittest.case.cover", files) 3827db96d56Sopenharmony_ci 3837db96d56Sopenharmony_ci def test_coverage_ignore(self): 3847db96d56Sopenharmony_ci # Ignore all files, nothing should be traced nor printed 3857db96d56Sopenharmony_ci libpath = os.path.normpath(os.path.dirname(os.path.dirname(__file__))) 3867db96d56Sopenharmony_ci # sys.prefix does not work when running from a checkout 3877db96d56Sopenharmony_ci tracer = trace.Trace(ignoredirs=[sys.base_prefix, sys.base_exec_prefix, 3887db96d56Sopenharmony_ci libpath], trace=0, count=1) 3897db96d56Sopenharmony_ci with captured_stdout() as stdout: 3907db96d56Sopenharmony_ci self._coverage(tracer) 3917db96d56Sopenharmony_ci if os.path.exists(TESTFN): 3927db96d56Sopenharmony_ci files = os.listdir(TESTFN) 3937db96d56Sopenharmony_ci self.assertEqual(files, ['_importlib.cover']) # Ignore __import__ 3947db96d56Sopenharmony_ci 3957db96d56Sopenharmony_ci def test_issue9936(self): 3967db96d56Sopenharmony_ci tracer = trace.Trace(trace=0, count=1) 3977db96d56Sopenharmony_ci modname = 'test.tracedmodules.testmod' 3987db96d56Sopenharmony_ci # Ensure that the module is executed in import 3997db96d56Sopenharmony_ci if modname in sys.modules: 4007db96d56Sopenharmony_ci del sys.modules[modname] 4017db96d56Sopenharmony_ci cmd = ("import test.tracedmodules.testmod as t;" 4027db96d56Sopenharmony_ci "t.func(0); t.func2();") 4037db96d56Sopenharmony_ci with captured_stdout() as stdout: 4047db96d56Sopenharmony_ci self._coverage(tracer, cmd) 4057db96d56Sopenharmony_ci stdout.seek(0) 4067db96d56Sopenharmony_ci stdout.readline() 4077db96d56Sopenharmony_ci coverage = {} 4087db96d56Sopenharmony_ci for line in stdout: 4097db96d56Sopenharmony_ci lines, cov, module = line.split()[:3] 4107db96d56Sopenharmony_ci coverage[module] = (int(lines), int(cov[:-1])) 4117db96d56Sopenharmony_ci # XXX This is needed to run regrtest.py as a script 4127db96d56Sopenharmony_ci modname = trace._fullmodname(sys.modules[modname].__file__) 4137db96d56Sopenharmony_ci self.assertIn(modname, coverage) 4147db96d56Sopenharmony_ci self.assertEqual(coverage[modname], (5, 100)) 4157db96d56Sopenharmony_ci 4167db96d56Sopenharmony_ci def test_coverageresults_update(self): 4177db96d56Sopenharmony_ci # Update empty CoverageResults with a non-empty infile. 4187db96d56Sopenharmony_ci infile = TESTFN + '-infile' 4197db96d56Sopenharmony_ci with open(infile, 'wb') as f: 4207db96d56Sopenharmony_ci dump(({}, {}, {'caller': 1}), f, protocol=1) 4217db96d56Sopenharmony_ci self.addCleanup(unlink, infile) 4227db96d56Sopenharmony_ci results = trace.CoverageResults({}, {}, infile, {}) 4237db96d56Sopenharmony_ci self.assertEqual(results.callers, {'caller': 1}) 4247db96d56Sopenharmony_ci 4257db96d56Sopenharmony_ci### Tests that don't mess with sys.settrace and can be traced 4267db96d56Sopenharmony_ci### themselves TODO: Skip tests that do mess with sys.settrace when 4277db96d56Sopenharmony_ci### regrtest is invoked with -T option. 4287db96d56Sopenharmony_ciclass Test_Ignore(unittest.TestCase): 4297db96d56Sopenharmony_ci def test_ignored(self): 4307db96d56Sopenharmony_ci jn = os.path.join 4317db96d56Sopenharmony_ci ignore = trace._Ignore(['x', 'y.z'], [jn('foo', 'bar')]) 4327db96d56Sopenharmony_ci self.assertTrue(ignore.names('x.py', 'x')) 4337db96d56Sopenharmony_ci self.assertFalse(ignore.names('xy.py', 'xy')) 4347db96d56Sopenharmony_ci self.assertFalse(ignore.names('y.py', 'y')) 4357db96d56Sopenharmony_ci self.assertTrue(ignore.names(jn('foo', 'bar', 'baz.py'), 'baz')) 4367db96d56Sopenharmony_ci self.assertFalse(ignore.names(jn('bar', 'z.py'), 'z')) 4377db96d56Sopenharmony_ci # Matched before. 4387db96d56Sopenharmony_ci self.assertTrue(ignore.names(jn('bar', 'baz.py'), 'baz')) 4397db96d56Sopenharmony_ci 4407db96d56Sopenharmony_ci# Created for Issue 31908 -- CLI utility not writing cover files 4417db96d56Sopenharmony_ciclass TestCoverageCommandLineOutput(unittest.TestCase): 4427db96d56Sopenharmony_ci 4437db96d56Sopenharmony_ci codefile = 'tmp.py' 4447db96d56Sopenharmony_ci coverfile = 'tmp.cover' 4457db96d56Sopenharmony_ci 4467db96d56Sopenharmony_ci def setUp(self): 4477db96d56Sopenharmony_ci with open(self.codefile, 'w', encoding='iso-8859-15') as f: 4487db96d56Sopenharmony_ci f.write(textwrap.dedent('''\ 4497db96d56Sopenharmony_ci # coding: iso-8859-15 4507db96d56Sopenharmony_ci x = 'spœm' 4517db96d56Sopenharmony_ci if []: 4527db96d56Sopenharmony_ci print('unreachable') 4537db96d56Sopenharmony_ci ''')) 4547db96d56Sopenharmony_ci 4557db96d56Sopenharmony_ci def tearDown(self): 4567db96d56Sopenharmony_ci unlink(self.codefile) 4577db96d56Sopenharmony_ci unlink(self.coverfile) 4587db96d56Sopenharmony_ci 4597db96d56Sopenharmony_ci def test_cover_files_written_no_highlight(self): 4607db96d56Sopenharmony_ci # Test also that the cover file for the trace module is not created 4617db96d56Sopenharmony_ci # (issue #34171). 4627db96d56Sopenharmony_ci tracedir = os.path.dirname(os.path.abspath(trace.__file__)) 4637db96d56Sopenharmony_ci tracecoverpath = os.path.join(tracedir, 'trace.cover') 4647db96d56Sopenharmony_ci unlink(tracecoverpath) 4657db96d56Sopenharmony_ci 4667db96d56Sopenharmony_ci argv = '-m trace --count'.split() + [self.codefile] 4677db96d56Sopenharmony_ci status, stdout, stderr = assert_python_ok(*argv) 4687db96d56Sopenharmony_ci self.assertEqual(stderr, b'') 4697db96d56Sopenharmony_ci self.assertFalse(os.path.exists(tracecoverpath)) 4707db96d56Sopenharmony_ci self.assertTrue(os.path.exists(self.coverfile)) 4717db96d56Sopenharmony_ci with open(self.coverfile, encoding='iso-8859-15') as f: 4727db96d56Sopenharmony_ci self.assertEqual(f.read(), 4737db96d56Sopenharmony_ci " # coding: iso-8859-15\n" 4747db96d56Sopenharmony_ci " 1: x = 'spœm'\n" 4757db96d56Sopenharmony_ci " 1: if []:\n" 4767db96d56Sopenharmony_ci " print('unreachable')\n" 4777db96d56Sopenharmony_ci ) 4787db96d56Sopenharmony_ci 4797db96d56Sopenharmony_ci def test_cover_files_written_with_highlight(self): 4807db96d56Sopenharmony_ci argv = '-m trace --count --missing'.split() + [self.codefile] 4817db96d56Sopenharmony_ci status, stdout, stderr = assert_python_ok(*argv) 4827db96d56Sopenharmony_ci self.assertTrue(os.path.exists(self.coverfile)) 4837db96d56Sopenharmony_ci with open(self.coverfile, encoding='iso-8859-15') as f: 4847db96d56Sopenharmony_ci self.assertEqual(f.read(), textwrap.dedent('''\ 4857db96d56Sopenharmony_ci # coding: iso-8859-15 4867db96d56Sopenharmony_ci 1: x = 'spœm' 4877db96d56Sopenharmony_ci 1: if []: 4887db96d56Sopenharmony_ci >>>>>> print('unreachable') 4897db96d56Sopenharmony_ci ''')) 4907db96d56Sopenharmony_ci 4917db96d56Sopenharmony_ciclass TestCommandLine(unittest.TestCase): 4927db96d56Sopenharmony_ci 4937db96d56Sopenharmony_ci def test_failures(self): 4947db96d56Sopenharmony_ci _errors = ( 4957db96d56Sopenharmony_ci (b'progname is missing: required with the main options', '-l', '-T'), 4967db96d56Sopenharmony_ci (b'cannot specify both --listfuncs and (--trace or --count)', '-lc'), 4977db96d56Sopenharmony_ci (b'argument -R/--no-report: not allowed with argument -r/--report', '-rR'), 4987db96d56Sopenharmony_ci (b'must specify one of --trace, --count, --report, --listfuncs, or --trackcalls', '-g'), 4997db96d56Sopenharmony_ci (b'-r/--report requires -f/--file', '-r'), 5007db96d56Sopenharmony_ci (b'--summary can only be used with --count or --report', '-sT'), 5017db96d56Sopenharmony_ci (b'unrecognized arguments: -y', '-y')) 5027db96d56Sopenharmony_ci for message, *args in _errors: 5037db96d56Sopenharmony_ci *_, stderr = assert_python_failure('-m', 'trace', *args) 5047db96d56Sopenharmony_ci self.assertIn(message, stderr) 5057db96d56Sopenharmony_ci 5067db96d56Sopenharmony_ci def test_listfuncs_flag_success(self): 5077db96d56Sopenharmony_ci filename = TESTFN + '.py' 5087db96d56Sopenharmony_ci modulename = os.path.basename(TESTFN) 5097db96d56Sopenharmony_ci with open(filename, 'w', encoding='utf-8') as fd: 5107db96d56Sopenharmony_ci self.addCleanup(unlink, filename) 5117db96d56Sopenharmony_ci fd.write("a = 1\n") 5127db96d56Sopenharmony_ci status, stdout, stderr = assert_python_ok('-m', 'trace', '-l', filename, 5137db96d56Sopenharmony_ci PYTHONIOENCODING='utf-8') 5147db96d56Sopenharmony_ci self.assertIn(b'functions called:', stdout) 5157db96d56Sopenharmony_ci expected = f'filename: {filename}, modulename: {modulename}, funcname: <module>' 5167db96d56Sopenharmony_ci self.assertIn(expected.encode(), stdout) 5177db96d56Sopenharmony_ci 5187db96d56Sopenharmony_ci def test_sys_argv_list(self): 5197db96d56Sopenharmony_ci with open(TESTFN, 'w', encoding='utf-8') as fd: 5207db96d56Sopenharmony_ci self.addCleanup(unlink, TESTFN) 5217db96d56Sopenharmony_ci fd.write("import sys\n") 5227db96d56Sopenharmony_ci fd.write("print(type(sys.argv))\n") 5237db96d56Sopenharmony_ci 5247db96d56Sopenharmony_ci status, direct_stdout, stderr = assert_python_ok(TESTFN) 5257db96d56Sopenharmony_ci status, trace_stdout, stderr = assert_python_ok('-m', 'trace', '-l', TESTFN, 5267db96d56Sopenharmony_ci PYTHONIOENCODING='utf-8') 5277db96d56Sopenharmony_ci self.assertIn(direct_stdout.strip(), trace_stdout) 5287db96d56Sopenharmony_ci 5297db96d56Sopenharmony_ci def test_count_and_summary(self): 5307db96d56Sopenharmony_ci filename = f'{TESTFN}.py' 5317db96d56Sopenharmony_ci coverfilename = f'{TESTFN}.cover' 5327db96d56Sopenharmony_ci modulename = os.path.basename(TESTFN) 5337db96d56Sopenharmony_ci with open(filename, 'w', encoding='utf-8') as fd: 5347db96d56Sopenharmony_ci self.addCleanup(unlink, filename) 5357db96d56Sopenharmony_ci self.addCleanup(unlink, coverfilename) 5367db96d56Sopenharmony_ci fd.write(textwrap.dedent("""\ 5377db96d56Sopenharmony_ci x = 1 5387db96d56Sopenharmony_ci y = 2 5397db96d56Sopenharmony_ci 5407db96d56Sopenharmony_ci def f(): 5417db96d56Sopenharmony_ci return x + y 5427db96d56Sopenharmony_ci 5437db96d56Sopenharmony_ci for i in range(10): 5447db96d56Sopenharmony_ci f() 5457db96d56Sopenharmony_ci """)) 5467db96d56Sopenharmony_ci status, stdout, _ = assert_python_ok('-m', 'trace', '-cs', filename, 5477db96d56Sopenharmony_ci PYTHONIOENCODING='utf-8') 5487db96d56Sopenharmony_ci stdout = stdout.decode() 5497db96d56Sopenharmony_ci self.assertEqual(status, 0) 5507db96d56Sopenharmony_ci self.assertIn('lines cov% module (path)', stdout) 5517db96d56Sopenharmony_ci self.assertIn(f'6 100% {modulename} ({filename})', stdout) 5527db96d56Sopenharmony_ci 5537db96d56Sopenharmony_ci def test_run_as_module(self): 5547db96d56Sopenharmony_ci assert_python_ok('-m', 'trace', '-l', '--module', 'timeit', '-n', '1') 5557db96d56Sopenharmony_ci assert_python_failure('-m', 'trace', '-l', '--module', 'not_a_module_zzz') 5567db96d56Sopenharmony_ci 5577db96d56Sopenharmony_ci 5587db96d56Sopenharmony_ciif __name__ == '__main__': 5597db96d56Sopenharmony_ci unittest.main() 560