[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