1"""
2Test lldb data formatter subsystem.
3"""
4
5
6import lldb
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9from lldbsuite.test import lldbutil
10
11
12class LibCxxFunctionTestCase(TestBase):
13    # Run frame var for a variable twice. Verify we do not hit the cache
14    # the first time but do the second time.
15    def run_frame_var_check_cache_use(
16        self, variable, result_to_match, skip_find_function=False
17    ):
18        self.runCmd("log timers reset")
19        self.expect(
20            "frame variable " + variable, substrs=[variable + " =  " + result_to_match]
21        )
22        if not skip_find_function:
23            self.expect(
24                "log timers dump", substrs=["lldb_private::CompileUnit::FindFunction"]
25            )
26
27        self.runCmd("log timers reset")
28        self.expect(
29            "frame variable " + variable, substrs=[variable + " =  " + result_to_match]
30        )
31        self.expect(
32            "log timers dump",
33            matching=False,
34            substrs=["lldb_private::CompileUnit::FindFunction"],
35        )
36
37    @add_test_categories(["libc++"])
38    def test(self):
39        """Test that std::function as defined by libc++ is correctly printed by LLDB"""
40        self.build()
41        self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
42
43        bkpt = self.target().FindBreakpointByID(
44            lldbutil.run_break_set_by_source_regexp(
45                self, "Set break point at this line."
46            )
47        )
48
49        self.runCmd("run", RUN_SUCCEEDED)
50
51        # The stop reason of the thread should be breakpoint.
52        self.expect(
53            "thread list",
54            STOPPED_DUE_TO_BREAKPOINT,
55            substrs=["stopped", "stop reason = breakpoint"],
56        )
57
58        self.run_frame_var_check_cache_use(
59            "foo2_f", "Lambda in File main.cpp at Line 22"
60        )
61
62        lldbutil.continue_to_breakpoint(self.process(), bkpt)
63
64        self.run_frame_var_check_cache_use(
65            "add_num2_f", "Lambda in File main.cpp at Line 13"
66        )
67
68        lldbutil.continue_to_breakpoint(self.process(), bkpt)
69
70        self.run_frame_var_check_cache_use("f2", "Lambda in File main.cpp at Line 35")
71        self.run_frame_var_check_cache_use(
72            "f3", "Lambda in File main.cpp at Line 39", True
73        )
74        # TODO reenable this case when std::function formatter supports
75        # general callable object case.
76        # self.run_frame_var_check_cache_use("f4", "Function in File main.cpp at Line 8")
77
78        # These cases won't hit the cache at all but also don't require
79        # an expensive lookup.
80        self.expect("frame variable f1", substrs=["f1 =  Function = foo(int, int)"])
81
82        self.expect(
83            "frame variable f5", substrs=["f5 =  Function = Bar::add_num(int) const"]
84        )
85