[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