xref: /llvm-project/lldb/test/API/lang/cpp/std-function-recognizer/TestStdFunctionRecognizer.py (revision 7293455cf292cfaa263ea04fc1bc2aee4ceab6a6)
1import lldb
2from lldbsuite.test.decorators import *
3from lldbsuite.test.lldbtest import *
4from lldbsuite.test import lldbutil
5
6
7class LibCxxStdFunctionRecognizerTestCase(TestBase):
8    NO_DEBUG_INFO_TESTCASE = True
9
10    @add_test_categories(["libc++"])
11    def test_frame_recognizer(self):
12        """Test that std::function all implementation details are hidden in SBFrame"""
13        self.build()
14        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
15            self, "// break here", lldb.SBFileSpec("main.cpp")
16        )
17        self.assertIn("foo", thread.GetFrameAtIndex(0).GetFunctionName())
18        # Skip all hidden frames
19        frame_id = 1
20        while (
21            frame_id < thread.GetNumFrames()
22            and thread.GetFrameAtIndex(frame_id).IsHidden()
23        ):
24            frame_id = frame_id + 1
25        # Expect `std::function<...>::operator()` to be the direct parent of `foo`
26        self.assertIn(
27            "::operator()", thread.GetFrameAtIndex(frame_id).GetFunctionName()
28        )
29        # And right above that, there should be the `main` frame
30        self.assertIn("main", thread.GetFrameAtIndex(frame_id + 1).GetFunctionName())
31
32    @add_test_categories(["libc++"])
33    def test_backtrace(self):
34        """Test that std::function implementation details are hidden in bt"""
35        self.build()
36        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
37            self, "// break here", lldb.SBFileSpec("main.cpp")
38        )
39        # Filtered.
40        self.expect(
41            "thread backtrace",
42            ordered=True,
43            substrs=["frame", "foo", "frame", "main"],
44        )
45        self.expect(
46            "thread backtrace", matching=False, patterns=["frame.*std::__.*::__function"]
47        )
48        # Unfiltered.
49        self.expect(
50            "bt -u",
51            ordered=True,
52            patterns=["frame.*foo", "frame.*std::__[^:]*::__function", "frame.*main"],
53        )
54        self.expect(
55            "thread backtrace -u",
56            ordered=True,
57            patterns=["frame.*foo", "frame.*std::__[^:]*::__function", "frame.*main"],
58        )
59        self.expect(
60            "thread backtrace --unfiltered",
61            ordered=True,
62            patterns=["frame.*foo", "frame.*std::__[^:]*::__function", "frame.*main"],
63        )
64
65    @add_test_categories(["libc++"])
66    def test_up_down(self):
67        """Test that std::function implementation details are skipped"""
68        self.build()
69        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
70            self, "// break here", lldb.SBFileSpec("main.cpp")
71        )
72        frame = thread.selected_frame
73        # up
74        self.assertIn("foo", frame.GetFunctionName())
75        start_idx = frame.GetFrameID()
76        i = 0
77        while i < thread.GetNumFrames():
78            self.expect("up")
79            frame = thread.selected_frame
80            if frame.GetFunctionName() == "main":
81                break
82        end_idx = frame.GetFrameID()
83        self.assertLess(i, end_idx - start_idx, "skipped frames")
84
85        # Back down again.
86        start_idx = frame.GetFrameID()
87        for i in range(1, thread.GetNumFrames()):
88            self.expect("down")
89            frame = thread.selected_frame
90            if "foo" in frame.GetFunctionName():
91                break
92        end_idx = frame.GetFrameID()
93        self.assertLess(i, start_idx - end_idx, "skipped frames")
94
95    @add_test_categories(["libc++"])
96    def test_api(self):
97        """Test that std::function implementation details are skipped"""
98        self.build()
99        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
100            self, "// break here", lldb.SBFileSpec("main.cpp")
101        )
102        num_hidden = 0
103        for frame in thread.frames:
104            if frame.IsHidden():
105                num_hidden += 1
106
107        self.assertGreater(num_hidden, 0)
108        self.assertLess(num_hidden, thread.GetNumFrames())
109