@@ -2644,20 +2644,29 @@ def test_cpu_mode_integration_filtering(self):
26442644import time
26452645import threading
26462646
2647+ # Event to signal when CPU thread is running
2648+ cpu_ready = threading.Event()
2649+
26472650def idle_worker():
26482651 time.sleep(999999)
26492652
26502653def cpu_active_worker():
2654+ cpu_ready.set() # Signal that we're running
26512655 x = 1
26522656 while True:
26532657 x += 1
26542658
26552659def main():
2656- # Start both threads
2660+ from test.support import SHORT_TIMEOUT
2661+ # Start both threads
26572662 idle_thread = threading.Thread(target=idle_worker)
26582663 cpu_thread = threading.Thread(target=cpu_active_worker)
26592664 idle_thread.start()
26602665 cpu_thread.start()
2666+
2667+ # Wait for CPU thread to be running before continuing
2668+ cpu_ready.wait(timeout=SHORT_TIMEOUT)
2669+
26612670 idle_thread.join()
26622671 cpu_thread.join()
26632672
@@ -2716,6 +2725,37 @@ def main():
27162725 self .assertIn ("cpu_active_worker" , wall_mode_output )
27172726 self .assertIn ("idle_worker" , wall_mode_output )
27182727
2728+ def test_cpu_mode_with_no_samples (self ):
2729+ """Test that CPU mode handles no samples gracefully when no samples are collected."""
2730+ # Mock a collector that returns empty stats
2731+ mock_collector = mock .MagicMock ()
2732+ mock_collector .stats = {}
2733+ mock_collector .create_stats = mock .MagicMock ()
2734+
2735+ with (
2736+ io .StringIO () as captured_output ,
2737+ mock .patch ("sys.stdout" , captured_output ),
2738+ mock .patch ("profiling.sampling.sample.PstatsCollector" , return_value = mock_collector ),
2739+ mock .patch ("profiling.sampling.sample.SampleProfiler" ) as mock_profiler_class ,
2740+ ):
2741+ mock_profiler = mock .MagicMock ()
2742+ mock_profiler_class .return_value = mock_profiler
2743+
2744+ profiling .sampling .sample .sample (
2745+ 12345 , # dummy PID
2746+ duration_sec = 0.5 ,
2747+ sample_interval_usec = 5000 ,
2748+ mode = 1 , # CPU mode
2749+ show_summary = False ,
2750+ all_threads = True ,
2751+ )
2752+
2753+ output = captured_output .getvalue ()
2754+
2755+ # Should see the "No samples were collected" message
2756+ self .assertIn ("No samples were collected" , output )
2757+ self .assertIn ("CPU mode" , output )
2758+
27192759
27202760class TestGilModeFiltering (unittest .TestCase ):
27212761 """Test GIL mode filtering functionality (--mode=gil)."""
@@ -2852,20 +2892,29 @@ def test_gil_mode_integration_behavior(self):
28522892import time
28532893import threading
28542894
2895+ # Event to signal when thread is running
2896+ gil_ready = threading.Event()
2897+
28552898def gil_releasing_work():
28562899 time.sleep(999999)
28572900
28582901def gil_holding_work():
2902+ gil_ready.set() # Signal that we're running
28592903 x = 1
28602904 while True:
28612905 x += 1
28622906
28632907def main():
2864- # Start both threads
2908+ from test.support import SHORT_TIMEOUT
2909+ # Start both threads
28652910 idle_thread = threading.Thread(target=gil_releasing_work)
28662911 cpu_thread = threading.Thread(target=gil_holding_work)
28672912 idle_thread.start()
28682913 cpu_thread.start()
2914+
2915+ # Wait for GIL-holding thread to be running before continuing
2916+ gil_ready.wait(timeout=SHORT_TIMEOUT)
2917+
28692918 idle_thread.join()
28702919 cpu_thread.join()
28712920
0 commit comments