1+ import os
12import textwrap
23import time
34import unittest
@@ -47,30 +48,7 @@ class TestGetGCStats(unittest.TestCase):
4748 @classmethod
4849 def setUpClass (cls ):
4950 cls ._main_iid = 0 # main interpreter ID
50- cls ._only_main_interpreter_script = '''
51- import gc
52- import time
53-
54- gc.collect(0)
55- gc.collect(1)
56- gc.collect(2)
57-
58- _test_sock.sendall(b"working")
59-
60- objects = []
61- while True:
62- if len(objects) > 100:
63- objects = []
64-
65- # objects that GC will visit should increase
66- objects.append(object())
67-
68- time.sleep(0.1)
69- gc.collect(0)
70- gc.collect(1)
71- gc.collect(2)
72- '''
73- cls ._subinterpreters_script = '''
51+ cls ._script = '''
7452 import concurrent.interpreters as interpreters
7553 import gc
7654 import time
@@ -83,8 +61,9 @@ def setUpClass(cls):
8361 gc.collect(2)
8462 """
8563
86- interp = interpreters.create()
87- interp.exec(source)
64+ if {0}:
65+ interp = interpreters.create()
66+ interp.exec(source)
8867
8968 gc.collect(0)
9069 gc.collect(1)
@@ -100,7 +79,8 @@ def setUpClass(cls):
10079 objects.append(object())
10180
10281 time.sleep(0.1)
103- interp.exec(source)
82+ if {0}:
83+ interp.exec(source)
10484 gc.collect(0)
10585 gc.collect(1)
10686 gc.collect(2)
@@ -124,7 +104,7 @@ def _collect_gc_stats(self, script:str, all_interpreters:bool):
124104
125105 return before_stats , after_stats
126106
127- def _check_gc_state (self , before , after ):
107+ def _check_gc_stats (self , before , after ):
128108 self .assertIsNotNone (before )
129109 self .assertIsNotNone (after )
130110
@@ -148,41 +128,55 @@ def _check_gc_state(self, before, after):
148128 before ["objects_not_transitively_reachable" ],
149129 (before , after ))
150130
151- def _check_main_interpreter_stats (self , before_stats , after_stats ):
131+ def _check_interpreter_gc_stats (self , before_stats , after_stats ):
152132 before_iids = get_interpreter_identifiers (before_stats )
153133 after_iids = get_interpreter_identifiers (after_stats )
154134
155- self .assertEqual (before_iids , (0 ,))
156- self .assertEqual (after_iids , (0 ,))
135+ self .assertEqual (before_iids , after_iids )
157136
158137 self .assertEqual (get_generations (before_stats ), (0 , 1 , 2 ))
159138 self .assertEqual (get_generations (after_stats ), (0 , 1 , 2 ))
160139
161- before_last_items = (get_last_item (before_stats , 0 , self ._main_iid ),
162- get_last_item (before_stats , 1 , self ._main_iid ),
163- get_last_item (before_stats , 2 , self ._main_iid ))
140+ for iid in after_iids :
141+ with self .subTest (f"interpreter id={ iid } " ):
142+ before_last_items = (get_last_item (before_stats , 0 , iid ),
143+ get_last_item (before_stats , 1 , iid ),
144+ get_last_item (before_stats , 2 , iid ))
164145
165- after_last_items = (get_last_item (after_stats , 0 , self . _main_iid ),
166- get_last_item (after_stats , 1 , self . _main_iid ),
167- get_last_item (after_stats , 2 , self . _main_iid ))
146+ after_last_items = (get_last_item (after_stats , 0 , iid ),
147+ get_last_item (after_stats , 1 , iid ),
148+ get_last_item (after_stats , 2 , iid ))
168149
169- for before , after in zip (before_last_items , after_last_items ):
170- self ._check_gc_state (before , after )
150+ for before , after in zip (before_last_items , after_last_items ):
151+ self ._check_gc_stats (before , after )
152+
153+ def test_get_gc_stats_fields (self ):
154+ keys = sorted (("gen" , "iid" , "ts_start" , "ts_stop" , "heap_size" ,
155+ "work_to_do" , "collections" , "object_visits" ,
156+ "collected" , "uncollectable" , "candidates" ,
157+ "objects_transitively_reachable" ,
158+ "objects_not_transitively_reachable" ,
159+ "duration" ))
160+ stats = _remote_debugging .get_gc_stats (os .getpid (), all_interpreters = False )
161+ self .assertIsInstance (stats , list )
162+ for item in stats :
163+ self .assertIsInstance (item , dict )
164+ self .assertEqual (sorted (item .keys ()), keys )
171165
172166 def test_get_gc_stats_for_main_interpreter (self ):
173- script = textwrap .dedent (self ._only_main_interpreter_script )
167+ script = textwrap .dedent (self ._script . format ( False ) )
174168 before_stats , after_stats = self ._collect_gc_stats (script , False )
175169
176- self ._check_main_interpreter_stats (before_stats ,after_stats )
170+ self ._check_interpreter_gc_stats (before_stats ,after_stats )
177171
178172 def test_get_gc_stats_for_main_interpreter_if_subinterpreter_exists (self ):
179- script = textwrap .dedent (self ._subinterpreters_script )
173+ script = textwrap .dedent (self ._script . format ( True ) )
180174 before_stats , after_stats = self ._collect_gc_stats (script , False )
181175
182- self ._check_main_interpreter_stats (before_stats ,after_stats )
176+ self ._check_interpreter_gc_stats (before_stats , after_stats )
183177
184178 def test_get_gc_stats_for_all_interpreters (self ):
185- script = textwrap .dedent (self ._subinterpreters_script )
179+ script = textwrap .dedent (self ._script . format ( True ) )
186180 before_stats , after_stats = self ._collect_gc_stats (script , True )
187181
188182 before_iids = get_interpreter_identifiers (before_stats )
@@ -192,21 +186,4 @@ def test_get_gc_stats_for_all_interpreters(self):
192186 self .assertGreater (len (after_iids ), 1 )
193187 self .assertEqual (before_iids , after_iids )
194188
195- before_gens = get_generations (before_stats )
196- after_gens = get_generations (after_stats )
197-
198- self .assertEqual (before_gens , (0 , 1 , 2 ))
199- self .assertEqual (after_gens , (0 , 1 , 2 ))
200-
201- for iid in after_iids :
202- with self .subTest (f"iid={ iid } " ):
203- before_last_items = (get_last_item (before_stats , 0 , iid ),
204- get_last_item (before_stats , 1 , iid ),
205- get_last_item (before_stats , 2 , iid ))
206-
207- after_last_items = (get_last_item (after_stats , 0 , iid ),
208- get_last_item (after_stats , 1 , iid ),
209- get_last_item (after_stats , 2 , iid ))
210-
211- for before , after in zip (before_last_items , after_last_items ):
212- self ._check_gc_state (before , after )
189+ self ._check_interpreter_gc_stats (before_stats , after_stats )
0 commit comments