1"""Test Python APIs for target (launch and attach), breakpoint, and process."""
2
3import os, sys, time
4import unittest2
5import lldb
6import time
7from lldbtest import *
8
9class 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
198if __name__ == '__main__':
199    import atexit
200    lldb.SBDebugger.Initialize()
201    atexit.register(lambda: lldb.SBDebugger.Terminate())
202    unittest2.main()
203