Test keepalive.
authorEmil Mikulic <emikulic@gmail.com>
Thu, 1 Jan 2015 11:18:10 +0000 (22:18 +1100)
committerEmil Mikulic <emikulic@gmail.com>
Thu, 1 Jan 2015 11:18:10 +0000 (22:18 +1100)
devel/test.py

index a79fd31..e11e789 100755 (executable)
@@ -9,6 +9,16 @@ import random
 
 WWWROOT = "tmp.httpd.tests"
 
+def between(s, start, end):
+    assert start in s, s
+    p = s.index(start) + len(start)
+    s = s[p:]
+    assert end in s, s
+    p = s.index(end)
+    return s[:p]
+
+assert between("hello world", "hell", "world") == "o "
+
 class Conn:
     def __init__(self):
         self.port = 12346
@@ -39,11 +49,43 @@ class Conn:
                 ret += r
         return ret
 
+    def get_keepalive(self, url, endl="\n", req_hdrs={}, method="GET"):
+        req = method+" "+url+" HTTP/1.1"+endl
+        req_hdrs["User-Agent"] = "test.py"
+        req_hdrs["Connection"] = "keep-alive"
+        for k,v in req_hdrs.items():
+            req += k+": "+v+endl
+        req += endl # end of request
+        self.s.send(req)
+        signal.alarm(1) # don't wait forever
+        ret = ""
+        while True:
+            ret += self.s.recv(65536)
+            if "\r\n\r\n" not in ret:
+                # Don't have headers yet.
+                continue
+            if method == "HEAD":
+                # We're done.
+                break
+            if "Content-Length: " in ret:
+                cl = between(ret, "Content-Length: ", "\r\n")
+                cl = int(cl)
+            else:
+                cl = 0
+            p = ret.index("\r\n\r\n") + 4
+            assert len(ret) - p <= cl, [ret, p, cl]
+            if len(ret) == p + cl:
+                # Complete response.
+                break
+        signal.alarm(0)
+        return ret
+
 def parse(resp):
     """
     Parse response into status line, headers and body.
     """
-    pos = resp.index("\r\n\r\n") # throws exception on failure
+    pos = resp.find("\r\n\r\n")
+    assert pos != -1, 'response is %s' % repr(resp)
     head = resp[:pos]
     body = resp[pos+4:]
     status,head = head.split("\r\n", 1)
@@ -55,7 +97,6 @@ def parse(resp):
 
 class TestHelper(unittest.TestCase):
     def get(self, url, http_ver="1.0", endl="\n", req_hdrs={}, method="GET"):
-        self.curr_url = url
         self.curr_conn = Conn()
         return self.curr_conn.get(url, http_ver, endl, req_hdrs, method)
 
@@ -225,6 +266,7 @@ class TestFileGet(TestHelper):
         self.assertEquals(hdrs["Content-Length"], str(self.datalen))
         self.assertEquals(hdrs["Content-Type"], "image/jpeg")
         self.assertContains(hdrs["Server"], "darkhttpd/")
+        assert body == self.data, [url, resp, status, hdrs, body]
         self.assertEquals(body, self.data)
 
     def test_file_get(self):
@@ -319,6 +361,14 @@ class TestFileGet(TestHelper):
         status, hdrs, body = parse(resp)
         self.assertContains(status, "416 Requested Range Not Satisfiable")
 
+class TestKeepAlive(TestFileGet):
+    def setUp(self):
+        TestFileGet.setUp(self)
+        self.conn = Conn()
+
+    def get(self, url, endl="\n", req_hdrs={}, method="GET"):
+        return self.conn.get_keepalive(url, endl, req_hdrs, method)
+
 def make_large_file(fn, boundary, data):
     big = 1<<33
     assert big == 8589934592L