Skip to content

Commit

Permalink
add request unitests. fix TeeInput & parser
Browse files Browse the repository at this point in the history
  • Loading branch information
Benoit Chesneau committed Jan 20, 2010
1 parent ba6db08 commit b568852
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 29 deletions.
4 changes: 2 additions & 2 deletions gunicorn/http/__init__.py
Expand Up @@ -4,5 +4,5 @@
# See the NOTICE for more information.

from gunicorn.http.http_parser import HttpParser
from gunicorn.http.request import HTTPRequest, RequestError
from gunicorn.http.response import HTTPResponse
from gunicorn.http.request import HttpRequest, RequestError
from gunicorn.http.response import HttpResponse
9 changes: 4 additions & 5 deletions gunicorn/http/http_parser.py
Expand Up @@ -16,9 +16,9 @@ def __init__(self):
self.status = ""
self.headers = []
self.headers_dict = {}
self.raw_version = ""
self.raw_version = "HTTP/1.0"
self.raw_path = ""
self.version = None
self.version = (1,0)
self.method = ""
self.path = ""
self.query_string = ""
Expand Down Expand Up @@ -70,8 +70,7 @@ def finalize_headers(self, headers, headers_str, pos):
self.headers_dict = _headers
headers.extend(list(_headers.items()))
self.headers = headers
self._content_len = int(_headers.get('Content-Length') or 0)

self._content_len = int(_headers.get('Content-Length',0))
(_, _, self.path, self.query_string, self.fragment) = urlparse.urlsplit(self.raw_path)
return pos

Expand Down Expand Up @@ -122,7 +121,7 @@ def content_len(self):
None."""
transfert_encoding = self.headers_dict.get('Transfer-Encoding')
content_length = self.headers_dict.get('Content-Length')
if transfert_encoding is None:
if transfert_encoding != "chunked":
if content_length is None:
return 0
return int(content_length)
Expand Down
5 changes: 1 addition & 4 deletions gunicorn/http/request.py
Expand Up @@ -30,7 +30,7 @@ class RequestError(Exception):
""" raised when something wrong happend"""


class HTTPRequest(object):
class HttpRequest(object):

SERVER_VERSION = "gunicorn/%s" % __version__

Expand Down Expand Up @@ -74,9 +74,6 @@ def read(self):
i = self.parser.filter_headers(headers, buf)
if i != -1: break

if not headers:
environ.update(self.DEFAULTS)
return environ

self.log.info("%s", self.parser.status)

Expand Down
2 changes: 1 addition & 1 deletion gunicorn/http/response.py
Expand Up @@ -11,7 +11,7 @@
import os
from gunicorn.util import http_date, write, read_partial, close

class HTTPResponse(object):
class HttpResponse(object):

def __init__(self, sock, response, req):
self.req = req
Expand Down
11 changes: 4 additions & 7 deletions gunicorn/http/tee.py
Expand Up @@ -43,6 +43,7 @@ def len(self):
if self._len: return self._len
if self._is_socket:
pos = self.tmp.tell()
print pos
while True:
if not self._tee(CHUNK_SIZE):
break
Expand All @@ -53,14 +54,13 @@ def len(self):
def flush(self):
self.tmp.flush()

def read(self, length=None):
def read(self, length=-1):
""" read """
if not self._is_socket:
return self.tmp.read(length)

if length is None:
if length < 0:
r = self.tmp.read() or ""
print "avant %s" % str(len(r))
while True:
chunk = self._tee(CHUNK_SIZE)
if not chunk: break
Expand Down Expand Up @@ -125,10 +125,7 @@ def _tee(self, length):
if chunk:
self.tmp.write(chunk)
self.tmp.seek(0, os.SEEK_END)
return chunk
if not data:
self._is_socket = False
break
return chunk
self._finalize()
return ""

Expand Down
5 changes: 2 additions & 3 deletions gunicorn/worker.py
Expand Up @@ -19,7 +19,6 @@
from gunicorn import util



class Worker(object):

SIGNALS = map(
Expand Down Expand Up @@ -126,9 +125,9 @@ def run(self):
def handle(self, client, addr):
self.close_on_exec(client)
try:
req = http.HTTPRequest(client, addr, self.address)
req = http.HttpRequest(client, addr, self.address)
response = self.app(req.read(), req.start_response)
http.HTTPResponse(client, response, req).send()
http.HttpResponse(client, response, req).send()
except Exception, e:
# TODO: try to send something if an error happend
self.log.exception("Error processing request. [%s]" % str(e))
Expand Down
2 changes: 1 addition & 1 deletion tests/001-test-parser.py
Expand Up @@ -22,7 +22,7 @@ def test_001(buf, p):
])
body, tr = p.filter_body(buf[i:])
t.eq(body, '{"nom": "nom"}')
print t.eq(p.body_eof(), True)
t.eq(p.body_eof(), True)

@t.request("002.http")
def test_002(buf, p):
Expand Down
139 changes: 139 additions & 0 deletions tests/002-test-request.py
@@ -0,0 +1,139 @@
# -*- coding: utf-8 -
#
# This file is part of gunicorn released under the MIT license.
# See the NOTICE for more information.


import t

from gunicorn.http import tee

@t.http_request("001.http")
def test_001(req):
e = req.read()
t.eq(e['CONTENT_LENGTH'], '14')
t.eq(e['wsgi.version'], (1,0))
t.eq(e['REQUEST_METHOD'], 'PUT')
t.eq(e['PATH_INFO'], '/stuff/here')
t.eq(e['CONTENT_TYPE'], 'application/json')
t.eq(e['QUERY_STRING'], 'foo=bar')

t.eq(isinstance(e['wsgi.input'], tee.TeeInput), True)
body = e['wsgi.input'].read()
t.eq(body, '{"nom": "nom"}')

@t.http_request("002.http")
def http_request(req):
e = req.read()

t.eq(e['REQUEST_METHOD'], 'GET')
t.eq(e['PATH_INFO'], "/test")
t.eq(e['QUERY_STRING'], "")
t.eq(sorted(p.headers), [
("Accept", "*/*"),
("Host", "0.0.0.0=5000"),
("User-Agent", "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1")
])
t.eq(e['HTTP_ACCEPT'], "*/*")
t.eq(e['HTTP_HOST'], "0.0.0.0=5000")
t.eq(e['HTTP_USER_AGENT', "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1"])
body = e['wsgi.input'].read()
t.eq(body, '')

@t.http_request("003.http")
def test_003(req):
e = req.read()

t.eq(e['REQUEST_METHOD'], 'GET')
t.eq(e['PATH_INFO'], "/favicon.ico")
t.eq(e['QUERY_STRING'], "")
t.eq(e['HTTP_ACCEPT'], "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
t.eq(e['HTTP_KEEP_ALIVE'], "300")

body = e['wsgi.input'].read()
t.eq(body, '')

@t.http_request("004.http")
def test_004(req):
e = req.read()
t.eq(e['REQUEST_METHOD'], 'GET')
t.eq(e['PATH_INFO'], "/dumbfuck")
t.eq(e['QUERY_STRING'], "")
body = e['wsgi.input'].read()
t.eq(body, '')


@t.http_request("005.http")
def test_005(req):
e = req.read()
t.eq(e['REQUEST_METHOD'], 'GET')
t.eq(e['PATH_INFO'], "/forums/1/topics/2375")
t.eq(e['QUERY_STRING'], "page=1")
body = e['wsgi.input'].read()
t.eq(body, '')


@t.http_request("006.http")
def test_006(req):
e = req.read()
t.eq(e['REQUEST_METHOD'], 'GET')
t.eq(e['PATH_INFO'], "/get_no_headers_no_body/world")
t.eq(e['QUERY_STRING'], "")
body = e['wsgi.input'].read()
t.eq(body, '')


@t.http_request("007.http")
def test_007(req):
e = req.read()
t.eq(e['REQUEST_METHOD'], 'GET')
t.eq(e['PATH_INFO'], "/get_one_header_no_body")
t.eq(e['QUERY_STRING'], "")
t.eq(e['HTTP_ACCEPT'], "*/*")
body = e['wsgi.input'].read()
t.eq(body, '')


@t.http_request("008.http")
def test_008(req):
e = req.read()
t.eq(e['REQUEST_METHOD'], 'GET')
t.eq(e['PATH_INFO'], "/get_funky_content_length_body_hello")
t.eq(e['QUERY_STRING'], "")
t.eq(e['CONTENT_LENGTH'], '5')
body = e['wsgi.input'].read()
t.eq(body, "HELLO")


@t.http_request("009.http")
def test_009(req):
e = req.read()
t.eq(e['REQUEST_METHOD'], 'POST')
t.eq(e['PATH_INFO'], "/post_identity_body_world")
t.eq(e['QUERY_STRING'], "q=search")
t.eq(e['CONTENT_LENGTH'], '5')
body = e['wsgi.input'].read()
t.eq(body, "World")


@t.http_request("010.http")
def test_010(req):
e = req.read()
t.eq(e['REQUEST_METHOD'], 'POST')
t.eq(e['PATH_INFO'], "/post_chunked_all_your_base")
t.eq(e['HTTP_TRANSFER_ENCODING'], "chunked")
t.eq(e['CONTENT_LENGTH'], '30')
body = e['wsgi.input'].read()
t.eq(body, "all your base are belong to us")


@t.http_request("011.http")
def test_011(req):
e = req.read()
t.eq(e['REQUEST_METHOD'], 'POST')
t.eq(e['PATH_INFO'], "/two_chunks_mult_zero_end")
t.eq(e['HTTP_TRANSFER_ENCODING'], "chunked")
t.eq(e['CONTENT_LENGTH'], '11')
body = e['wsgi.input'].read()
t.eq(body, "hello world")

53 changes: 47 additions & 6 deletions tests/t.py
Expand Up @@ -7,14 +7,15 @@
import inspect
import os
import re
import tempfile
import unittest

from gunicorn.http import HttpParser

dirname = os.path.dirname(__file__)

from gunicorn.http.http_parser import HttpParser
from gunicorn.http.request import HttpRequest

def data_source(fname, eol):
def data_source(fname):
with open(fname) as handle:
lines = []
for line in handle:
Expand All @@ -23,16 +24,56 @@ def data_source(fname, eol):
return "".join(lines)

class request(object):
def __init__(self, name, eol="\r\n"):
def __init__(self, name):
self.fname = os.path.join(dirname, "requests", name)
self.eol = eol

def __call__(self, func):
def run():
src = data_source(self.fname, self.eol)
src = data_source(self.fname)
func(src, HttpParser())
run.func_name = func.func_name
return run


class FakeSocket(object):

def __init__(self, data):
self.tmp = tempfile.TemporaryFile()
self.tmp.write(data)
self.tmp.flush()
self.tmp.seek(0)

def fileno(self):
return self.tmp.fileno()

def len(self):
return self.tmp.len

def recv(self, length=None):
return self.tmp.read()

def seek(self, offset, whence=0):
self.tmp.seek(offset, whence)


class http_request(object):
def __init__(self, name):
self.fname = os.path.join(dirname, "requests", name)

def __call__(self, func):
def run():
fsock = FakeSocket(data_source(self.fname))


req = HttpRequest(fsock, ('127.0.0.1', 6000),
('127.0.0.1', 8000))
func(req)
run.func_name = func.func_name
return run





def eq(a, b):
assert a == b, "%r != %r" % (a, b)
Expand Down

0 comments on commit b568852

Please sign in to comment.