blob: bb59b2ff78058facd582364e9c343ab408d87f0d [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.
Greg Clayton6f907e62011-01-23 17:46:22 +000063 error = lldb.SBError()
64 self.process = target.Launch (None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error)
Johnny Chenf667ab52010-12-21 02:06:56 +000065
66 self.process = target.GetProcess()
67 self.assertTrue(self.process.IsValid(), PROCESS_IS_VALID)
68
69 # Get a handle on the process's broadcaster.
70 broadcaster = self.process.GetBroadcaster()
71 self.assertTrue(broadcaster.IsValid(), "Process with valid broadcaster")
72
73 # Create an empty event object.
74 event = lldb.SBEvent()
75 self.assertFalse(event.IsValid(), "Event should not be valid initially")
76
Johnny Chen0b0c5782010-12-21 02:10:18 +000077 # Get the debugger listener.
Johnny Chenf667ab52010-12-21 02:06:56 +000078 listener = self.dbg.GetListener()
79
80 # Create MyListeningThread to wait for any kind of event.
81 import threading
82 class MyListeningThread(threading.Thread):
83 def run(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
Johnny Chenf667ab52010-12-21 02:06:56 +000089 return
90 count = count + 1
91 print "Timeout: listener.WaitForEvent"
92
93 return
94
Johnny Chen4f8caab2010-12-21 05:43:37 +000095 # Use Python API to kill the process. The listening thread should be
96 # able to receive a state changed event.
97 self.process.Kill()
98
Johnny Chenf2df1892010-12-22 00:32:54 +000099 # Let's start the listening thread to retrieve the event.
100 my_thread = MyListeningThread()
101 my_thread.start()
102
Johnny Chen4f8caab2010-12-21 05:43:37 +0000103 # Wait until the 'MyListeningThread' terminates.
Johnny Chenf667ab52010-12-21 02:06:56 +0000104 my_thread.join()
Johnny Chen4f8caab2010-12-21 05:43:37 +0000105
Johnny Chenf2df1892010-12-22 00:32:54 +0000106 self.assertTrue(event.IsValid(),
107 "My listening thread successfully received an event")
Johnny Chen4f8caab2010-12-21 05:43:37 +0000108
Johnny Chen77c46972010-12-22 00:56:47 +0000109 def do_add_listener_to_broadcaster(self):
110 """Get the broadcaster associated with the process and wait for broadcaster events."""
Johnny Chenf2df1892010-12-22 00:32:54 +0000111 exe = os.path.join(os.getcwd(), "a.out")
112
113 # Create a target by the debugger.
114 target = self.dbg.CreateTarget(exe)
115 self.assertTrue(target.IsValid(), VALID_TARGET)
116
117 # Now create a breakpoint on main.c by name 'c'.
118 breakpoint = target.BreakpointCreateByName('c', 'a.out')
119 #print "breakpoint:", breakpoint
120 self.assertTrue(breakpoint.IsValid() and
121 breakpoint.GetNumLocations() == 1,
122 VALID_BREAKPOINT)
123
124 # Now launch the process, and do not stop at the entry point.
Greg Clayton6f907e62011-01-23 17:46:22 +0000125 error = lldb.SBError()
126 self.process = target.Launch (None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error)
Johnny Chenf2df1892010-12-22 00:32:54 +0000127
128 self.process = target.GetProcess()
129 self.assertTrue(self.process.GetState() == lldb.eStateStopped,
130 PROCESS_STOPPED)
131
132 # Get a handle on the process's broadcaster.
133 broadcaster = self.process.GetBroadcaster()
134 self.assertTrue(broadcaster.IsValid(), "Process with valid broadcaster")
135
136 # Create an empty event object.
137 event = lldb.SBEvent()
138 self.assertFalse(event.IsValid(), "Event should not be valid initially")
139
140 # Create a listener object and register with the broadcaster.
141 listener = lldb.SBListener("TestEvents.listener")
142 rc = broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
143 self.assertTrue(rc, "AddListener successfully retruns")
144
145 # The finite state machine for our custom listening thread, with an
146 # initail state of 0, which means a "running" event is expected.
147 # It changes to 1 after "running" is received.
148 # It cahnges to 2 after "stopped" is received.
149 # 2 will be our final state and the test is complete.
150 self.state = 0
151
152 # Create MyListeningThread to wait for state changed events.
153 # By design, a "running" event is expected following by a "stopped" event.
154 import threading
155 class MyListeningThread(threading.Thread):
156 def run(self):
157 #print "Running MyListeningThread:", self
158
159 # Regular expression pattern for the event description.
160 pattern = re.compile("data = {.*, state = (.*)}$")
161
162 # Let's only try at most 6 times to retrieve our events.
163 count = 0
164 while True:
Johnny Chen77c46972010-12-22 00:56:47 +0000165 if listener.WaitForEventForBroadcasterWithType(5,
166 broadcaster,
167 lldb.SBProcess.eBroadcastBitStateChanged,
168 event):
Johnny Chenf2df1892010-12-22 00:32:54 +0000169 stream = lldb.SBStream()
170 event.GetDescription(stream)
171 description = stream.GetData()
Johnny Chenf2df1892010-12-22 00:32:54 +0000172 #print "Event description:", description
173 match = pattern.search(description)
174 if not match:
175 break;
176 if self.context.state == 0 and match.group(1) == 'running':
177 self.context.state = 1
178 continue
179 elif self.context.state == 1 and match.group(1) == 'stopped':
180 # Whoopee, both events have been received!
181 self.context.state = 2
182 break
183 else:
184 break
185 print "Timeout: listener.WaitForEvent"
186 count = count + 1
187 if count > 6:
188 break
189
190 return
191
192 # Use Python API to continue the process. The listening thread should be
193 # able to receive the state changed events.
194 self.process.Continue()
195
196 # Start the listening thread to receive the "running" followed by the
197 # "stopped" events.
198 my_thread = MyListeningThread()
199 # Supply the enclosing context so that our listening thread can access
200 # the 'state' variable.
201 my_thread.context = self
202 my_thread.start()
203
204 # Wait until the 'MyListeningThread' terminates.
205 my_thread.join()
206
207 # We are no longer interested in receiving state changed events.
208 # Remove our custom listener before the inferior is killed.
209 broadcaster.RemoveListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
210
211 # The final judgement. :-)
212 self.assertTrue(self.state == 2,
213 "Both expected state changed events received")
Johnny Chenf667ab52010-12-21 02:06:56 +0000214
215
216if __name__ == '__main__':
217 import atexit
218 lldb.SBDebugger.Initialize()
219 atexit.register(lambda: lldb.SBDebugger.Terminate())
220 unittest2.main()