[Lldb-commits] [lldb] r207395 - Added two new test types: @debugserver_test and @llgs_test.

Todd Fiala todd.fiala at gmail.com
Sun Apr 27 21:49:41 PDT 2014


Author: tfiala
Date: Sun Apr 27 23:49:40 2014
New Revision: 207395

URL: http://llvm.org/viewvc/llvm-project?rev=207395&view=rev
Log:
Added two new test types: @debugserver_test and @llgs_test.

TestLldbGdbServer now supports both lldb-gdbserver (llgs) and
debugserver tests.  Similar to the dsym/dwarf tests, they allow
running the same underlying gdb remote protocol tests against
lldb-gdbserver and debugserver.  This will help make sure the
protocol-level tests for lldb-gdbserver faithfully represent
what debugserver does on OS X.

Switched back gdb remote protocol test logging to warning
and above (accidentally submitted it at debug level in a
recent commit).


Modified:
    lldb/trunk/test/dotest.py
    lldb/trunk/test/lldbtest.py
    lldb/trunk/test/tools/lldb-gdbserver/TestLldbGdbServer.py
    lldb/trunk/test/tools/lldb-gdbserver/lldbgdbserverutils.py

Modified: lldb/trunk/test/dotest.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/dotest.py?rev=207395&r1=207394&r2=207395&view=diff
==============================================================================
--- lldb/trunk/test/dotest.py (original)
+++ lldb/trunk/test/dotest.py Sun Apr 27 23:49:40 2014
@@ -126,6 +126,13 @@ just_do_benchmarks_test = False
 dont_do_dsym_test = "linux" in sys.platform or "freebsd" in sys.platform
 dont_do_dwarf_test = False
 
+# Don't do debugserver tests on everything except OS X.
+# Something for Windows here?
+dont_do_debugserver_test = "linux" in sys.platform or "freebsd" in sys.platform
+
+# Don't do lldb-gdbserver (llgs) tests on anything except Linux.
+dont_do_llgs_test = not ("linux" in sys.platform)
+
 # The blacklist is optional (-b blacklistFile) and allows a central place to skip
 # testclass's and/or testclass.testmethod's.
 blacklist = None
@@ -1300,6 +1307,8 @@ lldb.just_do_python_api_test = just_do_p
 lldb.just_do_benchmarks_test = just_do_benchmarks_test
 lldb.dont_do_dsym_test = dont_do_dsym_test
 lldb.dont_do_dwarf_test = dont_do_dwarf_test
+lldb.dont_do_debugserver_test = dont_do_debugserver_test
+lldb.dont_do_llgs_test = dont_do_llgs_test
 
 # Do we need to skip build and cleanup?
 lldb.skip_build_and_cleanup = skip_build_and_cleanup

Modified: lldb/trunk/test/lldbtest.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lldbtest.py?rev=207395&r1=207394&r2=207395&view=diff
==============================================================================
--- lldb/trunk/test/lldbtest.py (original)
+++ lldb/trunk/test/lldbtest.py Sun Apr 27 23:49:40 2014
@@ -373,6 +373,40 @@ def dwarf_test(func):
     wrapper.__dwarf_test__ = True
     return wrapper
 
+def debugserver_test(func):
+    """Decorate the item as a debugserver test."""
+    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
+        raise Exception("@debugserver_test can only be used to decorate a test method")
+    @wraps(func)
+    def wrapper(self, *args, **kwargs):
+        try:
+            if lldb.dont_do_debugserver_test:
+                self.skipTest("debugserver tests")
+        except AttributeError:
+            pass
+        return func(self, *args, **kwargs)
+
+    # Mark this function as such to separate them from the regular tests.
+    wrapper.__debugserver_test__ = True
+    return wrapper
+
+def llgs_test(func):
+    """Decorate the item as a lldb-gdbserver test."""
+    if isinstance(func, type) and issubclass(func, unittest2.TestCase):
+        raise Exception("@llgs_test can only be used to decorate a test method")
+    @wraps(func)
+    def wrapper(self, *args, **kwargs):
+        try:
+            if lldb.dont_do_llgs_test:
+                self.skipTest("llgs tests")
+        except AttributeError:
+            pass
+        return func(self, *args, **kwargs)
+
+    # Mark this function as such to separate them from the regular tests.
+    wrapper.__llgs_test__ = True
+    return wrapper
+
 def not_remote_testsuite_ready(func):
     """Decorate the item as a test which is not ready yet for remote testsuite."""
     if isinstance(func, type) and issubclass(func, unittest2.TestCase):

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=207395&r1=207394&r2=207395&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-gdbserver/TestLldbGdbServer.py (original)
+++ lldb/trunk/test/tools/lldb-gdbserver/TestLldbGdbServer.py Sun Apr 27 23:49:40 2014
@@ -21,20 +21,27 @@ 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)
-        self.lldb_gdbserver_exe = get_lldb_gdbserver_exe()
-        if not self.lldb_gdbserver_exe:
-            self.skipTest("lldb_gdbserver exe not specified")
 
         FORMAT = '%(asctime)-15s %(levelname)-8s %(message)s'
         logging.basicConfig(format=FORMAT)
         self.logger = logging.getLogger(__name__)
         self.logger.setLevel(self._LOGGING_LEVEL)
 
+    def init_llgs_test(self):
+        self.debug_monitor_exe = get_lldb_gdbserver_exe()
+        if not self.debug_monitor_exe:
+            self.skipTest("lldb_gdbserver exe not found")
+
+    def init_debugserver_test(self):
+        self.debug_monitor_exe = get_debugserver_exe()
+        if not self.debug_monitor_exe:
+            self.skipTest("debugserver exe not found")
+
     def create_socket(self):
         sock = socket.socket()
         logger = self.logger
@@ -59,24 +66,24 @@ class LldbGdbServerTestCase(TestBase):
 
     def start_server(self):
         # start the server
-        server = pexpect.spawn("{} localhost:{}".format(self.lldb_gdbserver_exe, self.port))
+        server = pexpect.spawn("{} localhost:{}".format(self.debug_monitor_exe, self.port))
 
         # Turn on logging for what the child sends back.
         if self.TraceOn():
             server.logfile_read = sys.stdout
 
-        # Schedule lldb-gdbserver to be shutting down during teardown.
+        # Schedule debug monitor to be shut down during teardown.
         logger = self.logger
-        def shutdown_lldb_gdbserver():
+        def shutdown_debug_monitor():
             try:
                 server.close()
             except:
                 logger.warning("failed to close pexpect server for debug monitor: {}; ignoring".format(sys.exc_info()[0]))
 
-        self.addTearDownHook(shutdown_lldb_gdbserver)
+        self.addTearDownHook(shutdown_debug_monitor)
 
         # Wait until we receive the server ready message before continuing.
-        server.expect_exact('Listening for a connection on localhost:{}'.format(self.port))
+        server.expect_exact('Listening to port {} for a connection from localhost'.format(self.port))
 
         # Create a socket to talk to the server
         self.sock = self.create_socket()
@@ -91,11 +98,17 @@ class LldbGdbServerTestCase(TestBase):
             "lldb-gdbserver <   6> send packet: $OK#9a",
             "lldb-gdbserver <   1> read packet: +"]
 
+    @debugserver_test
+    def test_exe_starts_debugserver(self):
+        self.init_debugserver_test()
+        server = self.start_server()
 
-    def test_exe_starts(self):
+    @llgs_test
+    def test_exe_starts_llgs(self):
+        self.init_llgs_test()
         server = self.start_server()
 
-    def test_start_no_ack_mode(self):
+    def start_no_ack_mode(self):
         server = self.start_server()
         self.assertIsNotNone(server)
 
@@ -104,8 +117,17 @@ class LldbGdbServerTestCase(TestBase):
         expect_lldb_gdbserver_replay(self, self.sock, log_lines, True,
                                      self._TIMEOUT_SECONDS, self.logger)
 
-    @unittest2.expectedFailure()
-    def test_thread_suffix_supported(self):
+    @debugserver_test
+    def test_start_no_ack_mode_debugserver(self):
+        self.init_debugserver_test()
+        self.start_no_ack_mode()
+
+    @llgs_test
+    def test_start_no_ack_mode_llgs(self):
+        self.init_llgs_test()
+        self.start_no_ack_mode()
+
+    def thread_suffix_supported(self):
         server = self.start_server()
         self.assertIsNotNone(server)
 
@@ -117,8 +139,18 @@ class LldbGdbServerTestCase(TestBase):
         expect_lldb_gdbserver_replay(self, self.sock, log_lines, True,
                                      self._TIMEOUT_SECONDS, self.logger)
 
+    @debugserver_test
+    def test_thread_suffix_supported_debugserver(self):
+        self.init_debugserver_test()
+        self.thread_suffix_supported()
+
+    @llgs_test
     @unittest2.expectedFailure()
-    def test_list_threads_in_stop_reply_supported(self):
+    def test_thread_suffix_supported_llgs(self):
+        self.init_llgs_test()
+        self.thread_suffix_supported()
+
+    def list_threads_in_stop_reply_supported(self):
         server = self.start_server()
         self.assertIsNotNone(server)
 
@@ -130,6 +162,17 @@ class LldbGdbServerTestCase(TestBase):
         expect_lldb_gdbserver_replay(self, self.sock, log_lines, True,
                                      self._TIMEOUT_SECONDS, self.logger)
 
+    @debugserver_test
+    def test_list_threads_in_stop_reply_supported_debugserver(self):
+        self.init_debugserver_test()
+        self.list_threads_in_stop_reply_supported()
+
+    @llgs_test
+    @unittest2.expectedFailure()
+    def test_list_threads_in_stop_reply_supported_llgs(self):
+        self.init_llgs_test()
+        self.list_threads_in_stop_reply_supported()
+
     def start_inferior(self):
         server = self.start_server()
         self.assertIsNotNone(server)
@@ -148,13 +191,17 @@ class LldbGdbServerTestCase(TestBase):
         expect_lldb_gdbserver_replay(self, self.sock, log_lines, True,
                                      self._TIMEOUT_SECONDS, self.logger)
 
+    @debugserver_test
     @dsym_test
-    def test_start_inferior(self):
+    def test_start_inferior_debugserver_dsym(self):
+        self.init_debugserver_test()
         self.buildDsym()
         self.start_inferior()
 
+    @llgs_test
     @dwarf_test
-    def test_start_inferior(self):
+    def test_start_inferior_llgs_dwarf(self):
+        self.init_llgs_test()
         self.buildDwarf()
         self.start_inferior()
 

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=207395&r1=207394&r2=207395&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-gdbserver/lldbgdbserverutils.py (original)
+++ lldb/trunk/test/tools/lldb-gdbserver/lldbgdbserverutils.py Sun Apr 27 23:49:40 2014
@@ -7,36 +7,42 @@ import re
 import select
 import time
 
-def _get_lldb_gdbserver_from_lldb(lldb_exe):
-    """Return the lldb-gdbserver exe path given the lldb exe path.
 
-    This method attempts to construct a valid lldb-gdbserver exe name
+def _get_debug_monitor_from_lldb(lldb_exe, debug_monitor_basename):
+    """Return the debug monitor exe path given the lldb exe path.
+
+    This method attempts to construct a valid debug monitor exe name
     from a given lldb exe name.  It will return None if the synthesized
-    lldb-gdbserver name is not found to exist.
+    debug monitor name is not found to exist.
 
-    The lldb-gdbserver exe path is synthesized by taking the directory
+    The debug monitor exe path is synthesized by taking the directory
     of the lldb exe, and replacing the portion of the base name that
-    matches "lldb" (case insensitive) and replacing with "lldb-gdbserver".
+    matches "lldb" (case insensitive) and replacing with the value of
+    debug_monitor_basename.
 
     Args:
         lldb_exe: the path to an lldb executable.
 
+        debug_monitor_basename: the base name portion of the debug monitor
+            that will replace 'lldb'.
+
     Returns:
-        A path to the lldb-gdbserver exe if it is found to exist; otherwise,
+        A path to the debug monitor exe if it is found to exist; otherwise,
         returns None.
+
     """
 
     exe_dir = os.path.dirname(lldb_exe)
     exe_base = os.path.basename(lldb_exe)
 
     # we'll rebuild the filename by replacing lldb with
-    # lldb-gdbserver, keeping any prefix or suffix in place.
+    # the debug monitor basename, keeping any prefix or suffix in place.
     regex = re.compile(r"lldb", re.IGNORECASE)
-    new_base = regex.sub("lldb-gdbserver", exe_base)
+    new_base = regex.sub(debug_monitor_basename, exe_base)
 
-    lldb_gdbserver_exe = os.path.join(exe_dir, new_base)
-    if os.path.exists(lldb_gdbserver_exe):
-        return lldb_gdbserver_exe
+    debug_monitor_exe = os.path.join(exe_dir, new_base)
+    if os.path.exists(debug_monitor_exe):
+        return debug_monitor_exe
     else:
         return None
 
@@ -52,7 +58,20 @@ def get_lldb_gdbserver_exe():
     if not lldb_exe:
         return None
     else:
-        return _get_lldb_gdbserver_from_lldb(lldb_exe)
+        return _get_debug_monitor_from_lldb(lldb_exe, "lldb-gedbserver")
+
+def get_debugserver_exe():
+    """Return the debugserver exe path.
+
+    Returns:
+        A path to the debugserver exe if it is found to exist; otherwise,
+        returns None.
+    """
+    lldb_exe = os.environ["LLDB_EXEC"]
+    if not lldb_exe:
+        return None
+    else:
+        return _get_debug_monitor_from_lldb(lldb_exe, "debugserver")
 
 
 _LOG_LINE_REGEX = re.compile(r'^(lldb-gdbserver|debugserver)\s+<\s*(\d+)>' +
@@ -87,8 +106,18 @@ def _is_packet_lldb_gdbserver_input(pack
         raise "Unknown packet type: {}".format(packet_type)
 
 
-_GDB_REMOTE_PACKET_REGEX = re.compile(r'^\$[^\#]*\#[0-9a-fA-F]{2}')
+_STRIP_CHECKSUM_REGEX = re.compile(r'#[0-9a-fA-F]{2}$')
+
+def assert_packets_equal(asserter, actual_packet, expected_packet):
+    # strip off the checksum digits of the packet.  When we're in
+    # no-ack mode, the # checksum is ignored, and should not be cause
+    # for a mismatched packet.
+    actual_stripped = _STRIP_CHECKSUM_REGEX.sub('', actual_packet)
+    expected_stripped = _STRIP_CHECKSUM_REGEX.sub('', expected_packet)
+    asserter.assertEqual(actual_stripped, expected_stripped)
+
 
+_GDB_REMOTE_PACKET_REGEX = re.compile(r'^\$([^\#]*)#[0-9a-fA-F]{2}')
 
 def expect_lldb_gdbserver_replay(
     asserter,
@@ -134,19 +163,20 @@ def expect_lldb_gdbserver_replay(
             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(match.group(4)))
-                sock.sendall(match.group(4))
+                    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(match.group(4)))
+                    logger.info("receiving packet from llgs, should match: {}".format(playback_packet))
                 start_time = time.time()
                 timeout_time = start_time + timeout_seconds
 
@@ -157,7 +187,7 @@ def expect_lldb_gdbserver_replay(
                     if time.time() > timeout_time:
                         raise Exception(
                             'timed out after {} seconds while waiting for llgs to respond with: {}, currently received: {}'.format(
-                                timeout_seconds, match.group(4), receive_buffer))
+                                timeout_seconds, playback_packet, receive_buffer))
                     can_read, _, _ = select.select(
                         [sock], [], [], 0)
                     if can_read and sock in can_read:
@@ -191,9 +221,8 @@ def expect_lldb_gdbserver_replay(
 
                 # got a line - now try to match it against expected line
                 if len(received_lines) > 0:
-                    actual_receive = received_lines.pop(0)
-                    expected_receive = match.group(4)
-                    asserter.assertEqual(actual_receive, expected_receive)
+                    received_packet = received_lines.pop(0)
+                    assert_packets_equal(asserter, received_packet, playback_packet)
 
     return None
 





More information about the lldb-commits mailing list