benoitc/gunicorn — Issue #294: Test failure with 012.http due to readline(0)
Author: danc86
Created: 2012-01-31 03:42:25+00:00
State: open

Occasionally the gunicorn unit tests fail with an error like this:

======================================================================
FAIL: 012.http: MT: readline SZ: small_random SN: random
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python2.6/site-packages/nose/case.py", line 187, in runTest
self.test(*self.arg)
File "gunicorn-0.13.4/tests/treq.py", line 219, in test_req
self.check(sn, sz, mt)
File "gunicorn-0.13.4/tests/treq.py", line 229, in check
self.same(req, sizer, matcher, cases.pop(0))
File "gunicorn-0.13.4/tests/treq.py", line 244, in same
t.eq(req.trailers, exp.get("trailers", []))
File "gunicorn-0.13.4/tests/t.py", line 85, in eq
assert a == b, "%r != %r" % (a, b)
AssertionError: [] != [('VARY', '*'), ('CONTENT-TYPE', 'text/plain')]

----------------------------------------------------------------------

I eventually narrowed it down to cases where `treq.request.size_small_random` was returning a sequence like `[11, 0, 0]`. Actually it could be any sequence which sums to 11, followed by two zeroes. Here is a reproducer:

```python
req = treq.request(
os.path.join(os.path.dirname(__file__), 'requests', 'valid', '012.http'),
treq.load_py(os.path.join(os.path.dirname(__file__), 'requests', 'valid', '012.py')))
sizes = iter([11, 0, 0])
req.check(req.send_all, sizes.next, req.match_readline)
```

The test ends up calling `req.body.readline(11)`, which returns the complete request body `'hello world'`. It then calls `req.body.readline(0)`, which returns `''`. But the test assumes it is finished reading the request, when in fact it is not. So the parser never has a chance to read the trailers, so they come out as an empty list.

I think this is an invalid test, and there's no reason to test calling body.readline(0) at all, because why would anyone do that? Here is a simple patch to stop testing with zero:

```diff
--- gunicorn-0.13.4/tests/treq.py	2011-08-22 05:11:35.000000000 +1000
+++ gunicorn-0.13.4.patched/tests/treq.py	2012-01-31 13:28:37.687182655 +1000
@@ -97,7 +97,7 @@
return 1

def size_small_random(self):
- return random.randint(0, 4)
+ return random.randint(1, 4)

def size_random(self):
return random.randint(1, 4096)
```