@@ -466,6 +466,28 @@ def test_collapsed_stack_collector_export(self):
466466 self .assertIn (stack1_expected , lines )
467467 self .assertIn (stack2_expected , lines )
468468
469+ def test_collapsed_stack_collector_export_non_ascii_names (self ):
470+ # gh-156810: frame names are written verbatim, so the output must be
471+ # opened with an encoding that can represent non-ASCII and
472+ # surrogate-escaped (undecodable-path) names.
473+ collapsed_out = tempfile .NamedTemporaryFile (delete = False )
474+ self .addCleanup (close_and_unlink , collapsed_out )
475+
476+ collector = CollapsedStackCollector (1000 )
477+ frame = MockFrameInfo ("/tmp/ba\udc80 d.py" , 5 , "计算" )
478+ collector .collect ([
479+ MockInterpreterInfo (0 , [MockThreadInfo (1 , [frame ])])
480+ ])
481+
482+ with captured_stdout (), captured_stderr ():
483+ collector .export (collapsed_out .name )
484+
485+ with open (collapsed_out .name , encoding = "utf-8" ,
486+ errors = "surrogatepass" ) as f :
487+ content = f .read ()
488+ self .assertIn ("计算" , content )
489+ self .assertIn ("ba\udc80 d.py" , content )
490+
469491 def test_flamegraph_collector_basic (self ):
470492 """Test basic FlamegraphCollector functionality."""
471493 collector = FlamegraphCollector (1000 )
0 commit comments