13c0fba4fSAdrian Prantlimport lldb 23c0fba4fSAdrian Prantlfrom lldbsuite.test.decorators import * 33c0fba4fSAdrian Prantlfrom lldbsuite.test.lldbtest import * 43c0fba4fSAdrian Prantlfrom lldbsuite.test import lldbutil 53c0fba4fSAdrian Prantl 63c0fba4fSAdrian Prantl 73c0fba4fSAdrian Prantlclass LibCxxStdFunctionRecognizerTestCase(TestBase): 83c0fba4fSAdrian Prantl NO_DEBUG_INFO_TESTCASE = True 93c0fba4fSAdrian Prantl 103c0fba4fSAdrian Prantl @add_test_categories(["libc++"]) 11dd060bdeSAdrian Vogelsgesang def test_frame_recognizer(self): 12dd060bdeSAdrian Vogelsgesang """Test that std::function all implementation details are hidden in SBFrame""" 13dd060bdeSAdrian Vogelsgesang self.build() 14dd060bdeSAdrian Vogelsgesang (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( 15dd060bdeSAdrian Vogelsgesang self, "// break here", lldb.SBFileSpec("main.cpp") 16dd060bdeSAdrian Vogelsgesang ) 17dd060bdeSAdrian Vogelsgesang self.assertIn("foo", thread.GetFrameAtIndex(0).GetFunctionName()) 18dd060bdeSAdrian Vogelsgesang # Skip all hidden frames 19dd060bdeSAdrian Vogelsgesang frame_id = 1 20dd060bdeSAdrian Vogelsgesang while ( 21dd060bdeSAdrian Vogelsgesang frame_id < thread.GetNumFrames() 22dd060bdeSAdrian Vogelsgesang and thread.GetFrameAtIndex(frame_id).IsHidden() 23dd060bdeSAdrian Vogelsgesang ): 24dd060bdeSAdrian Vogelsgesang frame_id = frame_id + 1 25dd060bdeSAdrian Vogelsgesang # Expect `std::function<...>::operator()` to be the direct parent of `foo` 26dd060bdeSAdrian Vogelsgesang self.assertIn( 27dd060bdeSAdrian Vogelsgesang "::operator()", thread.GetFrameAtIndex(frame_id).GetFunctionName() 28dd060bdeSAdrian Vogelsgesang ) 29dd060bdeSAdrian Vogelsgesang # And right above that, there should be the `main` frame 30dd060bdeSAdrian Vogelsgesang self.assertIn("main", thread.GetFrameAtIndex(frame_id + 1).GetFunctionName()) 31dd060bdeSAdrian Vogelsgesang 32dd060bdeSAdrian Vogelsgesang @add_test_categories(["libc++"]) 333c0fba4fSAdrian Prantl def test_backtrace(self): 343c0fba4fSAdrian Prantl """Test that std::function implementation details are hidden in bt""" 353c0fba4fSAdrian Prantl self.build() 363c0fba4fSAdrian Prantl (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( 373c0fba4fSAdrian Prantl self, "// break here", lldb.SBFileSpec("main.cpp") 383c0fba4fSAdrian Prantl ) 393c0fba4fSAdrian Prantl # Filtered. 403c0fba4fSAdrian Prantl self.expect( 413c0fba4fSAdrian Prantl "thread backtrace", 423c0fba4fSAdrian Prantl ordered=True, 433c0fba4fSAdrian Prantl substrs=["frame", "foo", "frame", "main"], 443c0fba4fSAdrian Prantl ) 453c0fba4fSAdrian Prantl self.expect( 4668a1593aSPetr Hosek "thread backtrace", matching=False, patterns=["frame.*std::__.*::__function"] 473c0fba4fSAdrian Prantl ) 483c0fba4fSAdrian Prantl # Unfiltered. 493c0fba4fSAdrian Prantl self.expect( 505d16fbc2SDave Lee "bt -u", 515d16fbc2SDave Lee ordered=True, 525d16fbc2SDave Lee patterns=["frame.*foo", "frame.*std::__[^:]*::__function", "frame.*main"], 535d16fbc2SDave Lee ) 545d16fbc2SDave Lee self.expect( 553c0fba4fSAdrian Prantl "thread backtrace -u", 563c0fba4fSAdrian Prantl ordered=True, 57dd060bdeSAdrian Vogelsgesang patterns=["frame.*foo", "frame.*std::__[^:]*::__function", "frame.*main"], 583c0fba4fSAdrian Prantl ) 593c0fba4fSAdrian Prantl self.expect( 603c0fba4fSAdrian Prantl "thread backtrace --unfiltered", 613c0fba4fSAdrian Prantl ordered=True, 62dd060bdeSAdrian Vogelsgesang patterns=["frame.*foo", "frame.*std::__[^:]*::__function", "frame.*main"], 633c0fba4fSAdrian Prantl ) 643c0fba4fSAdrian Prantl 653c0fba4fSAdrian Prantl @add_test_categories(["libc++"]) 663c0fba4fSAdrian Prantl def test_up_down(self): 673c0fba4fSAdrian Prantl """Test that std::function implementation details are skipped""" 683c0fba4fSAdrian Prantl self.build() 693c0fba4fSAdrian Prantl (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( 703c0fba4fSAdrian Prantl self, "// break here", lldb.SBFileSpec("main.cpp") 713c0fba4fSAdrian Prantl ) 72*7293455cSDave Lee frame = thread.selected_frame 733c0fba4fSAdrian Prantl # up 743c0fba4fSAdrian Prantl self.assertIn("foo", frame.GetFunctionName()) 753c0fba4fSAdrian Prantl start_idx = frame.GetFrameID() 763c0fba4fSAdrian Prantl i = 0 773c0fba4fSAdrian Prantl while i < thread.GetNumFrames(): 783c0fba4fSAdrian Prantl self.expect("up") 79*7293455cSDave Lee frame = thread.selected_frame 803c0fba4fSAdrian Prantl if frame.GetFunctionName() == "main": 813c0fba4fSAdrian Prantl break 823c0fba4fSAdrian Prantl end_idx = frame.GetFrameID() 833c0fba4fSAdrian Prantl self.assertLess(i, end_idx - start_idx, "skipped frames") 843c0fba4fSAdrian Prantl 853c0fba4fSAdrian Prantl # Back down again. 863c0fba4fSAdrian Prantl start_idx = frame.GetFrameID() 873c0fba4fSAdrian Prantl for i in range(1, thread.GetNumFrames()): 883c0fba4fSAdrian Prantl self.expect("down") 89*7293455cSDave Lee frame = thread.selected_frame 903c0fba4fSAdrian Prantl if "foo" in frame.GetFunctionName(): 913c0fba4fSAdrian Prantl break 923c0fba4fSAdrian Prantl end_idx = frame.GetFrameID() 933c0fba4fSAdrian Prantl self.assertLess(i, start_idx - end_idx, "skipped frames") 943c0fba4fSAdrian Prantl 953c0fba4fSAdrian Prantl @add_test_categories(["libc++"]) 963c0fba4fSAdrian Prantl def test_api(self): 973c0fba4fSAdrian Prantl """Test that std::function implementation details are skipped""" 983c0fba4fSAdrian Prantl self.build() 993c0fba4fSAdrian Prantl (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( 1003c0fba4fSAdrian Prantl self, "// break here", lldb.SBFileSpec("main.cpp") 1013c0fba4fSAdrian Prantl ) 1023c0fba4fSAdrian Prantl num_hidden = 0 103*7293455cSDave Lee for frame in thread.frames: 1043c0fba4fSAdrian Prantl if frame.IsHidden(): 1053c0fba4fSAdrian Prantl num_hidden += 1 1063c0fba4fSAdrian Prantl 1073c0fba4fSAdrian Prantl self.assertGreater(num_hidden, 0) 1083c0fba4fSAdrian Prantl self.assertLess(num_hidden, thread.GetNumFrames()) 109