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