1 """Test queues inspection SB APIs."""
3 from __future__ import print_function
10 from lldbsuite.test.decorators import *
11 from lldbsuite.test.lldbtest import *
12 from lldbsuite.test import lldbutil
15 class TestQueues(TestBase):
17 mydir = TestBase.compute_mydir(__file__)
20 @add_test_categories(['pyapi'])
21 @expectedFailureAll(bugnumber="rdar://28658529")
22 def test_with_python_api(self):
23 """Test queues inspection SB APIs."""
26 self.queues_with_libBacktraceRecording()
29 # Call super's setUp().
31 # Find the line numbers that we will step to in main:
32 self.main_source = "main.c"
34 def check_queue_for_valid_queue_id(self, queue):
36 queue.GetQueueID() != 0, "Check queue %s for valid QueueID (got 0x%x)" %
37 (queue.GetName(), queue.GetQueueID()))
39 def check_running_and_pending_items_on_queue(
40 self, queue, expected_running, expected_pending):
42 queue.GetNumPendingItems() == expected_pending,
43 "queue %s should have %d pending items, instead has %d pending items" %
46 (queue.GetNumPendingItems())))
48 queue.GetNumRunningItems() == expected_running,
49 "queue %s should have %d running items, instead has %d running items" %
52 (queue.GetNumRunningItems())))
54 def check_number_of_threads_owned_by_queue(self, queue, number_threads):
56 queue.GetNumThreads() == number_threads,
57 "queue %s should have %d thread executing, but has %d" %
60 queue.GetNumThreads()))
62 def check_queue_kind(self, queue, kind):
63 expected_kind_string = "Unknown"
64 if kind == lldb.eQueueKindSerial:
65 expected_kind_string = "Serial queue"
66 if kind == lldb.eQueueKindConcurrent:
67 expected_kind_string = "Concurrent queue"
68 actual_kind_string = "Unknown"
69 if queue.GetKind() == lldb.eQueueKindSerial:
70 actual_kind_string = "Serial queue"
71 if queue.GetKind() == lldb.eQueueKindConcurrent:
72 actual_kind_string = "Concurrent queue"
74 queue.GetKind() == kind,
75 "queue %s is expected to be a %s but it is actually a %s" %
80 def check_queues_threads_match_queue(self, queue):
81 for idx in range(0, queue.GetNumThreads()):
82 t = queue.GetThreadAtIndex(idx)
84 t.IsValid(), "Queue %s's thread #%d must be valid" %
85 (queue.GetName(), idx))
87 t.GetQueueID() == queue.GetQueueID(),
88 "Queue %s has a QueueID of %d but its thread #%d has a QueueID of %d" %
94 t.GetQueueName() == queue.GetName(),
95 "Queue %s has a QueueName of %s but its thread #%d has a QueueName of %s" %
101 t.GetQueue().GetQueueID() == queue.GetQueueID(),
102 "Thread #%d's Queue's QueueID of %d is not the same as the QueueID of its owning queue %d" %
104 t.GetQueue().GetQueueID(),
108 """Test queues inspection SB APIs without libBacktraceRecording."""
109 exe = os.path.join(os.getcwd(), "a.out")
111 target = self.dbg.CreateTarget(exe)
112 self.assertTrue(target, VALID_TARGET)
113 self.main_source_spec = lldb.SBFileSpec(self.main_source)
114 break1 = target.BreakpointCreateByName("stopper", 'a.out')
115 self.assertTrue(break1, VALID_BREAKPOINT)
116 process = target.LaunchSimple(
117 None, None, self.get_process_working_directory())
118 self.assertTrue(process, PROCESS_IS_VALID)
119 threads = lldbutil.get_threads_stopped_at_breakpoint(process, break1)
120 if len(threads) != 1:
121 self.fail("Failed to stop at breakpoint 1.")
123 queue_submittor_1 = lldb.SBQueue()
124 queue_performer_1 = lldb.SBQueue()
125 queue_performer_2 = lldb.SBQueue()
126 queue_performer_3 = lldb.SBQueue()
127 for idx in range(0, process.GetNumQueues()):
128 q = process.GetQueueAtIndex(idx)
129 if q.GetName() == "com.apple.work_submittor_1":
130 queue_submittor_1 = q
131 if q.GetName() == "com.apple.work_performer_1":
132 queue_performer_1 = q
133 if q.GetName() == "com.apple.work_performer_2":
134 queue_performer_2 = q
135 if q.GetName() == "com.apple.work_performer_3":
136 queue_performer_3 = q
139 queue_submittor_1.IsValid() and queue_performer_1.IsValid() and queue_performer_2.IsValid() and queue_performer_3.IsValid(),
140 "Got all four expected queues: %s %s %s %s" %
141 (queue_submittor_1.IsValid(),
142 queue_performer_1.IsValid(),
143 queue_performer_2.IsValid(),
144 queue_performer_3.IsValid()))
146 self.check_queue_for_valid_queue_id(queue_submittor_1)
147 self.check_queue_for_valid_queue_id(queue_performer_1)
148 self.check_queue_for_valid_queue_id(queue_performer_2)
149 self.check_queue_for_valid_queue_id(queue_performer_3)
151 self.check_number_of_threads_owned_by_queue(queue_submittor_1, 1)
152 self.check_number_of_threads_owned_by_queue(queue_performer_1, 1)
153 self.check_number_of_threads_owned_by_queue(queue_performer_2, 1)
154 self.check_number_of_threads_owned_by_queue(queue_performer_3, 4)
156 self.check_queue_kind(queue_submittor_1, lldb.eQueueKindSerial)
157 self.check_queue_kind(queue_performer_1, lldb.eQueueKindSerial)
158 self.check_queue_kind(queue_performer_2, lldb.eQueueKindSerial)
159 self.check_queue_kind(queue_performer_3, lldb.eQueueKindConcurrent)
161 self.check_queues_threads_match_queue(queue_submittor_1)
162 self.check_queues_threads_match_queue(queue_performer_1)
163 self.check_queues_threads_match_queue(queue_performer_2)
164 self.check_queues_threads_match_queue(queue_performer_3)
166 # We have threads running with all the different dispatch QoS service
167 # levels - find those threads and check that we can get the correct
168 # QoS name for each of them.
170 user_initiated_thread = lldb.SBThread()
171 user_interactive_thread = lldb.SBThread()
172 utility_thread = lldb.SBThread()
173 unspecified_thread = lldb.SBThread()
174 background_thread = lldb.SBThread()
175 for th in process.threads:
176 if th.GetName() == "user initiated QoS":
177 user_initiated_thread = th
178 if th.GetName() == "user interactive QoS":
179 user_interactive_thread = th
180 if th.GetName() == "utility QoS":
182 if th.GetName() == "unspecified QoS":
183 unspecified_thread = th
184 if th.GetName() == "background QoS":
185 background_thread = th
188 user_initiated_thread.IsValid(),
189 "Found user initiated QoS thread")
191 user_interactive_thread.IsValid(),
192 "Found user interactive QoS thread")
193 self.assertTrue(utility_thread.IsValid(), "Found utility QoS thread")
195 unspecified_thread.IsValid(),
196 "Found unspecified QoS thread")
198 background_thread.IsValid(),
199 "Found background QoS thread")
201 stream = lldb.SBStream()
203 user_initiated_thread.GetInfoItemByPathAsString(
204 "requested_qos.printable_name",
206 "Get QoS printable string for user initiated QoS thread")
208 stream.GetData() == "User Initiated",
209 "user initiated QoS thread name is valid")
212 user_interactive_thread.GetInfoItemByPathAsString(
213 "requested_qos.printable_name",
215 "Get QoS printable string for user interactive QoS thread")
217 stream.GetData() == "User Interactive",
218 "user interactive QoS thread name is valid")
221 utility_thread.GetInfoItemByPathAsString(
222 "requested_qos.printable_name",
224 "Get QoS printable string for utility QoS thread")
226 stream.GetData() == "Utility",
227 "utility QoS thread name is valid")
230 unspecified_thread.GetInfoItemByPathAsString(
231 "requested_qos.printable_name",
233 "Get QoS printable string for unspecified QoS thread")
235 stream.GetData() == "User Initiated",
236 "unspecified QoS thread name is valid")
239 background_thread.GetInfoItemByPathAsString(
240 "requested_qos.printable_name",
242 "Get QoS printable string for background QoS thread")
244 stream.GetData() == "Background",
245 "background QoS thread name is valid")
247 def queues_with_libBacktraceRecording(self):
248 """Test queues inspection SB APIs with libBacktraceRecording present."""
249 exe = os.path.join(os.getcwd(), "a.out")
251 if not os.path.isfile(
252 '/Applications/Xcode.app/Contents/Developer/usr/lib/libBacktraceRecording.dylib'):
254 "Skipped because libBacktraceRecording.dylib was present on the system.")
256 if not os.path.isfile(
257 '/usr/lib/system/introspection/libdispatch.dylib'):
259 "Skipped because introspection libdispatch dylib is not present.")
261 target = self.dbg.CreateTarget(exe)
262 self.assertTrue(target, VALID_TARGET)
264 self.main_source_spec = lldb.SBFileSpec(self.main_source)
266 break1 = target.BreakpointCreateByName("stopper", 'a.out')
267 self.assertTrue(break1, VALID_BREAKPOINT)
269 # Now launch the process, and do not stop at entry point.
270 process = target.LaunchSimple(
273 'DYLD_INSERT_LIBRARIES=/Applications/Xcode.app/Contents/Developer/usr/lib/libBacktraceRecording.dylib',
274 'DYLD_LIBRARY_PATH=/usr/lib/system/introspection'],
275 self.get_process_working_directory())
277 self.assertTrue(process, PROCESS_IS_VALID)
279 # The stop reason of the thread should be breakpoint.
280 threads = lldbutil.get_threads_stopped_at_breakpoint(process, break1)
281 if len(threads) != 1:
282 self.fail("Failed to stop at breakpoint 1.")
284 libbtr_module_filespec = lldb.SBFileSpec("libBacktraceRecording.dylib")
285 libbtr_module = target.FindModule(libbtr_module_filespec)
286 if not libbtr_module.IsValid():
288 "Skipped because libBacktraceRecording.dylib was not loaded into the process.")
291 process.GetNumQueues() >= 4,
292 "Found the correct number of queues.")
294 queue_submittor_1 = lldb.SBQueue()
295 queue_performer_1 = lldb.SBQueue()
296 queue_performer_2 = lldb.SBQueue()
297 queue_performer_3 = lldb.SBQueue()
298 for idx in range(0, process.GetNumQueues()):
299 q = process.GetQueueAtIndex(idx)
300 if q.GetName() == "com.apple.work_submittor_1":
301 queue_submittor_1 = q
302 if q.GetName() == "com.apple.work_performer_1":
303 queue_performer_1 = q
304 if q.GetName() == "com.apple.work_performer_2":
305 queue_performer_2 = q
306 if q.GetName() == "com.apple.work_performer_3":
307 queue_performer_3 = q
310 queue_submittor_1.IsValid() and queue_performer_1.IsValid() and queue_performer_2.IsValid() and queue_performer_3.IsValid(),
311 "Got all four expected queues: %s %s %s %s" %
312 (queue_submittor_1.IsValid(),
313 queue_performer_1.IsValid(),
314 queue_performer_2.IsValid(),
315 queue_performer_3.IsValid()))
317 self.check_queue_for_valid_queue_id(queue_submittor_1)
318 self.check_queue_for_valid_queue_id(queue_performer_1)
319 self.check_queue_for_valid_queue_id(queue_performer_2)
320 self.check_queue_for_valid_queue_id(queue_performer_3)
322 self.check_running_and_pending_items_on_queue(queue_submittor_1, 1, 0)
323 self.check_running_and_pending_items_on_queue(queue_performer_1, 1, 3)
324 self.check_running_and_pending_items_on_queue(
325 queue_performer_2, 1, 9999)
326 self.check_running_and_pending_items_on_queue(queue_performer_3, 4, 0)
328 self.check_number_of_threads_owned_by_queue(queue_submittor_1, 1)
329 self.check_number_of_threads_owned_by_queue(queue_performer_1, 1)
330 self.check_number_of_threads_owned_by_queue(queue_performer_2, 1)
331 self.check_number_of_threads_owned_by_queue(queue_performer_3, 4)
333 self.check_queue_kind(queue_submittor_1, lldb.eQueueKindSerial)
334 self.check_queue_kind(queue_performer_1, lldb.eQueueKindSerial)
335 self.check_queue_kind(queue_performer_2, lldb.eQueueKindSerial)
336 self.check_queue_kind(queue_performer_3, lldb.eQueueKindConcurrent)
338 self.check_queues_threads_match_queue(queue_submittor_1)
339 self.check_queues_threads_match_queue(queue_performer_1)
340 self.check_queues_threads_match_queue(queue_performer_2)
341 self.check_queues_threads_match_queue(queue_performer_3)
343 self.assertTrue(queue_performer_2.GetPendingItemAtIndex(
344 0).IsValid(), "queue 2's pending item #0 is valid")
345 self.assertTrue(queue_performer_2.GetPendingItemAtIndex(0).GetAddress().GetSymbol(
346 ).GetName() == "doing_the_work_2", "queue 2's pending item #0 should be doing_the_work_2")
348 queue_performer_2.GetNumPendingItems() == 9999,
349 "verify that queue 2 still has 9999 pending items")
350 self.assertTrue(queue_performer_2.GetPendingItemAtIndex(
351 9998).IsValid(), "queue 2's pending item #9998 is valid")
352 self.assertTrue(queue_performer_2.GetPendingItemAtIndex(9998).GetAddress().GetSymbol(
353 ).GetName() == "doing_the_work_2", "queue 2's pending item #0 should be doing_the_work_2")
354 self.assertTrue(queue_performer_2.GetPendingItemAtIndex(
355 9999).IsValid() == False, "queue 2's pending item #9999 is invalid")