1"""
2Test lldb breakpoint ids.
3"""
4
5from __future__ import print_function
6
7
8import lldb
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbutil
12
13
14class TestCPPBreakpointLocations(TestBase):
15
16    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")
17    def test(self):
18        self.build()
19        self.breakpoint_id_tests()
20
21    def verify_breakpoint_locations(self, target, bp_dict):
22
23        name = bp_dict['name']
24        names = bp_dict['loc_names']
25        bp = target.BreakpointCreateByName(name)
26        self.assertEquals(
27            bp.GetNumLocations(),
28            len(names),
29            "Make sure we find the right number of breakpoint locations for {}".format(name))
30
31        bp_loc_names = list()
32        for bp_loc in bp:
33            bp_loc_names.append(bp_loc.GetAddress().GetFunction().GetName())
34
35        for name in names:
36            found = name in bp_loc_names
37            if not found:
38                print("Didn't find '%s' in: %s" % (name, bp_loc_names))
39            self.assertTrue(found, "Make sure we find all required locations")
40
41    def breakpoint_id_tests(self):
42
43        # Create a target by the debugger.
44        exe = self.getBuildArtifact("a.out")
45        target = self.dbg.CreateTarget(exe)
46        self.assertTrue(target, VALID_TARGET)
47        bp_dicts = [
48            {'name': 'func1', 'loc_names': ['a::c::func1()', 'aa::cc::func1()', 'b::c::func1()']},
49            {'name': 'func2', 'loc_names': ['a::c::func2()', 'aa::cc::func2()', 'c::d::func2()']},
50            {'name': 'func3', 'loc_names': ['a::c::func3()', 'aa::cc::func3()', 'b::c::func3()', 'c::d::func3()']},
51            {'name': 'c::func1', 'loc_names': ['a::c::func1()', 'b::c::func1()']},
52            {'name': 'c::func2', 'loc_names': ['a::c::func2()']},
53            {'name': 'c::func3', 'loc_names': ['a::c::func3()', 'b::c::func3()']},
54            {'name': 'a::c::func1', 'loc_names': ['a::c::func1()']},
55            {'name': 'b::c::func1', 'loc_names': ['b::c::func1()']},
56            {'name': 'c::d::func2', 'loc_names': ['c::d::func2()']},
57            {'name': 'a::c::func1()', 'loc_names': ['a::c::func1()']},
58            {'name': 'b::c::func1()', 'loc_names': ['b::c::func1()']},
59            {'name': 'c::d::func2()', 'loc_names': ['c::d::func2()']},
60        ]
61
62        for bp_dict in bp_dicts:
63            self.verify_breakpoint_locations(target, bp_dict)
64
65    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")
66    def test_destructors(self):
67        self.build()
68        exe = self.getBuildArtifact("a.out")
69        target = self.dbg.CreateTarget(exe)
70
71        # Don't skip prologue, so we can check the breakpoint address more
72        # easily
73        self.runCmd("settings set target.skip-prologue false")
74        try:
75            names = ['~c', 'c::~c', 'c::~c()']
76            loc_names = {'a::c::~c()', 'b::c::~c()'}
77            # TODO: For windows targets we should put windows mangled names
78            # here
79            symbols = [
80                '_ZN1a1cD1Ev',
81                '_ZN1a1cD2Ev',
82                '_ZN1b1cD1Ev',
83                '_ZN1b1cD2Ev']
84
85            for name in names:
86                bp = target.BreakpointCreateByName(name)
87
88                bp_loc_names = {bp_loc.GetAddress().GetFunction().GetName()
89                                for bp_loc in bp}
90                self.assertEquals(
91                    bp_loc_names,
92                    loc_names,
93                    "Breakpoint set on the correct symbol")
94
95                bp_addresses = {bp_loc.GetLoadAddress() for bp_loc in bp}
96                symbol_addresses = set()
97                for symbol in symbols:
98                    sc_list = target.FindSymbols(symbol, lldb.eSymbolTypeCode)
99                    self.assertEquals(
100                        sc_list.GetSize(), 1, "Found symbol " + symbol)
101                    symbol = sc_list.GetContextAtIndex(0).GetSymbol()
102                    symbol_addresses.add(
103                        symbol.GetStartAddress().GetLoadAddress(target))
104
105                self.assertEquals(
106                    symbol_addresses,
107                    bp_addresses,
108                    "Breakpoint set on correct address")
109        finally:
110            self.runCmd("settings clear target.skip-prologue")
111