blob: d33683e9c64b28330fb69024b4a17a1f282a8df5 [file] [log] [blame]
Johnny Chenf667ab52010-12-21 02:06:56 +00001"""
2Test lldb Python event APIs.
3"""
4
5import os, time
6import re
7import unittest2
8import lldb, lldbutil
9from lldbtest import *
10
11class EventAPITestCase(TestBase):
12
Greg Clayton4570d3e2013-12-10 23:19:29 +000013 mydir = TestBase.compute_mydir(__file__)
Johnny Chenf667ab52010-12-21 02:06:56 +000014
Robert Flack13c7ad92015-03-30 14:12:17 +000015 @skipUnlessDarwin
Johnny Chenf667ab52010-12-21 02:06:56 +000016 @python_api_test
Johnny Chen24086bc2012-04-06 19:54:10 +000017 @dsym_test
Johnny Chen3a709ac2011-07-08 23:02:33 +000018 def test_listen_for_and_print_event_with_dsym(self):
19 """Exercise SBEvent API."""
20 self.buildDsym()
21 self.do_listen_for_and_print_event()
22
23 @python_api_test
Johnny Chen24086bc2012-04-06 19:54:10 +000024 @dwarf_test
Johnny Chen3a709ac2011-07-08 23:02:33 +000025 def test_listen_for_and_print_event_with_dwarf(self):
26 """Exercise SBEvent API."""
27 self.buildDwarf()
28 self.do_listen_for_and_print_event()
29
Robert Flack13c7ad92015-03-30 14:12:17 +000030 @skipUnlessDarwin
Johnny Chen3a709ac2011-07-08 23:02:33 +000031 @python_api_test
Johnny Chen24086bc2012-04-06 19:54:10 +000032 @dsym_test
Johnny Chen3635eae2010-12-21 19:52:54 +000033 def test_wait_for_event_with_dsym(self):
Johnny Chenf2df1892010-12-22 00:32:54 +000034 """Exercise SBListener.WaitForEvent() API."""
Johnny Chenf667ab52010-12-21 02:06:56 +000035 self.buildDsym()
Johnny Chen3635eae2010-12-21 19:52:54 +000036 self.do_wait_for_event()
Johnny Chenf667ab52010-12-21 02:06:56 +000037
38 @python_api_test
Johnny Chen24086bc2012-04-06 19:54:10 +000039 @dwarf_test
Johnny Chen3635eae2010-12-21 19:52:54 +000040 def test_wait_for_event_with_dwarf(self):
Johnny Chenf2df1892010-12-22 00:32:54 +000041 """Exercise SBListener.WaitForEvent() API."""
Johnny Chenf667ab52010-12-21 02:06:56 +000042 self.buildDwarf()
Johnny Chen3635eae2010-12-21 19:52:54 +000043 self.do_wait_for_event()
Johnny Chenf667ab52010-12-21 02:06:56 +000044
Robert Flack13c7ad92015-03-30 14:12:17 +000045 @skipUnlessDarwin
Johnny Chenf2df1892010-12-22 00:32:54 +000046 @python_api_test
Johnny Chen24086bc2012-04-06 19:54:10 +000047 @dsym_test
48 def test_add_listener_to_broadcaster_with_dsym(self):
Johnny Chen77c46972010-12-22 00:56:47 +000049 """Exercise some SBBroadcaster APIs."""
Johnny Chenf2df1892010-12-22 00:32:54 +000050 self.buildDsym()
Johnny Chen77c46972010-12-22 00:56:47 +000051 self.do_add_listener_to_broadcaster()
Johnny Chenf2df1892010-12-22 00:32:54 +000052
Ed Maste2ec8e1b2014-10-29 20:02:54 +000053 @skipIfFreeBSD # llvm.org/pr21325
Johnny Chenf2df1892010-12-22 00:32:54 +000054 @python_api_test
Johnny Chen24086bc2012-04-06 19:54:10 +000055 @dwarf_test
Tamas Berghammera98788d2015-05-21 14:04:17 +000056 @expectedFailureLinux("llvm.org/pr23617") # Flaky, fails ~1/10 cases
Johnny Chen24086bc2012-04-06 19:54:10 +000057 def test_add_listener_to_broadcaster_with_dwarf(self):
Johnny Chen77c46972010-12-22 00:56:47 +000058 """Exercise some SBBroadcaster APIs."""
Johnny Chenf2df1892010-12-22 00:32:54 +000059 self.buildDwarf()
Johnny Chen77c46972010-12-22 00:56:47 +000060 self.do_add_listener_to_broadcaster()
Johnny Chenf2df1892010-12-22 00:32:54 +000061
Johnny Chenf667ab52010-12-21 02:06:56 +000062 def setUp(self):
63 # Call super's setUp().
64 TestBase.setUp(self)
65 # Find the line number to of function 'c'.
66 self.line = line_number('main.c', '// Find the line number of function "c" here.')
67
Johnny Chen3a709ac2011-07-08 23:02:33 +000068 def do_listen_for_and_print_event(self):
69 """Create a listener and use SBEvent API to print the events received."""
70 exe = os.path.join(os.getcwd(), "a.out")
71
Greg Claytona6cffde2014-10-17 23:58:27 +000072 self.dbg.SetAsync(True)
73
Johnny Chen3a709ac2011-07-08 23:02:33 +000074 # Create a target by the debugger.
75 target = self.dbg.CreateTarget(exe)
76 self.assertTrue(target, VALID_TARGET)
77
78 # Now create a breakpoint on main.c by name 'c'.
79 breakpoint = target.BreakpointCreateByName('c', 'a.out')
80
Greg Claytona6cffde2014-10-17 23:58:27 +000081 listener = lldb.SBListener("my listener")
Johnny Chen3a709ac2011-07-08 23:02:33 +000082
Greg Claytona6cffde2014-10-17 23:58:27 +000083 # Now launch the process, and do not stop at the entry point.
84 error = lldb.SBError()
85 process = target.Launch (listener,
86 None, # argv
87 None, # envp
88 None, # stdin_path
89 None, # stdout_path
90 None, # stderr_path
91 None, # working directory
92 0, # launch flags
93 False, # Stop at entry
94 error) # error
95
96 self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED)
Johnny Chen3a709ac2011-07-08 23:02:33 +000097
98 # Create an empty event object.
99 event = lldb.SBEvent()
100
Johnny Chen3a709ac2011-07-08 23:02:33 +0000101 traceOn = self.TraceOn()
102 if traceOn:
103 lldbutil.print_stacktraces(process)
104
105 # Create MyListeningThread class to wait for any kind of event.
106 import threading
107 class MyListeningThread(threading.Thread):
108 def run(self):
109 count = 0
110 # Let's only try at most 4 times to retrieve any kind of event.
111 # After that, the thread exits.
112 while not count > 3:
113 if traceOn:
114 print "Try wait for event..."
Greg Claytona6cffde2014-10-17 23:58:27 +0000115 if listener.WaitForEvent(5, event):
Johnny Chen3a709ac2011-07-08 23:02:33 +0000116 if traceOn:
117 desc = lldbutil.get_description(event)
118 print "Event description:", desc
119 print "Event data flavor:", event.GetDataFlavor()
120 print "Process state:", lldbutil.state_type_to_str(process.GetState())
121 print
122 else:
123 if traceOn:
124 print "timeout occurred waiting for event..."
125 count = count + 1
126 return
127
128 # Let's start the listening thread to retrieve the events.
129 my_thread = MyListeningThread()
130 my_thread.start()
131
132 # Use Python API to continue the process. The listening thread should be
133 # able to receive the state changed events.
134 process.Continue()
135
136 # Use Python API to kill the process. The listening thread should be
137 # able to receive the state changed event, too.
138 process.Kill()
139
140 # Wait until the 'MyListeningThread' terminates.
141 my_thread.join()
142
Johnny Chen3635eae2010-12-21 19:52:54 +0000143 def do_wait_for_event(self):
144 """Get the listener associated with the debugger and exercise WaitForEvent API."""
Johnny Chenf667ab52010-12-21 02:06:56 +0000145 exe = os.path.join(os.getcwd(), "a.out")
146
Greg Claytona6cffde2014-10-17 23:58:27 +0000147 self.dbg.SetAsync(True)
148
Johnny Chenf667ab52010-12-21 02:06:56 +0000149 # Create a target by the debugger.
150 target = self.dbg.CreateTarget(exe)
Johnny Chen4ebd0192011-05-24 18:22:45 +0000151 self.assertTrue(target, VALID_TARGET)
Johnny Chenf667ab52010-12-21 02:06:56 +0000152
153 # Now create a breakpoint on main.c by name 'c'.
154 breakpoint = target.BreakpointCreateByName('c', 'a.out')
155 #print "breakpoint:", breakpoint
Johnny Chen4ebd0192011-05-24 18:22:45 +0000156 self.assertTrue(breakpoint and
Johnny Chenf667ab52010-12-21 02:06:56 +0000157 breakpoint.GetNumLocations() == 1,
158 VALID_BREAKPOINT)
159
Johnny Chend762ff12011-02-03 23:15:53 +0000160 # Get the debugger listener.
161 listener = self.dbg.GetListener()
162
Johnny Chenf667ab52010-12-21 02:06:56 +0000163 # Now launch the process, and do not stop at entry point.
Greg Clayton6f907e62011-01-23 17:46:22 +0000164 error = lldb.SBError()
Greg Claytona6cffde2014-10-17 23:58:27 +0000165 process = target.Launch (listener,
166 None, # argv
167 None, # envp
168 None, # stdin_path
169 None, # stdout_path
170 None, # stderr_path
171 None, # working directory
172 0, # launch flags
173 False, # Stop at entry
174 error) # error
Johnny Chen2494f552011-07-20 00:14:20 +0000175 self.assertTrue(error.Success() and process, PROCESS_IS_VALID)
Johnny Chenf667ab52010-12-21 02:06:56 +0000176
Johnny Chenf667ab52010-12-21 02:06:56 +0000177 # Create an empty event object.
178 event = lldb.SBEvent()
Johnny Chen4ebd0192011-05-24 18:22:45 +0000179 self.assertFalse(event, "Event should not be valid initially")
Johnny Chenf667ab52010-12-21 02:06:56 +0000180
Johnny Chenf667ab52010-12-21 02:06:56 +0000181 # Create MyListeningThread to wait for any kind of event.
182 import threading
183 class MyListeningThread(threading.Thread):
184 def run(self):
Johnny Chenf667ab52010-12-21 02:06:56 +0000185 count = 0
186 # Let's only try at most 3 times to retrieve any kind of event.
187 while not count > 3:
188 if listener.WaitForEvent(5, event):
Johnny Chenf2df1892010-12-22 00:32:54 +0000189 #print "Got a valid event:", event
Johnny Chen3a709ac2011-07-08 23:02:33 +0000190 #print "Event data flavor:", event.GetDataFlavor()
191 #print "Event type:", lldbutil.state_type_to_str(event.GetType())
Johnny Chenf667ab52010-12-21 02:06:56 +0000192 return
193 count = count + 1
194 print "Timeout: listener.WaitForEvent"
195
196 return
197
Johnny Chen4f8caab2010-12-21 05:43:37 +0000198 # Use Python API to kill the process. The listening thread should be
199 # able to receive a state changed event.
Johnny Chen5a0bee72011-06-15 22:14:12 +0000200 process.Kill()
Johnny Chen4f8caab2010-12-21 05:43:37 +0000201
Johnny Chenf2df1892010-12-22 00:32:54 +0000202 # Let's start the listening thread to retrieve the event.
203 my_thread = MyListeningThread()
204 my_thread.start()
205
Johnny Chen4f8caab2010-12-21 05:43:37 +0000206 # Wait until the 'MyListeningThread' terminates.
Johnny Chenf667ab52010-12-21 02:06:56 +0000207 my_thread.join()
Johnny Chen4f8caab2010-12-21 05:43:37 +0000208
Johnny Chen4ebd0192011-05-24 18:22:45 +0000209 self.assertTrue(event,
Johnny Chenf2df1892010-12-22 00:32:54 +0000210 "My listening thread successfully received an event")
Johnny Chen4f8caab2010-12-21 05:43:37 +0000211
Johnny Chen77c46972010-12-22 00:56:47 +0000212 def do_add_listener_to_broadcaster(self):
213 """Get the broadcaster associated with the process and wait for broadcaster events."""
Johnny Chenf2df1892010-12-22 00:32:54 +0000214 exe = os.path.join(os.getcwd(), "a.out")
215
Greg Claytona6cffde2014-10-17 23:58:27 +0000216 self.dbg.SetAsync(True)
217
Johnny Chenf2df1892010-12-22 00:32:54 +0000218 # Create a target by the debugger.
219 target = self.dbg.CreateTarget(exe)
Johnny Chen4ebd0192011-05-24 18:22:45 +0000220 self.assertTrue(target, VALID_TARGET)
Johnny Chenf2df1892010-12-22 00:32:54 +0000221
222 # Now create a breakpoint on main.c by name 'c'.
223 breakpoint = target.BreakpointCreateByName('c', 'a.out')
224 #print "breakpoint:", breakpoint
Johnny Chen4ebd0192011-05-24 18:22:45 +0000225 self.assertTrue(breakpoint and
Johnny Chenf2df1892010-12-22 00:32:54 +0000226 breakpoint.GetNumLocations() == 1,
227 VALID_BREAKPOINT)
228
Greg Claytona6cffde2014-10-17 23:58:27 +0000229 listener = lldb.SBListener("my listener")
Johnny Chenf2df1892010-12-22 00:32:54 +0000230
Greg Claytona6cffde2014-10-17 23:58:27 +0000231 # Now launch the process, and do not stop at the entry point.
232 error = lldb.SBError()
233 process = target.Launch (listener,
234 None, # argv
235 None, # envp
236 None, # stdin_path
237 None, # stdout_path
238 None, # stderr_path
239 None, # working directory
240 0, # launch flags
241 False, # Stop at entry
242 error) # error
Johnny Chenf2df1892010-12-22 00:32:54 +0000243
244 # Create an empty event object.
245 event = lldb.SBEvent()
Johnny Chen4ebd0192011-05-24 18:22:45 +0000246 self.assertFalse(event, "Event should not be valid initially")
Johnny Chenf2df1892010-12-22 00:32:54 +0000247
Johnny Chenf2df1892010-12-22 00:32:54 +0000248
249 # The finite state machine for our custom listening thread, with an
Siva Chandra8a1f7692015-05-08 00:43:28 +0000250 # initail state of None, which means no event has been received.
251 # It changes to 'connected' after 'connected' event is received (for remote platforms)
252 # It changes to 'running' after 'running' event is received (should happen only if the
253 # currentstate is either 'None' or 'connected')
254 # It changes to 'stopped' if a 'stopped' event is received (should happen only if the
255 # current state is 'running'.)
256 self.state = None
Johnny Chenf2df1892010-12-22 00:32:54 +0000257
258 # Create MyListeningThread to wait for state changed events.
259 # By design, a "running" event is expected following by a "stopped" event.
260 import threading
261 class MyListeningThread(threading.Thread):
262 def run(self):
263 #print "Running MyListeningThread:", self
264
265 # Regular expression pattern for the event description.
266 pattern = re.compile("data = {.*, state = (.*)}$")
267
268 # Let's only try at most 6 times to retrieve our events.
269 count = 0
270 while True:
Greg Claytona6cffde2014-10-17 23:58:27 +0000271 if listener.WaitForEvent(5, event):
Johnny Chen9ae98202011-04-23 00:34:56 +0000272 desc = lldbutil.get_description(event)
273 #print "Event description:", desc
274 match = pattern.search(desc)
Johnny Chenf2df1892010-12-22 00:32:54 +0000275 if not match:
276 break;
Siva Chandra8a1f7692015-05-08 00:43:28 +0000277 if match.group(1) == 'connected':
278 # When debugging remote targets with lldb-server, we
279 # first get the 'connected' event.
280 self.context.assertTrue(self.context.state == None)
281 self.context.state = 'connected'
Johnny Chenf2df1892010-12-22 00:32:54 +0000282 continue
Siva Chandra8a1f7692015-05-08 00:43:28 +0000283 elif match.group(1) == 'running':
284 self.context.assertTrue(self.context.state == None or self.context.state == 'connected')
285 self.context.state = 'running'
286 continue
287 elif match.group(1) == 'stopped':
288 self.context.assertTrue(self.context.state == 'running')
Johnny Chenf2df1892010-12-22 00:32:54 +0000289 # Whoopee, both events have been received!
Siva Chandra8a1f7692015-05-08 00:43:28 +0000290 self.context.state = 'stopped'
Johnny Chenf2df1892010-12-22 00:32:54 +0000291 break
292 else:
293 break
294 print "Timeout: listener.WaitForEvent"
295 count = count + 1
296 if count > 6:
297 break
298
299 return
300
301 # Use Python API to continue the process. The listening thread should be
302 # able to receive the state changed events.
Johnny Chen5a0bee72011-06-15 22:14:12 +0000303 process.Continue()
Johnny Chenf2df1892010-12-22 00:32:54 +0000304
305 # Start the listening thread to receive the "running" followed by the
306 # "stopped" events.
307 my_thread = MyListeningThread()
308 # Supply the enclosing context so that our listening thread can access
309 # the 'state' variable.
310 my_thread.context = self
311 my_thread.start()
312
313 # Wait until the 'MyListeningThread' terminates.
314 my_thread.join()
315
Johnny Chenf2df1892010-12-22 00:32:54 +0000316 # The final judgement. :-)
Siva Chandra8a1f7692015-05-08 00:43:28 +0000317 self.assertTrue(self.state == 'stopped',
Johnny Chenf2df1892010-12-22 00:32:54 +0000318 "Both expected state changed events received")
Johnny Chenf667ab52010-12-21 02:06:56 +0000319
320
321if __name__ == '__main__':
322 import atexit
323 lldb.SBDebugger.Initialize()
324 atexit.register(lambda: lldb.SBDebugger.Terminate())
325 unittest2.main()