17db96d56Sopenharmony_ciimport contextlib 27db96d56Sopenharmony_ciimport os 37db96d56Sopenharmony_ciimport sys 47db96d56Sopenharmony_ciimport tracemalloc 57db96d56Sopenharmony_ciimport unittest 67db96d56Sopenharmony_cifrom unittest.mock import patch 77db96d56Sopenharmony_cifrom test.support.script_helper import (assert_python_ok, assert_python_failure, 87db96d56Sopenharmony_ci interpreter_requires_environment) 97db96d56Sopenharmony_cifrom test import support 107db96d56Sopenharmony_cifrom test.support import os_helper 117db96d56Sopenharmony_ci 127db96d56Sopenharmony_citry: 137db96d56Sopenharmony_ci import _testcapi 147db96d56Sopenharmony_ciexcept ImportError: 157db96d56Sopenharmony_ci _testcapi = None 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_ci 187db96d56Sopenharmony_ciEMPTY_STRING_SIZE = sys.getsizeof(b'') 197db96d56Sopenharmony_ciINVALID_NFRAME = (-1, 2**30) 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_cidef get_frames(nframe, lineno_delta): 237db96d56Sopenharmony_ci frames = [] 247db96d56Sopenharmony_ci frame = sys._getframe(1) 257db96d56Sopenharmony_ci for index in range(nframe): 267db96d56Sopenharmony_ci code = frame.f_code 277db96d56Sopenharmony_ci lineno = frame.f_lineno + lineno_delta 287db96d56Sopenharmony_ci frames.append((code.co_filename, lineno)) 297db96d56Sopenharmony_ci lineno_delta = 0 307db96d56Sopenharmony_ci frame = frame.f_back 317db96d56Sopenharmony_ci if frame is None: 327db96d56Sopenharmony_ci break 337db96d56Sopenharmony_ci return tuple(frames) 347db96d56Sopenharmony_ci 357db96d56Sopenharmony_cidef allocate_bytes(size): 367db96d56Sopenharmony_ci nframe = tracemalloc.get_traceback_limit() 377db96d56Sopenharmony_ci bytes_len = (size - EMPTY_STRING_SIZE) 387db96d56Sopenharmony_ci frames = get_frames(nframe, 1) 397db96d56Sopenharmony_ci data = b'x' * bytes_len 407db96d56Sopenharmony_ci return data, tracemalloc.Traceback(frames, min(len(frames), nframe)) 417db96d56Sopenharmony_ci 427db96d56Sopenharmony_cidef create_snapshots(): 437db96d56Sopenharmony_ci traceback_limit = 2 447db96d56Sopenharmony_ci 457db96d56Sopenharmony_ci # _tracemalloc._get_traces() returns a list of (domain, size, 467db96d56Sopenharmony_ci # traceback_frames) tuples. traceback_frames is a tuple of (filename, 477db96d56Sopenharmony_ci # line_number) tuples. 487db96d56Sopenharmony_ci raw_traces = [ 497db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 507db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 517db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_ci (1, 2, (('a.py', 5), ('b.py', 4)), 3), 547db96d56Sopenharmony_ci 557db96d56Sopenharmony_ci (2, 66, (('b.py', 1),), 1), 567db96d56Sopenharmony_ci 577db96d56Sopenharmony_ci (3, 7, (('<unknown>', 0),), 1), 587db96d56Sopenharmony_ci ] 597db96d56Sopenharmony_ci snapshot = tracemalloc.Snapshot(raw_traces, traceback_limit) 607db96d56Sopenharmony_ci 617db96d56Sopenharmony_ci raw_traces2 = [ 627db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 637db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 647db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 657db96d56Sopenharmony_ci 667db96d56Sopenharmony_ci (2, 2, (('a.py', 5), ('b.py', 4)), 3), 677db96d56Sopenharmony_ci (2, 5000, (('a.py', 5), ('b.py', 4)), 3), 687db96d56Sopenharmony_ci 697db96d56Sopenharmony_ci (4, 400, (('c.py', 578),), 1), 707db96d56Sopenharmony_ci ] 717db96d56Sopenharmony_ci snapshot2 = tracemalloc.Snapshot(raw_traces2, traceback_limit) 727db96d56Sopenharmony_ci 737db96d56Sopenharmony_ci return (snapshot, snapshot2) 747db96d56Sopenharmony_ci 757db96d56Sopenharmony_cidef frame(filename, lineno): 767db96d56Sopenharmony_ci return tracemalloc._Frame((filename, lineno)) 777db96d56Sopenharmony_ci 787db96d56Sopenharmony_cidef traceback(*frames): 797db96d56Sopenharmony_ci return tracemalloc.Traceback(frames) 807db96d56Sopenharmony_ci 817db96d56Sopenharmony_cidef traceback_lineno(filename, lineno): 827db96d56Sopenharmony_ci return traceback((filename, lineno)) 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_cidef traceback_filename(filename): 857db96d56Sopenharmony_ci return traceback_lineno(filename, 0) 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_ci 887db96d56Sopenharmony_ciclass TestTraceback(unittest.TestCase): 897db96d56Sopenharmony_ci def test_repr(self): 907db96d56Sopenharmony_ci def get_repr(*args) -> str: 917db96d56Sopenharmony_ci return repr(tracemalloc.Traceback(*args)) 927db96d56Sopenharmony_ci 937db96d56Sopenharmony_ci self.assertEqual(get_repr(()), "<Traceback ()>") 947db96d56Sopenharmony_ci self.assertEqual(get_repr((), 0), "<Traceback () total_nframe=0>") 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_ci frames = (("f1", 1), ("f2", 2)) 977db96d56Sopenharmony_ci exp_repr_frames = ( 987db96d56Sopenharmony_ci "(<Frame filename='f2' lineno=2>," 997db96d56Sopenharmony_ci " <Frame filename='f1' lineno=1>)" 1007db96d56Sopenharmony_ci ) 1017db96d56Sopenharmony_ci self.assertEqual(get_repr(frames), 1027db96d56Sopenharmony_ci f"<Traceback {exp_repr_frames}>") 1037db96d56Sopenharmony_ci self.assertEqual(get_repr(frames, 2), 1047db96d56Sopenharmony_ci f"<Traceback {exp_repr_frames} total_nframe=2>") 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_ci 1077db96d56Sopenharmony_ciclass TestTracemallocEnabled(unittest.TestCase): 1087db96d56Sopenharmony_ci def setUp(self): 1097db96d56Sopenharmony_ci if tracemalloc.is_tracing(): 1107db96d56Sopenharmony_ci self.skipTest("tracemalloc must be stopped before the test") 1117db96d56Sopenharmony_ci 1127db96d56Sopenharmony_ci tracemalloc.start(1) 1137db96d56Sopenharmony_ci 1147db96d56Sopenharmony_ci def tearDown(self): 1157db96d56Sopenharmony_ci tracemalloc.stop() 1167db96d56Sopenharmony_ci 1177db96d56Sopenharmony_ci def test_get_tracemalloc_memory(self): 1187db96d56Sopenharmony_ci data = [allocate_bytes(123) for count in range(1000)] 1197db96d56Sopenharmony_ci size = tracemalloc.get_tracemalloc_memory() 1207db96d56Sopenharmony_ci self.assertGreaterEqual(size, 0) 1217db96d56Sopenharmony_ci 1227db96d56Sopenharmony_ci tracemalloc.clear_traces() 1237db96d56Sopenharmony_ci size2 = tracemalloc.get_tracemalloc_memory() 1247db96d56Sopenharmony_ci self.assertGreaterEqual(size2, 0) 1257db96d56Sopenharmony_ci self.assertLessEqual(size2, size) 1267db96d56Sopenharmony_ci 1277db96d56Sopenharmony_ci def test_get_object_traceback(self): 1287db96d56Sopenharmony_ci tracemalloc.clear_traces() 1297db96d56Sopenharmony_ci obj_size = 12345 1307db96d56Sopenharmony_ci obj, obj_traceback = allocate_bytes(obj_size) 1317db96d56Sopenharmony_ci traceback = tracemalloc.get_object_traceback(obj) 1327db96d56Sopenharmony_ci self.assertEqual(traceback, obj_traceback) 1337db96d56Sopenharmony_ci 1347db96d56Sopenharmony_ci def test_new_reference(self): 1357db96d56Sopenharmony_ci tracemalloc.clear_traces() 1367db96d56Sopenharmony_ci # gc.collect() indirectly calls PyList_ClearFreeList() 1377db96d56Sopenharmony_ci support.gc_collect() 1387db96d56Sopenharmony_ci 1397db96d56Sopenharmony_ci # Create a list and "destroy it": put it in the PyListObject free list 1407db96d56Sopenharmony_ci obj = [] 1417db96d56Sopenharmony_ci obj = None 1427db96d56Sopenharmony_ci 1437db96d56Sopenharmony_ci # Create a list which should reuse the previously created empty list 1447db96d56Sopenharmony_ci obj = [] 1457db96d56Sopenharmony_ci 1467db96d56Sopenharmony_ci nframe = tracemalloc.get_traceback_limit() 1477db96d56Sopenharmony_ci frames = get_frames(nframe, -3) 1487db96d56Sopenharmony_ci obj_traceback = tracemalloc.Traceback(frames, min(len(frames), nframe)) 1497db96d56Sopenharmony_ci 1507db96d56Sopenharmony_ci traceback = tracemalloc.get_object_traceback(obj) 1517db96d56Sopenharmony_ci self.assertIsNotNone(traceback) 1527db96d56Sopenharmony_ci self.assertEqual(traceback, obj_traceback) 1537db96d56Sopenharmony_ci 1547db96d56Sopenharmony_ci def test_set_traceback_limit(self): 1557db96d56Sopenharmony_ci obj_size = 10 1567db96d56Sopenharmony_ci 1577db96d56Sopenharmony_ci tracemalloc.stop() 1587db96d56Sopenharmony_ci self.assertRaises(ValueError, tracemalloc.start, -1) 1597db96d56Sopenharmony_ci 1607db96d56Sopenharmony_ci tracemalloc.stop() 1617db96d56Sopenharmony_ci tracemalloc.start(10) 1627db96d56Sopenharmony_ci obj2, obj2_traceback = allocate_bytes(obj_size) 1637db96d56Sopenharmony_ci traceback = tracemalloc.get_object_traceback(obj2) 1647db96d56Sopenharmony_ci self.assertEqual(len(traceback), 10) 1657db96d56Sopenharmony_ci self.assertEqual(traceback, obj2_traceback) 1667db96d56Sopenharmony_ci 1677db96d56Sopenharmony_ci tracemalloc.stop() 1687db96d56Sopenharmony_ci tracemalloc.start(1) 1697db96d56Sopenharmony_ci obj, obj_traceback = allocate_bytes(obj_size) 1707db96d56Sopenharmony_ci traceback = tracemalloc.get_object_traceback(obj) 1717db96d56Sopenharmony_ci self.assertEqual(len(traceback), 1) 1727db96d56Sopenharmony_ci self.assertEqual(traceback, obj_traceback) 1737db96d56Sopenharmony_ci 1747db96d56Sopenharmony_ci def find_trace(self, traces, traceback): 1757db96d56Sopenharmony_ci for trace in traces: 1767db96d56Sopenharmony_ci if trace[2] == traceback._frames: 1777db96d56Sopenharmony_ci return trace 1787db96d56Sopenharmony_ci 1797db96d56Sopenharmony_ci self.fail("trace not found") 1807db96d56Sopenharmony_ci 1817db96d56Sopenharmony_ci def test_get_traces(self): 1827db96d56Sopenharmony_ci tracemalloc.clear_traces() 1837db96d56Sopenharmony_ci obj_size = 12345 1847db96d56Sopenharmony_ci obj, obj_traceback = allocate_bytes(obj_size) 1857db96d56Sopenharmony_ci 1867db96d56Sopenharmony_ci traces = tracemalloc._get_traces() 1877db96d56Sopenharmony_ci trace = self.find_trace(traces, obj_traceback) 1887db96d56Sopenharmony_ci 1897db96d56Sopenharmony_ci self.assertIsInstance(trace, tuple) 1907db96d56Sopenharmony_ci domain, size, traceback, length = trace 1917db96d56Sopenharmony_ci self.assertEqual(size, obj_size) 1927db96d56Sopenharmony_ci self.assertEqual(traceback, obj_traceback._frames) 1937db96d56Sopenharmony_ci 1947db96d56Sopenharmony_ci tracemalloc.stop() 1957db96d56Sopenharmony_ci self.assertEqual(tracemalloc._get_traces(), []) 1967db96d56Sopenharmony_ci 1977db96d56Sopenharmony_ci def test_get_traces_intern_traceback(self): 1987db96d56Sopenharmony_ci # dummy wrappers to get more useful and identical frames in the traceback 1997db96d56Sopenharmony_ci def allocate_bytes2(size): 2007db96d56Sopenharmony_ci return allocate_bytes(size) 2017db96d56Sopenharmony_ci def allocate_bytes3(size): 2027db96d56Sopenharmony_ci return allocate_bytes2(size) 2037db96d56Sopenharmony_ci def allocate_bytes4(size): 2047db96d56Sopenharmony_ci return allocate_bytes3(size) 2057db96d56Sopenharmony_ci 2067db96d56Sopenharmony_ci # Ensure that two identical tracebacks are not duplicated 2077db96d56Sopenharmony_ci tracemalloc.stop() 2087db96d56Sopenharmony_ci tracemalloc.start(4) 2097db96d56Sopenharmony_ci obj_size = 123 2107db96d56Sopenharmony_ci obj1, obj1_traceback = allocate_bytes4(obj_size) 2117db96d56Sopenharmony_ci obj2, obj2_traceback = allocate_bytes4(obj_size) 2127db96d56Sopenharmony_ci 2137db96d56Sopenharmony_ci traces = tracemalloc._get_traces() 2147db96d56Sopenharmony_ci 2157db96d56Sopenharmony_ci obj1_traceback._frames = tuple(reversed(obj1_traceback._frames)) 2167db96d56Sopenharmony_ci obj2_traceback._frames = tuple(reversed(obj2_traceback._frames)) 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_ci trace1 = self.find_trace(traces, obj1_traceback) 2197db96d56Sopenharmony_ci trace2 = self.find_trace(traces, obj2_traceback) 2207db96d56Sopenharmony_ci domain1, size1, traceback1, length1 = trace1 2217db96d56Sopenharmony_ci domain2, size2, traceback2, length2 = trace2 2227db96d56Sopenharmony_ci self.assertIs(traceback2, traceback1) 2237db96d56Sopenharmony_ci 2247db96d56Sopenharmony_ci def test_get_traced_memory(self): 2257db96d56Sopenharmony_ci # Python allocates some internals objects, so the test must tolerate 2267db96d56Sopenharmony_ci # a small difference between the expected size and the real usage 2277db96d56Sopenharmony_ci max_error = 2048 2287db96d56Sopenharmony_ci 2297db96d56Sopenharmony_ci # allocate one object 2307db96d56Sopenharmony_ci obj_size = 1024 * 1024 2317db96d56Sopenharmony_ci tracemalloc.clear_traces() 2327db96d56Sopenharmony_ci obj, obj_traceback = allocate_bytes(obj_size) 2337db96d56Sopenharmony_ci size, peak_size = tracemalloc.get_traced_memory() 2347db96d56Sopenharmony_ci self.assertGreaterEqual(size, obj_size) 2357db96d56Sopenharmony_ci self.assertGreaterEqual(peak_size, size) 2367db96d56Sopenharmony_ci 2377db96d56Sopenharmony_ci self.assertLessEqual(size - obj_size, max_error) 2387db96d56Sopenharmony_ci self.assertLessEqual(peak_size - size, max_error) 2397db96d56Sopenharmony_ci 2407db96d56Sopenharmony_ci # destroy the object 2417db96d56Sopenharmony_ci obj = None 2427db96d56Sopenharmony_ci size2, peak_size2 = tracemalloc.get_traced_memory() 2437db96d56Sopenharmony_ci self.assertLess(size2, size) 2447db96d56Sopenharmony_ci self.assertGreaterEqual(size - size2, obj_size - max_error) 2457db96d56Sopenharmony_ci self.assertGreaterEqual(peak_size2, peak_size) 2467db96d56Sopenharmony_ci 2477db96d56Sopenharmony_ci # clear_traces() must reset traced memory counters 2487db96d56Sopenharmony_ci tracemalloc.clear_traces() 2497db96d56Sopenharmony_ci self.assertEqual(tracemalloc.get_traced_memory(), (0, 0)) 2507db96d56Sopenharmony_ci 2517db96d56Sopenharmony_ci # allocate another object 2527db96d56Sopenharmony_ci obj, obj_traceback = allocate_bytes(obj_size) 2537db96d56Sopenharmony_ci size, peak_size = tracemalloc.get_traced_memory() 2547db96d56Sopenharmony_ci self.assertGreaterEqual(size, obj_size) 2557db96d56Sopenharmony_ci 2567db96d56Sopenharmony_ci # stop() also resets traced memory counters 2577db96d56Sopenharmony_ci tracemalloc.stop() 2587db96d56Sopenharmony_ci self.assertEqual(tracemalloc.get_traced_memory(), (0, 0)) 2597db96d56Sopenharmony_ci 2607db96d56Sopenharmony_ci def test_clear_traces(self): 2617db96d56Sopenharmony_ci obj, obj_traceback = allocate_bytes(123) 2627db96d56Sopenharmony_ci traceback = tracemalloc.get_object_traceback(obj) 2637db96d56Sopenharmony_ci self.assertIsNotNone(traceback) 2647db96d56Sopenharmony_ci 2657db96d56Sopenharmony_ci tracemalloc.clear_traces() 2667db96d56Sopenharmony_ci traceback2 = tracemalloc.get_object_traceback(obj) 2677db96d56Sopenharmony_ci self.assertIsNone(traceback2) 2687db96d56Sopenharmony_ci 2697db96d56Sopenharmony_ci def test_reset_peak(self): 2707db96d56Sopenharmony_ci # Python allocates some internals objects, so the test must tolerate 2717db96d56Sopenharmony_ci # a small difference between the expected size and the real usage 2727db96d56Sopenharmony_ci tracemalloc.clear_traces() 2737db96d56Sopenharmony_ci 2747db96d56Sopenharmony_ci # Example: allocate a large piece of memory, temporarily 2757db96d56Sopenharmony_ci large_sum = sum(list(range(100000))) 2767db96d56Sopenharmony_ci size1, peak1 = tracemalloc.get_traced_memory() 2777db96d56Sopenharmony_ci 2787db96d56Sopenharmony_ci # reset_peak() resets peak to traced memory: peak2 < peak1 2797db96d56Sopenharmony_ci tracemalloc.reset_peak() 2807db96d56Sopenharmony_ci size2, peak2 = tracemalloc.get_traced_memory() 2817db96d56Sopenharmony_ci self.assertGreaterEqual(peak2, size2) 2827db96d56Sopenharmony_ci self.assertLess(peak2, peak1) 2837db96d56Sopenharmony_ci 2847db96d56Sopenharmony_ci # check that peak continue to be updated if new memory is allocated: 2857db96d56Sopenharmony_ci # peak3 > peak2 2867db96d56Sopenharmony_ci obj_size = 1024 * 1024 2877db96d56Sopenharmony_ci obj, obj_traceback = allocate_bytes(obj_size) 2887db96d56Sopenharmony_ci size3, peak3 = tracemalloc.get_traced_memory() 2897db96d56Sopenharmony_ci self.assertGreaterEqual(peak3, size3) 2907db96d56Sopenharmony_ci self.assertGreater(peak3, peak2) 2917db96d56Sopenharmony_ci self.assertGreaterEqual(peak3 - peak2, obj_size) 2927db96d56Sopenharmony_ci 2937db96d56Sopenharmony_ci def test_is_tracing(self): 2947db96d56Sopenharmony_ci tracemalloc.stop() 2957db96d56Sopenharmony_ci self.assertFalse(tracemalloc.is_tracing()) 2967db96d56Sopenharmony_ci 2977db96d56Sopenharmony_ci tracemalloc.start() 2987db96d56Sopenharmony_ci self.assertTrue(tracemalloc.is_tracing()) 2997db96d56Sopenharmony_ci 3007db96d56Sopenharmony_ci def test_snapshot(self): 3017db96d56Sopenharmony_ci obj, source = allocate_bytes(123) 3027db96d56Sopenharmony_ci 3037db96d56Sopenharmony_ci # take a snapshot 3047db96d56Sopenharmony_ci snapshot = tracemalloc.take_snapshot() 3057db96d56Sopenharmony_ci 3067db96d56Sopenharmony_ci # This can vary 3077db96d56Sopenharmony_ci self.assertGreater(snapshot.traces[1].traceback.total_nframe, 10) 3087db96d56Sopenharmony_ci 3097db96d56Sopenharmony_ci # write on disk 3107db96d56Sopenharmony_ci snapshot.dump(os_helper.TESTFN) 3117db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, os_helper.TESTFN) 3127db96d56Sopenharmony_ci 3137db96d56Sopenharmony_ci # load from disk 3147db96d56Sopenharmony_ci snapshot2 = tracemalloc.Snapshot.load(os_helper.TESTFN) 3157db96d56Sopenharmony_ci self.assertEqual(snapshot2.traces, snapshot.traces) 3167db96d56Sopenharmony_ci 3177db96d56Sopenharmony_ci # tracemalloc must be tracing memory allocations to take a snapshot 3187db96d56Sopenharmony_ci tracemalloc.stop() 3197db96d56Sopenharmony_ci with self.assertRaises(RuntimeError) as cm: 3207db96d56Sopenharmony_ci tracemalloc.take_snapshot() 3217db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 3227db96d56Sopenharmony_ci "the tracemalloc module must be tracing memory " 3237db96d56Sopenharmony_ci "allocations to take a snapshot") 3247db96d56Sopenharmony_ci 3257db96d56Sopenharmony_ci def test_snapshot_save_attr(self): 3267db96d56Sopenharmony_ci # take a snapshot with a new attribute 3277db96d56Sopenharmony_ci snapshot = tracemalloc.take_snapshot() 3287db96d56Sopenharmony_ci snapshot.test_attr = "new" 3297db96d56Sopenharmony_ci snapshot.dump(os_helper.TESTFN) 3307db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, os_helper.TESTFN) 3317db96d56Sopenharmony_ci 3327db96d56Sopenharmony_ci # load() should recreate the attribute 3337db96d56Sopenharmony_ci snapshot2 = tracemalloc.Snapshot.load(os_helper.TESTFN) 3347db96d56Sopenharmony_ci self.assertEqual(snapshot2.test_attr, "new") 3357db96d56Sopenharmony_ci 3367db96d56Sopenharmony_ci def fork_child(self): 3377db96d56Sopenharmony_ci if not tracemalloc.is_tracing(): 3387db96d56Sopenharmony_ci return 2 3397db96d56Sopenharmony_ci 3407db96d56Sopenharmony_ci obj_size = 12345 3417db96d56Sopenharmony_ci obj, obj_traceback = allocate_bytes(obj_size) 3427db96d56Sopenharmony_ci traceback = tracemalloc.get_object_traceback(obj) 3437db96d56Sopenharmony_ci if traceback is None: 3447db96d56Sopenharmony_ci return 3 3457db96d56Sopenharmony_ci 3467db96d56Sopenharmony_ci # everything is fine 3477db96d56Sopenharmony_ci return 0 3487db96d56Sopenharmony_ci 3497db96d56Sopenharmony_ci @support.requires_fork() 3507db96d56Sopenharmony_ci def test_fork(self): 3517db96d56Sopenharmony_ci # check that tracemalloc is still working after fork 3527db96d56Sopenharmony_ci pid = os.fork() 3537db96d56Sopenharmony_ci if not pid: 3547db96d56Sopenharmony_ci # child 3557db96d56Sopenharmony_ci exitcode = 1 3567db96d56Sopenharmony_ci try: 3577db96d56Sopenharmony_ci exitcode = self.fork_child() 3587db96d56Sopenharmony_ci finally: 3597db96d56Sopenharmony_ci os._exit(exitcode) 3607db96d56Sopenharmony_ci else: 3617db96d56Sopenharmony_ci support.wait_process(pid, exitcode=0) 3627db96d56Sopenharmony_ci 3637db96d56Sopenharmony_ci def test_no_incomplete_frames(self): 3647db96d56Sopenharmony_ci tracemalloc.stop() 3657db96d56Sopenharmony_ci tracemalloc.start(8) 3667db96d56Sopenharmony_ci 3677db96d56Sopenharmony_ci def f(x): 3687db96d56Sopenharmony_ci def g(): 3697db96d56Sopenharmony_ci return x 3707db96d56Sopenharmony_ci return g 3717db96d56Sopenharmony_ci 3727db96d56Sopenharmony_ci obj = f(0).__closure__[0] 3737db96d56Sopenharmony_ci traceback = tracemalloc.get_object_traceback(obj) 3747db96d56Sopenharmony_ci self.assertIn("test_tracemalloc", traceback[-1].filename) 3757db96d56Sopenharmony_ci self.assertNotIn("test_tracemalloc", traceback[-2].filename) 3767db96d56Sopenharmony_ci 3777db96d56Sopenharmony_ci 3787db96d56Sopenharmony_ciclass TestSnapshot(unittest.TestCase): 3797db96d56Sopenharmony_ci maxDiff = 4000 3807db96d56Sopenharmony_ci 3817db96d56Sopenharmony_ci def test_create_snapshot(self): 3827db96d56Sopenharmony_ci raw_traces = [(0, 5, (('a.py', 2),), 10)] 3837db96d56Sopenharmony_ci 3847db96d56Sopenharmony_ci with contextlib.ExitStack() as stack: 3857db96d56Sopenharmony_ci stack.enter_context(patch.object(tracemalloc, 'is_tracing', 3867db96d56Sopenharmony_ci return_value=True)) 3877db96d56Sopenharmony_ci stack.enter_context(patch.object(tracemalloc, 'get_traceback_limit', 3887db96d56Sopenharmony_ci return_value=5)) 3897db96d56Sopenharmony_ci stack.enter_context(patch.object(tracemalloc, '_get_traces', 3907db96d56Sopenharmony_ci return_value=raw_traces)) 3917db96d56Sopenharmony_ci 3927db96d56Sopenharmony_ci snapshot = tracemalloc.take_snapshot() 3937db96d56Sopenharmony_ci self.assertEqual(snapshot.traceback_limit, 5) 3947db96d56Sopenharmony_ci self.assertEqual(len(snapshot.traces), 1) 3957db96d56Sopenharmony_ci trace = snapshot.traces[0] 3967db96d56Sopenharmony_ci self.assertEqual(trace.size, 5) 3977db96d56Sopenharmony_ci self.assertEqual(trace.traceback.total_nframe, 10) 3987db96d56Sopenharmony_ci self.assertEqual(len(trace.traceback), 1) 3997db96d56Sopenharmony_ci self.assertEqual(trace.traceback[0].filename, 'a.py') 4007db96d56Sopenharmony_ci self.assertEqual(trace.traceback[0].lineno, 2) 4017db96d56Sopenharmony_ci 4027db96d56Sopenharmony_ci def test_filter_traces(self): 4037db96d56Sopenharmony_ci snapshot, snapshot2 = create_snapshots() 4047db96d56Sopenharmony_ci filter1 = tracemalloc.Filter(False, "b.py") 4057db96d56Sopenharmony_ci filter2 = tracemalloc.Filter(True, "a.py", 2) 4067db96d56Sopenharmony_ci filter3 = tracemalloc.Filter(True, "a.py", 5) 4077db96d56Sopenharmony_ci 4087db96d56Sopenharmony_ci original_traces = list(snapshot.traces._traces) 4097db96d56Sopenharmony_ci 4107db96d56Sopenharmony_ci # exclude b.py 4117db96d56Sopenharmony_ci snapshot3 = snapshot.filter_traces((filter1,)) 4127db96d56Sopenharmony_ci self.assertEqual(snapshot3.traces._traces, [ 4137db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 4147db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 4157db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 4167db96d56Sopenharmony_ci (1, 2, (('a.py', 5), ('b.py', 4)), 3), 4177db96d56Sopenharmony_ci (3, 7, (('<unknown>', 0),), 1), 4187db96d56Sopenharmony_ci ]) 4197db96d56Sopenharmony_ci 4207db96d56Sopenharmony_ci # filter_traces() must not touch the original snapshot 4217db96d56Sopenharmony_ci self.assertEqual(snapshot.traces._traces, original_traces) 4227db96d56Sopenharmony_ci 4237db96d56Sopenharmony_ci # only include two lines of a.py 4247db96d56Sopenharmony_ci snapshot4 = snapshot3.filter_traces((filter2, filter3)) 4257db96d56Sopenharmony_ci self.assertEqual(snapshot4.traces._traces, [ 4267db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 4277db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 4287db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 4297db96d56Sopenharmony_ci (1, 2, (('a.py', 5), ('b.py', 4)), 3), 4307db96d56Sopenharmony_ci ]) 4317db96d56Sopenharmony_ci 4327db96d56Sopenharmony_ci # No filter: just duplicate the snapshot 4337db96d56Sopenharmony_ci snapshot5 = snapshot.filter_traces(()) 4347db96d56Sopenharmony_ci self.assertIsNot(snapshot5, snapshot) 4357db96d56Sopenharmony_ci self.assertIsNot(snapshot5.traces, snapshot.traces) 4367db96d56Sopenharmony_ci self.assertEqual(snapshot5.traces, snapshot.traces) 4377db96d56Sopenharmony_ci 4387db96d56Sopenharmony_ci self.assertRaises(TypeError, snapshot.filter_traces, filter1) 4397db96d56Sopenharmony_ci 4407db96d56Sopenharmony_ci def test_filter_traces_domain(self): 4417db96d56Sopenharmony_ci snapshot, snapshot2 = create_snapshots() 4427db96d56Sopenharmony_ci filter1 = tracemalloc.Filter(False, "a.py", domain=1) 4437db96d56Sopenharmony_ci filter2 = tracemalloc.Filter(True, "a.py", domain=1) 4447db96d56Sopenharmony_ci 4457db96d56Sopenharmony_ci original_traces = list(snapshot.traces._traces) 4467db96d56Sopenharmony_ci 4477db96d56Sopenharmony_ci # exclude a.py of domain 1 4487db96d56Sopenharmony_ci snapshot3 = snapshot.filter_traces((filter1,)) 4497db96d56Sopenharmony_ci self.assertEqual(snapshot3.traces._traces, [ 4507db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 4517db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 4527db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 4537db96d56Sopenharmony_ci (2, 66, (('b.py', 1),), 1), 4547db96d56Sopenharmony_ci (3, 7, (('<unknown>', 0),), 1), 4557db96d56Sopenharmony_ci ]) 4567db96d56Sopenharmony_ci 4577db96d56Sopenharmony_ci # include domain 1 4587db96d56Sopenharmony_ci snapshot3 = snapshot.filter_traces((filter1,)) 4597db96d56Sopenharmony_ci self.assertEqual(snapshot3.traces._traces, [ 4607db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 4617db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 4627db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 4637db96d56Sopenharmony_ci (2, 66, (('b.py', 1),), 1), 4647db96d56Sopenharmony_ci (3, 7, (('<unknown>', 0),), 1), 4657db96d56Sopenharmony_ci ]) 4667db96d56Sopenharmony_ci 4677db96d56Sopenharmony_ci def test_filter_traces_domain_filter(self): 4687db96d56Sopenharmony_ci snapshot, snapshot2 = create_snapshots() 4697db96d56Sopenharmony_ci filter1 = tracemalloc.DomainFilter(False, domain=3) 4707db96d56Sopenharmony_ci filter2 = tracemalloc.DomainFilter(True, domain=3) 4717db96d56Sopenharmony_ci 4727db96d56Sopenharmony_ci # exclude domain 2 4737db96d56Sopenharmony_ci snapshot3 = snapshot.filter_traces((filter1,)) 4747db96d56Sopenharmony_ci self.assertEqual(snapshot3.traces._traces, [ 4757db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 4767db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 4777db96d56Sopenharmony_ci (0, 10, (('a.py', 2), ('b.py', 4)), 3), 4787db96d56Sopenharmony_ci (1, 2, (('a.py', 5), ('b.py', 4)), 3), 4797db96d56Sopenharmony_ci (2, 66, (('b.py', 1),), 1), 4807db96d56Sopenharmony_ci ]) 4817db96d56Sopenharmony_ci 4827db96d56Sopenharmony_ci # include domain 2 4837db96d56Sopenharmony_ci snapshot3 = snapshot.filter_traces((filter2,)) 4847db96d56Sopenharmony_ci self.assertEqual(snapshot3.traces._traces, [ 4857db96d56Sopenharmony_ci (3, 7, (('<unknown>', 0),), 1), 4867db96d56Sopenharmony_ci ]) 4877db96d56Sopenharmony_ci 4887db96d56Sopenharmony_ci def test_snapshot_group_by_line(self): 4897db96d56Sopenharmony_ci snapshot, snapshot2 = create_snapshots() 4907db96d56Sopenharmony_ci tb_0 = traceback_lineno('<unknown>', 0) 4917db96d56Sopenharmony_ci tb_a_2 = traceback_lineno('a.py', 2) 4927db96d56Sopenharmony_ci tb_a_5 = traceback_lineno('a.py', 5) 4937db96d56Sopenharmony_ci tb_b_1 = traceback_lineno('b.py', 1) 4947db96d56Sopenharmony_ci tb_c_578 = traceback_lineno('c.py', 578) 4957db96d56Sopenharmony_ci 4967db96d56Sopenharmony_ci # stats per file and line 4977db96d56Sopenharmony_ci stats1 = snapshot.statistics('lineno') 4987db96d56Sopenharmony_ci self.assertEqual(stats1, [ 4997db96d56Sopenharmony_ci tracemalloc.Statistic(tb_b_1, 66, 1), 5007db96d56Sopenharmony_ci tracemalloc.Statistic(tb_a_2, 30, 3), 5017db96d56Sopenharmony_ci tracemalloc.Statistic(tb_0, 7, 1), 5027db96d56Sopenharmony_ci tracemalloc.Statistic(tb_a_5, 2, 1), 5037db96d56Sopenharmony_ci ]) 5047db96d56Sopenharmony_ci 5057db96d56Sopenharmony_ci # stats per file and line (2) 5067db96d56Sopenharmony_ci stats2 = snapshot2.statistics('lineno') 5077db96d56Sopenharmony_ci self.assertEqual(stats2, [ 5087db96d56Sopenharmony_ci tracemalloc.Statistic(tb_a_5, 5002, 2), 5097db96d56Sopenharmony_ci tracemalloc.Statistic(tb_c_578, 400, 1), 5107db96d56Sopenharmony_ci tracemalloc.Statistic(tb_a_2, 30, 3), 5117db96d56Sopenharmony_ci ]) 5127db96d56Sopenharmony_ci 5137db96d56Sopenharmony_ci # stats diff per file and line 5147db96d56Sopenharmony_ci statistics = snapshot2.compare_to(snapshot, 'lineno') 5157db96d56Sopenharmony_ci self.assertEqual(statistics, [ 5167db96d56Sopenharmony_ci tracemalloc.StatisticDiff(tb_a_5, 5002, 5000, 2, 1), 5177db96d56Sopenharmony_ci tracemalloc.StatisticDiff(tb_c_578, 400, 400, 1, 1), 5187db96d56Sopenharmony_ci tracemalloc.StatisticDiff(tb_b_1, 0, -66, 0, -1), 5197db96d56Sopenharmony_ci tracemalloc.StatisticDiff(tb_0, 0, -7, 0, -1), 5207db96d56Sopenharmony_ci tracemalloc.StatisticDiff(tb_a_2, 30, 0, 3, 0), 5217db96d56Sopenharmony_ci ]) 5227db96d56Sopenharmony_ci 5237db96d56Sopenharmony_ci def test_snapshot_group_by_file(self): 5247db96d56Sopenharmony_ci snapshot, snapshot2 = create_snapshots() 5257db96d56Sopenharmony_ci tb_0 = traceback_filename('<unknown>') 5267db96d56Sopenharmony_ci tb_a = traceback_filename('a.py') 5277db96d56Sopenharmony_ci tb_b = traceback_filename('b.py') 5287db96d56Sopenharmony_ci tb_c = traceback_filename('c.py') 5297db96d56Sopenharmony_ci 5307db96d56Sopenharmony_ci # stats per file 5317db96d56Sopenharmony_ci stats1 = snapshot.statistics('filename') 5327db96d56Sopenharmony_ci self.assertEqual(stats1, [ 5337db96d56Sopenharmony_ci tracemalloc.Statistic(tb_b, 66, 1), 5347db96d56Sopenharmony_ci tracemalloc.Statistic(tb_a, 32, 4), 5357db96d56Sopenharmony_ci tracemalloc.Statistic(tb_0, 7, 1), 5367db96d56Sopenharmony_ci ]) 5377db96d56Sopenharmony_ci 5387db96d56Sopenharmony_ci # stats per file (2) 5397db96d56Sopenharmony_ci stats2 = snapshot2.statistics('filename') 5407db96d56Sopenharmony_ci self.assertEqual(stats2, [ 5417db96d56Sopenharmony_ci tracemalloc.Statistic(tb_a, 5032, 5), 5427db96d56Sopenharmony_ci tracemalloc.Statistic(tb_c, 400, 1), 5437db96d56Sopenharmony_ci ]) 5447db96d56Sopenharmony_ci 5457db96d56Sopenharmony_ci # stats diff per file 5467db96d56Sopenharmony_ci diff = snapshot2.compare_to(snapshot, 'filename') 5477db96d56Sopenharmony_ci self.assertEqual(diff, [ 5487db96d56Sopenharmony_ci tracemalloc.StatisticDiff(tb_a, 5032, 5000, 5, 1), 5497db96d56Sopenharmony_ci tracemalloc.StatisticDiff(tb_c, 400, 400, 1, 1), 5507db96d56Sopenharmony_ci tracemalloc.StatisticDiff(tb_b, 0, -66, 0, -1), 5517db96d56Sopenharmony_ci tracemalloc.StatisticDiff(tb_0, 0, -7, 0, -1), 5527db96d56Sopenharmony_ci ]) 5537db96d56Sopenharmony_ci 5547db96d56Sopenharmony_ci def test_snapshot_group_by_traceback(self): 5557db96d56Sopenharmony_ci snapshot, snapshot2 = create_snapshots() 5567db96d56Sopenharmony_ci 5577db96d56Sopenharmony_ci # stats per file 5587db96d56Sopenharmony_ci tb1 = traceback(('a.py', 2), ('b.py', 4)) 5597db96d56Sopenharmony_ci tb2 = traceback(('a.py', 5), ('b.py', 4)) 5607db96d56Sopenharmony_ci tb3 = traceback(('b.py', 1)) 5617db96d56Sopenharmony_ci tb4 = traceback(('<unknown>', 0)) 5627db96d56Sopenharmony_ci stats1 = snapshot.statistics('traceback') 5637db96d56Sopenharmony_ci self.assertEqual(stats1, [ 5647db96d56Sopenharmony_ci tracemalloc.Statistic(tb3, 66, 1), 5657db96d56Sopenharmony_ci tracemalloc.Statistic(tb1, 30, 3), 5667db96d56Sopenharmony_ci tracemalloc.Statistic(tb4, 7, 1), 5677db96d56Sopenharmony_ci tracemalloc.Statistic(tb2, 2, 1), 5687db96d56Sopenharmony_ci ]) 5697db96d56Sopenharmony_ci 5707db96d56Sopenharmony_ci # stats per file (2) 5717db96d56Sopenharmony_ci tb5 = traceback(('c.py', 578)) 5727db96d56Sopenharmony_ci stats2 = snapshot2.statistics('traceback') 5737db96d56Sopenharmony_ci self.assertEqual(stats2, [ 5747db96d56Sopenharmony_ci tracemalloc.Statistic(tb2, 5002, 2), 5757db96d56Sopenharmony_ci tracemalloc.Statistic(tb5, 400, 1), 5767db96d56Sopenharmony_ci tracemalloc.Statistic(tb1, 30, 3), 5777db96d56Sopenharmony_ci ]) 5787db96d56Sopenharmony_ci 5797db96d56Sopenharmony_ci # stats diff per file 5807db96d56Sopenharmony_ci diff = snapshot2.compare_to(snapshot, 'traceback') 5817db96d56Sopenharmony_ci self.assertEqual(diff, [ 5827db96d56Sopenharmony_ci tracemalloc.StatisticDiff(tb2, 5002, 5000, 2, 1), 5837db96d56Sopenharmony_ci tracemalloc.StatisticDiff(tb5, 400, 400, 1, 1), 5847db96d56Sopenharmony_ci tracemalloc.StatisticDiff(tb3, 0, -66, 0, -1), 5857db96d56Sopenharmony_ci tracemalloc.StatisticDiff(tb4, 0, -7, 0, -1), 5867db96d56Sopenharmony_ci tracemalloc.StatisticDiff(tb1, 30, 0, 3, 0), 5877db96d56Sopenharmony_ci ]) 5887db96d56Sopenharmony_ci 5897db96d56Sopenharmony_ci self.assertRaises(ValueError, 5907db96d56Sopenharmony_ci snapshot.statistics, 'traceback', cumulative=True) 5917db96d56Sopenharmony_ci 5927db96d56Sopenharmony_ci def test_snapshot_group_by_cumulative(self): 5937db96d56Sopenharmony_ci snapshot, snapshot2 = create_snapshots() 5947db96d56Sopenharmony_ci tb_0 = traceback_filename('<unknown>') 5957db96d56Sopenharmony_ci tb_a = traceback_filename('a.py') 5967db96d56Sopenharmony_ci tb_b = traceback_filename('b.py') 5977db96d56Sopenharmony_ci tb_a_2 = traceback_lineno('a.py', 2) 5987db96d56Sopenharmony_ci tb_a_5 = traceback_lineno('a.py', 5) 5997db96d56Sopenharmony_ci tb_b_1 = traceback_lineno('b.py', 1) 6007db96d56Sopenharmony_ci tb_b_4 = traceback_lineno('b.py', 4) 6017db96d56Sopenharmony_ci 6027db96d56Sopenharmony_ci # per file 6037db96d56Sopenharmony_ci stats = snapshot.statistics('filename', True) 6047db96d56Sopenharmony_ci self.assertEqual(stats, [ 6057db96d56Sopenharmony_ci tracemalloc.Statistic(tb_b, 98, 5), 6067db96d56Sopenharmony_ci tracemalloc.Statistic(tb_a, 32, 4), 6077db96d56Sopenharmony_ci tracemalloc.Statistic(tb_0, 7, 1), 6087db96d56Sopenharmony_ci ]) 6097db96d56Sopenharmony_ci 6107db96d56Sopenharmony_ci # per line 6117db96d56Sopenharmony_ci stats = snapshot.statistics('lineno', True) 6127db96d56Sopenharmony_ci self.assertEqual(stats, [ 6137db96d56Sopenharmony_ci tracemalloc.Statistic(tb_b_1, 66, 1), 6147db96d56Sopenharmony_ci tracemalloc.Statistic(tb_b_4, 32, 4), 6157db96d56Sopenharmony_ci tracemalloc.Statistic(tb_a_2, 30, 3), 6167db96d56Sopenharmony_ci tracemalloc.Statistic(tb_0, 7, 1), 6177db96d56Sopenharmony_ci tracemalloc.Statistic(tb_a_5, 2, 1), 6187db96d56Sopenharmony_ci ]) 6197db96d56Sopenharmony_ci 6207db96d56Sopenharmony_ci def test_trace_format(self): 6217db96d56Sopenharmony_ci snapshot, snapshot2 = create_snapshots() 6227db96d56Sopenharmony_ci trace = snapshot.traces[0] 6237db96d56Sopenharmony_ci self.assertEqual(str(trace), 'b.py:4: 10 B') 6247db96d56Sopenharmony_ci traceback = trace.traceback 6257db96d56Sopenharmony_ci self.assertEqual(str(traceback), 'b.py:4') 6267db96d56Sopenharmony_ci frame = traceback[0] 6277db96d56Sopenharmony_ci self.assertEqual(str(frame), 'b.py:4') 6287db96d56Sopenharmony_ci 6297db96d56Sopenharmony_ci def test_statistic_format(self): 6307db96d56Sopenharmony_ci snapshot, snapshot2 = create_snapshots() 6317db96d56Sopenharmony_ci stats = snapshot.statistics('lineno') 6327db96d56Sopenharmony_ci stat = stats[0] 6337db96d56Sopenharmony_ci self.assertEqual(str(stat), 6347db96d56Sopenharmony_ci 'b.py:1: size=66 B, count=1, average=66 B') 6357db96d56Sopenharmony_ci 6367db96d56Sopenharmony_ci def test_statistic_diff_format(self): 6377db96d56Sopenharmony_ci snapshot, snapshot2 = create_snapshots() 6387db96d56Sopenharmony_ci stats = snapshot2.compare_to(snapshot, 'lineno') 6397db96d56Sopenharmony_ci stat = stats[0] 6407db96d56Sopenharmony_ci self.assertEqual(str(stat), 6417db96d56Sopenharmony_ci 'a.py:5: size=5002 B (+5000 B), count=2 (+1), average=2501 B') 6427db96d56Sopenharmony_ci 6437db96d56Sopenharmony_ci def test_slices(self): 6447db96d56Sopenharmony_ci snapshot, snapshot2 = create_snapshots() 6457db96d56Sopenharmony_ci self.assertEqual(snapshot.traces[:2], 6467db96d56Sopenharmony_ci (snapshot.traces[0], snapshot.traces[1])) 6477db96d56Sopenharmony_ci 6487db96d56Sopenharmony_ci traceback = snapshot.traces[0].traceback 6497db96d56Sopenharmony_ci self.assertEqual(traceback[:2], 6507db96d56Sopenharmony_ci (traceback[0], traceback[1])) 6517db96d56Sopenharmony_ci 6527db96d56Sopenharmony_ci def test_format_traceback(self): 6537db96d56Sopenharmony_ci snapshot, snapshot2 = create_snapshots() 6547db96d56Sopenharmony_ci def getline(filename, lineno): 6557db96d56Sopenharmony_ci return ' <%s, %s>' % (filename, lineno) 6567db96d56Sopenharmony_ci with unittest.mock.patch('tracemalloc.linecache.getline', 6577db96d56Sopenharmony_ci side_effect=getline): 6587db96d56Sopenharmony_ci tb = snapshot.traces[0].traceback 6597db96d56Sopenharmony_ci self.assertEqual(tb.format(), 6607db96d56Sopenharmony_ci [' File "b.py", line 4', 6617db96d56Sopenharmony_ci ' <b.py, 4>', 6627db96d56Sopenharmony_ci ' File "a.py", line 2', 6637db96d56Sopenharmony_ci ' <a.py, 2>']) 6647db96d56Sopenharmony_ci 6657db96d56Sopenharmony_ci self.assertEqual(tb.format(limit=1), 6667db96d56Sopenharmony_ci [' File "a.py", line 2', 6677db96d56Sopenharmony_ci ' <a.py, 2>']) 6687db96d56Sopenharmony_ci 6697db96d56Sopenharmony_ci self.assertEqual(tb.format(limit=-1), 6707db96d56Sopenharmony_ci [' File "b.py", line 4', 6717db96d56Sopenharmony_ci ' <b.py, 4>']) 6727db96d56Sopenharmony_ci 6737db96d56Sopenharmony_ci self.assertEqual(tb.format(most_recent_first=True), 6747db96d56Sopenharmony_ci [' File "a.py", line 2', 6757db96d56Sopenharmony_ci ' <a.py, 2>', 6767db96d56Sopenharmony_ci ' File "b.py", line 4', 6777db96d56Sopenharmony_ci ' <b.py, 4>']) 6787db96d56Sopenharmony_ci 6797db96d56Sopenharmony_ci self.assertEqual(tb.format(limit=1, most_recent_first=True), 6807db96d56Sopenharmony_ci [' File "a.py", line 2', 6817db96d56Sopenharmony_ci ' <a.py, 2>']) 6827db96d56Sopenharmony_ci 6837db96d56Sopenharmony_ci self.assertEqual(tb.format(limit=-1, most_recent_first=True), 6847db96d56Sopenharmony_ci [' File "b.py", line 4', 6857db96d56Sopenharmony_ci ' <b.py, 4>']) 6867db96d56Sopenharmony_ci 6877db96d56Sopenharmony_ci 6887db96d56Sopenharmony_ciclass TestFilters(unittest.TestCase): 6897db96d56Sopenharmony_ci maxDiff = 2048 6907db96d56Sopenharmony_ci 6917db96d56Sopenharmony_ci def test_filter_attributes(self): 6927db96d56Sopenharmony_ci # test default values 6937db96d56Sopenharmony_ci f = tracemalloc.Filter(True, "abc") 6947db96d56Sopenharmony_ci self.assertEqual(f.inclusive, True) 6957db96d56Sopenharmony_ci self.assertEqual(f.filename_pattern, "abc") 6967db96d56Sopenharmony_ci self.assertIsNone(f.lineno) 6977db96d56Sopenharmony_ci self.assertEqual(f.all_frames, False) 6987db96d56Sopenharmony_ci 6997db96d56Sopenharmony_ci # test custom values 7007db96d56Sopenharmony_ci f = tracemalloc.Filter(False, "test.py", 123, True) 7017db96d56Sopenharmony_ci self.assertEqual(f.inclusive, False) 7027db96d56Sopenharmony_ci self.assertEqual(f.filename_pattern, "test.py") 7037db96d56Sopenharmony_ci self.assertEqual(f.lineno, 123) 7047db96d56Sopenharmony_ci self.assertEqual(f.all_frames, True) 7057db96d56Sopenharmony_ci 7067db96d56Sopenharmony_ci # parameters passed by keyword 7077db96d56Sopenharmony_ci f = tracemalloc.Filter(inclusive=False, filename_pattern="test.py", lineno=123, all_frames=True) 7087db96d56Sopenharmony_ci self.assertEqual(f.inclusive, False) 7097db96d56Sopenharmony_ci self.assertEqual(f.filename_pattern, "test.py") 7107db96d56Sopenharmony_ci self.assertEqual(f.lineno, 123) 7117db96d56Sopenharmony_ci self.assertEqual(f.all_frames, True) 7127db96d56Sopenharmony_ci 7137db96d56Sopenharmony_ci # read-only attribute 7147db96d56Sopenharmony_ci self.assertRaises(AttributeError, setattr, f, "filename_pattern", "abc") 7157db96d56Sopenharmony_ci 7167db96d56Sopenharmony_ci def test_filter_match(self): 7177db96d56Sopenharmony_ci # filter without line number 7187db96d56Sopenharmony_ci f = tracemalloc.Filter(True, "abc") 7197db96d56Sopenharmony_ci self.assertTrue(f._match_frame("abc", 0)) 7207db96d56Sopenharmony_ci self.assertTrue(f._match_frame("abc", 5)) 7217db96d56Sopenharmony_ci self.assertTrue(f._match_frame("abc", 10)) 7227db96d56Sopenharmony_ci self.assertFalse(f._match_frame("12356", 0)) 7237db96d56Sopenharmony_ci self.assertFalse(f._match_frame("12356", 5)) 7247db96d56Sopenharmony_ci self.assertFalse(f._match_frame("12356", 10)) 7257db96d56Sopenharmony_ci 7267db96d56Sopenharmony_ci f = tracemalloc.Filter(False, "abc") 7277db96d56Sopenharmony_ci self.assertFalse(f._match_frame("abc", 0)) 7287db96d56Sopenharmony_ci self.assertFalse(f._match_frame("abc", 5)) 7297db96d56Sopenharmony_ci self.assertFalse(f._match_frame("abc", 10)) 7307db96d56Sopenharmony_ci self.assertTrue(f._match_frame("12356", 0)) 7317db96d56Sopenharmony_ci self.assertTrue(f._match_frame("12356", 5)) 7327db96d56Sopenharmony_ci self.assertTrue(f._match_frame("12356", 10)) 7337db96d56Sopenharmony_ci 7347db96d56Sopenharmony_ci # filter with line number > 0 7357db96d56Sopenharmony_ci f = tracemalloc.Filter(True, "abc", 5) 7367db96d56Sopenharmony_ci self.assertFalse(f._match_frame("abc", 0)) 7377db96d56Sopenharmony_ci self.assertTrue(f._match_frame("abc", 5)) 7387db96d56Sopenharmony_ci self.assertFalse(f._match_frame("abc", 10)) 7397db96d56Sopenharmony_ci self.assertFalse(f._match_frame("12356", 0)) 7407db96d56Sopenharmony_ci self.assertFalse(f._match_frame("12356", 5)) 7417db96d56Sopenharmony_ci self.assertFalse(f._match_frame("12356", 10)) 7427db96d56Sopenharmony_ci 7437db96d56Sopenharmony_ci f = tracemalloc.Filter(False, "abc", 5) 7447db96d56Sopenharmony_ci self.assertTrue(f._match_frame("abc", 0)) 7457db96d56Sopenharmony_ci self.assertFalse(f._match_frame("abc", 5)) 7467db96d56Sopenharmony_ci self.assertTrue(f._match_frame("abc", 10)) 7477db96d56Sopenharmony_ci self.assertTrue(f._match_frame("12356", 0)) 7487db96d56Sopenharmony_ci self.assertTrue(f._match_frame("12356", 5)) 7497db96d56Sopenharmony_ci self.assertTrue(f._match_frame("12356", 10)) 7507db96d56Sopenharmony_ci 7517db96d56Sopenharmony_ci # filter with line number 0 7527db96d56Sopenharmony_ci f = tracemalloc.Filter(True, "abc", 0) 7537db96d56Sopenharmony_ci self.assertTrue(f._match_frame("abc", 0)) 7547db96d56Sopenharmony_ci self.assertFalse(f._match_frame("abc", 5)) 7557db96d56Sopenharmony_ci self.assertFalse(f._match_frame("abc", 10)) 7567db96d56Sopenharmony_ci self.assertFalse(f._match_frame("12356", 0)) 7577db96d56Sopenharmony_ci self.assertFalse(f._match_frame("12356", 5)) 7587db96d56Sopenharmony_ci self.assertFalse(f._match_frame("12356", 10)) 7597db96d56Sopenharmony_ci 7607db96d56Sopenharmony_ci f = tracemalloc.Filter(False, "abc", 0) 7617db96d56Sopenharmony_ci self.assertFalse(f._match_frame("abc", 0)) 7627db96d56Sopenharmony_ci self.assertTrue(f._match_frame("abc", 5)) 7637db96d56Sopenharmony_ci self.assertTrue(f._match_frame("abc", 10)) 7647db96d56Sopenharmony_ci self.assertTrue(f._match_frame("12356", 0)) 7657db96d56Sopenharmony_ci self.assertTrue(f._match_frame("12356", 5)) 7667db96d56Sopenharmony_ci self.assertTrue(f._match_frame("12356", 10)) 7677db96d56Sopenharmony_ci 7687db96d56Sopenharmony_ci def test_filter_match_filename(self): 7697db96d56Sopenharmony_ci def fnmatch(inclusive, filename, pattern): 7707db96d56Sopenharmony_ci f = tracemalloc.Filter(inclusive, pattern) 7717db96d56Sopenharmony_ci return f._match_frame(filename, 0) 7727db96d56Sopenharmony_ci 7737db96d56Sopenharmony_ci self.assertTrue(fnmatch(True, "abc", "abc")) 7747db96d56Sopenharmony_ci self.assertFalse(fnmatch(True, "12356", "abc")) 7757db96d56Sopenharmony_ci self.assertFalse(fnmatch(True, "<unknown>", "abc")) 7767db96d56Sopenharmony_ci 7777db96d56Sopenharmony_ci self.assertFalse(fnmatch(False, "abc", "abc")) 7787db96d56Sopenharmony_ci self.assertTrue(fnmatch(False, "12356", "abc")) 7797db96d56Sopenharmony_ci self.assertTrue(fnmatch(False, "<unknown>", "abc")) 7807db96d56Sopenharmony_ci 7817db96d56Sopenharmony_ci def test_filter_match_filename_joker(self): 7827db96d56Sopenharmony_ci def fnmatch(filename, pattern): 7837db96d56Sopenharmony_ci filter = tracemalloc.Filter(True, pattern) 7847db96d56Sopenharmony_ci return filter._match_frame(filename, 0) 7857db96d56Sopenharmony_ci 7867db96d56Sopenharmony_ci # empty string 7877db96d56Sopenharmony_ci self.assertFalse(fnmatch('abc', '')) 7887db96d56Sopenharmony_ci self.assertFalse(fnmatch('', 'abc')) 7897db96d56Sopenharmony_ci self.assertTrue(fnmatch('', '')) 7907db96d56Sopenharmony_ci self.assertTrue(fnmatch('', '*')) 7917db96d56Sopenharmony_ci 7927db96d56Sopenharmony_ci # no * 7937db96d56Sopenharmony_ci self.assertTrue(fnmatch('abc', 'abc')) 7947db96d56Sopenharmony_ci self.assertFalse(fnmatch('abc', 'abcd')) 7957db96d56Sopenharmony_ci self.assertFalse(fnmatch('abc', 'def')) 7967db96d56Sopenharmony_ci 7977db96d56Sopenharmony_ci # a* 7987db96d56Sopenharmony_ci self.assertTrue(fnmatch('abc', 'a*')) 7997db96d56Sopenharmony_ci self.assertTrue(fnmatch('abc', 'abc*')) 8007db96d56Sopenharmony_ci self.assertFalse(fnmatch('abc', 'b*')) 8017db96d56Sopenharmony_ci self.assertFalse(fnmatch('abc', 'abcd*')) 8027db96d56Sopenharmony_ci 8037db96d56Sopenharmony_ci # a*b 8047db96d56Sopenharmony_ci self.assertTrue(fnmatch('abc', 'a*c')) 8057db96d56Sopenharmony_ci self.assertTrue(fnmatch('abcdcx', 'a*cx')) 8067db96d56Sopenharmony_ci self.assertFalse(fnmatch('abb', 'a*c')) 8077db96d56Sopenharmony_ci self.assertFalse(fnmatch('abcdce', 'a*cx')) 8087db96d56Sopenharmony_ci 8097db96d56Sopenharmony_ci # a*b*c 8107db96d56Sopenharmony_ci self.assertTrue(fnmatch('abcde', 'a*c*e')) 8117db96d56Sopenharmony_ci self.assertTrue(fnmatch('abcbdefeg', 'a*bd*eg')) 8127db96d56Sopenharmony_ci self.assertFalse(fnmatch('abcdd', 'a*c*e')) 8137db96d56Sopenharmony_ci self.assertFalse(fnmatch('abcbdefef', 'a*bd*eg')) 8147db96d56Sopenharmony_ci 8157db96d56Sopenharmony_ci # replace .pyc suffix with .py 8167db96d56Sopenharmony_ci self.assertTrue(fnmatch('a.pyc', 'a.py')) 8177db96d56Sopenharmony_ci self.assertTrue(fnmatch('a.py', 'a.pyc')) 8187db96d56Sopenharmony_ci 8197db96d56Sopenharmony_ci if os.name == 'nt': 8207db96d56Sopenharmony_ci # case insensitive 8217db96d56Sopenharmony_ci self.assertTrue(fnmatch('aBC', 'ABc')) 8227db96d56Sopenharmony_ci self.assertTrue(fnmatch('aBcDe', 'Ab*dE')) 8237db96d56Sopenharmony_ci 8247db96d56Sopenharmony_ci self.assertTrue(fnmatch('a.pyc', 'a.PY')) 8257db96d56Sopenharmony_ci self.assertTrue(fnmatch('a.py', 'a.PYC')) 8267db96d56Sopenharmony_ci else: 8277db96d56Sopenharmony_ci # case sensitive 8287db96d56Sopenharmony_ci self.assertFalse(fnmatch('aBC', 'ABc')) 8297db96d56Sopenharmony_ci self.assertFalse(fnmatch('aBcDe', 'Ab*dE')) 8307db96d56Sopenharmony_ci 8317db96d56Sopenharmony_ci self.assertFalse(fnmatch('a.pyc', 'a.PY')) 8327db96d56Sopenharmony_ci self.assertFalse(fnmatch('a.py', 'a.PYC')) 8337db96d56Sopenharmony_ci 8347db96d56Sopenharmony_ci if os.name == 'nt': 8357db96d56Sopenharmony_ci # normalize alternate separator "/" to the standard separator "\" 8367db96d56Sopenharmony_ci self.assertTrue(fnmatch(r'a/b', r'a\b')) 8377db96d56Sopenharmony_ci self.assertTrue(fnmatch(r'a\b', r'a/b')) 8387db96d56Sopenharmony_ci self.assertTrue(fnmatch(r'a/b\c', r'a\b/c')) 8397db96d56Sopenharmony_ci self.assertTrue(fnmatch(r'a/b/c', r'a\b\c')) 8407db96d56Sopenharmony_ci else: 8417db96d56Sopenharmony_ci # there is no alternate separator 8427db96d56Sopenharmony_ci self.assertFalse(fnmatch(r'a/b', r'a\b')) 8437db96d56Sopenharmony_ci self.assertFalse(fnmatch(r'a\b', r'a/b')) 8447db96d56Sopenharmony_ci self.assertFalse(fnmatch(r'a/b\c', r'a\b/c')) 8457db96d56Sopenharmony_ci self.assertFalse(fnmatch(r'a/b/c', r'a\b\c')) 8467db96d56Sopenharmony_ci 8477db96d56Sopenharmony_ci # as of 3.5, .pyo is no longer munged to .py 8487db96d56Sopenharmony_ci self.assertFalse(fnmatch('a.pyo', 'a.py')) 8497db96d56Sopenharmony_ci 8507db96d56Sopenharmony_ci def test_filter_match_trace(self): 8517db96d56Sopenharmony_ci t1 = (("a.py", 2), ("b.py", 3)) 8527db96d56Sopenharmony_ci t2 = (("b.py", 4), ("b.py", 5)) 8537db96d56Sopenharmony_ci t3 = (("c.py", 5), ('<unknown>', 0)) 8547db96d56Sopenharmony_ci unknown = (('<unknown>', 0),) 8557db96d56Sopenharmony_ci 8567db96d56Sopenharmony_ci f = tracemalloc.Filter(True, "b.py", all_frames=True) 8577db96d56Sopenharmony_ci self.assertTrue(f._match_traceback(t1)) 8587db96d56Sopenharmony_ci self.assertTrue(f._match_traceback(t2)) 8597db96d56Sopenharmony_ci self.assertFalse(f._match_traceback(t3)) 8607db96d56Sopenharmony_ci self.assertFalse(f._match_traceback(unknown)) 8617db96d56Sopenharmony_ci 8627db96d56Sopenharmony_ci f = tracemalloc.Filter(True, "b.py", all_frames=False) 8637db96d56Sopenharmony_ci self.assertFalse(f._match_traceback(t1)) 8647db96d56Sopenharmony_ci self.assertTrue(f._match_traceback(t2)) 8657db96d56Sopenharmony_ci self.assertFalse(f._match_traceback(t3)) 8667db96d56Sopenharmony_ci self.assertFalse(f._match_traceback(unknown)) 8677db96d56Sopenharmony_ci 8687db96d56Sopenharmony_ci f = tracemalloc.Filter(False, "b.py", all_frames=True) 8697db96d56Sopenharmony_ci self.assertFalse(f._match_traceback(t1)) 8707db96d56Sopenharmony_ci self.assertFalse(f._match_traceback(t2)) 8717db96d56Sopenharmony_ci self.assertTrue(f._match_traceback(t3)) 8727db96d56Sopenharmony_ci self.assertTrue(f._match_traceback(unknown)) 8737db96d56Sopenharmony_ci 8747db96d56Sopenharmony_ci f = tracemalloc.Filter(False, "b.py", all_frames=False) 8757db96d56Sopenharmony_ci self.assertTrue(f._match_traceback(t1)) 8767db96d56Sopenharmony_ci self.assertFalse(f._match_traceback(t2)) 8777db96d56Sopenharmony_ci self.assertTrue(f._match_traceback(t3)) 8787db96d56Sopenharmony_ci self.assertTrue(f._match_traceback(unknown)) 8797db96d56Sopenharmony_ci 8807db96d56Sopenharmony_ci f = tracemalloc.Filter(False, "<unknown>", all_frames=False) 8817db96d56Sopenharmony_ci self.assertTrue(f._match_traceback(t1)) 8827db96d56Sopenharmony_ci self.assertTrue(f._match_traceback(t2)) 8837db96d56Sopenharmony_ci self.assertTrue(f._match_traceback(t3)) 8847db96d56Sopenharmony_ci self.assertFalse(f._match_traceback(unknown)) 8857db96d56Sopenharmony_ci 8867db96d56Sopenharmony_ci f = tracemalloc.Filter(True, "<unknown>", all_frames=True) 8877db96d56Sopenharmony_ci self.assertFalse(f._match_traceback(t1)) 8887db96d56Sopenharmony_ci self.assertFalse(f._match_traceback(t2)) 8897db96d56Sopenharmony_ci self.assertTrue(f._match_traceback(t3)) 8907db96d56Sopenharmony_ci self.assertTrue(f._match_traceback(unknown)) 8917db96d56Sopenharmony_ci 8927db96d56Sopenharmony_ci f = tracemalloc.Filter(False, "<unknown>", all_frames=True) 8937db96d56Sopenharmony_ci self.assertTrue(f._match_traceback(t1)) 8947db96d56Sopenharmony_ci self.assertTrue(f._match_traceback(t2)) 8957db96d56Sopenharmony_ci self.assertFalse(f._match_traceback(t3)) 8967db96d56Sopenharmony_ci self.assertFalse(f._match_traceback(unknown)) 8977db96d56Sopenharmony_ci 8987db96d56Sopenharmony_ci 8997db96d56Sopenharmony_ciclass TestCommandLine(unittest.TestCase): 9007db96d56Sopenharmony_ci def test_env_var_disabled_by_default(self): 9017db96d56Sopenharmony_ci # not tracing by default 9027db96d56Sopenharmony_ci code = 'import tracemalloc; print(tracemalloc.is_tracing())' 9037db96d56Sopenharmony_ci ok, stdout, stderr = assert_python_ok('-c', code) 9047db96d56Sopenharmony_ci stdout = stdout.rstrip() 9057db96d56Sopenharmony_ci self.assertEqual(stdout, b'False') 9067db96d56Sopenharmony_ci 9077db96d56Sopenharmony_ci @unittest.skipIf(interpreter_requires_environment(), 9087db96d56Sopenharmony_ci 'Cannot run -E tests when PYTHON env vars are required.') 9097db96d56Sopenharmony_ci def test_env_var_ignored_with_E(self): 9107db96d56Sopenharmony_ci """PYTHON* environment variables must be ignored when -E is present.""" 9117db96d56Sopenharmony_ci code = 'import tracemalloc; print(tracemalloc.is_tracing())' 9127db96d56Sopenharmony_ci ok, stdout, stderr = assert_python_ok('-E', '-c', code, PYTHONTRACEMALLOC='1') 9137db96d56Sopenharmony_ci stdout = stdout.rstrip() 9147db96d56Sopenharmony_ci self.assertEqual(stdout, b'False') 9157db96d56Sopenharmony_ci 9167db96d56Sopenharmony_ci def test_env_var_disabled(self): 9177db96d56Sopenharmony_ci # tracing at startup 9187db96d56Sopenharmony_ci code = 'import tracemalloc; print(tracemalloc.is_tracing())' 9197db96d56Sopenharmony_ci ok, stdout, stderr = assert_python_ok('-c', code, PYTHONTRACEMALLOC='0') 9207db96d56Sopenharmony_ci stdout = stdout.rstrip() 9217db96d56Sopenharmony_ci self.assertEqual(stdout, b'False') 9227db96d56Sopenharmony_ci 9237db96d56Sopenharmony_ci def test_env_var_enabled_at_startup(self): 9247db96d56Sopenharmony_ci # tracing at startup 9257db96d56Sopenharmony_ci code = 'import tracemalloc; print(tracemalloc.is_tracing())' 9267db96d56Sopenharmony_ci ok, stdout, stderr = assert_python_ok('-c', code, PYTHONTRACEMALLOC='1') 9277db96d56Sopenharmony_ci stdout = stdout.rstrip() 9287db96d56Sopenharmony_ci self.assertEqual(stdout, b'True') 9297db96d56Sopenharmony_ci 9307db96d56Sopenharmony_ci def test_env_limit(self): 9317db96d56Sopenharmony_ci # start and set the number of frames 9327db96d56Sopenharmony_ci code = 'import tracemalloc; print(tracemalloc.get_traceback_limit())' 9337db96d56Sopenharmony_ci ok, stdout, stderr = assert_python_ok('-c', code, PYTHONTRACEMALLOC='10') 9347db96d56Sopenharmony_ci stdout = stdout.rstrip() 9357db96d56Sopenharmony_ci self.assertEqual(stdout, b'10') 9367db96d56Sopenharmony_ci 9377db96d56Sopenharmony_ci def check_env_var_invalid(self, nframe): 9387db96d56Sopenharmony_ci with support.SuppressCrashReport(): 9397db96d56Sopenharmony_ci ok, stdout, stderr = assert_python_failure( 9407db96d56Sopenharmony_ci '-c', 'pass', 9417db96d56Sopenharmony_ci PYTHONTRACEMALLOC=str(nframe)) 9427db96d56Sopenharmony_ci 9437db96d56Sopenharmony_ci if b'ValueError: the number of frames must be in range' in stderr: 9447db96d56Sopenharmony_ci return 9457db96d56Sopenharmony_ci if b'PYTHONTRACEMALLOC: invalid number of frames' in stderr: 9467db96d56Sopenharmony_ci return 9477db96d56Sopenharmony_ci self.fail(f"unexpected output: {stderr!a}") 9487db96d56Sopenharmony_ci 9497db96d56Sopenharmony_ci 9507db96d56Sopenharmony_ci def test_env_var_invalid(self): 9517db96d56Sopenharmony_ci for nframe in INVALID_NFRAME: 9527db96d56Sopenharmony_ci with self.subTest(nframe=nframe): 9537db96d56Sopenharmony_ci self.check_env_var_invalid(nframe) 9547db96d56Sopenharmony_ci 9557db96d56Sopenharmony_ci def test_sys_xoptions(self): 9567db96d56Sopenharmony_ci for xoptions, nframe in ( 9577db96d56Sopenharmony_ci ('tracemalloc', 1), 9587db96d56Sopenharmony_ci ('tracemalloc=1', 1), 9597db96d56Sopenharmony_ci ('tracemalloc=15', 15), 9607db96d56Sopenharmony_ci ): 9617db96d56Sopenharmony_ci with self.subTest(xoptions=xoptions, nframe=nframe): 9627db96d56Sopenharmony_ci code = 'import tracemalloc; print(tracemalloc.get_traceback_limit())' 9637db96d56Sopenharmony_ci ok, stdout, stderr = assert_python_ok('-X', xoptions, '-c', code) 9647db96d56Sopenharmony_ci stdout = stdout.rstrip() 9657db96d56Sopenharmony_ci self.assertEqual(stdout, str(nframe).encode('ascii')) 9667db96d56Sopenharmony_ci 9677db96d56Sopenharmony_ci def check_sys_xoptions_invalid(self, nframe): 9687db96d56Sopenharmony_ci args = ('-X', 'tracemalloc=%s' % nframe, '-c', 'pass') 9697db96d56Sopenharmony_ci with support.SuppressCrashReport(): 9707db96d56Sopenharmony_ci ok, stdout, stderr = assert_python_failure(*args) 9717db96d56Sopenharmony_ci 9727db96d56Sopenharmony_ci if b'ValueError: the number of frames must be in range' in stderr: 9737db96d56Sopenharmony_ci return 9747db96d56Sopenharmony_ci if b'-X tracemalloc=NFRAME: invalid number of frames' in stderr: 9757db96d56Sopenharmony_ci return 9767db96d56Sopenharmony_ci self.fail(f"unexpected output: {stderr!a}") 9777db96d56Sopenharmony_ci 9787db96d56Sopenharmony_ci def test_sys_xoptions_invalid(self): 9797db96d56Sopenharmony_ci for nframe in INVALID_NFRAME: 9807db96d56Sopenharmony_ci with self.subTest(nframe=nframe): 9817db96d56Sopenharmony_ci self.check_sys_xoptions_invalid(nframe) 9827db96d56Sopenharmony_ci 9837db96d56Sopenharmony_ci @unittest.skipIf(_testcapi is None, 'need _testcapi') 9847db96d56Sopenharmony_ci def test_pymem_alloc0(self): 9857db96d56Sopenharmony_ci # Issue #21639: Check that PyMem_Malloc(0) with tracemalloc enabled 9867db96d56Sopenharmony_ci # does not crash. 9877db96d56Sopenharmony_ci code = 'import _testcapi; _testcapi.test_pymem_alloc0(); 1' 9887db96d56Sopenharmony_ci assert_python_ok('-X', 'tracemalloc', '-c', code) 9897db96d56Sopenharmony_ci 9907db96d56Sopenharmony_ci 9917db96d56Sopenharmony_ci@unittest.skipIf(_testcapi is None, 'need _testcapi') 9927db96d56Sopenharmony_ciclass TestCAPI(unittest.TestCase): 9937db96d56Sopenharmony_ci maxDiff = 80 * 20 9947db96d56Sopenharmony_ci 9957db96d56Sopenharmony_ci def setUp(self): 9967db96d56Sopenharmony_ci if tracemalloc.is_tracing(): 9977db96d56Sopenharmony_ci self.skipTest("tracemalloc must be stopped before the test") 9987db96d56Sopenharmony_ci 9997db96d56Sopenharmony_ci self.domain = 5 10007db96d56Sopenharmony_ci self.size = 123 10017db96d56Sopenharmony_ci self.obj = allocate_bytes(self.size)[0] 10027db96d56Sopenharmony_ci 10037db96d56Sopenharmony_ci # for the type "object", id(obj) is the address of its memory block. 10047db96d56Sopenharmony_ci # This type is not tracked by the garbage collector 10057db96d56Sopenharmony_ci self.ptr = id(self.obj) 10067db96d56Sopenharmony_ci 10077db96d56Sopenharmony_ci def tearDown(self): 10087db96d56Sopenharmony_ci tracemalloc.stop() 10097db96d56Sopenharmony_ci 10107db96d56Sopenharmony_ci def get_traceback(self): 10117db96d56Sopenharmony_ci frames = _testcapi.tracemalloc_get_traceback(self.domain, self.ptr) 10127db96d56Sopenharmony_ci if frames is not None: 10137db96d56Sopenharmony_ci return tracemalloc.Traceback(frames) 10147db96d56Sopenharmony_ci else: 10157db96d56Sopenharmony_ci return None 10167db96d56Sopenharmony_ci 10177db96d56Sopenharmony_ci def track(self, release_gil=False, nframe=1): 10187db96d56Sopenharmony_ci frames = get_frames(nframe, 1) 10197db96d56Sopenharmony_ci _testcapi.tracemalloc_track(self.domain, self.ptr, self.size, 10207db96d56Sopenharmony_ci release_gil) 10217db96d56Sopenharmony_ci return frames 10227db96d56Sopenharmony_ci 10237db96d56Sopenharmony_ci def untrack(self): 10247db96d56Sopenharmony_ci _testcapi.tracemalloc_untrack(self.domain, self.ptr) 10257db96d56Sopenharmony_ci 10267db96d56Sopenharmony_ci def get_traced_memory(self): 10277db96d56Sopenharmony_ci # Get the traced size in the domain 10287db96d56Sopenharmony_ci snapshot = tracemalloc.take_snapshot() 10297db96d56Sopenharmony_ci domain_filter = tracemalloc.DomainFilter(True, self.domain) 10307db96d56Sopenharmony_ci snapshot = snapshot.filter_traces([domain_filter]) 10317db96d56Sopenharmony_ci return sum(trace.size for trace in snapshot.traces) 10327db96d56Sopenharmony_ci 10337db96d56Sopenharmony_ci def check_track(self, release_gil): 10347db96d56Sopenharmony_ci nframe = 5 10357db96d56Sopenharmony_ci tracemalloc.start(nframe) 10367db96d56Sopenharmony_ci 10377db96d56Sopenharmony_ci size = tracemalloc.get_traced_memory()[0] 10387db96d56Sopenharmony_ci 10397db96d56Sopenharmony_ci frames = self.track(release_gil, nframe) 10407db96d56Sopenharmony_ci self.assertEqual(self.get_traceback(), 10417db96d56Sopenharmony_ci tracemalloc.Traceback(frames)) 10427db96d56Sopenharmony_ci 10437db96d56Sopenharmony_ci self.assertEqual(self.get_traced_memory(), self.size) 10447db96d56Sopenharmony_ci 10457db96d56Sopenharmony_ci def test_track(self): 10467db96d56Sopenharmony_ci self.check_track(False) 10477db96d56Sopenharmony_ci 10487db96d56Sopenharmony_ci def test_track_without_gil(self): 10497db96d56Sopenharmony_ci # check that calling _PyTraceMalloc_Track() without holding the GIL 10507db96d56Sopenharmony_ci # works too 10517db96d56Sopenharmony_ci self.check_track(True) 10527db96d56Sopenharmony_ci 10537db96d56Sopenharmony_ci def test_track_already_tracked(self): 10547db96d56Sopenharmony_ci nframe = 5 10557db96d56Sopenharmony_ci tracemalloc.start(nframe) 10567db96d56Sopenharmony_ci 10577db96d56Sopenharmony_ci # track a first time 10587db96d56Sopenharmony_ci self.track() 10597db96d56Sopenharmony_ci 10607db96d56Sopenharmony_ci # calling _PyTraceMalloc_Track() must remove the old trace and add 10617db96d56Sopenharmony_ci # a new trace with the new traceback 10627db96d56Sopenharmony_ci frames = self.track(nframe=nframe) 10637db96d56Sopenharmony_ci self.assertEqual(self.get_traceback(), 10647db96d56Sopenharmony_ci tracemalloc.Traceback(frames)) 10657db96d56Sopenharmony_ci 10667db96d56Sopenharmony_ci def test_untrack(self): 10677db96d56Sopenharmony_ci tracemalloc.start() 10687db96d56Sopenharmony_ci 10697db96d56Sopenharmony_ci self.track() 10707db96d56Sopenharmony_ci self.assertIsNotNone(self.get_traceback()) 10717db96d56Sopenharmony_ci self.assertEqual(self.get_traced_memory(), self.size) 10727db96d56Sopenharmony_ci 10737db96d56Sopenharmony_ci # untrack must remove the trace 10747db96d56Sopenharmony_ci self.untrack() 10757db96d56Sopenharmony_ci self.assertIsNone(self.get_traceback()) 10767db96d56Sopenharmony_ci self.assertEqual(self.get_traced_memory(), 0) 10777db96d56Sopenharmony_ci 10787db96d56Sopenharmony_ci # calling _PyTraceMalloc_Untrack() multiple times must not crash 10797db96d56Sopenharmony_ci self.untrack() 10807db96d56Sopenharmony_ci self.untrack() 10817db96d56Sopenharmony_ci 10827db96d56Sopenharmony_ci def test_stop_track(self): 10837db96d56Sopenharmony_ci tracemalloc.start() 10847db96d56Sopenharmony_ci tracemalloc.stop() 10857db96d56Sopenharmony_ci 10867db96d56Sopenharmony_ci with self.assertRaises(RuntimeError): 10877db96d56Sopenharmony_ci self.track() 10887db96d56Sopenharmony_ci self.assertIsNone(self.get_traceback()) 10897db96d56Sopenharmony_ci 10907db96d56Sopenharmony_ci def test_stop_untrack(self): 10917db96d56Sopenharmony_ci tracemalloc.start() 10927db96d56Sopenharmony_ci self.track() 10937db96d56Sopenharmony_ci 10947db96d56Sopenharmony_ci tracemalloc.stop() 10957db96d56Sopenharmony_ci with self.assertRaises(RuntimeError): 10967db96d56Sopenharmony_ci self.untrack() 10977db96d56Sopenharmony_ci 10987db96d56Sopenharmony_ci 10997db96d56Sopenharmony_ciif __name__ == "__main__": 11007db96d56Sopenharmony_ci unittest.main() 1101