[Lldb-commits] [lldb] r209314 - Added gdb-remote tests for q{f, s}ThreadInfo.
Todd Fiala
todd.fiala at gmail.com
Wed May 21 11:12:14 PDT 2014
Author: tfiala
Date: Wed May 21 13:12:14 2014
New Revision: 209314
URL: http://llvm.org/viewvc/llvm-project?rev=209314&view=rev
Log:
Added gdb-remote tests for q{f,s}ThreadInfo.
The First test verifies that qThreadInfo queries work for stub-launched processes.
The second test verifies that $qC after stub-launched inferior returns the same
thread as the qThreadInfo queries.
Modified:
lldb/trunk/test/tools/lldb-gdbserver/TestLldbGdbServer.py
lldb/trunk/test/tools/lldb-gdbserver/lldbgdbserverutils.py
Modified: lldb/trunk/test/tools/lldb-gdbserver/TestLldbGdbServer.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-gdbserver/TestLldbGdbServer.py?rev=209314&r1=209313&r2=209314&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-gdbserver/TestLldbGdbServer.py (original)
+++ lldb/trunk/test/tools/lldb-gdbserver/TestLldbGdbServer.py Wed May 21 13:12:14 2014
@@ -177,6 +177,26 @@ class LldbGdbServerTestCase(TestBase):
self.assertTrue("format" in reg_info)
+ def add_threadinfo_collection_packets(self):
+ self.test_sequence.add_log_lines(
+ [ { "type":"multi_response", "first_query":"qfThreadInfo", "next_query":"qsThreadInfo",
+ "append_iteration_suffix":False, "end_regex":re.compile(r"^\$(l)?#[0-9a-fA-F]{2}$"),
+ "save_key":"threadinfo_responses" } ],
+ True)
+
+
+ def parse_threadinfo_packets(self, context):
+ """Return an array of thread ids (decimal ints), one per thread."""
+ threadinfo_responses = context.get("threadinfo_responses")
+ self.assertIsNotNone(threadinfo_responses)
+
+ thread_ids = []
+ for threadinfo_response in threadinfo_responses:
+ new_thread_infos = parse_threadinfo_response(threadinfo_response)
+ thread_ids.extend(new_thread_infos)
+ return thread_ids
+
+
@debugserver_test
def test_exe_starts_debugserver(self):
self.init_debugserver_test()
@@ -657,7 +677,7 @@ class LldbGdbServerTestCase(TestBase):
# Gather register info entries.
reg_infos = self.parse_register_info_packets(context)
- # Collect all generics found.
+ # Collect all generic registers found.
generic_regs = { reg_info['generic']:1 for reg_info in reg_infos if 'generic' in reg_info }
# Ensure we have a program counter register.
@@ -708,7 +728,7 @@ class LldbGdbServerTestCase(TestBase):
# Gather register info entries.
reg_infos = self.parse_register_info_packets(context)
- # Collect all generics found.
+ # Collect all register sets found.
register_sets = { reg_info['set']:1 for reg_info in reg_infos if 'set' in reg_info }
self.assertTrue(len(register_sets) >= 1)
@@ -730,5 +750,99 @@ class LldbGdbServerTestCase(TestBase):
self.qRegisterInfo_contains_at_least_one_register_set()
+ def qThreadInfo_contains_thread_after_launch(self):
+ server = self.start_server()
+ self.assertIsNotNone(server)
+
+ # Build launch args
+ launch_args = [os.path.abspath('a.out')]
+
+ # Build the expected protocol stream
+ self.add_no_ack_remote_stream()
+ self.add_verified_launch_packets(launch_args)
+ self.add_threadinfo_collection_packets()
+
+ # Run the packet stream.
+ context = self.expect_gdbremote_sequence()
+ self.assertIsNotNone(context)
+
+ # Gather threadinfo entries.
+ threads = self.parse_threadinfo_packets(context)
+ self.assertIsNotNone(threads)
+
+ # We should have exactly one thread.
+ self.assertEqual(len(threads), 1)
+
+
+ @debugserver_test
+ @dsym_test
+ def test_qThreadInfo_contains_thread_after_launch_debugserver_dsym(self):
+ self.init_debugserver_test()
+ self.buildDsym()
+ self.qThreadInfo_contains_thread_after_launch()
+
+
+ @llgs_test
+ @dwarf_test
+ @unittest2.expectedFailure()
+ def test_qThreadInfo_contains_thread_after_launch_llgs_dwarf(self):
+ self.init_llgs_test()
+ self.buildDwarf()
+ self.qThreadInfo_contains_thread_after_launch()
+
+
+ def qThreadInfo_matches_qC_after_launch(self):
+ server = self.start_server()
+ self.assertIsNotNone(server)
+
+ # Build launch args
+ launch_args = [os.path.abspath('a.out')]
+
+ # Build the expected protocol stream
+ self.add_no_ack_remote_stream()
+ self.add_verified_launch_packets(launch_args)
+ self.add_threadinfo_collection_packets()
+ self.test_sequence.add_log_lines(
+ ["read packet: $qC#00",
+ { "direction":"send", "regex":r"^\$QC([0-9a-fA-F]+)#", "capture":{1:"thread_id"} }],
+ True)
+
+ # Run the packet stream.
+ context = self.expect_gdbremote_sequence()
+ self.assertIsNotNone(context)
+
+ # Gather threadinfo entries.
+ threads = self.parse_threadinfo_packets(context)
+ self.assertIsNotNone(threads)
+
+ # We should have exactly one thread from threadinfo.
+ self.assertEqual(len(threads), 1)
+
+ # We should have a valid thread_id from $QC.
+ QC_thread_id_hex = context.get("thread_id")
+ self.assertIsNotNone(QC_thread_id_hex)
+ QC_thread_id = int(QC_thread_id_hex, 16)
+
+ # Those two should be the same.
+ self.assertEquals(threads[0], QC_thread_id)
+
+
+ @debugserver_test
+ @dsym_test
+ def test_qThreadInfo_matches_qC_after_launch_debugserver_dsym(self):
+ self.init_debugserver_test()
+ self.buildDsym()
+ self.qThreadInfo_matches_qC_after_launch()
+
+
+ @llgs_test
+ @dwarf_test
+ @unittest2.expectedFailure()
+ def test_qThreadInfo_matches_qC_after_launch_llgs_dwarf(self):
+ self.init_llgs_test()
+ self.buildDwarf()
+ self.qThreadInfo_matches_qC_after_launch()
+
+
if __name__ == '__main__':
unittest2.main()
Modified: lldb/trunk/test/tools/lldb-gdbserver/lldbgdbserverutils.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-gdbserver/lldbgdbserverutils.py?rev=209314&r1=209313&r2=209314&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-gdbserver/lldbgdbserverutils.py (original)
+++ lldb/trunk/test/tools/lldb-gdbserver/lldbgdbserverutils.py Wed May 21 13:12:14 2014
@@ -110,6 +110,7 @@ def _is_packet_lldb_gdbserver_input(pack
_STRIP_CHECKSUM_REGEX = re.compile(r'#[0-9a-fA-F]{2}$')
_STRIP_COMMAND_PREFIX_REGEX = re.compile(r"^\$")
+_STRIP_COMMAND_PREFIX_M_REGEX = re.compile(r"^\$m")
def assert_packets_equal(asserter, actual_packet, expected_packet):
@@ -285,6 +286,19 @@ def parse_reg_info_response(response_pac
return values
+
+def parse_threadinfo_response(response_packet):
+ if not response_packet:
+ raise Exception("response_packet cannot be None")
+
+ # Strip off prefix $ and suffix #xx if present.
+ response_packet = _STRIP_COMMAND_PREFIX_M_REGEX.sub("", response_packet)
+ response_packet = _STRIP_CHECKSUM_REGEX.sub("", response_packet)
+
+ # Return list of thread ids
+ return [int(thread_id_hex,16) for thread_id_hex in response_packet.split(",") if len(thread_id_hex) > 0]
+
+
class GdbRemoteEntry(object):
def __init__(self, is_send_to_remote=True, exact_payload=None, regex=None, capture=None, expect_captures=None):
@@ -438,7 +452,10 @@ class MultiResponseGdbRemoteEntry(object
detection regex and throw an exception.
"""
def __init__(self, params):
- self._next_query = params.get("next_query", params["query"])
+ self._next_query = params.get("next_query", params.get("query"))
+ if not self._next_query:
+ raise "either next_query or query key must be specified for MultiResponseGdbRemoteEntry"
+
self._first_query = params.get("first_query", self._next_query)
self._append_iteration_suffix = params.get("append_iteration_suffix", False)
self._iteration = 0
More information about the lldb-commits
mailing list