xref: /llvm-project/lldb/test/API/lang/cpp/std-function-recognizer/TestStdFunctionRecognizer.py (revision dd060bdede8edec18ad5ca122e15cc24a821e3fe)
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            "thread backtrace -u",
51            ordered=True,
52            patterns=["frame.*foo", "frame.*std::__[^:]*::__function", "frame.*main"],
53        )
54        self.expect(
55            "thread backtrace --unfiltered",
56            ordered=True,
57            patterns=["frame.*foo", "frame.*std::__[^:]*::__function", "frame.*main"],
58        )
59
60    @add_test_categories(["libc++"])
61    def test_up_down(self):
62        """Test that std::function implementation details are skipped"""
63        self.build()
64        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
65            self, "// break here", lldb.SBFileSpec("main.cpp")
66        )
67        frame = thread.GetSelectedFrame()
68        # up
69        self.assertIn("foo", frame.GetFunctionName())
70        start_idx = frame.GetFrameID()
71        i = 0
72        while i < thread.GetNumFrames():
73            self.expect("up")
74            frame = thread.GetSelectedFrame()
75            if frame.GetFunctionName() == "main":
76                break
77        end_idx = frame.GetFrameID()
78        self.assertLess(i, end_idx - start_idx, "skipped frames")
79
80        # Back down again.
81        start_idx = frame.GetFrameID()
82        for i in range(1, thread.GetNumFrames()):
83            self.expect("down")
84            frame = thread.GetSelectedFrame()
85            if "foo" in frame.GetFunctionName():
86                break
87        end_idx = frame.GetFrameID()
88        self.assertLess(i, start_idx - end_idx, "skipped frames")
89
90    @add_test_categories(["libc++"])
91    def test_api(self):
92        """Test that std::function implementation details are skipped"""
93        self.build()
94        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
95            self, "// break here", lldb.SBFileSpec("main.cpp")
96        )
97        frame = thread.GetSelectedFrame()
98        num_hidden = 0
99        for i in range(1, thread.GetNumFrames()):
100            thread.SetSelectedFrame(i)
101            frame = thread.GetSelectedFrame()
102            if frame.IsHidden():
103                num_hidden += 1
104
105        self.assertGreater(num_hidden, 0)
106        self.assertLess(num_hidden, thread.GetNumFrames())
107