reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
  249
  250
  251
  252
  253
  254
  255
  256
  257
  258
  259
  260
  261
  262
  263
  264
  265
  266
  267
  268
  269
  270
  271
  272
  273
  274
  275
  276
  277
  278
  279
  280
  281
  282
  283
  284
  285
  286
  287
  288
  289
  290
  291
  292
  293
  294
  295
  296
  297
  298
  299
  300
  301
  302
  303
  304
  305
  306
  307
  308
  309
  310
  311
  312
  313
  314
  315
  316
  317
  318
  319
  320
  321
  322
  323
  324
  325
  326
  327
  328
  329
  330
  331
  332
  333
  334
  335
  336
  337
  338
  339
  340
  341
  342
  343
  344
  345
  346
  347
  348
  349
  350
  351
  352
  353
  354
  355
  356
  357
  358
  359
  360
  361
  362
  363
  364
  365
"""
Test breakpoint names.
"""

from __future__ import print_function


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


class BreakpointNames(TestBase):

    mydir = TestBase.compute_mydir(__file__)
    NO_DEBUG_INFO_TESTCASE = True

    @add_test_categories(['pyapi'])
    def test_setting_names(self):
        """Use Python APIs to test that we can set breakpoint names."""
        self.build()
        self.setup_target()
        self.do_check_names()

    def test_illegal_names(self):
        """Use Python APIs to test that we don't allow illegal names."""
        self.build()
        self.setup_target()
        self.do_check_illegal_names()

    def test_using_names(self):
        """Use Python APIs to test that operations on names works correctly."""
        self.build()
        self.setup_target()
        self.do_check_using_names()

    def test_configuring_names(self):
        """Use Python APIs to test that configuring options on breakpoint names works correctly."""
        self.build()
        self.make_a_dummy_name()
        self.setup_target()
        self.do_check_configuring_names()

    def test_configuring_permissions_sb(self):
        """Use Python APIs to test that configuring permissions on names works correctly."""
        self.build()
        self.setup_target()
        self.do_check_configuring_permissions_sb()

    def test_configuring_permissions_cli(self):
        """Use Python APIs to test that configuring permissions on names works correctly."""
        self.build()
        self.setup_target()
        self.do_check_configuring_permissions_cli()

    def setup_target(self):
        exe = self.getBuildArtifact("a.out")

        # Create a targets we are making breakpoint in and copying to:
        self.target = self.dbg.CreateTarget(exe)
        self.assertTrue(self.target, VALID_TARGET)
        self.main_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "main.c"))

    def check_name_in_target(self, bkpt_name):
        name_list = lldb.SBStringList()
        self.target.GetBreakpointNames(name_list)
        found_it = False
        for name in name_list:
            if name == bkpt_name:
                found_it = True
                break
        self.assertTrue(found_it, "Didn't find the name %s in the target's name list:"%(bkpt_name))

    def setUp(self):
        # Call super's setUp().
        TestBase.setUp(self)

        # These are the settings we're going to be putting into names & breakpoints:
        self.bp_name_string = "ABreakpoint"
        self.is_one_shot = True
        self.ignore_count = 1000
        self.condition = "1 == 2"
        self.auto_continue = True
        self.tid = 0xaaaa
        self.tidx = 10
        self.thread_name = "Fooey"
        self.queue_name = "Blooey"
        self.cmd_list = lldb.SBStringList()
        self.cmd_list.AppendString("frame var")
        self.cmd_list.AppendString("bt")
        self.help_string = "I do something interesting"


    def do_check_names(self):
        """Use Python APIs to check that we can set & retrieve breakpoint names"""
        bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)
        bkpt_name = "ABreakpoint"
        other_bkpt_name = "_AnotherBreakpoint"

        # Add a name and make sure we match it:
        success = bkpt.AddName(bkpt_name)
        self.assertTrue(success, "We couldn't add a legal name to a breakpoint.")

        matches = bkpt.MatchesName(bkpt_name)
        self.assertTrue(matches, "We didn't match the name we just set")

        # Make sure we don't match irrelevant names:
        matches = bkpt.MatchesName("NotABreakpoint")
        self.assertTrue(not matches, "We matched a name we didn't set.")

        # Make sure the name is also in the target:
        self.check_name_in_target(bkpt_name)

        # Add another name, make sure that works too:
        bkpt.AddName(other_bkpt_name)

        matches = bkpt.MatchesName(bkpt_name)
        self.assertTrue(matches, "Adding a name means we didn't match the name we just set")
        self.check_name_in_target(other_bkpt_name)

        # Remove the name and make sure we no longer match it:
        bkpt.RemoveName(bkpt_name)
        matches = bkpt.MatchesName(bkpt_name)
        self.assertTrue(not matches,"We still match a name after removing it.")

        # Make sure the name list has the remaining name:
        name_list = lldb.SBStringList()
        bkpt.GetNames(name_list)
        num_names = name_list.GetSize()
        self.assertTrue(num_names == 1, "Name list has %d items, expected 1."%(num_names))

        name = name_list.GetStringAtIndex(0)
        self.assertTrue(name == other_bkpt_name, "Remaining name was: %s expected %s."%(name, other_bkpt_name))

    def do_check_illegal_names(self):
        """Use Python APIs to check that we reject illegal names."""
        bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)
        bad_names = ["-CantStartWithADash",
                     "1CantStartWithANumber",
                     "^CantStartWithNonAlpha",
                     "CantHave-ADash",
                     "Cant Have Spaces"]
        for bad_name in bad_names:
            success = bkpt.AddName(bad_name)
            self.assertTrue(not success,"We allowed an illegal name: %s"%(bad_name))
            bp_name = lldb.SBBreakpointName(self.target, bad_name)
            self.assertFalse(bp_name.IsValid(), "We made a breakpoint name with an illegal name: %s"%(bad_name));

            retval =lldb.SBCommandReturnObject()
            self.dbg.GetCommandInterpreter().HandleCommand("break set -n whatever -N '%s'"%(bad_name), retval)
            self.assertTrue(not retval.Succeeded(), "break set succeeded with: illegal name: %s"%(bad_name))

    def do_check_using_names(self):
        """Use Python APIs to check names work in place of breakpoint ID's."""

        bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)
        bkpt_name = "ABreakpoint"
        other_bkpt_name= "_AnotherBreakpoint"

        # Add a name and make sure we match it:
        success = bkpt.AddName(bkpt_name)
        self.assertTrue(success, "We couldn't add a legal name to a breakpoint.")

        bkpts = lldb.SBBreakpointList(self.target)
        self.target.FindBreakpointsByName(bkpt_name, bkpts)

        self.assertTrue(bkpts.GetSize() == 1, "One breakpoint matched.")
        found_bkpt = bkpts.GetBreakpointAtIndex(0)
        self.assertTrue(bkpt.GetID() == found_bkpt.GetID(),"The right breakpoint.")

        retval = lldb.SBCommandReturnObject()
        self.dbg.GetCommandInterpreter().HandleCommand("break disable %s"%(bkpt_name), retval)
        self.assertTrue(retval.Succeeded(), "break disable failed with: %s."%(retval.GetError()))
        self.assertTrue(not bkpt.IsEnabled(), "We didn't disable the breakpoint.")

        # Also make sure we don't apply commands to non-matching names:
        self.dbg.GetCommandInterpreter().HandleCommand("break modify --one-shot 1 %s"%(other_bkpt_name), retval)
        self.assertTrue(retval.Succeeded(), "break modify failed with: %s."%(retval.GetError()))
        self.assertTrue(not bkpt.IsOneShot(), "We applied one-shot to the wrong breakpoint.")

    def check_option_values(self, bp_object):
        self.assertEqual(bp_object.IsOneShot(), self.is_one_shot, "IsOneShot")
        self.assertEqual(bp_object.GetIgnoreCount(), self.ignore_count, "IgnoreCount")
        self.assertEqual(bp_object.GetCondition(), self.condition, "Condition")
        self.assertEqual(bp_object.GetAutoContinue(), self.auto_continue, "AutoContinue")
        self.assertEqual(bp_object.GetThreadID(), self.tid, "Thread ID")
        self.assertEqual(bp_object.GetThreadIndex(), self.tidx, "Thread Index")
        self.assertEqual(bp_object.GetThreadName(), self.thread_name, "Thread Name")
        self.assertEqual(bp_object.GetQueueName(), self.queue_name, "Queue Name")
        set_cmds = lldb.SBStringList()
        bp_object.GetCommandLineCommands(set_cmds)
        self.assertEqual(set_cmds.GetSize(), self.cmd_list.GetSize(), "Size of command line commands")
        for idx in range(0, set_cmds.GetSize()):
            self.assertEqual(self.cmd_list.GetStringAtIndex(idx), set_cmds.GetStringAtIndex(idx), "Command %d"%(idx))

    def make_a_dummy_name(self):
        "This makes a breakpoint name in the dummy target to make sure it gets copied over"

        dummy_target = self.dbg.GetDummyTarget()
        self.assertTrue(dummy_target.IsValid(), "Dummy target was not valid.")

        def cleanup ():
            self.dbg.GetDummyTarget().DeleteBreakpointName(self.bp_name_string)

        # Execute the cleanup function during test case tear down.
        self.addTearDownHook(cleanup)

        # Now find it in the dummy target, and make sure these settings took:
        bp_name = lldb.SBBreakpointName(dummy_target, self.bp_name_string)
        # Make sure the name is right:
        self.assertTrue (bp_name.GetName() == self.bp_name_string, "Wrong bp_name: %s"%(bp_name.GetName()))
        bp_name.SetOneShot(self.is_one_shot)
        bp_name.SetIgnoreCount(self.ignore_count)
        bp_name.SetCondition(self.condition)
        bp_name.SetAutoContinue(self.auto_continue)
        bp_name.SetThreadID(self.tid)
        bp_name.SetThreadIndex(self.tidx)
        bp_name.SetThreadName(self.thread_name)
        bp_name.SetQueueName(self.queue_name)
        bp_name.SetCommandLineCommands(self.cmd_list)

        # Now look it up again, and make sure it got set correctly.
        bp_name = lldb.SBBreakpointName(dummy_target, self.bp_name_string)
        self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name.")
        self.check_option_values(bp_name)

    def do_check_configuring_names(self):
        """Use Python APIs to check that configuring breakpoint names works correctly."""
        other_bp_name_string = "AnotherBreakpointName"
        cl_bp_name_string = "CLBreakpointName"

        # Now find the version copied in from the dummy target, and make sure these settings took:
        bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string)
        self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name.")
        self.check_option_values(bp_name)

        # Now add this name to a breakpoint, and make sure it gets configured properly
        bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)
        success = bkpt.AddName(self.bp_name_string)
        self.assertTrue(success, "Couldn't add this name to the breakpoint")
        self.check_option_values(bkpt)

        # Now make a name from this breakpoint, and make sure the new name is properly configured:
        new_name = lldb.SBBreakpointName(bkpt, other_bp_name_string)
        self.assertTrue(new_name.IsValid(), "Couldn't make a valid bp_name from a breakpoint.")
        self.check_option_values(bkpt)

        # Now change the name's option and make sure it gets propagated to
        # the breakpoint:
        new_auto_continue = not self.auto_continue
        bp_name.SetAutoContinue(new_auto_continue)
        self.assertEqual(bp_name.GetAutoContinue(), new_auto_continue, "Couldn't change auto-continue on the name")
        self.assertEqual(bkpt.GetAutoContinue(), new_auto_continue, "Option didn't propagate to the breakpoint.")

        # Now make this same breakpoint name - but from the command line
        cmd_str = "breakpoint name configure %s -o %d -i %d -c '%s' -G %d -t %d -x %d -T '%s' -q '%s' -H '%s'"%(cl_bp_name_string,
                                                                             self.is_one_shot,
                                                                             self.ignore_count,
                                                                             self.condition,
                                                                             self.auto_continue,
                                                                             self.tid,
                                                                             self.tidx,
                                                                             self.thread_name,
                                                                             self.queue_name,
                                                                             self.help_string)
        for cmd in self.cmd_list:
            cmd_str += " -C '%s'"%(cmd)

        self.runCmd(cmd_str, check=True)
        # Now look up this name again and check its options:
        cl_name = lldb.SBBreakpointName(self.target, cl_bp_name_string)
        self.check_option_values(cl_name)
        # Also check the help string:
        self.assertEqual(self.help_string, cl_name.GetHelpString(), "Help string didn't match")
        # Change the name and make sure that works:
        new_help = "I do something even more interesting"
        cl_name.SetHelpString(new_help)
        self.assertEqual(new_help, cl_name.GetHelpString(), "SetHelpString didn't")

        # We should have three names now, make sure the target can list them:
        name_list = lldb.SBStringList()
        self.target.GetBreakpointNames(name_list)
        for name_string in [self.bp_name_string, other_bp_name_string, cl_bp_name_string]:
            self.assertTrue(name_string in name_list, "Didn't find %s in names"%(name_string))

        # Delete the name from the current target.  Make sure that works and deletes the
        # name from the breakpoint as well:
        self.target.DeleteBreakpointName(self.bp_name_string)
        name_list.Clear()
        self.target.GetBreakpointNames(name_list)
        self.assertTrue(self.bp_name_string not in name_list, "Didn't delete %s from a real target"%(self.bp_name_string))
        # Also make sure the name got removed from breakpoints holding it:
        self.assertFalse(bkpt.MatchesName(self.bp_name_string), "Didn't remove the name from the breakpoint.")

        # Test that deleting the name we injected into the dummy target works (there's also a
        # cleanup that will do this, but that won't test the result...
        dummy_target = self.dbg.GetDummyTarget()
        dummy_target.DeleteBreakpointName(self.bp_name_string)
        name_list.Clear()
        dummy_target.GetBreakpointNames(name_list)
        self.assertTrue(self.bp_name_string not in name_list, "Didn't delete %s from the dummy target"%(self.bp_name_string))
        # Also make sure the name got removed from breakpoints holding it:
        self.assertFalse(bkpt.MatchesName(self.bp_name_string), "Didn't remove the name from the breakpoint.")

    def check_permission_results(self, bp_name):
        self.assertEqual(bp_name.GetAllowDelete(), False, "Didn't set allow delete.")
        protected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)
        protected_id = protected_bkpt.GetID()

        unprotected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)
        unprotected_id = unprotected_bkpt.GetID()

        success = protected_bkpt.AddName(self.bp_name_string)
        self.assertTrue(success, "Couldn't add this name to the breakpoint")

        self.target.DisableAllBreakpoints()
        self.assertEqual(protected_bkpt.IsEnabled(), True, "Didnt' keep breakpoint from being disabled")
        self.assertEqual(unprotected_bkpt.IsEnabled(), False, "Protected too many breakpoints from disabling.")

        # Try from the command line too:
        unprotected_bkpt.SetEnabled(True)
        result = lldb.SBCommandReturnObject()
        self.dbg.GetCommandInterpreter().HandleCommand("break disable", result)
        self.assertTrue(result.Succeeded())
        self.assertEqual(protected_bkpt.IsEnabled(), True, "Didnt' keep breakpoint from being disabled")
        self.assertEqual(unprotected_bkpt.IsEnabled(), False, "Protected too many breakpoints from disabling.")

        self.target.DeleteAllBreakpoints()
        bkpt = self.target.FindBreakpointByID(protected_id)
        self.assertTrue(bkpt.IsValid(), "Didn't keep the breakpoint from being deleted.")
        bkpt = self.target.FindBreakpointByID(unprotected_id)
        self.assertFalse(bkpt.IsValid(), "Protected too many breakpoints from deletion.")

        # Remake the unprotected breakpoint and try again from the command line:
        unprotected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)
        unprotected_id = unprotected_bkpt.GetID()

        self.dbg.GetCommandInterpreter().HandleCommand("break delete -f", result)
        self.assertTrue(result.Succeeded())
        bkpt = self.target.FindBreakpointByID(protected_id)
        self.assertTrue(bkpt.IsValid(), "Didn't keep the breakpoint from being deleted.")
        bkpt = self.target.FindBreakpointByID(unprotected_id)
        self.assertFalse(bkpt.IsValid(), "Protected too many breakpoints from deletion.")

    def do_check_configuring_permissions_sb(self):
        bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string)

        # Make a breakpoint name with delete disallowed:
        bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string)
        self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name for valid name.")

        bp_name.SetAllowDelete(False)
        bp_name.SetAllowDisable(False)
        bp_name.SetAllowList(False)
        self.check_permission_results(bp_name)

    def do_check_configuring_permissions_cli(self):
        # Make the name with the right options using the command line:
        self.runCmd("breakpoint name configure -L 0 -D 0 -A 0 %s"%(self.bp_name_string), check=True)
        # Now look up the breakpoint we made, and check that it works.
        bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string)
        self.assertTrue(bp_name.IsValid(), "Didn't make a breakpoint name we could find.")
        self.check_permission_results(bp_name)