1"""
2Test that C++ template classes that have integer parameters work correctly.
3
4We must reconstruct the types correctly so the template types are correct
5and display correctly, and also make sure the expression parser works and
6is able the find all needed functions when evaluating expressions
7"""
8import lldb
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbutil
12
13
14class TemplateArgsTestCase(TestBase):
15
16    def prepareProcess(self):
17        self.build()
18
19        # Create a target by the debugger.
20        exe = self.getBuildArtifact("a.out")
21        target = self.dbg.CreateTarget(exe)
22        self.assertTrue(target, VALID_TARGET)
23
24        # Set breakpoints inside and outside methods that take pointers to the
25        # containing struct.
26        line = line_number('main.cpp', '// Breakpoint 1')
27        lldbutil.run_break_set_by_file_and_line(
28            self, "main.cpp", line, num_expected_locations=1, loc_exact=True)
29
30        arguments = None
31        environment = None
32
33        # Now launch the process, and do not stop at entry point.
34        process = target.LaunchSimple(
35            arguments, environment, self.get_process_working_directory())
36        self.assertTrue(process, PROCESS_IS_VALID)
37
38        # Get the thread of the process
39        self.assertEqual(
40            process.GetState(), lldb.eStateStopped,
41            PROCESS_STOPPED)
42        thread = lldbutil.get_stopped_thread(
43            process, lldb.eStopReasonBreakpoint)
44
45        # Get frame for current thread
46        return thread.GetSelectedFrame()
47
48    def test_integer_args(self):
49        frame = self.prepareProcess()
50
51        testpos = frame.FindVariable('testpos')
52        self.assertTrue(
53            testpos.IsValid(),
54            'make sure we find a local variabble named "testpos"')
55        self.assertEquals(testpos.GetType().GetName(), 'TestObj<1>')
56
57        expr_result = frame.EvaluateExpression("testpos.getArg()")
58        self.assertTrue(
59            expr_result.IsValid(),
60            'got a valid expression result from expression "testpos.getArg()"')
61        self.assertEquals(expr_result.GetValue(), "1", "testpos.getArg() == 1")
62        self.assertEqual(
63            expr_result.GetType().GetName(), "int",
64            'expr_result.GetType().GetName() == "int"')
65
66        testneg = frame.FindVariable('testneg')
67        self.assertTrue(
68            testneg.IsValid(),
69            'make sure we find a local variabble named "testneg"')
70        self.assertEquals(testneg.GetType().GetName(), 'TestObj<-1>')
71
72        expr_result = frame.EvaluateExpression("testneg.getArg()")
73        self.assertTrue(
74            expr_result.IsValid(),
75            'got a valid expression result from expression "testneg.getArg()"')
76        self.assertEqual(
77            expr_result.GetValue(), "-1",
78            "testneg.getArg() == -1")
79        self.assertEqual(
80            expr_result.GetType().GetName(), "int",
81            'expr_result.GetType().GetName() == "int"')
82
83    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489")
84    def test_template_template_args(self):
85        frame = self.prepareProcess()
86
87        c1 = frame.FindVariable('c1')
88        self.assertTrue(
89            c1.IsValid(),
90            'make sure we find a local variabble named "c1"')
91        self.assertEquals(c1.GetType().GetName(), 'C<float, T1>')
92        f1 = c1.GetChildMemberWithName("V").GetChildAtIndex(0).GetChildMemberWithName("f")
93        self.assertEquals(f1.GetType().GetName(), 'float')
94        self.assertEquals(f1.GetValue(), '1.5')
95
96        c2 = frame.FindVariable('c2')
97        self.assertTrue(
98            c2.IsValid(),
99            'make sure we find a local variabble named "c2"')
100        self.assertEquals(c2.GetType().GetName(), 'C<double, T1, T2>')
101        f2 = c2.GetChildMemberWithName("V").GetChildAtIndex(0).GetChildMemberWithName("f")
102        self.assertEquals(f2.GetType().GetName(), 'double')
103        self.assertEquals(f2.GetValue(), '1.5')
104        f3 = c2.GetChildMemberWithName("V").GetChildAtIndex(1).GetChildMemberWithName("f")
105        self.assertEquals(f3.GetType().GetName(), 'double')
106        self.assertEquals(f3.GetValue(), '2.5')
107        f4 = c2.GetChildMemberWithName("V").GetChildAtIndex(1).GetChildMemberWithName("i")
108        self.assertEquals(f4.GetType().GetName(), 'int')
109        self.assertEquals(f4.GetValue(), '42')
110
111    # Gcc does not generate the necessary DWARF attribute for enum template
112    # parameters.
113    @expectedFailureAll(bugnumber="llvm.org/pr28354", compiler="gcc")
114    @skipIf(dwarf_version=['<', '4'])
115    def test_enum_args(self):
116        frame = self.prepareProcess()
117
118        # Make sure "member" can be displayed and also used in an expression
119        # correctly
120        member = frame.FindVariable('member')
121        self.assertTrue(
122            member.IsValid(),
123            'make sure we find a local variabble named "member"')
124        self.assertEqual(member.GetType().GetName(),
125                        'EnumTemplate<EnumType::Member>')
126
127        expr_result = frame.EvaluateExpression("member.getMember()")
128        self.assertTrue(
129            expr_result.IsValid(),
130            'got a valid expression result from expression "member.getMember()"')
131        self.assertEqual(
132            expr_result.GetValue(), "123",
133            "member.getMember() == 123")
134        self.assertEqual(
135            expr_result.GetType().GetName(), "int",
136            'expr_result.GetType().GetName() == "int"')
137
138        # Make sure "subclass" can be displayed and also used in an expression
139        # correctly
140        subclass = frame.FindVariable('subclass')
141        self.assertTrue(
142            subclass.IsValid(),
143            'make sure we find a local variabble named "subclass"')
144        self.assertEqual(subclass.GetType().GetName(),
145                        'EnumTemplate<EnumType::Subclass>')
146
147        expr_result = frame.EvaluateExpression("subclass.getMember()")
148        self.assertTrue(
149            expr_result.IsValid(),
150            'got a valid expression result from expression "subclass.getMember()"')
151        self.assertEqual(
152            expr_result.GetValue(), "246",
153            "subclass.getMember() == 246")
154        self.assertEqual(
155            expr_result.GetType().GetName(), "int",
156            'expr_result.GetType().GetName() == "int"')
157