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