blob: b0a0e1b2d7860a56e05bfc03c65affae563efd11 [file] [log] [blame]
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001import contextlib
Victor Stinnered3b0bc2013-11-23 12:27:24 +01002import os
3import sys
4import tracemalloc
5import unittest
6from unittest.mock import patch
Berker Peksagce643912015-05-06 06:33:17 +03007from test.support.script_helper import (assert_python_ok, assert_python_failure,
8 interpreter_requires_environment)
9from test import support
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020010
Victor Stinner10b73e12016-03-22 13:39:05 +010011try:
12 import _testcapi
13except ImportError:
14 _testcapi = None
15
Victor Stinnered3b0bc2013-11-23 12:27:24 +010016
17EMPTY_STRING_SIZE = sys.getsizeof(b'')
18
Victor Stinner10b73e12016-03-22 13:39:05 +010019
Victor Stinnered3b0bc2013-11-23 12:27:24 +010020def get_frames(nframe, lineno_delta):
21 frames = []
22 frame = sys._getframe(1)
23 for index in range(nframe):
24 code = frame.f_code
25 lineno = frame.f_lineno + lineno_delta
26 frames.append((code.co_filename, lineno))
27 lineno_delta = 0
28 frame = frame.f_back
29 if frame is None:
30 break
31 return tuple(frames)
32
33def allocate_bytes(size):
34 nframe = tracemalloc.get_traceback_limit()
35 bytes_len = (size - EMPTY_STRING_SIZE)
36 frames = get_frames(nframe, 1)
37 data = b'x' * bytes_len
38 return data, tracemalloc.Traceback(frames)
39
40def create_snapshots():
41 traceback_limit = 2
42
Victor Stinnere492ae52016-03-22 12:58:23 +010043 # _tracemalloc._get_traces() returns a list of (domain, size,
44 # traceback_frames) tuples. traceback_frames is a tuple of (filename,
45 # line_number) tuples.
Victor Stinnered3b0bc2013-11-23 12:27:24 +010046 raw_traces = [
Victor Stinnere492ae52016-03-22 12:58:23 +010047 (0, 10, (('a.py', 2), ('b.py', 4))),
48 (0, 10, (('a.py', 2), ('b.py', 4))),
49 (0, 10, (('a.py', 2), ('b.py', 4))),
Victor Stinnered3b0bc2013-11-23 12:27:24 +010050
Victor Stinnere492ae52016-03-22 12:58:23 +010051 (1, 2, (('a.py', 5), ('b.py', 4))),
Victor Stinnered3b0bc2013-11-23 12:27:24 +010052
Victor Stinnere492ae52016-03-22 12:58:23 +010053 (2, 66, (('b.py', 1),)),
Victor Stinnered3b0bc2013-11-23 12:27:24 +010054
Victor Stinnere492ae52016-03-22 12:58:23 +010055 (3, 7, (('<unknown>', 0),)),
Victor Stinnered3b0bc2013-11-23 12:27:24 +010056 ]
57 snapshot = tracemalloc.Snapshot(raw_traces, traceback_limit)
58
59 raw_traces2 = [
Victor Stinnere492ae52016-03-22 12:58:23 +010060 (0, 10, (('a.py', 2), ('b.py', 4))),
61 (0, 10, (('a.py', 2), ('b.py', 4))),
62 (0, 10, (('a.py', 2), ('b.py', 4))),
Victor Stinnered3b0bc2013-11-23 12:27:24 +010063
Victor Stinnere492ae52016-03-22 12:58:23 +010064 (2, 2, (('a.py', 5), ('b.py', 4))),
65 (2, 5000, (('a.py', 5), ('b.py', 4))),
Victor Stinnered3b0bc2013-11-23 12:27:24 +010066
Victor Stinnere492ae52016-03-22 12:58:23 +010067 (4, 400, (('c.py', 578),)),
Victor Stinnered3b0bc2013-11-23 12:27:24 +010068 ]
69 snapshot2 = tracemalloc.Snapshot(raw_traces2, traceback_limit)
70
71 return (snapshot, snapshot2)
72
73def frame(filename, lineno):
74 return tracemalloc._Frame((filename, lineno))
75
76def traceback(*frames):
77 return tracemalloc.Traceback(frames)
78
79def traceback_lineno(filename, lineno):
80 return traceback((filename, lineno))
81
82def traceback_filename(filename):
83 return traceback_lineno(filename, 0)
84
85
86class TestTracemallocEnabled(unittest.TestCase):
87 def setUp(self):
88 if tracemalloc.is_tracing():
89 self.skipTest("tracemalloc must be stopped before the test")
90
Victor Stinner3728d6c2013-11-23 12:37:20 +010091 tracemalloc.start(1)
Victor Stinnered3b0bc2013-11-23 12:27:24 +010092
93 def tearDown(self):
94 tracemalloc.stop()
95
96 def test_get_tracemalloc_memory(self):
97 data = [allocate_bytes(123) for count in range(1000)]
98 size = tracemalloc.get_tracemalloc_memory()
99 self.assertGreaterEqual(size, 0)
100
101 tracemalloc.clear_traces()
102 size2 = tracemalloc.get_tracemalloc_memory()
103 self.assertGreaterEqual(size2, 0)
104 self.assertLessEqual(size2, size)
105
106 def test_get_object_traceback(self):
107 tracemalloc.clear_traces()
108 obj_size = 12345
109 obj, obj_traceback = allocate_bytes(obj_size)
110 traceback = tracemalloc.get_object_traceback(obj)
111 self.assertEqual(traceback, obj_traceback)
112
113 def test_set_traceback_limit(self):
114 obj_size = 10
115
Victor Stinner3728d6c2013-11-23 12:37:20 +0100116 tracemalloc.stop()
117 self.assertRaises(ValueError, tracemalloc.start, -1)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100118
Victor Stinner3728d6c2013-11-23 12:37:20 +0100119 tracemalloc.stop()
120 tracemalloc.start(10)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100121 obj2, obj2_traceback = allocate_bytes(obj_size)
122 traceback = tracemalloc.get_object_traceback(obj2)
123 self.assertEqual(len(traceback), 10)
124 self.assertEqual(traceback, obj2_traceback)
125
Victor Stinner3728d6c2013-11-23 12:37:20 +0100126 tracemalloc.stop()
127 tracemalloc.start(1)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100128 obj, obj_traceback = allocate_bytes(obj_size)
129 traceback = tracemalloc.get_object_traceback(obj)
130 self.assertEqual(len(traceback), 1)
131 self.assertEqual(traceback, obj_traceback)
132
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100133 def find_trace(self, traces, traceback):
134 for trace in traces:
Victor Stinnere492ae52016-03-22 12:58:23 +0100135 if trace[2] == traceback._frames:
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100136 return trace
137
138 self.fail("trace not found")
139
140 def test_get_traces(self):
141 tracemalloc.clear_traces()
142 obj_size = 12345
143 obj, obj_traceback = allocate_bytes(obj_size)
144
145 traces = tracemalloc._get_traces()
146 trace = self.find_trace(traces, obj_traceback)
147
148 self.assertIsInstance(trace, tuple)
Victor Stinnere492ae52016-03-22 12:58:23 +0100149 domain, size, traceback = trace
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100150 self.assertEqual(size, obj_size)
151 self.assertEqual(traceback, obj_traceback._frames)
152
153 tracemalloc.stop()
154 self.assertEqual(tracemalloc._get_traces(), [])
155
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100156 def test_get_traces_intern_traceback(self):
157 # dummy wrappers to get more useful and identical frames in the traceback
158 def allocate_bytes2(size):
159 return allocate_bytes(size)
160 def allocate_bytes3(size):
161 return allocate_bytes2(size)
162 def allocate_bytes4(size):
163 return allocate_bytes3(size)
164
165 # Ensure that two identical tracebacks are not duplicated
Victor Stinner3728d6c2013-11-23 12:37:20 +0100166 tracemalloc.stop()
167 tracemalloc.start(4)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100168 obj_size = 123
169 obj1, obj1_traceback = allocate_bytes4(obj_size)
170 obj2, obj2_traceback = allocate_bytes4(obj_size)
171
172 traces = tracemalloc._get_traces()
173
Jesse-Bakker706e10b2017-11-30 00:05:07 +0100174 obj1_traceback._frames = tuple(reversed(obj1_traceback._frames))
175 obj2_traceback._frames = tuple(reversed(obj2_traceback._frames))
176
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100177 trace1 = self.find_trace(traces, obj1_traceback)
178 trace2 = self.find_trace(traces, obj2_traceback)
Victor Stinnere492ae52016-03-22 12:58:23 +0100179 domain1, size1, traceback1 = trace1
180 domain2, size2, traceback2 = trace2
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100181 self.assertIs(traceback2, traceback1)
182
183 def test_get_traced_memory(self):
184 # Python allocates some internals objects, so the test must tolerate
185 # a small difference between the expected size and the real usage
186 max_error = 2048
187
188 # allocate one object
189 obj_size = 1024 * 1024
190 tracemalloc.clear_traces()
191 obj, obj_traceback = allocate_bytes(obj_size)
Victor Stinner3c0481d2013-11-27 21:39:49 +0100192 size, peak_size = tracemalloc.get_traced_memory()
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100193 self.assertGreaterEqual(size, obj_size)
Victor Stinner3c0481d2013-11-27 21:39:49 +0100194 self.assertGreaterEqual(peak_size, size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100195
196 self.assertLessEqual(size - obj_size, max_error)
Victor Stinner3c0481d2013-11-27 21:39:49 +0100197 self.assertLessEqual(peak_size - size, max_error)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100198
199 # destroy the object
200 obj = None
Victor Stinner3c0481d2013-11-27 21:39:49 +0100201 size2, peak_size2 = tracemalloc.get_traced_memory()
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100202 self.assertLess(size2, size)
203 self.assertGreaterEqual(size - size2, obj_size - max_error)
Victor Stinner3c0481d2013-11-27 21:39:49 +0100204 self.assertGreaterEqual(peak_size2, peak_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100205
206 # clear_traces() must reset traced memory counters
207 tracemalloc.clear_traces()
208 self.assertEqual(tracemalloc.get_traced_memory(), (0, 0))
209
210 # allocate another object
211 obj, obj_traceback = allocate_bytes(obj_size)
Victor Stinner3c0481d2013-11-27 21:39:49 +0100212 size, peak_size = tracemalloc.get_traced_memory()
213 self.assertGreaterEqual(size, obj_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100214
Victor Stinnera89ecc72013-11-25 09:29:45 +0100215 # stop() also resets traced memory counters
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100216 tracemalloc.stop()
217 self.assertEqual(tracemalloc.get_traced_memory(), (0, 0))
218
219 def test_clear_traces(self):
220 obj, obj_traceback = allocate_bytes(123)
221 traceback = tracemalloc.get_object_traceback(obj)
222 self.assertIsNotNone(traceback)
223
224 tracemalloc.clear_traces()
225 traceback2 = tracemalloc.get_object_traceback(obj)
226 self.assertIsNone(traceback2)
227
228 def test_is_tracing(self):
229 tracemalloc.stop()
230 self.assertFalse(tracemalloc.is_tracing())
231
232 tracemalloc.start()
233 self.assertTrue(tracemalloc.is_tracing())
234
235 def test_snapshot(self):
236 obj, source = allocate_bytes(123)
237
238 # take a snapshot
239 snapshot = tracemalloc.take_snapshot()
240
241 # write on disk
242 snapshot.dump(support.TESTFN)
243 self.addCleanup(support.unlink, support.TESTFN)
244
245 # load from disk
246 snapshot2 = tracemalloc.Snapshot.load(support.TESTFN)
247 self.assertEqual(snapshot2.traces, snapshot.traces)
248
249 # tracemalloc must be tracing memory allocations to take a snapshot
250 tracemalloc.stop()
251 with self.assertRaises(RuntimeError) as cm:
252 tracemalloc.take_snapshot()
253 self.assertEqual(str(cm.exception),
254 "the tracemalloc module must be tracing memory "
255 "allocations to take a snapshot")
256
257 def test_snapshot_save_attr(self):
258 # take a snapshot with a new attribute
259 snapshot = tracemalloc.take_snapshot()
260 snapshot.test_attr = "new"
261 snapshot.dump(support.TESTFN)
262 self.addCleanup(support.unlink, support.TESTFN)
263
Martin Panter8f265652016-04-19 04:03:41 +0000264 # load() should recreate the attribute
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100265 snapshot2 = tracemalloc.Snapshot.load(support.TESTFN)
266 self.assertEqual(snapshot2.test_attr, "new")
267
268 def fork_child(self):
269 if not tracemalloc.is_tracing():
270 return 2
271
272 obj_size = 12345
273 obj, obj_traceback = allocate_bytes(obj_size)
274 traceback = tracemalloc.get_object_traceback(obj)
275 if traceback is None:
276 return 3
277
278 # everything is fine
279 return 0
280
281 @unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork()')
282 def test_fork(self):
283 # check that tracemalloc is still working after fork
284 pid = os.fork()
285 if not pid:
286 # child
287 exitcode = 1
288 try:
289 exitcode = self.fork_child()
290 finally:
291 os._exit(exitcode)
292 else:
293 pid2, status = os.waitpid(pid, 0)
294 self.assertTrue(os.WIFEXITED(status))
295 exitcode = os.WEXITSTATUS(status)
296 self.assertEqual(exitcode, 0)
297
298
299class TestSnapshot(unittest.TestCase):
300 maxDiff = 4000
301
302 def test_create_snapshot(self):
Victor Stinnere492ae52016-03-22 12:58:23 +0100303 raw_traces = [(0, 5, (('a.py', 2),))]
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100304
305 with contextlib.ExitStack() as stack:
306 stack.enter_context(patch.object(tracemalloc, 'is_tracing',
307 return_value=True))
308 stack.enter_context(patch.object(tracemalloc, 'get_traceback_limit',
309 return_value=5))
310 stack.enter_context(patch.object(tracemalloc, '_get_traces',
311 return_value=raw_traces))
312
313 snapshot = tracemalloc.take_snapshot()
314 self.assertEqual(snapshot.traceback_limit, 5)
315 self.assertEqual(len(snapshot.traces), 1)
316 trace = snapshot.traces[0]
317 self.assertEqual(trace.size, 5)
318 self.assertEqual(len(trace.traceback), 1)
319 self.assertEqual(trace.traceback[0].filename, 'a.py')
320 self.assertEqual(trace.traceback[0].lineno, 2)
321
322 def test_filter_traces(self):
323 snapshot, snapshot2 = create_snapshots()
324 filter1 = tracemalloc.Filter(False, "b.py")
325 filter2 = tracemalloc.Filter(True, "a.py", 2)
326 filter3 = tracemalloc.Filter(True, "a.py", 5)
327
328 original_traces = list(snapshot.traces._traces)
329
330 # exclude b.py
331 snapshot3 = snapshot.filter_traces((filter1,))
332 self.assertEqual(snapshot3.traces._traces, [
Victor Stinnere492ae52016-03-22 12:58:23 +0100333 (0, 10, (('a.py', 2), ('b.py', 4))),
334 (0, 10, (('a.py', 2), ('b.py', 4))),
335 (0, 10, (('a.py', 2), ('b.py', 4))),
336 (1, 2, (('a.py', 5), ('b.py', 4))),
337 (3, 7, (('<unknown>', 0),)),
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100338 ])
339
340 # filter_traces() must not touch the original snapshot
341 self.assertEqual(snapshot.traces._traces, original_traces)
342
343 # only include two lines of a.py
344 snapshot4 = snapshot3.filter_traces((filter2, filter3))
345 self.assertEqual(snapshot4.traces._traces, [
Victor Stinnere492ae52016-03-22 12:58:23 +0100346 (0, 10, (('a.py', 2), ('b.py', 4))),
347 (0, 10, (('a.py', 2), ('b.py', 4))),
348 (0, 10, (('a.py', 2), ('b.py', 4))),
349 (1, 2, (('a.py', 5), ('b.py', 4))),
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100350 ])
351
352 # No filter: just duplicate the snapshot
353 snapshot5 = snapshot.filter_traces(())
354 self.assertIsNot(snapshot5, snapshot)
355 self.assertIsNot(snapshot5.traces, snapshot.traces)
356 self.assertEqual(snapshot5.traces, snapshot.traces)
357
Victor Stinner8ce8ff92014-03-10 11:05:07 +0100358 self.assertRaises(TypeError, snapshot.filter_traces, filter1)
359
Victor Stinnere492ae52016-03-22 12:58:23 +0100360 def test_filter_traces_domain(self):
361 snapshot, snapshot2 = create_snapshots()
362 filter1 = tracemalloc.Filter(False, "a.py", domain=1)
363 filter2 = tracemalloc.Filter(True, "a.py", domain=1)
364
365 original_traces = list(snapshot.traces._traces)
366
367 # exclude a.py of domain 1
368 snapshot3 = snapshot.filter_traces((filter1,))
369 self.assertEqual(snapshot3.traces._traces, [
370 (0, 10, (('a.py', 2), ('b.py', 4))),
371 (0, 10, (('a.py', 2), ('b.py', 4))),
372 (0, 10, (('a.py', 2), ('b.py', 4))),
373 (2, 66, (('b.py', 1),)),
374 (3, 7, (('<unknown>', 0),)),
375 ])
376
377 # include domain 1
378 snapshot3 = snapshot.filter_traces((filter1,))
379 self.assertEqual(snapshot3.traces._traces, [
380 (0, 10, (('a.py', 2), ('b.py', 4))),
381 (0, 10, (('a.py', 2), ('b.py', 4))),
382 (0, 10, (('a.py', 2), ('b.py', 4))),
383 (2, 66, (('b.py', 1),)),
384 (3, 7, (('<unknown>', 0),)),
385 ])
386
387 def test_filter_traces_domain_filter(self):
388 snapshot, snapshot2 = create_snapshots()
389 filter1 = tracemalloc.DomainFilter(False, domain=3)
390 filter2 = tracemalloc.DomainFilter(True, domain=3)
391
392 # exclude domain 2
393 snapshot3 = snapshot.filter_traces((filter1,))
394 self.assertEqual(snapshot3.traces._traces, [
395 (0, 10, (('a.py', 2), ('b.py', 4))),
396 (0, 10, (('a.py', 2), ('b.py', 4))),
397 (0, 10, (('a.py', 2), ('b.py', 4))),
398 (1, 2, (('a.py', 5), ('b.py', 4))),
399 (2, 66, (('b.py', 1),)),
400 ])
401
402 # include domain 2
403 snapshot3 = snapshot.filter_traces((filter2,))
404 self.assertEqual(snapshot3.traces._traces, [
405 (3, 7, (('<unknown>', 0),)),
406 ])
407
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100408 def test_snapshot_group_by_line(self):
409 snapshot, snapshot2 = create_snapshots()
410 tb_0 = traceback_lineno('<unknown>', 0)
411 tb_a_2 = traceback_lineno('a.py', 2)
412 tb_a_5 = traceback_lineno('a.py', 5)
413 tb_b_1 = traceback_lineno('b.py', 1)
414 tb_c_578 = traceback_lineno('c.py', 578)
415
416 # stats per file and line
417 stats1 = snapshot.statistics('lineno')
418 self.assertEqual(stats1, [
419 tracemalloc.Statistic(tb_b_1, 66, 1),
420 tracemalloc.Statistic(tb_a_2, 30, 3),
421 tracemalloc.Statistic(tb_0, 7, 1),
422 tracemalloc.Statistic(tb_a_5, 2, 1),
423 ])
424
425 # stats per file and line (2)
426 stats2 = snapshot2.statistics('lineno')
427 self.assertEqual(stats2, [
428 tracemalloc.Statistic(tb_a_5, 5002, 2),
429 tracemalloc.Statistic(tb_c_578, 400, 1),
430 tracemalloc.Statistic(tb_a_2, 30, 3),
431 ])
432
433 # stats diff per file and line
434 statistics = snapshot2.compare_to(snapshot, 'lineno')
435 self.assertEqual(statistics, [
436 tracemalloc.StatisticDiff(tb_a_5, 5002, 5000, 2, 1),
437 tracemalloc.StatisticDiff(tb_c_578, 400, 400, 1, 1),
438 tracemalloc.StatisticDiff(tb_b_1, 0, -66, 0, -1),
439 tracemalloc.StatisticDiff(tb_0, 0, -7, 0, -1),
440 tracemalloc.StatisticDiff(tb_a_2, 30, 0, 3, 0),
441 ])
442
443 def test_snapshot_group_by_file(self):
444 snapshot, snapshot2 = create_snapshots()
445 tb_0 = traceback_filename('<unknown>')
446 tb_a = traceback_filename('a.py')
447 tb_b = traceback_filename('b.py')
448 tb_c = traceback_filename('c.py')
449
450 # stats per file
451 stats1 = snapshot.statistics('filename')
452 self.assertEqual(stats1, [
453 tracemalloc.Statistic(tb_b, 66, 1),
454 tracemalloc.Statistic(tb_a, 32, 4),
455 tracemalloc.Statistic(tb_0, 7, 1),
456 ])
457
458 # stats per file (2)
459 stats2 = snapshot2.statistics('filename')
460 self.assertEqual(stats2, [
461 tracemalloc.Statistic(tb_a, 5032, 5),
462 tracemalloc.Statistic(tb_c, 400, 1),
463 ])
464
465 # stats diff per file
466 diff = snapshot2.compare_to(snapshot, 'filename')
467 self.assertEqual(diff, [
468 tracemalloc.StatisticDiff(tb_a, 5032, 5000, 5, 1),
469 tracemalloc.StatisticDiff(tb_c, 400, 400, 1, 1),
470 tracemalloc.StatisticDiff(tb_b, 0, -66, 0, -1),
471 tracemalloc.StatisticDiff(tb_0, 0, -7, 0, -1),
472 ])
473
474 def test_snapshot_group_by_traceback(self):
475 snapshot, snapshot2 = create_snapshots()
476
477 # stats per file
478 tb1 = traceback(('a.py', 2), ('b.py', 4))
479 tb2 = traceback(('a.py', 5), ('b.py', 4))
480 tb3 = traceback(('b.py', 1))
481 tb4 = traceback(('<unknown>', 0))
482 stats1 = snapshot.statistics('traceback')
483 self.assertEqual(stats1, [
484 tracemalloc.Statistic(tb3, 66, 1),
485 tracemalloc.Statistic(tb1, 30, 3),
486 tracemalloc.Statistic(tb4, 7, 1),
487 tracemalloc.Statistic(tb2, 2, 1),
488 ])
489
490 # stats per file (2)
491 tb5 = traceback(('c.py', 578))
492 stats2 = snapshot2.statistics('traceback')
493 self.assertEqual(stats2, [
494 tracemalloc.Statistic(tb2, 5002, 2),
495 tracemalloc.Statistic(tb5, 400, 1),
496 tracemalloc.Statistic(tb1, 30, 3),
497 ])
498
499 # stats diff per file
500 diff = snapshot2.compare_to(snapshot, 'traceback')
501 self.assertEqual(diff, [
502 tracemalloc.StatisticDiff(tb2, 5002, 5000, 2, 1),
503 tracemalloc.StatisticDiff(tb5, 400, 400, 1, 1),
504 tracemalloc.StatisticDiff(tb3, 0, -66, 0, -1),
505 tracemalloc.StatisticDiff(tb4, 0, -7, 0, -1),
506 tracemalloc.StatisticDiff(tb1, 30, 0, 3, 0),
507 ])
508
509 self.assertRaises(ValueError,
510 snapshot.statistics, 'traceback', cumulative=True)
511
512 def test_snapshot_group_by_cumulative(self):
513 snapshot, snapshot2 = create_snapshots()
514 tb_0 = traceback_filename('<unknown>')
515 tb_a = traceback_filename('a.py')
516 tb_b = traceback_filename('b.py')
517 tb_a_2 = traceback_lineno('a.py', 2)
518 tb_a_5 = traceback_lineno('a.py', 5)
519 tb_b_1 = traceback_lineno('b.py', 1)
520 tb_b_4 = traceback_lineno('b.py', 4)
521
522 # per file
523 stats = snapshot.statistics('filename', True)
524 self.assertEqual(stats, [
525 tracemalloc.Statistic(tb_b, 98, 5),
526 tracemalloc.Statistic(tb_a, 32, 4),
527 tracemalloc.Statistic(tb_0, 7, 1),
528 ])
529
530 # per line
531 stats = snapshot.statistics('lineno', True)
532 self.assertEqual(stats, [
533 tracemalloc.Statistic(tb_b_1, 66, 1),
534 tracemalloc.Statistic(tb_b_4, 32, 4),
535 tracemalloc.Statistic(tb_a_2, 30, 3),
536 tracemalloc.Statistic(tb_0, 7, 1),
537 tracemalloc.Statistic(tb_a_5, 2, 1),
538 ])
539
540 def test_trace_format(self):
541 snapshot, snapshot2 = create_snapshots()
542 trace = snapshot.traces[0]
Jesse-Bakker706e10b2017-11-30 00:05:07 +0100543 self.assertEqual(str(trace), 'b.py:4: 10 B')
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100544 traceback = trace.traceback
Jesse-Bakker706e10b2017-11-30 00:05:07 +0100545 self.assertEqual(str(traceback), 'b.py:4')
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100546 frame = traceback[0]
Jesse-Bakker706e10b2017-11-30 00:05:07 +0100547 self.assertEqual(str(frame), 'b.py:4')
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100548
549 def test_statistic_format(self):
550 snapshot, snapshot2 = create_snapshots()
551 stats = snapshot.statistics('lineno')
552 stat = stats[0]
553 self.assertEqual(str(stat),
554 'b.py:1: size=66 B, count=1, average=66 B')
555
556 def test_statistic_diff_format(self):
557 snapshot, snapshot2 = create_snapshots()
558 stats = snapshot2.compare_to(snapshot, 'lineno')
559 stat = stats[0]
560 self.assertEqual(str(stat),
561 'a.py:5: size=5002 B (+5000 B), count=2 (+1), average=2501 B')
562
Victor Stinner524be302014-02-01 04:07:02 +0100563 def test_slices(self):
564 snapshot, snapshot2 = create_snapshots()
565 self.assertEqual(snapshot.traces[:2],
566 (snapshot.traces[0], snapshot.traces[1]))
567
568 traceback = snapshot.traces[0].traceback
569 self.assertEqual(traceback[:2],
570 (traceback[0], traceback[1]))
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100571
Victor Stinner23f628d2014-02-16 23:53:38 +0100572 def test_format_traceback(self):
573 snapshot, snapshot2 = create_snapshots()
574 def getline(filename, lineno):
575 return ' <%s, %s>' % (filename, lineno)
576 with unittest.mock.patch('tracemalloc.linecache.getline',
577 side_effect=getline):
578 tb = snapshot.traces[0].traceback
579 self.assertEqual(tb.format(),
Jesse-Bakker706e10b2017-11-30 00:05:07 +0100580 [' File "b.py", line 4',
581 ' <b.py, 4>',
582 ' File "a.py", line 2',
583 ' <a.py, 2>'])
Victor Stinner23f628d2014-02-16 23:53:38 +0100584
585 self.assertEqual(tb.format(limit=1),
586 [' File "a.py", line 2',
587 ' <a.py, 2>'])
588
589 self.assertEqual(tb.format(limit=-1),
Jesse-Bakker706e10b2017-11-30 00:05:07 +0100590 [' File "b.py", line 4',
591 ' <b.py, 4>'])
592
593 self.assertEqual(tb.format(most_recent_first=True),
594 [' File "a.py", line 2',
595 ' <a.py, 2>',
596 ' File "b.py", line 4',
597 ' <b.py, 4>'])
598
599 self.assertEqual(tb.format(limit=1, most_recent_first=True),
600 [' File "a.py", line 2',
601 ' <a.py, 2>'])
602
603 self.assertEqual(tb.format(limit=-1, most_recent_first=True),
604 [' File "b.py", line 4',
605 ' <b.py, 4>'])
Victor Stinner23f628d2014-02-16 23:53:38 +0100606
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100607
608class TestFilters(unittest.TestCase):
609 maxDiff = 2048
610
611 def test_filter_attributes(self):
612 # test default values
613 f = tracemalloc.Filter(True, "abc")
614 self.assertEqual(f.inclusive, True)
615 self.assertEqual(f.filename_pattern, "abc")
616 self.assertIsNone(f.lineno)
617 self.assertEqual(f.all_frames, False)
618
619 # test custom values
620 f = tracemalloc.Filter(False, "test.py", 123, True)
621 self.assertEqual(f.inclusive, False)
622 self.assertEqual(f.filename_pattern, "test.py")
623 self.assertEqual(f.lineno, 123)
624 self.assertEqual(f.all_frames, True)
625
626 # parameters passed by keyword
627 f = tracemalloc.Filter(inclusive=False, filename_pattern="test.py", lineno=123, all_frames=True)
628 self.assertEqual(f.inclusive, False)
629 self.assertEqual(f.filename_pattern, "test.py")
630 self.assertEqual(f.lineno, 123)
631 self.assertEqual(f.all_frames, True)
632
633 # read-only attribute
634 self.assertRaises(AttributeError, setattr, f, "filename_pattern", "abc")
635
636 def test_filter_match(self):
637 # filter without line number
638 f = tracemalloc.Filter(True, "abc")
639 self.assertTrue(f._match_frame("abc", 0))
640 self.assertTrue(f._match_frame("abc", 5))
641 self.assertTrue(f._match_frame("abc", 10))
642 self.assertFalse(f._match_frame("12356", 0))
643 self.assertFalse(f._match_frame("12356", 5))
644 self.assertFalse(f._match_frame("12356", 10))
645
646 f = tracemalloc.Filter(False, "abc")
647 self.assertFalse(f._match_frame("abc", 0))
648 self.assertFalse(f._match_frame("abc", 5))
649 self.assertFalse(f._match_frame("abc", 10))
650 self.assertTrue(f._match_frame("12356", 0))
651 self.assertTrue(f._match_frame("12356", 5))
652 self.assertTrue(f._match_frame("12356", 10))
653
654 # filter with line number > 0
655 f = tracemalloc.Filter(True, "abc", 5)
656 self.assertFalse(f._match_frame("abc", 0))
657 self.assertTrue(f._match_frame("abc", 5))
658 self.assertFalse(f._match_frame("abc", 10))
659 self.assertFalse(f._match_frame("12356", 0))
660 self.assertFalse(f._match_frame("12356", 5))
661 self.assertFalse(f._match_frame("12356", 10))
662
663 f = tracemalloc.Filter(False, "abc", 5)
664 self.assertTrue(f._match_frame("abc", 0))
665 self.assertFalse(f._match_frame("abc", 5))
666 self.assertTrue(f._match_frame("abc", 10))
667 self.assertTrue(f._match_frame("12356", 0))
668 self.assertTrue(f._match_frame("12356", 5))
669 self.assertTrue(f._match_frame("12356", 10))
670
671 # filter with line number 0
672 f = tracemalloc.Filter(True, "abc", 0)
673 self.assertTrue(f._match_frame("abc", 0))
674 self.assertFalse(f._match_frame("abc", 5))
675 self.assertFalse(f._match_frame("abc", 10))
676 self.assertFalse(f._match_frame("12356", 0))
677 self.assertFalse(f._match_frame("12356", 5))
678 self.assertFalse(f._match_frame("12356", 10))
679
680 f = tracemalloc.Filter(False, "abc", 0)
681 self.assertFalse(f._match_frame("abc", 0))
682 self.assertTrue(f._match_frame("abc", 5))
683 self.assertTrue(f._match_frame("abc", 10))
684 self.assertTrue(f._match_frame("12356", 0))
685 self.assertTrue(f._match_frame("12356", 5))
686 self.assertTrue(f._match_frame("12356", 10))
687
688 def test_filter_match_filename(self):
689 def fnmatch(inclusive, filename, pattern):
690 f = tracemalloc.Filter(inclusive, pattern)
691 return f._match_frame(filename, 0)
692
693 self.assertTrue(fnmatch(True, "abc", "abc"))
694 self.assertFalse(fnmatch(True, "12356", "abc"))
695 self.assertFalse(fnmatch(True, "<unknown>", "abc"))
696
697 self.assertFalse(fnmatch(False, "abc", "abc"))
698 self.assertTrue(fnmatch(False, "12356", "abc"))
699 self.assertTrue(fnmatch(False, "<unknown>", "abc"))
700
701 def test_filter_match_filename_joker(self):
702 def fnmatch(filename, pattern):
703 filter = tracemalloc.Filter(True, pattern)
704 return filter._match_frame(filename, 0)
705
706 # empty string
707 self.assertFalse(fnmatch('abc', ''))
708 self.assertFalse(fnmatch('', 'abc'))
709 self.assertTrue(fnmatch('', ''))
710 self.assertTrue(fnmatch('', '*'))
711
712 # no *
713 self.assertTrue(fnmatch('abc', 'abc'))
714 self.assertFalse(fnmatch('abc', 'abcd'))
715 self.assertFalse(fnmatch('abc', 'def'))
716
717 # a*
718 self.assertTrue(fnmatch('abc', 'a*'))
719 self.assertTrue(fnmatch('abc', 'abc*'))
720 self.assertFalse(fnmatch('abc', 'b*'))
721 self.assertFalse(fnmatch('abc', 'abcd*'))
722
723 # a*b
724 self.assertTrue(fnmatch('abc', 'a*c'))
725 self.assertTrue(fnmatch('abcdcx', 'a*cx'))
726 self.assertFalse(fnmatch('abb', 'a*c'))
727 self.assertFalse(fnmatch('abcdce', 'a*cx'))
728
729 # a*b*c
730 self.assertTrue(fnmatch('abcde', 'a*c*e'))
731 self.assertTrue(fnmatch('abcbdefeg', 'a*bd*eg'))
732 self.assertFalse(fnmatch('abcdd', 'a*c*e'))
733 self.assertFalse(fnmatch('abcbdefef', 'a*bd*eg'))
734
Brett Cannonf299abd2015-04-13 14:21:02 -0400735 # replace .pyc suffix with .py
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100736 self.assertTrue(fnmatch('a.pyc', 'a.py'))
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100737 self.assertTrue(fnmatch('a.py', 'a.pyc'))
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100738
739 if os.name == 'nt':
740 # case insensitive
741 self.assertTrue(fnmatch('aBC', 'ABc'))
742 self.assertTrue(fnmatch('aBcDe', 'Ab*dE'))
743
744 self.assertTrue(fnmatch('a.pyc', 'a.PY'))
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100745 self.assertTrue(fnmatch('a.py', 'a.PYC'))
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100746 else:
747 # case sensitive
748 self.assertFalse(fnmatch('aBC', 'ABc'))
749 self.assertFalse(fnmatch('aBcDe', 'Ab*dE'))
750
751 self.assertFalse(fnmatch('a.pyc', 'a.PY'))
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100752 self.assertFalse(fnmatch('a.py', 'a.PYC'))
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100753
754 if os.name == 'nt':
755 # normalize alternate separator "/" to the standard separator "\"
756 self.assertTrue(fnmatch(r'a/b', r'a\b'))
757 self.assertTrue(fnmatch(r'a\b', r'a/b'))
758 self.assertTrue(fnmatch(r'a/b\c', r'a\b/c'))
759 self.assertTrue(fnmatch(r'a/b/c', r'a\b\c'))
760 else:
761 # there is no alternate separator
762 self.assertFalse(fnmatch(r'a/b', r'a\b'))
763 self.assertFalse(fnmatch(r'a\b', r'a/b'))
764 self.assertFalse(fnmatch(r'a/b\c', r'a\b/c'))
765 self.assertFalse(fnmatch(r'a/b/c', r'a\b\c'))
766
Zachary Wared9b25bb2015-05-13 00:27:01 -0500767 # as of 3.5, .pyo is no longer munged to .py
768 self.assertFalse(fnmatch('a.pyo', 'a.py'))
769
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100770 def test_filter_match_trace(self):
771 t1 = (("a.py", 2), ("b.py", 3))
772 t2 = (("b.py", 4), ("b.py", 5))
773 t3 = (("c.py", 5), ('<unknown>', 0))
774 unknown = (('<unknown>', 0),)
775
776 f = tracemalloc.Filter(True, "b.py", all_frames=True)
777 self.assertTrue(f._match_traceback(t1))
778 self.assertTrue(f._match_traceback(t2))
779 self.assertFalse(f._match_traceback(t3))
780 self.assertFalse(f._match_traceback(unknown))
781
782 f = tracemalloc.Filter(True, "b.py", all_frames=False)
783 self.assertFalse(f._match_traceback(t1))
784 self.assertTrue(f._match_traceback(t2))
785 self.assertFalse(f._match_traceback(t3))
786 self.assertFalse(f._match_traceback(unknown))
787
788 f = tracemalloc.Filter(False, "b.py", all_frames=True)
789 self.assertFalse(f._match_traceback(t1))
790 self.assertFalse(f._match_traceback(t2))
791 self.assertTrue(f._match_traceback(t3))
792 self.assertTrue(f._match_traceback(unknown))
793
794 f = tracemalloc.Filter(False, "b.py", all_frames=False)
795 self.assertTrue(f._match_traceback(t1))
796 self.assertFalse(f._match_traceback(t2))
797 self.assertTrue(f._match_traceback(t3))
798 self.assertTrue(f._match_traceback(unknown))
799
800 f = tracemalloc.Filter(False, "<unknown>", all_frames=False)
801 self.assertTrue(f._match_traceback(t1))
802 self.assertTrue(f._match_traceback(t2))
803 self.assertTrue(f._match_traceback(t3))
804 self.assertFalse(f._match_traceback(unknown))
805
806 f = tracemalloc.Filter(True, "<unknown>", all_frames=True)
807 self.assertFalse(f._match_traceback(t1))
808 self.assertFalse(f._match_traceback(t2))
809 self.assertTrue(f._match_traceback(t3))
810 self.assertTrue(f._match_traceback(unknown))
811
812 f = tracemalloc.Filter(False, "<unknown>", all_frames=True)
813 self.assertTrue(f._match_traceback(t1))
814 self.assertTrue(f._match_traceback(t2))
815 self.assertFalse(f._match_traceback(t3))
816 self.assertFalse(f._match_traceback(unknown))
817
818
819class TestCommandLine(unittest.TestCase):
Gregory P. Smith34cd2ae2015-01-22 14:38:00 -0800820 def test_env_var_disabled_by_default(self):
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100821 # not tracing by default
822 code = 'import tracemalloc; print(tracemalloc.is_tracing())'
823 ok, stdout, stderr = assert_python_ok('-c', code)
824 stdout = stdout.rstrip()
825 self.assertEqual(stdout, b'False')
826
Berker Peksagce643912015-05-06 06:33:17 +0300827 @unittest.skipIf(interpreter_requires_environment(),
Gregory P. Smithb9a3dd92015-02-04 00:59:40 -0800828 'Cannot run -E tests when PYTHON env vars are required.')
Gregory P. Smith34cd2ae2015-01-22 14:38:00 -0800829 def test_env_var_ignored_with_E(self):
830 """PYTHON* environment variables must be ignored when -E is present."""
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100831 code = 'import tracemalloc; print(tracemalloc.is_tracing())'
832 ok, stdout, stderr = assert_python_ok('-E', '-c', code, PYTHONTRACEMALLOC='1')
833 stdout = stdout.rstrip()
834 self.assertEqual(stdout, b'False')
835
Gregory P. Smith34cd2ae2015-01-22 14:38:00 -0800836 def test_env_var_enabled_at_startup(self):
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100837 # tracing at startup
838 code = 'import tracemalloc; print(tracemalloc.is_tracing())'
839 ok, stdout, stderr = assert_python_ok('-c', code, PYTHONTRACEMALLOC='1')
840 stdout = stdout.rstrip()
841 self.assertEqual(stdout, b'True')
842
Gregory P. Smith34cd2ae2015-01-22 14:38:00 -0800843 def test_env_limit(self):
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100844 # start and set the number of frames
845 code = 'import tracemalloc; print(tracemalloc.get_traceback_limit())'
846 ok, stdout, stderr = assert_python_ok('-c', code, PYTHONTRACEMALLOC='10')
847 stdout = stdout.rstrip()
848 self.assertEqual(stdout, b'10')
849
Victor Stinnera7368ac2017-11-15 18:11:45 -0800850 def check_env_var_invalid(self, nframe):
851 with support.SuppressCrashReport():
852 ok, stdout, stderr = assert_python_failure(
853 '-c', 'pass',
854 PYTHONTRACEMALLOC=str(nframe))
855
856 if b'ValueError: the number of frames must be in range' in stderr:
857 return
858 if b'PYTHONTRACEMALLOC: invalid number of frames' in stderr:
859 return
860 self.fail(f"unexpeced output: {stderr!a}")
861
862
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100863 def test_env_var_invalid(self):
Victor Stinnerf28ce602013-11-27 22:27:13 +0100864 for nframe in (-1, 0, 2**30):
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100865 with self.subTest(nframe=nframe):
Victor Stinnera7368ac2017-11-15 18:11:45 -0800866 self.check_env_var_invalid(nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100867
868 def test_sys_xoptions(self):
869 for xoptions, nframe in (
870 ('tracemalloc', 1),
871 ('tracemalloc=1', 1),
872 ('tracemalloc=15', 15),
873 ):
874 with self.subTest(xoptions=xoptions, nframe=nframe):
875 code = 'import tracemalloc; print(tracemalloc.get_traceback_limit())'
876 ok, stdout, stderr = assert_python_ok('-X', xoptions, '-c', code)
877 stdout = stdout.rstrip()
878 self.assertEqual(stdout, str(nframe).encode('ascii'))
879
Victor Stinnera7368ac2017-11-15 18:11:45 -0800880 def check_sys_xoptions_invalid(self, nframe):
881 args = ('-X', 'tracemalloc=%s' % nframe, '-c', 'pass')
882 with support.SuppressCrashReport():
883 ok, stdout, stderr = assert_python_failure(*args)
884
885 if b'ValueError: the number of frames must be in range' in stderr:
886 return
887 if b'-X tracemalloc=NFRAME: invalid number of frames' in stderr:
888 return
889 self.fail(f"unexpeced output: {stderr!a}")
890
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100891 def test_sys_xoptions_invalid(self):
Victor Stinnerf28ce602013-11-27 22:27:13 +0100892 for nframe in (-1, 0, 2**30):
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100893 with self.subTest(nframe=nframe):
Victor Stinnera7368ac2017-11-15 18:11:45 -0800894 self.check_sys_xoptions_invalid(nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100895
Serhiy Storchaka24c738a2017-03-19 20:20:10 +0200896 @unittest.skipIf(_testcapi is None, 'need _testcapi')
Victor Stinner8dd49fe2014-06-02 21:36:59 +0200897 def test_pymem_alloc0(self):
898 # Issue #21639: Check that PyMem_Malloc(0) with tracemalloc enabled
899 # does not crash.
900 code = 'import _testcapi; _testcapi.test_pymem_alloc0(); 1'
901 assert_python_ok('-X', 'tracemalloc', '-c', code)
902
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100903
Victor Stinner10b73e12016-03-22 13:39:05 +0100904@unittest.skipIf(_testcapi is None, 'need _testcapi')
905class TestCAPI(unittest.TestCase):
906 maxDiff = 80 * 20
907
908 def setUp(self):
909 if tracemalloc.is_tracing():
910 self.skipTest("tracemalloc must be stopped before the test")
911
912 self.domain = 5
913 self.size = 123
914 self.obj = allocate_bytes(self.size)[0]
915
916 # for the type "object", id(obj) is the address of its memory block.
917 # This type is not tracked by the garbage collector
918 self.ptr = id(self.obj)
919
920 def tearDown(self):
921 tracemalloc.stop()
922
923 def get_traceback(self):
924 frames = _testcapi.tracemalloc_get_traceback(self.domain, self.ptr)
925 if frames is not None:
926 return tracemalloc.Traceback(frames)
927 else:
928 return None
929
930 def track(self, release_gil=False, nframe=1):
931 frames = get_frames(nframe, 2)
932 _testcapi.tracemalloc_track(self.domain, self.ptr, self.size,
933 release_gil)
934 return frames
935
936 def untrack(self):
937 _testcapi.tracemalloc_untrack(self.domain, self.ptr)
938
939 def get_traced_memory(self):
940 # Get the traced size in the domain
941 snapshot = tracemalloc.take_snapshot()
942 domain_filter = tracemalloc.DomainFilter(True, self.domain)
943 snapshot = snapshot.filter_traces([domain_filter])
944 return sum(trace.size for trace in snapshot.traces)
945
946 def check_track(self, release_gil):
947 nframe = 5
948 tracemalloc.start(nframe)
949
950 size = tracemalloc.get_traced_memory()[0]
951
952 frames = self.track(release_gil, nframe)
953 self.assertEqual(self.get_traceback(),
954 tracemalloc.Traceback(frames))
955
956 self.assertEqual(self.get_traced_memory(), self.size)
957
958 def test_track(self):
959 self.check_track(False)
960
961 def test_track_without_gil(self):
962 # check that calling _PyTraceMalloc_Track() without holding the GIL
963 # works too
964 self.check_track(True)
965
966 def test_track_already_tracked(self):
967 nframe = 5
968 tracemalloc.start(nframe)
969
970 # track a first time
971 self.track()
972
973 # calling _PyTraceMalloc_Track() must remove the old trace and add
974 # a new trace with the new traceback
975 frames = self.track(nframe=nframe)
976 self.assertEqual(self.get_traceback(),
977 tracemalloc.Traceback(frames))
978
979 def test_untrack(self):
980 tracemalloc.start()
981
982 self.track()
983 self.assertIsNotNone(self.get_traceback())
984 self.assertEqual(self.get_traced_memory(), self.size)
985
986 # untrack must remove the trace
987 self.untrack()
988 self.assertIsNone(self.get_traceback())
989 self.assertEqual(self.get_traced_memory(), 0)
990
991 # calling _PyTraceMalloc_Untrack() multiple times must not crash
992 self.untrack()
993 self.untrack()
994
995 def test_stop_track(self):
996 tracemalloc.start()
997 tracemalloc.stop()
998
999 with self.assertRaises(RuntimeError):
1000 self.track()
1001 self.assertIsNone(self.get_traceback())
1002
1003 def test_stop_untrack(self):
1004 tracemalloc.start()
1005 self.track()
1006
1007 tracemalloc.stop()
1008 with self.assertRaises(RuntimeError):
1009 self.untrack()
1010
1011
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001012def test_main():
1013 support.run_unittest(
1014 TestTracemallocEnabled,
1015 TestSnapshot,
1016 TestFilters,
1017 TestCommandLine,
Victor Stinner10b73e12016-03-22 13:39:05 +01001018 TestCAPI,
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001019 )
1020
1021if __name__ == "__main__":
1022 test_main()