1"""
2Test lldb data formatter callback-based matching.
3"""
4
5import lldb
6from lldbsuite.test.decorators import *
7from lldbsuite.test.lldbtest import *
8from lldbsuite.test import lldbutil
9
10
11class PythonSynthDataFormatterTestCase(TestBase):
12    def setUp(self):
13        # Call super's setUp().
14        TestBase.setUp(self)
15        # Find the line number to break at.
16        self.line = line_number("main.cpp", "// Set break point at this line.")
17
18    def test_callback_matchers_api_registration(self):
19        """Test data formatter commands."""
20        self.build()
21
22        _, process, thread, _ = lldbutil.run_to_line_breakpoint(
23            self, lldb.SBFileSpec("main.cpp"), self.line
24        )
25
26        # Print derived without a formatter.
27        self.expect("frame variable derived", substrs=["x = 2222", "y = 3333"])
28
29        # now set up a summary function that uses a python callback to match
30        # classes that derive from `Base`.
31        self.runCmd(
32            "command script import --allow-reload ./formatters_with_callback.py"
33        )
34        self.runCmd(
35            "script formatters_with_callback.register_formatters(lldb.debugger)"
36        )
37
38        # Now `derived` should use our callback summary + synthetic children.
39        self.expect(
40            "frame variable derived",
41            substrs=["hello from callback summary", "synthetic_child = 9999"],
42        )
43
44        # But not other classes.
45        self.expect(
46            "frame variable base",
47            matching=False,
48            substrs=["hello from callback summary"],
49        )
50        self.expect("frame variable base", substrs=["x = 1111"])
51
52        self.expect(
53            "frame variable nd", matching=False, substrs=["hello from callback summary"]
54        )
55        self.expect("frame variable nd", substrs=["z = 4444"])
56
57    def test_callback_matchers_cli_registration(self):
58        """Test data formatter commands."""
59        self.build()
60
61        _, process, thread, _ = lldbutil.run_to_line_breakpoint(
62            self, lldb.SBFileSpec("main.cpp"), self.line
63        )
64
65        # Print derived without a formatter.
66        self.expect("frame variable derived", substrs=["x = 2222", "y = 3333"])
67
68        # now set up a summary function that uses a python callback to match
69        # classes that derive from `Base`.
70        self.runCmd(
71            "command script import --allow-reload ./formatters_with_callback.py"
72        )
73        self.runCmd(
74            "type summary add -e -s 'hello from callback summary' "
75            "--recognizer-function formatters_with_callback.derives_from_base"
76        )
77        self.runCmd(
78            "type synth add -l formatters_with_callback.SynthProvider "
79            "--recognizer-function formatters_with_callback.derives_from_base"
80        )
81
82        # Now `derived` should use our callback summary + synthetic children.
83        self.expect(
84            "frame variable derived",
85            substrs=["hello from callback summary", "synthetic_child = 9999"],
86        )
87
88        # But not other classes.
89        self.expect(
90            "frame variable base",
91            matching=False,
92            substrs=["hello from callback summary"],
93        )
94        self.expect("frame variable base", substrs=["x = 1111"])
95
96        self.expect(
97            "frame variable nd", matching=False, substrs=["hello from callback summary"]
98        )
99        self.expect("frame variable nd", substrs=["z = 4444"])
100