blob: 30665ad6404c14b8c4c8a2f82d970a12ae538d5a [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 Chen3635eae2010-12-21 19:52:54 +000017 def test_wait_for_event_with_dsym(self):
Johnny Chenf2df1892010-12-22 00:32:54 +000018 """Exercise SBListener.WaitForEvent() API."""
Johnny Chenf667ab52010-12-21 02:06:56 +000019 self.buildDsym()
Johnny Chen3635eae2010-12-21 19:52:54 +000020 self.do_wait_for_event()
Johnny Chenf667ab52010-12-21 02:06:56 +000021
22 @python_api_test
Johnny Chen3635eae2010-12-21 19:52:54 +000023 def test_wait_for_event_with_dwarf(self):
Johnny Chenf2df1892010-12-22 00:32:54 +000024 """Exercise SBListener.WaitForEvent() API."""
Johnny Chenf667ab52010-12-21 02:06:56 +000025 self.buildDwarf()
Johnny Chen3635eae2010-12-21 19:52:54 +000026 self.do_wait_for_event()
Johnny Chenf667ab52010-12-21 02:06:56 +000027
Johnny Chenf2df1892010-12-22 00:32:54 +000028 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
29 @python_api_test
Johnny Chen77c46972010-12-22 00:56:47 +000030 def test_add_listener_to_broadcaster_dsym(self):
31 """Exercise some SBBroadcaster APIs."""
Johnny Chenf2df1892010-12-22 00:32:54 +000032 self.buildDsym()
Johnny Chen77c46972010-12-22 00:56:47 +000033 self.do_add_listener_to_broadcaster()
Johnny Chenf2df1892010-12-22 00:32:54 +000034
35 @python_api_test
Johnny Chen77c46972010-12-22 00:56:47 +000036 def test_add_listener_to_broadcaster_dwarf(self):
37 """Exercise some SBBroadcaster APIs."""
Johnny Chenf2df1892010-12-22 00:32:54 +000038 self.buildDwarf()
Johnny Chen77c46972010-12-22 00:56:47 +000039 self.do_add_listener_to_broadcaster()
Johnny Chenf2df1892010-12-22 00:32:54 +000040
Johnny Chenf667ab52010-12-21 02:06:56 +000041 def setUp(self):
42 # Call super's setUp().
43 TestBase.setUp(self)
44 # Find the line number to of function 'c'.
45 self.line = line_number('main.c', '// Find the line number of function "c" here.')
46
Johnny Chen3635eae2010-12-21 19:52:54 +000047 def do_wait_for_event(self):
48 """Get the listener associated with the debugger and exercise WaitForEvent API."""
Johnny Chenf667ab52010-12-21 02:06:56 +000049 exe = os.path.join(os.getcwd(), "a.out")
50
51 # Create a target by the debugger.
52 target = self.dbg.CreateTarget(exe)
53 self.assertTrue(target.IsValid(), VALID_TARGET)
54
55 # Now create a breakpoint on main.c by name 'c'.
56 breakpoint = target.BreakpointCreateByName('c', 'a.out')
57 #print "breakpoint:", breakpoint
58 self.assertTrue(breakpoint.IsValid() and
59 breakpoint.GetNumLocations() == 1,
60 VALID_BREAKPOINT)
61
62 # Now launch the process, and do not stop at entry point.
63 self.process = target.LaunchProcess([''], [''], os.ctermid(), 0, False)
64
65 self.process = target.GetProcess()
66 self.assertTrue(self.process.IsValid(), PROCESS_IS_VALID)
67
68 # Get a handle on the process's broadcaster.
69 broadcaster = self.process.GetBroadcaster()
70 self.assertTrue(broadcaster.IsValid(), "Process with valid broadcaster")
71
72 # Create an empty event object.
73 event = lldb.SBEvent()
74 self.assertFalse(event.IsValid(), "Event should not be valid initially")
75
Johnny Chen0b0c5782010-12-21 02:10:18 +000076 # Get the debugger listener.
Johnny Chenf667ab52010-12-21 02:06:56 +000077 listener = self.dbg.GetListener()
78
79 # Create MyListeningThread to wait for any kind of event.
80 import threading
81 class MyListeningThread(threading.Thread):
82 def run(self):
Johnny Chenf667ab52010-12-21 02:06:56 +000083 count = 0
84 # Let's only try at most 3 times to retrieve any kind of event.
85 while not count > 3:
86 if listener.WaitForEvent(5, event):
Johnny Chenf2df1892010-12-22 00:32:54 +000087 #print "Got a valid event:", event
Johnny Chenf667ab52010-12-21 02:06:56 +000088 return
89 count = count + 1
90 print "Timeout: listener.WaitForEvent"
91
92 return
93
Johnny Chen4f8caab2010-12-21 05:43:37 +000094 # Use Python API to kill the process. The listening thread should be
95 # able to receive a state changed event.
96 self.process.Kill()
97
Johnny Chenf2df1892010-12-22 00:32:54 +000098 # Let's start the listening thread to retrieve the event.
99 my_thread = MyListeningThread()
100 my_thread.start()
101
Johnny Chen4f8caab2010-12-21 05:43:37 +0000102 # Wait until the 'MyListeningThread' terminates.
Johnny Chenf667ab52010-12-21 02:06:56 +0000103 my_thread.join()
Johnny Chen4f8caab2010-12-21 05:43:37 +0000104
Johnny Chenf2df1892010-12-22 00:32:54 +0000105 self.assertTrue(event.IsValid(),
106 "My listening thread successfully received an event")
Johnny Chen4f8caab2010-12-21 05:43:37 +0000107
Johnny Chen77c46972010-12-22 00:56:47 +0000108 def do_add_listener_to_broadcaster(self):
109 """Get the broadcaster associated with the process and wait for broadcaster events."""
Johnny Chenf2df1892010-12-22 00:32:54 +0000110 exe = os.path.join(os.getcwd(), "a.out")
111
112 # Create a target by the debugger.
113 target = self.dbg.CreateTarget(exe)
114 self.assertTrue(target.IsValid(), VALID_TARGET)
115
116 # Now create a breakpoint on main.c by name 'c'.
117 breakpoint = target.BreakpointCreateByName('c', 'a.out')
118 #print "breakpoint:", breakpoint
119 self.assertTrue(breakpoint.IsValid() and
120 breakpoint.GetNumLocations() == 1,
121 VALID_BREAKPOINT)
122
123 # Now launch the process, and do not stop at the entry point.
124 self.process = target.LaunchProcess([''], [''], os.ctermid(), 0, False)
125
126 self.process = target.GetProcess()
127 self.assertTrue(self.process.GetState() == lldb.eStateStopped,
128 PROCESS_STOPPED)
129
130 # Get a handle on the process's broadcaster.
131 broadcaster = self.process.GetBroadcaster()
132 self.assertTrue(broadcaster.IsValid(), "Process with valid broadcaster")
133
134 # Create an empty event object.
135 event = lldb.SBEvent()
136 self.assertFalse(event.IsValid(), "Event should not be valid initially")
137
138 # Create a listener object and register with the broadcaster.
139 listener = lldb.SBListener("TestEvents.listener")
140 rc = broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
141 self.assertTrue(rc, "AddListener successfully retruns")
142
143 # The finite state machine for our custom listening thread, with an
144 # initail state of 0, which means a "running" event is expected.
145 # It changes to 1 after "running" is received.
146 # It cahnges to 2 after "stopped" is received.
147 # 2 will be our final state and the test is complete.
148 self.state = 0
149
150 # Create MyListeningThread to wait for state changed events.
151 # By design, a "running" event is expected following by a "stopped" event.
152 import threading
153 class MyListeningThread(threading.Thread):
154 def run(self):
155 #print "Running MyListeningThread:", self
156
157 # Regular expression pattern for the event description.
158 pattern = re.compile("data = {.*, state = (.*)}$")
159
160 # Let's only try at most 6 times to retrieve our events.
161 count = 0
162 while True:
Johnny Chen77c46972010-12-22 00:56:47 +0000163 if listener.WaitForEventForBroadcasterWithType(5,
164 broadcaster,
165 lldb.SBProcess.eBroadcastBitStateChanged,
166 event):
Johnny Chenf2df1892010-12-22 00:32:54 +0000167 stream = lldb.SBStream()
168 event.GetDescription(stream)
169 description = stream.GetData()
Johnny Chenf2df1892010-12-22 00:32:54 +0000170 #print "Event description:", description
171 match = pattern.search(description)
172 if not match:
173 break;
174 if self.context.state == 0 and match.group(1) == 'running':
175 self.context.state = 1
176 continue
177 elif self.context.state == 1 and match.group(1) == 'stopped':
178 # Whoopee, both events have been received!
179 self.context.state = 2
180 break
181 else:
182 break
183 print "Timeout: listener.WaitForEvent"
184 count = count + 1
185 if count > 6:
186 break
187
188 return
189
190 # Use Python API to continue the process. The listening thread should be
191 # able to receive the state changed events.
192 self.process.Continue()
193
194 # Start the listening thread to receive the "running" followed by the
195 # "stopped" events.
196 my_thread = MyListeningThread()
197 # Supply the enclosing context so that our listening thread can access
198 # the 'state' variable.
199 my_thread.context = self
200 my_thread.start()
201
202 # Wait until the 'MyListeningThread' terminates.
203 my_thread.join()
204
205 # We are no longer interested in receiving state changed events.
206 # Remove our custom listener before the inferior is killed.
207 broadcaster.RemoveListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
208
209 # The final judgement. :-)
210 self.assertTrue(self.state == 2,
211 "Both expected state changed events received")
Johnny Chenf667ab52010-12-21 02:06:56 +0000212
213
214if __name__ == '__main__':
215 import atexit
216 lldb.SBDebugger.Initialize()
217 atexit.register(lambda: lldb.SBDebugger.Terminate())
218 unittest2.main()