[Lldb-commits] [lldb] r207998 - Refactored gdb remote protocol testing sequence handling.

Todd Fiala todd.fiala at gmail.com
Mon May 5 13:54:01 PDT 2014


Author: tfiala
Date: Mon May  5 15:54:01 2014
New Revision: 207998

URL: http://llvm.org/viewvc/llvm-project?rev=207998&view=rev
Log:
Refactored gdb remote protocol testing sequence handling.

Pushed gdbremote protocol sequence expectations into a separate
class and defer matching of llgs/debugserver output to the
sequence entry.  Pre-step to adding regex matching and
grouped content collecting.

No longer require anything before the read/send packet
portion of slurped-up log lines used for setting up
gdb remote test sequences.  Several packet logging options
produce a wide range of content before the read/send packet.

Added helpers to TestLldbGdbServer to clean up test setup
and test expectations matching.

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=207998&r1=207997&r2=207998&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-gdbserver/TestLldbGdbServer.py (original)
+++ lldb/trunk/test/tools/lldb-gdbserver/TestLldbGdbServer.py Mon May  5 15:54:01 2014
@@ -21,16 +21,16 @@ class LldbGdbServerTestCase(TestBase):
 
     _GDBREMOTE_KILL_PACKET = "$k#6b"
 
-    # _LOGGING_LEVEL = logging.WARNING
-    _LOGGING_LEVEL = logging.DEBUG
+    _LOGGING_LEVEL = logging.WARNING
+    # _LOGGING_LEVEL = logging.DEBUG
 
     def setUp(self):
         TestBase.setUp(self)
-
         FORMAT = '%(asctime)-15s %(levelname)-8s %(message)s'
         logging.basicConfig(format=FORMAT)
         self.logger = logging.getLogger(__name__)
         self.logger.setLevel(self._LOGGING_LEVEL)
+        self.test_sequence = GdbRemoteTestSequence(self.logger)
 
     def init_llgs_test(self):
         self.debug_monitor_exe = get_lldb_gdbserver_exe()
@@ -90,13 +90,17 @@ class LldbGdbServerTestCase(TestBase):
 
         return server
 
-    def create_no_ack_remote_stream(self):
-       return [
-            "lldb-gdbserver <  19> read packet: +",
-            "lldb-gdbserver <  19> read packet: $QStartNoAckMode#b0",
-            "lldb-gdbserver <   1> send packet: +",
-            "lldb-gdbserver <   6> send packet: $OK#9a",
-            "lldb-gdbserver <   1> read packet: +"]
+    def add_no_ack_remote_stream(self):
+        self.test_sequence.add_log_lines(
+            ["read packet: +",
+             "read packet: $QStartNoAckMode#b0",
+             "send packet: +",
+             "send packet: $OK#9a",
+             "read packet: +"],
+            True)
+
+    def expect_gdbremote_sequence(self):
+        expect_lldb_gdbserver_replay(self, self.sock, self.test_sequence, self._TIMEOUT_SECONDS, self.logger)
 
     @debugserver_test
     def test_exe_starts_debugserver(self):
@@ -112,10 +116,8 @@ class LldbGdbServerTestCase(TestBase):
         server = self.start_server()
         self.assertIsNotNone(server)
 
-        log_lines = self.create_no_ack_remote_stream()
-
-        expect_lldb_gdbserver_replay(self, self.sock, log_lines, True,
-                                     self._TIMEOUT_SECONDS, self.logger)
+        self.add_no_ack_remote_stream()
+        self.expect_gdbremote_sequence()
 
     @debugserver_test
     def test_start_no_ack_mode_debugserver(self):
@@ -131,13 +133,13 @@ class LldbGdbServerTestCase(TestBase):
         server = self.start_server()
         self.assertIsNotNone(server)
 
-        log_lines = self.create_no_ack_remote_stream()
-        log_lines.extend([
-            "lldb-gdbserver <  26> read packet: $QThreadSuffixSupported#e4",
-            "lldb-gdbserver <   6> send packet: $OK#9a"])
+        self.add_no_ack_remote_stream()
+        self.test_sequence.add_log_lines(
+            ["lldb-gdbserver <  26> read packet: $QThreadSuffixSupported#e4",
+             "lldb-gdbserver <   6> send packet: $OK#9a"],
+            True)
 
-        expect_lldb_gdbserver_replay(self, self.sock, log_lines, True,
-                                     self._TIMEOUT_SECONDS, self.logger)
+        self.expect_gdbremote_sequence()
 
     @debugserver_test
     def test_thread_suffix_supported_debugserver(self):
@@ -154,13 +156,12 @@ class LldbGdbServerTestCase(TestBase):
         server = self.start_server()
         self.assertIsNotNone(server)
 
-        log_lines = self.create_no_ack_remote_stream()
-        log_lines.extend([
-            "lldb-gdbserver <  27> read packet: $QListThreadsInStopReply#21",
-            "lldb-gdbserver <   6> send packet: $OK#9a"])
-
-        expect_lldb_gdbserver_replay(self, self.sock, log_lines, True,
-                                     self._TIMEOUT_SECONDS, self.logger)
+        self.add_no_ack_remote_stream()
+        self.test_sequence.add_log_lines(
+            ["lldb-gdbserver <  27> read packet: $QListThreadsInStopReply#21",
+             "lldb-gdbserver <   6> send packet: $OK#9a"],
+            True)
+        self.expect_gdbremote_sequence()
 
     @debugserver_test
     def test_list_threads_in_stop_reply_supported_debugserver(self):
@@ -180,13 +181,12 @@ class LldbGdbServerTestCase(TestBase):
         # build launch args
         launch_args = [os.path.abspath('a.out')]
 
-        log_lines = self.create_no_ack_remote_stream()
-        log_lines.extend([
-            "lldb-gdbserver <   0> read packet: %s" % build_gdbremote_A_packet(launch_args),
-            "lldb-gdbserver <   6> send packet: $OK#9a"])
-
-        expect_lldb_gdbserver_replay(self, self.sock, log_lines, True,
-                                     self._TIMEOUT_SECONDS, self.logger)
+        self.add_no_ack_remote_stream()
+        self.test_sequence.add_log_lines(
+            ["read packet: %s" % build_gdbremote_A_packet(launch_args),
+             "send packet: $OK#9a"],
+            True)
+        self.expect_gdbremote_sequence()
 
     @debugserver_test
     @dsym_test
@@ -209,17 +209,16 @@ class LldbGdbServerTestCase(TestBase):
         # build launch args
         launch_args = [os.path.abspath('a.out')]
 
-        log_lines = self.create_no_ack_remote_stream()
-        log_lines.extend([
-            "lldb-gdbserver <   0> read packet: %s" % build_gdbremote_A_packet(launch_args),
-            "lldb-gdbserver <   6> send packet: $OK#00",
-            "lldb-gdbserver <  18> read packet: $qLaunchSuccess#a5",
-            "lldb-gdbserver <   6> send packet: $OK#00",
-            "lldb-gdbserver <   5> read packet: $vCont;c#00",
-            "lldb-gdbserver <   7> send packet: $W00#00"])
-
-        expect_lldb_gdbserver_replay(self, self.sock, log_lines, True,
-                                     self._TIMEOUT_SECONDS, self.logger)
+        self.add_no_ack_remote_stream()
+        self.test_sequence.add_log_lines(
+            ["read packet: %s" % build_gdbremote_A_packet(launch_args),
+             "send packet: $OK#00",
+             "read packet: $qLaunchSuccess#a5",
+             "send packet: $OK#00",
+             "read packet: $vCont;c#00",
+             "send packet: $W00#00"],
+            True)
+        self.expect_gdbremote_sequence()
 
     @debugserver_test
     @dsym_test
@@ -245,17 +244,16 @@ class LldbGdbServerTestCase(TestBase):
         # build launch args
         launch_args = [os.path.abspath('a.out'), "retval:%d" % RETVAL]
 
-        log_lines = self.create_no_ack_remote_stream()
-        log_lines.extend([
-            "lldb-gdbserver <   0> read packet: %s" % build_gdbremote_A_packet(launch_args),
-            "lldb-gdbserver <   6> send packet: $OK#00",
-            "lldb-gdbserver <  18> read packet: $qLaunchSuccess#a5",
-            "lldb-gdbserver <   6> send packet: $OK#00",
-            "lldb-gdbserver <   5> read packet: $vCont;c#00",
-            "lldb-gdbserver <   7> send packet: $W{0:02x}#00".format(RETVAL)])
-
-        expect_lldb_gdbserver_replay(self, self.sock, log_lines, True,
-                                     self._TIMEOUT_SECONDS, self.logger)
+        self.add_no_ack_remote_stream()
+        self.test_sequence.add_log_lines(
+            ["lldb-gdbserver <   0> read packet: %s" % build_gdbremote_A_packet(launch_args),
+             "lldb-gdbserver <   6> send packet: $OK#00",
+             "lldb-gdbserver <  18> read packet: $qLaunchSuccess#a5",
+             "lldb-gdbserver <   6> send packet: $OK#00",
+             "lldb-gdbserver <   5> read packet: $vCont;c#00",
+             "lldb-gdbserver <   7> send packet: $W{0:02x}#00".format(RETVAL)],
+            True)
+        self.expect_gdbremote_sequence()
 
     @debugserver_test
     @dsym_test
@@ -279,18 +277,17 @@ class LldbGdbServerTestCase(TestBase):
         # build launch args
         launch_args = [os.path.abspath('a.out'), "hello, world"]
 
-        log_lines = self.create_no_ack_remote_stream()
-        log_lines.extend([
-            "lldb-gdbserver <   0> read packet: %s" % build_gdbremote_A_packet(launch_args),
-            "lldb-gdbserver <   6> send packet: $OK#00",
-            "lldb-gdbserver <  18> read packet: $qLaunchSuccess#a5",
-            "lldb-gdbserver <   6> send packet: $OK#00",
-            "lldb-gdbserver <   5> read packet: $vCont;c#00",
-            "lldb-gdbserver <   7> send packet: $O{}#00".format(gdbremote_hex_encode_string("hello, world\r\n")),
-            "lldb-gdbserver <   7> send packet: $W00#00"])
-
-        expect_lldb_gdbserver_replay(self, self.sock, log_lines, True,
-                                     self._TIMEOUT_SECONDS, self.logger)
+        self.add_no_ack_remote_stream()
+        self.test_sequence.add_log_lines(
+            ["lldb-gdbserver <   0> read packet: %s" % build_gdbremote_A_packet(launch_args),
+             "lldb-gdbserver <   6> send packet: $OK#00",
+             "lldb-gdbserver <  18> read packet: $qLaunchSuccess#a5",
+             "lldb-gdbserver <   6> send packet: $OK#00",
+             "lldb-gdbserver <   5> read packet: $vCont;c#00",
+             "lldb-gdbserver <   7> send packet: $O{}#00".format(gdbremote_hex_encode_string("hello, world\r\n")),
+             "lldb-gdbserver <   7> send packet: $W00#00"],
+            True)
+        self.expect_gdbremote_sequence()
 
     @debugserver_test
     @dsym_test

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=207998&r1=207997&r2=207998&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-gdbserver/lldbgdbserverutils.py (original)
+++ lldb/trunk/test/tools/lldb-gdbserver/lldbgdbserverutils.py Mon May  5 15:54:01 2014
@@ -122,8 +122,7 @@ _GDB_REMOTE_PACKET_REGEX = re.compile(r'
 def expect_lldb_gdbserver_replay(
     asserter,
     sock,
-    log_lines,
-    read_is_llgs_input,
+    test_sequence,
     timeout_seconds,
     logger=None):
     """Replay socket communication with lldb-gdbserver and verify responses.
@@ -158,72 +157,61 @@ def expect_lldb_gdbserver_replay(
     received_lines = []
     receive_buffer = ''
 
-    for packet in log_lines:
-        if logger:
-            logger.debug("processing log line: {}".format(packet))
-        match = _LOG_LINE_REGEX.match(packet)
-        if match:
-            playback_packet = match.group(4)
-            if _is_packet_lldb_gdbserver_input(
-                    match.group(3),
-                    read_is_llgs_input):
-                # handle as something to send to lldb-gdbserver on
-                # socket.
-                if logger:
-                    logger.info("sending packet to llgs: {}".format(playback_packet))
-                sock.sendall(playback_packet)
-            else:
-                # expect it as output from lldb-gdbserver received
-                # from socket.
-                if logger:
-                    logger.info("receiving packet from llgs, should match: {}".format(playback_packet))
-                start_time = time.time()
-                timeout_time = start_time + timeout_seconds
-
-                # while we don't have a complete line of input, wait
-                # for it from socket.
-                while len(received_lines) < 1:
-                    # check for timeout
-                    if time.time() > timeout_time:
-                        raise Exception(
-                            'timed out after {} seconds while waiting for llgs to respond with: {}, currently received: {}'.format(
-                                timeout_seconds, playback_packet, receive_buffer))
-                    can_read, _, _ = select.select(
-                        [sock], [], [], 0)
-                    if can_read and sock in can_read:
-                        new_bytes = sock.recv(4096)
-                        if new_bytes and len(new_bytes) > 0:
-                            # read the next bits from the socket
-                            if logger:
-                                logger.debug("llgs responded with bytes: {}".format(new_bytes))
-                            receive_buffer += new_bytes
-
-                            # parse fully-formed packets into individual packets
-                            has_more = len(receive_buffer) > 0
-                            while has_more:
-                                if len(receive_buffer) <= 0:
-                                    has_more = False
-                                # handle '+' ack
-                                elif receive_buffer[0] == '+':
-                                    received_lines.append('+')
-                                    receive_buffer = receive_buffer[1:]
+    for sequence_entry in test_sequence.entries:
+        if sequence_entry.is_send_to_remote:
+            # This is an entry to send to the remote debug monitor.
+            if logger:
+                logger.info("sending packet to remote: {}".format(sequence_entry.exact_payload))
+            sock.sendall(sequence_entry.exact_payload)
+        else:
+            # This is an entry to expect to receive from the remote debug monitor.
+            if logger:
+                logger.info("receiving packet from remote, should match: {}".format(sequence_entry.exact_payload))
+
+            start_time = time.time()
+            timeout_time = start_time + timeout_seconds
+
+            # while we don't have a complete line of input, wait
+            # for it from socket.
+            while len(received_lines) < 1:
+                # check for timeout
+                if time.time() > timeout_time:
+                    raise Exception(
+                        'timed out after {} seconds while waiting for llgs to respond with: {}, currently received: {}'.format(
+                            timeout_seconds, sequence_entry.exact_playload, receive_buffer))
+                can_read, _, _ = select.select([sock], [], [], 0)
+                if can_read and sock in can_read:
+                    new_bytes = sock.recv(4096)
+                    if new_bytes and len(new_bytes) > 0:
+                        # read the next bits from the socket
+                        if logger:
+                            logger.debug("llgs responded with bytes: {}".format(new_bytes))
+                        receive_buffer += new_bytes
+
+                        # parse fully-formed packets into individual packets
+                        has_more = len(receive_buffer) > 0
+                        while has_more:
+                            if len(receive_buffer) <= 0:
+                                has_more = False
+                            # handle '+' ack
+                            elif receive_buffer[0] == '+':
+                                received_lines.append('+')
+                                receive_buffer = receive_buffer[1:]
+                                if logger:
+                                    logger.debug('parsed packet from llgs: +, new receive_buffer: {}'.format(receive_buffer))
+                            else:
+                                packet_match = _GDB_REMOTE_PACKET_REGEX.match(receive_buffer)
+                                if packet_match:
+                                    received_lines.append(packet_match.group(0))
+                                    receive_buffer = receive_buffer[len(packet_match.group(0)):]
                                     if logger:
-                                        logger.debug('parsed packet from llgs: +, new receive_buffer: {}'.format(receive_buffer))
+                                        logger.debug('parsed packet from llgs: {}, new receive_buffer: {}'.format(packet_match.group(0), receive_buffer))
                                 else:
-                                    packet_match = _GDB_REMOTE_PACKET_REGEX.match(receive_buffer)
-                                    if packet_match:
-                                        received_lines.append(packet_match.group(0))
-                                        receive_buffer = receive_buffer[len(packet_match.group(0)):]
-                                        if logger:
-                                            logger.debug('parsed packet from llgs: {}, new receive_buffer: {}'.format(packet_match.group(0), receive_buffer))
-                                    else:
-                                        has_more = False
-
-                # got a line - now try to match it against expected line
-                if len(received_lines) > 0:
-                    received_packet = received_lines.pop(0)
-                    assert_packets_equal(asserter, received_packet, playback_packet)
-
+                                    has_more = False
+            # got a line - now try to match it against expected line
+            if len(received_lines) > 0:
+                received_packet = received_lines.pop(0)
+                sequence_entry.assert_match(asserter, received_packet)
     return None
 
 
@@ -265,6 +253,58 @@ def build_gdbremote_A_packet(args_list):
     # return the packetized payload
     return gdbremote_packet_encode_string(payload)
 
+class GdbRemoteEntry(object):
+
+    def __init__(self, is_send_to_remote=True, exact_payload=None):
+        self.is_send_to_remote = is_send_to_remote
+        self.exact_payload=exact_payload
+
+    def is_send_to_remote(self):
+        return self.is_send_to_remote
+
+    def assert_match(self, asserter, actual_packet):
+        # This only makes sense for matching lines coming from the
+        # remote debug monitor.
+        if self.is_send_to_remote:
+            raise Exception("Attempted to match a packet being sent to the remote debug monitor, doesn't make sense.")
+
+        # If this is an exact payload, ensure they match exactly,
+        # ignoring the packet checksum which is optional for no-ack
+        # mode.
+        if self.exact_payload:
+            assert_packets_equal(asserter, actual_packet, self.exact_payload)
+        else:
+            raise Exception("Don't know how to match a remote-sent packet when exact_payload isn't specified.")
+
+class GdbRemoteTestSequence(object):
+
+    _LOG_LINE_REGEX = re.compile(r'^.*(read|send)\s+packet:\s+(.+)$')
+
+    def __init__(self, logger):
+        self.entries = []
+        self.logger = logger
+
+    def add_log_lines(self, log_lines, remote_input_is_read):
+        for line in log_lines:
+            if self.logger:
+                self.logger.debug("processing log line: {}".format(line))
+            match = self._LOG_LINE_REGEX.match(line)
+            if match:
+                playback_packet = match.group(2)
+                direction = match.group(1)
+                if _is_packet_lldb_gdbserver_input(direction, remote_input_is_read):
+                    # Handle as something to send to the remote debug monitor.
+                    if self.logger:
+                        self.logger.info("processed packet to send to remote: {}".format(playback_packet))
+                    self.entries.append(GdbRemoteEntry(is_send_to_remote=True, exact_payload=playback_packet))
+                else:
+                    # Log line represents content to be expected from the remote debug monitor.
+                    if self.logger:
+                        self.logger.info("receiving packet from llgs, should match: {}".format(playback_packet))
+                    self.entries.append(GdbRemoteEntry(is_send_to_remote=False,exact_payload=playback_packet))
+            else:
+                raise Exception("failed to interpret log line: {}".format(line))
+
 if __name__ == '__main__':
     EXE_PATH = get_lldb_gdbserver_exe()
     if EXE_PATH:





More information about the lldb-commits mailing list