Home | History | Annotate | Download | only in hello_world
      1 """Test Python APIs for target (launch and attach), breakpoint, and process."""
      2 
      3 import os, sys, time
      4 import unittest2
      5 import lldb
      6 import time
      7 from lldbtest import *
      8 
      9 class HelloWorldTestCase(TestBase):
     10 
     11     mydir = os.path.join("python_api", "hello_world")
     12 
     13     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     14     @python_api_test
     15     @dsym_test
     16     def test_with_dsym_and_process_launch_api(self):
     17         """Create target, breakpoint, launch a process, and then kill it.
     18 
     19         Use dsym info and process launch API.
     20         """
     21         self.buildDsym(dictionary=self.d)
     22         self.setTearDownCleanup(dictionary=self.d)
     23         self.hello_world_python()
     24 
     25     @python_api_test
     26     @dwarf_test
     27     def test_with_dwarf_and_process_launch_api(self):
     28         """Create target, breakpoint, launch a process, and then kill it.
     29 
     30         Use dwarf debug map and process launch API.
     31         """
     32         self.buildDwarf(dictionary=self.d)
     33         self.setTearDownCleanup(dictionary=self.d)
     34         self.hello_world_python()
     35 
     36     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     37     @python_api_test
     38     @dsym_test
     39     def test_with_dsym_and_attach_to_process_with_id_api(self):
     40         """Create target, spawn a process, and attach to it with process id.
     41 
     42         Use dsym info and attach to process with id API.
     43         """
     44         self.buildDsym(dictionary=self.d)
     45         self.setTearDownCleanup(dictionary=self.d)
     46         self.hello_world_attach_with_id_api()
     47 
     48     @python_api_test
     49     @dwarf_test
     50     def test_with_dwarf_and_attach_to_process_with_id_api(self):
     51         """Create target, spawn a process, and attach to it with process id.
     52 
     53         Use dwarf map (no dsym) and attach to process with id API.
     54         """
     55         self.buildDwarf(dictionary=self.d)
     56         self.setTearDownCleanup(dictionary=self.d)
     57         self.hello_world_attach_with_id_api()
     58 
     59     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     60     @python_api_test
     61     @dsym_test
     62     def test_with_dsym_and_attach_to_process_with_name_api(self):
     63         """Create target, spawn a process, and attach to it with process name.
     64 
     65         Use dsym info and attach to process with name API.
     66         """
     67         self.buildDsym(dictionary=self.d)
     68         self.setTearDownCleanup(dictionary=self.d)
     69         self.hello_world_attach_with_name_api()
     70 
     71     @expectedFailureFreeBSD('llvm.org/pr16699') # attach by name not on FreeBSD yet
     72     @python_api_test
     73     @dwarf_test
     74     def test_with_dwarf_and_attach_to_process_with_name_api(self):
     75         """Create target, spawn a process, and attach to it with process name.
     76 
     77         Use dwarf map (no dsym) and attach to process with name API.
     78         """
     79         self.buildDwarf(dictionary=self.d)
     80         self.setTearDownCleanup(dictionary=self.d)
     81         self.hello_world_attach_with_name_api()
     82 
     83     def setUp(self):
     84         # Call super's setUp().
     85         TestBase.setUp(self)
     86         # Get the full path to our executable to be attached/debugged.
     87         self.exe = os.path.join(os.getcwd(), self.testMethodName)
     88         self.d = {'EXE': self.testMethodName}
     89         # Find a couple of the line numbers within main.c.
     90         self.line1 = line_number('main.c', '// Set break point at this line.')
     91         self.line2 = line_number('main.c', '// Waiting to be attached...')
     92 
     93     def hello_world_python(self):
     94         """Create target, breakpoint, launch a process, and then kill it."""
     95 
     96         target = self.dbg.CreateTarget(self.exe)
     97 
     98         breakpoint = target.BreakpointCreateByLocation("main.c", self.line1)
     99 
    100         # The default state after breakpoint creation should be enabled.
    101         self.assertTrue(breakpoint.IsEnabled(),
    102                         "Breakpoint should be enabled after creation")
    103 
    104         breakpoint.SetEnabled(False)
    105         self.assertTrue(not breakpoint.IsEnabled(),
    106                         "Breakpoint.SetEnabled(False) works")
    107 
    108         breakpoint.SetEnabled(True)
    109         self.assertTrue(breakpoint.IsEnabled(),
    110                         "Breakpoint.SetEnabled(True) works")
    111 
    112         # rdar://problem/8364687
    113         # SBTarget.Launch() issue (or is there some race condition)?
    114 
    115         process = target.LaunchSimple(None, None, os.getcwd())
    116         # The following isn't needed anymore, rdar://8364687 is fixed.
    117         #
    118         # Apply some dances after LaunchProcess() in order to break at "main".
    119         # It only works sometimes.
    120         #self.breakAfterLaunch(process, "main")
    121 
    122         process = target.GetProcess()
    123         self.assertTrue(process, PROCESS_IS_VALID)
    124 
    125         thread = process.GetThreadAtIndex(0)
    126         if thread.GetStopReason() != lldb.eStopReasonBreakpoint:
    127             from lldbutil import stop_reason_to_str
    128             self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS %
    129                       stop_reason_to_str(thread.GetStopReason()))
    130 
    131         # The breakpoint should have a hit count of 1.
    132         self.assertTrue(breakpoint.GetHitCount() == 1, BREAKPOINT_HIT_ONCE)
    133 
    134     def hello_world_attach_with_id_api(self):
    135         """Create target, spawn a process, and attach to it by id."""
    136 
    137         target = self.dbg.CreateTarget(self.exe)
    138 
    139         # Spawn a new process
    140         popen = self.spawnSubprocess(self.exe, ["abc", "xyz"])
    141         self.addTearDownHook(self.cleanupSubprocesses)
    142 
    143         # Give the subprocess time to start and wait for user input
    144         time.sleep(0.25)
    145 
    146         listener = lldb.SBListener("my.attach.listener")
    147         error = lldb.SBError()
    148         process = target.AttachToProcessWithID(listener, popen.pid, error)
    149 
    150         self.assertTrue(error.Success() and process, PROCESS_IS_VALID)
    151 
    152         # Let's check the stack traces of the attached process.
    153         import lldbutil
    154         stacktraces = lldbutil.print_stacktraces(process, string_buffer=True)
    155         self.expect(stacktraces, exe=False,
    156             substrs = ['main.c:%d' % self.line2,
    157                        '(int)argc=3'])
    158 
    159     def hello_world_attach_with_name_api(self):
    160         """Create target, spawn a process, and attach to it by name."""
    161 
    162         target = self.dbg.CreateTarget(self.exe)
    163 
    164         # Spawn a new process
    165         popen = self.spawnSubprocess(self.exe, ["abc", "xyz"])
    166         self.addTearDownHook(self.cleanupSubprocesses)
    167 
    168         # Give the subprocess time to start and wait for user input
    169         time.sleep(0.25)
    170 
    171         listener = lldb.SBListener("my.attach.listener")
    172         error = lldb.SBError()
    173         # Pass 'False' since we don't want to wait for new instance of "hello_world" to be launched.
    174         name = os.path.basename(self.exe)
    175 
    176         # While we're at it, make sure that passing a None as the process name
    177         # does not hang LLDB.
    178         target.AttachToProcessWithName(listener, None, False, error)
    179         # Also boundary condition test ConnectRemote(), too.
    180         target.ConnectRemote(listener, None, None, error)
    181 
    182         process = target.AttachToProcessWithName(listener, name, False, error)
    183 
    184         self.assertTrue(error.Success() and process, PROCESS_IS_VALID)
    185 
    186         # Verify that after attach, our selected target indeed matches name.
    187         self.expect(self.dbg.GetSelectedTarget().GetExecutable().GetFilename(), exe=False,
    188             startstr = name)
    189 
    190         # Let's check the stack traces of the attached process.
    191         import lldbutil
    192         stacktraces = lldbutil.print_stacktraces(process, string_buffer=True)
    193         self.expect(stacktraces, exe=False,
    194             substrs = ['main.c:%d' % self.line2,
    195                        '(int)argc=3'])
    196 
    197 
    198 if __name__ == '__main__':
    199     import atexit
    200     lldb.SBDebugger.Initialize()
    201     atexit.register(lambda: lldb.SBDebugger.Terminate())
    202     unittest2.main()
    203