From 2763fe8e9f35e91154d2df5765ae7ff3c8bb8d61 Mon Sep 17 00:00:00 2001 From: "Paul J. Davis" Date: Wed, 2 Jun 2010 23:18:44 -0400 Subject: [PATCH] Added tests for invalid requests. Need to flesh out more error cases. --- tests/001-test-valid-requests.py | 10 +--- tests/002-test-invalid-requests.py | 18 +++++++ tests/t.py | 1 - tests/treq.py | 83 +++++++++++++++++++++++++++++- 4 files changed, 102 insertions(+), 10 deletions(-) create mode 100644 tests/002-test-invalid-requests.py diff --git a/tests/001-test-valid-requests.py b/tests/001-test-valid-requests.py index 97d7ce48..2b953368 100644 --- a/tests/001-test-valid-requests.py +++ b/tests/001-test-valid-requests.py @@ -11,14 +11,8 @@ import os dirname = os.path.dirname(__file__) reqdir = os.path.join(dirname, "requests", "valid") -def load_py(fname): - config = globals().copy() - config["uri"] = treq.uri - execfile(fname, config) - return config["request"] - def a_case(fname): - expect = load_py(os.path.splitext(fname)[0] + ".py") + expect = treq.load_py(os.path.splitext(fname)[0] + ".py") req = treq.request(fname, expect) for case in req.gen_cases(): case[0](*case[1:]) @@ -26,7 +20,7 @@ def a_case(fname): def test_http_parser(): for fname in glob.glob(os.path.join(reqdir, "*.http")): if os.getenv("GUNS_BLAZING"): - expect = load_py(os.path.splitext(fname)[0] + ".py") + expect = treq.load_py(os.path.splitext(fname)[0] + ".py") req = treq.request(fname, expect) for case in req.gen_cases(): yield case diff --git a/tests/002-test-invalid-requests.py b/tests/002-test-invalid-requests.py new file mode 100644 index 00000000..880f2a86 --- /dev/null +++ b/tests/002-test-invalid-requests.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import t +import treq + +import glob +import os +dirname = os.path.dirname(__file__) +reqdir = os.path.join(dirname, "requests", "invalid") + +def test_http_parser(): + for fname in glob.glob(os.path.join(reqdir, "*.http")): + expect = treq.load_py(os.path.splitext(fname)[0] + ".py") + req = treq.badrequest(fname, expect) + yield (req.check,) diff --git a/tests/t.py b/tests/t.py index b44ef150..6c8058e9 100644 --- a/tests/t.py +++ b/tests/t.py @@ -12,7 +12,6 @@ import tempfile dirname = os.path.dirname(__file__) from gunicorn.http.parser import RequestParser -from gunicorn.http.request import Request from gunicorn.config import Config def data_source(fname): diff --git a/tests/treq.py b/tests/treq.py index 3aa325ad..5bd72bd5 100644 --- a/tests/treq.py +++ b/tests/treq.py @@ -35,6 +35,12 @@ def uri(data): ret["fragment"] = parts.fragment or None return ret +def load_py(fname): + config = globals().copy() + config["uri"] = uri + execfile(fname, config) + return config["request"] + class request(object): def __init__(self, fname, expect): self.fname = fname @@ -117,7 +123,6 @@ class request(object): if not data: count -= 1 if count <= 0: - print "BOD: %r" % body raise AssertionError("Unexpected apparent EOF") if len(body): @@ -235,3 +240,79 @@ class request(object): t.eq(req.headers, exp["headers"]) matcher(req, exp["body"], sizer) t.eq(req.trailers, exp.get("trailers", [])) + +class badrequest(object): + def __init__(self, fname, expect): + self.fname = fname + self.name = os.path.basename(fname) + + self.expect = expect + if not isinstance(self.expect, list): + self.expect = [self.expect] + + with open(self.fname) as handle: + self.data = handle.read() + self.data = self.data.replace("\n", "").replace("\\r\\n", "\r\n") + self.data = self.data.replace("\\0", "\000") + + def send(self): + maxs = len(self.data) / 10 + read = 0 + while read < len(self.data): + chunk = random.randint(1, maxs) + yield self.data[read:read+chunk] + read += chunk + + def size(self): + return random.randint(0, 4) + + def match(self, req, body): + data = req.body.read(self.size()) + count = 1000 + while len(body): + if body[:len(data)] != data: + raise AssertionError("Invalid body data read: %r != %r" % ( + data, body[:len(data)])) + body = body[len(data):] + data = req.body.read(self.size()) + if not data: + count -= 1 + if count <= 0: + raise AssertionError("Unexpected apparent EOF") + + if len(body): + raise AssertionError("Failed to read entire body: %r" % body) + elif len(data): + raise AssertionError("Read beyond expected body: %r" % data) + data = req.body.read(sizes()) + if data: + raise AssertionError("Read after body finished: %r" % data) + + def same(self, req, sizer, matcher, exp): + t.eq(req.method, exp["method"]) + t.eq(req.uri, exp["uri"]["raw"]) + t.eq(req.scheme, exp["uri"]["scheme"]) + t.eq(req.host, exp["uri"]["host"]) + t.eq(req.port, exp["uri"]["port"]) + t.eq(req.path, exp["uri"]["path"]) + t.eq(req.query, exp["uri"]["query"]) + t.eq(req.fragment, exp["uri"]["fragment"]) + t.eq(req.version, exp["version"]) + t.eq(req.headers, exp["headers"]) + self.match(req, exp["body"]) + t.eq(req.trailers, exp.get("trailers", [])) + + def check(self): + cases = self.expect[:] + p = RequestParser(self.send()) + try: + for req in p: + self.same(req, cases.pop(0)) + except Exception, inst: + exp = cases.pop(0) + if not issubclass(exp, Exception): + raise TypeError("Test case is not an exception calss: %s" % exp) + if not isinstance(inst, exp): + raise TypeError("Invalid error result: %s: %s" % (exp, inst)) + t.eq(len(cases), 0) +