blob: 912fc04dacb66df7fb19618b3d9fe55113092dff [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
30 def test_broadcast_event_with_dsym(self):
31 """Exercise SBBroadcaster.BroadcastEvent() API."""
32 self.buildDsym()
33 self.do_broadcast_event()
34
35 @python_api_test
36 def test_broadcast_event_with_dwarf(self):
37 """Exercise SBBroadcaster.BroadcastEvent() API."""
38 self.buildDwarf()
39 self.do_broadcast_event()
40
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 Chenf2df1892010-12-22 00:32:54 +000083 #print "Running MyListeningThread:", self
Johnny Chenf667ab52010-12-21 02:06:56 +000084 count = 0
85 # Let's only try at most 3 times to retrieve any kind of event.
86 while not count > 3:
87 if listener.WaitForEvent(5, event):
Johnny Chenf2df1892010-12-22 00:32:54 +000088 #print "Got a valid event:", event
89 #print "Event type:", event.GetType()
90 #print "Event broadcaster:", event.GetBroadcaster().GetName()
Johnny Chenf667ab52010-12-21 02:06:56 +000091 return
92 count = count + 1
93 print "Timeout: listener.WaitForEvent"
94
95 return
96
Johnny Chen4f8caab2010-12-21 05:43:37 +000097 # Use Python API to kill the process. The listening thread should be
98 # able to receive a state changed event.
99 self.process.Kill()
100
Johnny Chenf2df1892010-12-22 00:32:54 +0000101 # Let's start the listening thread to retrieve the event.
102 my_thread = MyListeningThread()
103 my_thread.start()
104
Johnny Chen4f8caab2010-12-21 05:43:37 +0000105 # Wait until the 'MyListeningThread' terminates.
Johnny Chenf667ab52010-12-21 02:06:56 +0000106 my_thread.join()
Johnny Chen4f8caab2010-12-21 05:43:37 +0000107
Johnny Chenf2df1892010-12-22 00:32:54 +0000108 self.assertTrue(event.IsValid(),
109 "My listening thread successfully received an event")
Johnny Chen4f8caab2010-12-21 05:43:37 +0000110
Johnny Chenf2df1892010-12-22 00:32:54 +0000111 def do_broadcast_event(self):
112 """Get the broadcaster associated with the process and exercise BroadcastEvent API."""
113 exe = os.path.join(os.getcwd(), "a.out")
114
115 # Create a target by the debugger.
116 target = self.dbg.CreateTarget(exe)
117 self.assertTrue(target.IsValid(), VALID_TARGET)
118
119 # Now create a breakpoint on main.c by name 'c'.
120 breakpoint = target.BreakpointCreateByName('c', 'a.out')
121 #print "breakpoint:", breakpoint
122 self.assertTrue(breakpoint.IsValid() and
123 breakpoint.GetNumLocations() == 1,
124 VALID_BREAKPOINT)
125
126 # Now launch the process, and do not stop at the entry point.
127 self.process = target.LaunchProcess([''], [''], os.ctermid(), 0, False)
128
129 self.process = target.GetProcess()
130 self.assertTrue(self.process.GetState() == lldb.eStateStopped,
131 PROCESS_STOPPED)
132
133 # Get a handle on the process's broadcaster.
134 broadcaster = self.process.GetBroadcaster()
135 self.assertTrue(broadcaster.IsValid(), "Process with valid broadcaster")
136
137 # Create an empty event object.
138 event = lldb.SBEvent()
139 self.assertFalse(event.IsValid(), "Event should not be valid initially")
140
141 # Create a listener object and register with the broadcaster.
142 listener = lldb.SBListener("TestEvents.listener")
143 rc = broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
144 self.assertTrue(rc, "AddListener successfully retruns")
145
146 # The finite state machine for our custom listening thread, with an
147 # initail state of 0, which means a "running" event is expected.
148 # It changes to 1 after "running" is received.
149 # It cahnges to 2 after "stopped" is received.
150 # 2 will be our final state and the test is complete.
151 self.state = 0
152
153 # Create MyListeningThread to wait for state changed events.
154 # By design, a "running" event is expected following by a "stopped" event.
155 import threading
156 class MyListeningThread(threading.Thread):
157 def run(self):
158 #print "Running MyListeningThread:", self
159
160 # Regular expression pattern for the event description.
161 pattern = re.compile("data = {.*, state = (.*)}$")
162
163 # Let's only try at most 6 times to retrieve our events.
164 count = 0
165 while True:
166 if listener.WaitForEvent(5, event):
167 stream = lldb.SBStream()
168 event.GetDescription(stream)
169 description = stream.GetData()
170 #print "Event data flavor:", event.GetDataFlavor()
171 #print "Event description:", description
172 match = pattern.search(description)
173 if not match:
174 break;
175 if self.context.state == 0 and match.group(1) == 'running':
176 self.context.state = 1
177 continue
178 elif self.context.state == 1 and match.group(1) == 'stopped':
179 # Whoopee, both events have been received!
180 self.context.state = 2
181 break
182 else:
183 break
184 print "Timeout: listener.WaitForEvent"
185 count = count + 1
186 if count > 6:
187 break
188
189 return
190
191 # Use Python API to continue the process. The listening thread should be
192 # able to receive the state changed events.
193 self.process.Continue()
194
195 # Start the listening thread to receive the "running" followed by the
196 # "stopped" events.
197 my_thread = MyListeningThread()
198 # Supply the enclosing context so that our listening thread can access
199 # the 'state' variable.
200 my_thread.context = self
201 my_thread.start()
202
203 # Wait until the 'MyListeningThread' terminates.
204 my_thread.join()
205
206 # We are no longer interested in receiving state changed events.
207 # Remove our custom listener before the inferior is killed.
208 broadcaster.RemoveListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
209
210 # The final judgement. :-)
211 self.assertTrue(self.state == 2,
212 "Both expected state changed events received")
Johnny Chenf667ab52010-12-21 02:06:56 +0000213
214
215if __name__ == '__main__':
216 import atexit
217 lldb.SBDebugger.Initialize()
218 atexit.register(lambda: lldb.SBDebugger.Terminate())
219 unittest2.main()