labath created this revision.
labath added reviewers: davide, zturner.
Herald added a reviewer: serge-sans-paille.

This patch finishes the python3-ification of the lldb-server test suite.
It reverts the partial attempt in r352709 to encode/decode the string
via utf8 before writing to the socket. This wasn't enough because the
gdb-remote protocol can sometimes (but not very often) carry binary
data, and the utf8 codec chokes on that. Instead I add utility functions
to the "seven" module for performing "identity" transformations on the
byte data. This basically drills back the hole in the python type system
that the string/bytes distinction was supposed to plug. That is not
ideal, but was the best solution of the alternatives I could come up
with. The options I considered were:

- make use of the type system to add type safety to the test suite: This 
required making a lot of changes to the test suite, since most of the strings 
would now become byte objects instead, and it was not even fully clear to me 
where to draw the line. One extreme solution would be to just use byte objects 
everywhere, as the protocol doesn't support non-ascii characters anyway. 
However, this appeared to be: a) weird, because most of the protocol actually 
deals with strings, but we would have to prefix everything with 'b' b) clunky, 
because the handling of the bytes objects is sufficiently different in PY2 and 
PY3 (e.g. b'a'[0] is a string in PY2, but an int in PY3).
- using the latin1 codec (which gives an identity transformation for the first 
256 code points of unicode) instead of the custom bytes_to_string functions. 
This almost could work, but it was still slightly different between python 2 
and 3, because in PY2 in would return a unicode object, which would then cause 
problems when combined with regular strings if it contained 8-bit chars.

With this in mind, I think the best solution for the time being is to
just coerce everything into the string type as early as possible, and
have things proceed indentically on both python versions. Once we stop
supporting python3, we can revisit the idea of using bytes objects more
prevasively.


https://reviews.llvm.org/D58177

Files:
  packages/Python/lldbsuite/support/seven.py
  packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteModuleInfo.py
  packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py
  packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
  packages/Python/lldbsuite/test/tools/lldb-server/lldbgdbserverutils.py
  packages/Python/lldbsuite/test/tools/lldb-server/socket_packet_pump.py

Index: packages/Python/lldbsuite/test/tools/lldb-server/socket_packet_pump.py
===================================================================
--- packages/Python/lldbsuite/test/tools/lldb-server/socket_packet_pump.py
+++ packages/Python/lldbsuite/test/tools/lldb-server/socket_packet_pump.py
@@ -9,6 +9,7 @@
 import codecs
 
 from six.moves import queue
+from lldbsuite.support import seven
 
 
 def _handle_output_packet_string(packet_contents):
@@ -19,7 +20,7 @@
     elif packet_contents == "OK":
         return None
     else:
-        return packet_contents[1:].decode("hex")
+        return seven.unhexlify(packet_contents[1:])
 
 
 def _dump_queue(the_queue):
@@ -174,7 +175,7 @@
             can_read, _, _ = select.select([self._socket], [], [], 0)
             if can_read and self._socket in can_read:
                 try:
-                    new_bytes = self._socket.recv(4096)
+                    new_bytes = seven.bytes_to_string(self._socket.recv(4096))
                     if self._logger and new_bytes and len(new_bytes) > 0:
                         self._logger.debug(
                             "pump received bytes: {}".format(new_bytes))
Index: packages/Python/lldbsuite/test/tools/lldb-server/lldbgdbserverutils.py
===================================================================
--- packages/Python/lldbsuite/test/tools/lldb-server/lldbgdbserverutils.py
+++ packages/Python/lldbsuite/test/tools/lldb-server/lldbgdbserverutils.py
@@ -412,7 +412,7 @@
             value = value >> 8
         if byte_size:
             # Add zero-fill to the right/end (MSB side) of the value.
-            retval += "00" * (byte_size - len(retval) / 2)
+            retval += "00" * (byte_size - len(retval) // 2)
         return retval
 
     elif endian == 'big':
@@ -422,7 +422,7 @@
             value = value >> 8
         if byte_size:
             # Add zero-fill to the left/front (MSB side) of the value.
-            retval = ("00" * (byte_size - len(retval) / 2)) + retval
+            retval = ("00" * (byte_size - len(retval) // 2)) + retval
         return retval
 
     else:
Index: packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
===================================================================
--- packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
+++ packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
@@ -20,6 +20,7 @@
 import time
 from lldbsuite.test import configuration
 from lldbsuite.test.lldbtest import *
+from lldbsuite.support import seven
 from lldbgdbserverutils import *
 import logging
 
@@ -589,7 +590,7 @@
             if can_read and sock in can_read:
                 recv_bytes = sock.recv(4096)
                 if recv_bytes:
-                    response += recv_bytes.decode("utf-8")
+                    response += seven.bytes_to_string(recv_bytes)
 
         self.assertTrue(expected_content_regex.match(response))
 
@@ -1235,7 +1236,7 @@
             reg_index = reg_info["lldb_register_index"]
             self.assertIsNotNone(reg_index)
 
-            reg_byte_size = int(reg_info["bitsize"]) / 8
+            reg_byte_size = int(reg_info["bitsize"]) // 8
             self.assertTrue(reg_byte_size > 0)
 
             # Handle thread suffix.
@@ -1261,7 +1262,7 @@
                 endian, p_response)
 
             # Flip the value by xoring with all 1s
-            all_one_bits_raw = "ff" * (int(reg_info["bitsize"]) / 8)
+            all_one_bits_raw = "ff" * (int(reg_info["bitsize"]) // 8)
             flipped_bits_int = initial_reg_value ^ int(all_one_bits_raw, 16)
             # print("reg (index={}, name={}): val={}, flipped bits (int={}, hex={:x})".format(reg_index, reg_info["name"], initial_reg_value, flipped_bits_int, flipped_bits_int))
 
@@ -1476,8 +1477,8 @@
         self.assertIsNotNone(context.get("g_c1_contents"))
         self.assertIsNotNone(context.get("g_c2_contents"))
 
-        return (context.get("g_c1_contents").decode("hex") == expected_g_c1) and (
-            context.get("g_c2_contents").decode("hex") == expected_g_c2)
+        return (seven.unhexlify(context.get("g_c1_contents")) == expected_g_c1) and (
+            seven.unhexlify(context.get("g_c2_contents")) == expected_g_c2)
 
     def single_step_only_steps_one_instruction(
             self, use_Hc_packet=True, step_instruction="s"):
Index: packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py
===================================================================
--- packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py
+++ packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py
@@ -18,6 +18,7 @@
 import lldbgdbserverutils
 import platform
 import signal
+from lldbsuite.support import seven
 from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
 from lldbsuite.test.lldbdwarf import *
@@ -868,7 +869,7 @@
 
         # Ensure what we read from inferior memory is what we wrote.
         self.assertIsNotNone(context.get("read_contents"))
-        read_contents = context.get("read_contents").decode("hex")
+        read_contents = seven.unhexlify(context.get("read_contents"))
         self.assertEqual(read_contents, MEMORY_CONTENTS)
 
     @debugserver_test
@@ -1352,7 +1353,7 @@
         message_address = int(context.get("message_address"), 16)
 
         # Hex-encode the test message, adding null termination.
-        hex_encoded_message = TEST_MESSAGE.encode("hex")
+        hex_encoded_message = seven.hexlify(TEST_MESSAGE)
 
         # Write the message to the inferior. Verify that we can read it with the hex-encoded (m)
         # and binary (x) memory read packets.
@@ -1467,7 +1468,7 @@
 
         reg_index = self.select_modifiable_register(reg_infos)
         self.assertIsNotNone(reg_index)
-        reg_byte_size = int(reg_infos[reg_index]["bitsize"]) / 8
+        reg_byte_size = int(reg_infos[reg_index]["bitsize"]) // 8
         self.assertTrue(reg_byte_size > 0)
 
         # Run the process a bit so threads can start up, and collect register
Index: packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteModuleInfo.py
===================================================================
--- packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteModuleInfo.py
+++ packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteModuleInfo.py
@@ -3,6 +3,7 @@
 
 import gdbremote_testcase
 import lldbgdbserverutils
+from lldbsuite.support import seven
 from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
 from lldbsuite.test import lldbutil
@@ -21,7 +22,7 @@
         self.test_sequence.add_log_lines([
             'read packet: $jModulesInfo:[{"file":"%s","triple":"%s"}]]#00' % (
                 lldbutil.append_to_process_working_directory(self, "a.out"),
-                info["triple"].decode('hex')),
+                seven.unhexlify(info["triple"])),
             {"direction": "send",
              "regex": r'^\$\[{(.*)}\]\]#[0-9A-Fa-f]{2}',
              "capture": {1: "spec"}},
Index: packages/Python/lldbsuite/support/seven.py
===================================================================
--- packages/Python/lldbsuite/support/seven.py
+++ packages/Python/lldbsuite/support/seven.py
@@ -1,3 +1,4 @@
+import binascii
 import six
 
 if six.PY2:
@@ -23,3 +24,19 @@
         return get_command_status_output(command)[1]
 
     cmp_ = lambda x, y: (x > y) - (x < y)
+
+def bytes_to_string(b):
+    """Take a string(PY2) or a bytes(PY3) object and return a string."""
+    return b if six.PY2 else b.decode("latin1")
+
+def string_to_bytes(s):
+    """Take a string and return a string(PY2) or a bytes(PY3) object."""
+    return s if six.PY2 else s.encode("latin1")
+
+def unhexlify(hexstr):
+    """Hex-decode a string. The result is always a string."""
+    return bytes_to_string(binascii.unhexlify(hexstr))
+
+def hexlify(data):
+    """Hex-encode string data. The result if always a string."""
+    return bytes_to_string(binascii.hexlify(string_to_bytes(data)))
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to