"""
Test lldb breakpoint ids.
"""

from __future__ import print_function


import os
import time
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil


class TestCPPBreakpointLocations(TestBase):

    mydir = TestBase.compute_mydir(__file__)

    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")
    def test(self):
        self.build()
        self.breakpoint_id_tests()

    def verify_breakpoint_locations(self, target, bp_dict):

        name = bp_dict['name']
        names = bp_dict['loc_names']
        bp = target.BreakpointCreateByName(name)
        self.assertEquals(
            bp.GetNumLocations(),
            len(names),
            "Make sure we find the right number of breakpoint locations")

        bp_loc_names = list()
        for bp_loc in bp:
            bp_loc_names.append(bp_loc.GetAddress().GetFunction().GetName())

        for name in names:
            found = name in bp_loc_names
            if not found:
                print("Didn't find '%s' in: %s" % (name, bp_loc_names))
            self.assertTrue(found, "Make sure we find all required locations")

    def breakpoint_id_tests(self):

        # Create a target by the debugger.
        exe = self.getBuildArtifact("a.out")
        target = self.dbg.CreateTarget(exe)
        self.assertTrue(target, VALID_TARGET)
        bp_dicts = [
            {'name': 'func1', 'loc_names': ['a::c::func1()', 'b::c::func1()']},
            {'name': 'func2', 'loc_names': ['a::c::func2()', 'c::d::func2()']},
            {'name': 'func3', 'loc_names': ['a::c::func3()', 'b::c::func3()', 'c::d::func3()']},
            {'name': 'c::func1', 'loc_names': ['a::c::func1()', 'b::c::func1()']},
            {'name': 'c::func2', 'loc_names': ['a::c::func2()']},
            {'name': 'c::func3', 'loc_names': ['a::c::func3()', 'b::c::func3()']},
            {'name': 'a::c::func1', 'loc_names': ['a::c::func1()']},
            {'name': 'b::c::func1', 'loc_names': ['b::c::func1()']},
            {'name': 'c::d::func2', 'loc_names': ['c::d::func2()']},
            {'name': 'a::c::func1()', 'loc_names': ['a::c::func1()']},
            {'name': 'b::c::func1()', 'loc_names': ['b::c::func1()']},
            {'name': 'c::d::func2()', 'loc_names': ['c::d::func2()']},
        ]

        for bp_dict in bp_dicts:
            self.verify_breakpoint_locations(target, bp_dict)

    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")
    def test_destructors(self):
        self.build()
        exe = self.getBuildArtifact("a.out")
        target = self.dbg.CreateTarget(exe)

        # Don't skip prologue, so we can check the breakpoint address more
        # easily
        self.runCmd("settings set target.skip-prologue false")
        try:
            names = ['~c', 'c::~c', 'c::~c()']
            loc_names = {'a::c::~c()', 'b::c::~c()'}
            # TODO: For windows targets we should put windows mangled names
            # here
            symbols = [
                '_ZN1a1cD1Ev',
                '_ZN1a1cD2Ev',
                '_ZN1b1cD1Ev',
                '_ZN1b1cD2Ev']

            for name in names:
                bp = target.BreakpointCreateByName(name)

                bp_loc_names = {bp_loc.GetAddress().GetFunction().GetName()
                                for bp_loc in bp}
                self.assertEquals(
                    bp_loc_names,
                    loc_names,
                    "Breakpoint set on the correct symbol")

                bp_addresses = {bp_loc.GetLoadAddress() for bp_loc in bp}
                symbol_addresses = set()
                for symbol in symbols:
                    sc_list = target.FindSymbols(symbol, lldb.eSymbolTypeCode)
                    self.assertEquals(
                        sc_list.GetSize(), 1, "Found symbol " + symbol)
                    symbol = sc_list.GetContextAtIndex(0).GetSymbol()
                    symbol_addresses.add(
                        symbol.GetStartAddress().GetLoadAddress(target))

                self.assertEquals(
                    symbol_addresses,
                    bp_addresses,
                    "Breakpoint set on correct address")
        finally:
            self.runCmd("settings clear target.skip-prologue")
