blob: a9a7edcbbfa394235ed2d4c9937ac02004923798 [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
13 mydir = os.path.join("python_api", "event")
14
15 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
16 @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
30 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
31 @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
Johnny Chenf2df1892010-12-22 00:32:54 +000045 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
46 @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
53 @python_api_test
Johnny Chen24086bc2012-04-06 19:54:10 +000054 @dwarf_test
55 def test_add_listener_to_broadcaster_with_dwarf(self):
Johnny Chen77c46972010-12-22 00:56:47 +000056 """Exercise some SBBroadcaster APIs."""
Johnny Chenf2df1892010-12-22 00:32:54 +000057 self.buildDwarf()
Johnny Chen77c46972010-12-22 00:56:47 +000058 self.do_add_listener_to_broadcaster()
Johnny Chenf2df1892010-12-22 00:32:54 +000059
Johnny Chenf667ab52010-12-21 02:06:56 +000060 def setUp(self):
61 # Call super's setUp().
62 TestBase.setUp(self)
63 # Find the line number to of function 'c'.
64 self.line = line_number('main.c', '// Find the line number of function "c" here.')
65
Johnny Chen3a709ac2011-07-08 23:02:33 +000066 def do_listen_for_and_print_event(self):
67 """Create a listener and use SBEvent API to print the events received."""
68 exe = os.path.join(os.getcwd(), "a.out")
69
70 # Create a target by the debugger.
71 target = self.dbg.CreateTarget(exe)
72 self.assertTrue(target, VALID_TARGET)
73
74 # Now create a breakpoint on main.c by name 'c'.
75 breakpoint = target.BreakpointCreateByName('c', 'a.out')
76
77 # Now launch the process, and do not stop at the entry point.
78 process = target.LaunchSimple(None, None, os.getcwd())
79 self.assertTrue(process.GetState() == lldb.eStateStopped,
80 PROCESS_STOPPED)
81
82 # Get a handle on the process's broadcaster.
83 broadcaster = process.GetBroadcaster()
84
85 # Create an empty event object.
86 event = lldb.SBEvent()
87
88 # Create a listener object and register with the broadcaster.
89 listener = lldb.SBListener("my listener")
90 rc = broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
91 self.assertTrue(rc, "AddListener successfully retruns")
92
93 traceOn = self.TraceOn()
94 if traceOn:
95 lldbutil.print_stacktraces(process)
96
97 # Create MyListeningThread class to wait for any kind of event.
98 import threading
99 class MyListeningThread(threading.Thread):
100 def run(self):
101 count = 0
102 # Let's only try at most 4 times to retrieve any kind of event.
103 # After that, the thread exits.
104 while not count > 3:
105 if traceOn:
106 print "Try wait for event..."
107 if listener.WaitForEventForBroadcasterWithType(5,
108 broadcaster,
109 lldb.SBProcess.eBroadcastBitStateChanged,
110 event):
111 if traceOn:
112 desc = lldbutil.get_description(event)
113 print "Event description:", desc
114 print "Event data flavor:", event.GetDataFlavor()
115 print "Process state:", lldbutil.state_type_to_str(process.GetState())
116 print
117 else:
118 if traceOn:
119 print "timeout occurred waiting for event..."
120 count = count + 1
121 return
122
123 # Let's start the listening thread to retrieve the events.
124 my_thread = MyListeningThread()
125 my_thread.start()
126
127 # Use Python API to continue the process. The listening thread should be
128 # able to receive the state changed events.
129 process.Continue()
130
131 # Use Python API to kill the process. The listening thread should be
132 # able to receive the state changed event, too.
133 process.Kill()
134
135 # Wait until the 'MyListeningThread' terminates.
136 my_thread.join()
137
Johnny Chen3635eae2010-12-21 19:52:54 +0000138 def do_wait_for_event(self):
139 """Get the listener associated with the debugger and exercise WaitForEvent API."""
Johnny Chenf667ab52010-12-21 02:06:56 +0000140 exe = os.path.join(os.getcwd(), "a.out")
141
142 # Create a target by the debugger.
143 target = self.dbg.CreateTarget(exe)
Johnny Chen4ebd0192011-05-24 18:22:45 +0000144 self.assertTrue(target, VALID_TARGET)
Johnny Chenf667ab52010-12-21 02:06:56 +0000145
146 # Now create a breakpoint on main.c by name 'c'.
147 breakpoint = target.BreakpointCreateByName('c', 'a.out')
148 #print "breakpoint:", breakpoint
Johnny Chen4ebd0192011-05-24 18:22:45 +0000149 self.assertTrue(breakpoint and
Johnny Chenf667ab52010-12-21 02:06:56 +0000150 breakpoint.GetNumLocations() == 1,
151 VALID_BREAKPOINT)
152
Johnny Chend762ff12011-02-03 23:15:53 +0000153 # Get the debugger listener.
154 listener = self.dbg.GetListener()
155
Johnny Chenf667ab52010-12-21 02:06:56 +0000156 # Now launch the process, and do not stop at entry point.
Greg Clayton6f907e62011-01-23 17:46:22 +0000157 error = lldb.SBError()
Johnny Chen1d3e8802011-07-11 23:38:23 +0000158 process = target.Launch (listener, None, None, None, None, None, None, 0, False, error)
Johnny Chen2494f552011-07-20 00:14:20 +0000159 self.assertTrue(error.Success() and process, PROCESS_IS_VALID)
Johnny Chenf667ab52010-12-21 02:06:56 +0000160
161 # Get a handle on the process's broadcaster.
Johnny Chen5a0bee72011-06-15 22:14:12 +0000162 broadcaster = process.GetBroadcaster()
Johnny Chen4ebd0192011-05-24 18:22:45 +0000163 self.assertTrue(broadcaster, "Process with valid broadcaster")
Johnny Chenf667ab52010-12-21 02:06:56 +0000164
165 # Create an empty event object.
166 event = lldb.SBEvent()
Johnny Chen4ebd0192011-05-24 18:22:45 +0000167 self.assertFalse(event, "Event should not be valid initially")
Johnny Chenf667ab52010-12-21 02:06:56 +0000168
Johnny Chenf667ab52010-12-21 02:06:56 +0000169 # Create MyListeningThread to wait for any kind of event.
170 import threading
171 class MyListeningThread(threading.Thread):
172 def run(self):
Johnny Chenf667ab52010-12-21 02:06:56 +0000173 count = 0
174 # Let's only try at most 3 times to retrieve any kind of event.
175 while not count > 3:
176 if listener.WaitForEvent(5, event):
Johnny Chenf2df1892010-12-22 00:32:54 +0000177 #print "Got a valid event:", event
Johnny Chen3a709ac2011-07-08 23:02:33 +0000178 #print "Event data flavor:", event.GetDataFlavor()
179 #print "Event type:", lldbutil.state_type_to_str(event.GetType())
Johnny Chenf667ab52010-12-21 02:06:56 +0000180 return
181 count = count + 1
182 print "Timeout: listener.WaitForEvent"
183
184 return
185
Johnny Chen4f8caab2010-12-21 05:43:37 +0000186 # Use Python API to kill the process. The listening thread should be
187 # able to receive a state changed event.
Johnny Chen5a0bee72011-06-15 22:14:12 +0000188 process.Kill()
Johnny Chen4f8caab2010-12-21 05:43:37 +0000189
Johnny Chenf2df1892010-12-22 00:32:54 +0000190 # Let's start the listening thread to retrieve the event.
191 my_thread = MyListeningThread()
192 my_thread.start()
193
Johnny Chen4f8caab2010-12-21 05:43:37 +0000194 # Wait until the 'MyListeningThread' terminates.
Johnny Chenf667ab52010-12-21 02:06:56 +0000195 my_thread.join()
Johnny Chen4f8caab2010-12-21 05:43:37 +0000196
Johnny Chen4ebd0192011-05-24 18:22:45 +0000197 self.assertTrue(event,
Johnny Chenf2df1892010-12-22 00:32:54 +0000198 "My listening thread successfully received an event")
Johnny Chen4f8caab2010-12-21 05:43:37 +0000199
Johnny Chen77c46972010-12-22 00:56:47 +0000200 def do_add_listener_to_broadcaster(self):
201 """Get the broadcaster associated with the process and wait for broadcaster events."""
Johnny Chenf2df1892010-12-22 00:32:54 +0000202 exe = os.path.join(os.getcwd(), "a.out")
203
204 # Create a target by the debugger.
205 target = self.dbg.CreateTarget(exe)
Johnny Chen4ebd0192011-05-24 18:22:45 +0000206 self.assertTrue(target, VALID_TARGET)
Johnny Chenf2df1892010-12-22 00:32:54 +0000207
208 # Now create a breakpoint on main.c by name 'c'.
209 breakpoint = target.BreakpointCreateByName('c', 'a.out')
210 #print "breakpoint:", breakpoint
Johnny Chen4ebd0192011-05-24 18:22:45 +0000211 self.assertTrue(breakpoint and
Johnny Chenf2df1892010-12-22 00:32:54 +0000212 breakpoint.GetNumLocations() == 1,
213 VALID_BREAKPOINT)
214
215 # Now launch the process, and do not stop at the entry point.
Johnny Chen5a0bee72011-06-15 22:14:12 +0000216 process = target.LaunchSimple(None, None, os.getcwd())
217 self.assertTrue(process.GetState() == lldb.eStateStopped,
Johnny Chenf2df1892010-12-22 00:32:54 +0000218 PROCESS_STOPPED)
219
220 # Get a handle on the process's broadcaster.
Johnny Chen5a0bee72011-06-15 22:14:12 +0000221 broadcaster = process.GetBroadcaster()
Johnny Chen4ebd0192011-05-24 18:22:45 +0000222 self.assertTrue(broadcaster, "Process with valid broadcaster")
Johnny Chenf2df1892010-12-22 00:32:54 +0000223
224 # Create an empty event object.
225 event = lldb.SBEvent()
Johnny Chen4ebd0192011-05-24 18:22:45 +0000226 self.assertFalse(event, "Event should not be valid initially")
Johnny Chenf2df1892010-12-22 00:32:54 +0000227
228 # Create a listener object and register with the broadcaster.
229 listener = lldb.SBListener("TestEvents.listener")
230 rc = broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
231 self.assertTrue(rc, "AddListener successfully retruns")
232
233 # The finite state machine for our custom listening thread, with an
234 # initail state of 0, which means a "running" event is expected.
235 # It changes to 1 after "running" is received.
236 # It cahnges to 2 after "stopped" is received.
237 # 2 will be our final state and the test is complete.
238 self.state = 0
239
240 # Create MyListeningThread to wait for state changed events.
241 # By design, a "running" event is expected following by a "stopped" event.
242 import threading
243 class MyListeningThread(threading.Thread):
244 def run(self):
245 #print "Running MyListeningThread:", self
246
247 # Regular expression pattern for the event description.
248 pattern = re.compile("data = {.*, state = (.*)}$")
249
250 # Let's only try at most 6 times to retrieve our events.
251 count = 0
252 while True:
Johnny Chen77c46972010-12-22 00:56:47 +0000253 if listener.WaitForEventForBroadcasterWithType(5,
254 broadcaster,
255 lldb.SBProcess.eBroadcastBitStateChanged,
256 event):
Johnny Chen9ae98202011-04-23 00:34:56 +0000257 desc = lldbutil.get_description(event)
258 #print "Event description:", desc
259 match = pattern.search(desc)
Johnny Chenf2df1892010-12-22 00:32:54 +0000260 if not match:
261 break;
262 if self.context.state == 0 and match.group(1) == 'running':
263 self.context.state = 1
264 continue
265 elif self.context.state == 1 and match.group(1) == 'stopped':
266 # Whoopee, both events have been received!
267 self.context.state = 2
268 break
269 else:
270 break
271 print "Timeout: listener.WaitForEvent"
272 count = count + 1
273 if count > 6:
274 break
275
276 return
277
278 # Use Python API to continue the process. The listening thread should be
279 # able to receive the state changed events.
Johnny Chen5a0bee72011-06-15 22:14:12 +0000280 process.Continue()
Johnny Chenf2df1892010-12-22 00:32:54 +0000281
282 # Start the listening thread to receive the "running" followed by the
283 # "stopped" events.
284 my_thread = MyListeningThread()
285 # Supply the enclosing context so that our listening thread can access
286 # the 'state' variable.
287 my_thread.context = self
288 my_thread.start()
289
290 # Wait until the 'MyListeningThread' terminates.
291 my_thread.join()
292
293 # We are no longer interested in receiving state changed events.
294 # Remove our custom listener before the inferior is killed.
295 broadcaster.RemoveListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
296
297 # The final judgement. :-)
298 self.assertTrue(self.state == 2,
299 "Both expected state changed events received")
Johnny Chenf667ab52010-12-21 02:06:56 +0000300
301
302if __name__ == '__main__':
303 import atexit
304 lldb.SBDebugger.Initialize()
305 atexit.register(lambda: lldb.SBDebugger.Terminate())
306 unittest2.main()