]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.11] gh-109845: Make test_ftplib more stable under load (GH-109912) (GH-109920)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Tue, 26 Sep 2023 20:23:20 +0000 (13:23 -0700)
committerGitHub <noreply@github.com>
Tue, 26 Sep 2023 20:23:20 +0000 (20:23 +0000)
recv() can return partial data cut in the middle of a multibyte
character. Test raw binary data instead of data incorrectly decoded by parts.
(cherry picked from commit 2ef2fffe3be953b91852585c75188d5475b09474)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Lib/test/test_ftplib.py

index 082a90d46baedcf9c204595581b435196426fb2e..7d6b12ffadcef390f3dbac82e2ae62fc3fd1a463 100644 (file)
@@ -34,7 +34,7 @@ TIMEOUT = support.LOOPBACK_TIMEOUT
 DEFAULT_ENCODING = 'utf-8'
 # the dummy data returned by server over the data channel when
 # RETR, LIST, NLST, MLSD commands are issued
-RETR_DATA = 'abcde12345\r\n' * 1000 + 'non-ascii char \xAE\r\n'
+RETR_DATA = 'abcde\xB9\xB2\xB3\xA4\xA6\r\n' * 1000
 LIST_DATA = 'foo\r\nbar\r\n non-ascii char \xAE\r\n'
 NLST_DATA = 'foo\r\nbar\r\n non-ascii char \xAE\r\n'
 MLSD_DATA = ("type=cdir;perm=el;unique==keVO1+ZF4; test\r\n"
@@ -69,11 +69,11 @@ class DummyDTPHandler(asynchat.async_chat):
     def __init__(self, conn, baseclass):
         asynchat.async_chat.__init__(self, conn)
         self.baseclass = baseclass
-        self.baseclass.last_received_data = ''
+        self.baseclass.last_received_data = bytearray()
         self.encoding = baseclass.encoding
 
     def handle_read(self):
-        new_data = self.recv(1024).decode(self.encoding, 'replace')
+        new_data = self.recv(1024)
         self.baseclass.last_received_data += new_data
 
     def handle_close(self):
@@ -109,7 +109,7 @@ class DummyFTPHandler(asynchat.async_chat):
         self.in_buffer = []
         self.dtp = None
         self.last_received_cmd = None
-        self.last_received_data = ''
+        self.last_received_data = bytearray()
         self.next_response = ''
         self.next_data = None
         self.rest = None
@@ -592,19 +592,17 @@ class TestFTPClass(TestCase):
         self.client.abort()
 
     def test_retrbinary(self):
-        def callback(data):
-            received.append(data.decode(self.client.encoding))
         received = []
-        self.client.retrbinary('retr', callback)
-        self.check_data(''.join(received), RETR_DATA)
+        self.client.retrbinary('retr', received.append)
+        self.check_data(b''.join(received),
+                        RETR_DATA.encode(self.client.encoding))
 
     def test_retrbinary_rest(self):
-        def callback(data):
-            received.append(data.decode(self.client.encoding))
         for rest in (0, 10, 20):
             received = []
-            self.client.retrbinary('retr', callback, rest=rest)
-            self.check_data(''.join(received), RETR_DATA[rest:])
+            self.client.retrbinary('retr', received.append, rest=rest)
+            self.check_data(b''.join(received),
+                            RETR_DATA[rest:].encode(self.client.encoding))
 
     def test_retrlines(self):
         received = []
@@ -614,7 +612,8 @@ class TestFTPClass(TestCase):
     def test_storbinary(self):
         f = io.BytesIO(RETR_DATA.encode(self.client.encoding))
         self.client.storbinary('stor', f)
-        self.check_data(self.server.handler_instance.last_received_data, RETR_DATA)
+        self.check_data(self.server.handler_instance.last_received_data,
+                        RETR_DATA.encode(self.server.encoding))
         # test new callback arg
         flag = []
         f.seek(0)
@@ -633,7 +632,8 @@ class TestFTPClass(TestCase):
         data = RETR_DATA.replace('\r\n', '\n').encode(self.client.encoding)
         f = io.BytesIO(data)
         self.client.storlines('stor', f)
-        self.check_data(self.server.handler_instance.last_received_data, RETR_DATA)
+        self.check_data(self.server.handler_instance.last_received_data,
+                        RETR_DATA.encode(self.server.encoding))
         # test new callback arg
         flag = []
         f.seek(0)
@@ -651,7 +651,7 @@ class TestFTPClass(TestCase):
 
     def test_dir(self):
         l = []
-        self.client.dir(lambda x: l.append(x))
+        self.client.dir(l.append)
         self.assertEqual(''.join(l), LIST_DATA.replace('\r\n', ''))
 
     def test_mlsd(self):
@@ -891,12 +891,10 @@ class TestIPv6Environment(TestCase):
 
     def test_transfer(self):
         def retr():
-            def callback(data):
-                received.append(data.decode(self.client.encoding))
             received = []
-            self.client.retrbinary('retr', callback)
-            self.assertEqual(len(''.join(received)), len(RETR_DATA))
-            self.assertEqual(''.join(received), RETR_DATA)
+            self.client.retrbinary('retr', received.append)
+            self.assertEqual(b''.join(received),
+                             RETR_DATA.encode(self.client.encoding))
         self.client.set_pasv(True)
         retr()
         self.client.set_pasv(False)