1"""
2Test lldb data formatter subsystem.
3"""
4
5
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11
12USE_LIBSTDCPP = "USE_LIBSTDCPP"
13USE_LIBCPP = "USE_LIBCPP"
14
15class GenericMultiSetDataFormatterTestCase(TestBase):
16
17    def setUp(self):
18        TestBase.setUp(self)
19        self.namespace = 'std'
20
21    def findVariable(self, name):
22        var = self.frame().FindVariable(name)
23        self.assertTrue(var.IsValid())
24        return var
25
26    def getVariableType(self, name):
27        var = self.findVariable(name)
28        return var.GetType().GetDisplayTypeName()
29
30
31    def check(self, var_name, size):
32        var = self.findVariable(var_name)
33        self.assertEqual(var.GetNumChildren(), size)
34        children = []
35        for i in range(size):
36            child = var.GetChildAtIndex(i)
37            children.append(ValueCheck(value=child.GetValue()))
38        self.expect_var_path(var_name, type=self.getVariableType(var_name), children=children)
39
40    def do_test_with_run_command(self, stdlib_type):
41        """Test that that file and class static variables display correctly."""
42        self.build(dictionary={stdlib_type: "1"})
43        (self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
44            self, "Set break point at this line.", lldb.SBFileSpec("main.cpp", False))
45
46        # This is the function to remove the custom formats in order to have a
47        # clean slate for the next test case.
48        def cleanup():
49            self.runCmd('type format clear', check=False)
50            self.runCmd('type summary clear', check=False)
51            self.runCmd('type filter clear', check=False)
52            self.runCmd('type synth clear', check=False)
53            self.runCmd(
54                "settings set target.max-children-count 256",
55                check=False)
56
57        # Execute the cleanup function during test case tear down.
58        self.addTearDownHook(cleanup)
59
60        ii_type = self.getVariableType("ii")
61        self.assertTrue(ii_type.startswith(self.namespace + "::multiset"),
62                        "Type: " + ii_type)
63
64        self.expect("frame variable ii", substrs=["size=0", "{}"])
65        lldbutil.continue_to_breakpoint(process, bkpt)
66        self.expect(
67            "frame variable ii",
68            substrs=[
69                "size=6",
70                "[0] = 0",
71                "[1] = 1",
72                "[2] = 2",
73                "[3] = 3",
74                "[4] = 4",
75                "[5] = 5"])
76        lldbutil.continue_to_breakpoint(process, bkpt)
77
78        self.check("ii", 7)
79
80        lldbutil.continue_to_breakpoint(process, bkpt)
81        self.expect("frame variable ii", substrs=["size=0", "{}"])
82        self.check("ii", 0)
83        lldbutil.continue_to_breakpoint(process, bkpt)
84        self.expect("frame variable ii", substrs=["size=0", "{}"])
85        ss_type = self.getVariableType("ss")
86        self.assertTrue(ss_type.startswith(self.namespace + "::multiset"),
87                        "Type: " + ss_type)
88        self.expect("frame variable ss", substrs=["size=0", "{}"])
89        self.check("ss", 0)
90        lldbutil.continue_to_breakpoint(process, bkpt)
91        self.expect(
92            "frame variable ss",
93            substrs=[
94                "size=2",
95                '[0] = "a"',
96                '[1] = "a very long string is right here"'])
97        self.check("ss", 2)
98        lldbutil.continue_to_breakpoint(process, bkpt)
99        self.expect(
100            "frame variable ss",
101            substrs=[
102                "size=4",
103                '[0] = "a"',
104                '[1] = "a very long string is right here"',
105                '[2] = "b"',
106                '[3] = "c"',
107            ])
108        self.check("ss", 4)
109        self.expect(
110            "p ss",
111            substrs=[
112                "size=4",
113                '[0] = "a"',
114                '[1] = "a very long string is right here"',
115                '[2] = "b"',
116                '[3] = "c"',
117            ])
118        self.expect("frame variable ss[2]", substrs=[' = "b"'])
119        lldbutil.continue_to_breakpoint(process, bkpt)
120        self.expect(
121            "frame variable ss",
122            substrs=[
123                "size=3",
124                '[0] = "a"',
125                '[1] = "a very long string is right here"',
126                '[2] = "c"'])
127
128    def do_test_ref_and_ptr(self, stdlib_type):
129        """Test that the data formatters work on ref and ptr."""
130        self.build(dictionary={stdlib_type: "1"})
131        (self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
132            self, "Stop here to check by ref and ptr.",
133            lldb.SBFileSpec("main.cpp", False))
134        # The reference should print just like the value:
135        self.check("ref", 7)
136
137        self.expect("frame variable ptr",
138                    substrs=["ptr =", "size=7"])
139        self.expect("expr ptr",
140                    substrs=["size=7"])
141
142    @add_test_categories(["libstdcxx"])
143    def test_with_run_command_libstdcpp(self):
144        self.do_test_with_run_command(USE_LIBSTDCPP)
145
146    @add_test_categories(["libc++"])
147    def test_with_run_command_libcpp(self):
148        self.do_test_with_run_command(USE_LIBCPP)
149
150    @add_test_categories(["libstdcxx"])
151    def test_ref_and_ptr_libstdcpp(self):
152        self.do_test_ref_and_ptr(USE_LIBSTDCPP)
153
154    @add_test_categories(["libc++"])
155    def test_ref_and_ptr_libcpp(self):
156        self.do_test_ref_and_ptr(USE_LIBCPP)
157