classification
Title: Test test.test_asynchat.TestAsynchat / test.test_asynchat.TestAsynchat_WithPoll fail test_close_when_done
Type: Stage: resolved
Components: Versions: Python 3.8, Python 3.7, Python 3.6, Python 3.5, Python 2.7
process
Status: closed Resolution: out of date
Dependencies: Superseder:
Assigned To: Nosy List: iritkatriel, patrila
Priority: normal Keywords: patch

Created on 2017-01-04 13:50 by patrila, last changed 2021-06-15 20:28 by iritkatriel. This issue is now closed.

Files
File name Uploaded Description Edit
test_asynchat_add_receive_something_flag_3.6.patch patrila, 2017-01-04 13:50 Patch for Python 3.6.0 to introduce receive_something flag
test_asynchat_add_receive_something_flag_2.7.13.patch patrila, 2017-01-04 13:52 Patch for Python 2.7.13 to introduce receive_something flag
Messages (3)
msg284636 - (view) Author: (patrila) Date: 2017-01-04 13:50
Dear Python developers

The tests

    test.test_asynchat.TestAsynchat.test_close_when_done
    test.test_asynchat.TestAsynchat_WitrhPoll.test_close_when_done

fail with

======================================================================
FAIL: test_close_when_done (test.test_asynchat.TestAsynchat)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".../Lib/test/test_asynchat.py", line 256, in test_close_when_done
    self.assertGreater(len(s.buffer), 0)
AssertionError: 0 not greater than 0

======================================================================
FAIL: test_close_when_done (test.test_asynchat.TestAsynchat_WithPoll)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".../Lib/test/test_asynchat.py", line 256, in test_close_when_done
    self.assertGreater(len(s.buffer), 0)
AssertionError: 0 not greater than 0

Looking in the source code we see

        self.assertEqual(c.contents, [])
        # the server might have been able to send a byte or two back, but this
        # at least checks that it received something and didn't just fail
        # (which could still result in the client not having received anything)
        self.assertGreater(len(s.buffer), 0)

We therefore conjecture that the server was able to send all data back.
The relevant part is around line 61, the run() method of echo_server.

                # this may fail on some tests, such as test_close_when_done,
                # since the client closes the channel when it's done sending
                while self.buffer:
                    n = conn.send(self.buffer[:self.chunk_size])
                    time.sleep(0.001)
                    self.buffer = self.buffer[n:]


Indeed, if we change the sleeping time to something larger, e.g. 1sec. The tests pass fine.

In general it is a bad habit to relay on "hardware to be slow enough" to work/pass.
I therefore propose to introduce a separate field in echo_server which is set to True if the server has received some data.
Patch is attached and also included below. It is tested against Python-3.6.0 (sorry no "default" branch).
Python 3.5.3rc1 also works, but the patch below has an offset of -1 (the import warnings line was added/removed depending on the point of view).
For Python 2.7.13 the "same patch" also works but needs different line numbers and also different context. Patch is attached.

Patch for 3.6.0:

--- a/Lib/test/test_asynchat.py
+++ b/Lib/test/test_asynchat.py
@@ -42,12 +42,15 @@
             self.event.set()
             conn, client = self.sock.accept()
             self.buffer = b"" 
+            self.received_something = False
             # collect data until quit message is seen
             while SERVER_QUIT not in self.buffer:
                 data = conn.recv(1)
                 if not data:
                     break
                 self.buffer = self.buffer + data
+            if self.buffer:
+                self.received_something = True

             # remove the SERVER_QUIT message
             self.buffer = self.buffer.replace(SERVER_QUIT, b'')
@@ -252,7 +255,7 @@
         # the server might have been able to send a byte or two back, but this
         # at least checks that it received something and didn't just fail
         # (which could still result in the client not having received anything)
-        self.assertGreater(len(s.buffer), 0)
+        self.assertTrue(s.received_something)

     def test_push(self):
         # Issue #12523: push() should raise a TypeError if it doesn't get
msg317734 - (view) Author: (patrila) Date: 2018-05-26 10:22
May I ask what's preventing this issue from being resolved?
msg395895 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2021-06-15 20:28
asynchat is deprecated since version 3.6 so there won't be any more development related to it.
History
Date User Action Args
2021-06-15 20:28:46iritkatrielsetstatus: open -> closed

nosy: + iritkatriel
messages: + msg395895

resolution: out of date
stage: resolved
2018-05-26 10:22:55patrilasetmessages: + msg317734
versions: + Python 3.8
2017-01-04 13:52:06patrilasetfiles: + test_asynchat_add_receive_something_flag_2.7.13.patch
2017-01-04 13:50:54patrilacreate