def test_01_writeResponse(self):
        """
        L{HTTP._writeResponse} writes a HTTP response to the protocol's
        transport, then closes the connection. It takes a L{Response}
        object that is constructed with three arguments, a numberic response
        code and the body of the response, whose length is included as a
        content-length header, and additional headers (as a dictionary mapping
        keys to values).
        """
        self.assertTrue(issubclass(HTTP, Protocol))
        protocol = HTTP(None, reactor=task.Clock())
        # Connect a fake, in-memory transport to the protocol:
        transport = AbortableTransport()
        protocol.makeConnection(transport)

        protocol._writeResponse(Response(200, "Response body!",
                                         {"content-type": "text/plain"}))
        self.assertEqual(transport.value(),
                         "HTTP/1.1 200 Reason\r\n"
                         "Content-Length: 14\r\n"
                         "content-type: text/plain\r\n"
                         "\r\n"
                         "Response body!")
        # The connection is closed once the response has been written,
        # i.e. transport.loseConnection() was called:
        self.assertEqual(transport.disconnecting, True)
    def test_02_handler(self):
        """
        L{HTTP.__init__} is called with a function as its argument. This
        function is called by L{HTTP.requestReceived} with the request
        parameters, and its response is passed to L{HTTP._writeResponse}.

        In other words, this function determines how the HTTP server processes
        and handles requests.
        """
        def handler(method, path, headers, body):
            self.assertEqual(method, "WOO")
            self.assertEqual(path, "/path")
            self.assertEqual(headers, {"Key": "value"})
            return Response(300, "hello", {"k": "v"})

        protocol = HTTP(handler, reactor=task.Clock())
        response = []
        protocol._writeResponse = lambda r: response.append(r)

        # Handler is stored as an attribute of the protocol:
        self.assertIdentical(protocol._handler, handler)
        # requestReceived calls handler, and then takes the results and passes
        # it to _writeResponse:
        protocol.requestReceived("WOO", "/path", {"Key": "value"}, "")
        self.assertResponsesEqual(response[0],
                                  Response(300, "hello", {"k": "v"}))
    def test_14_handlerReturnsDeferredWithFailure(self):
        """
        If the handler returns a Deferred that fires with a failure,
        L{HTTP.requestReceived} writes a 500 response code using
        L{HTTP._writeResponse} and logs the exception.
        """
        # Handler that returns eventual result:
        result = defer.Deferred()
        def handler(method, path, headers, body):
            return result

        protocol = HTTP(handler, reactor=task.Clock())
        response = []
        protocol._writeResponse = lambda r: response.append(r)

        protocol.requestReceived("GET", "/", [], "")
        # Deferred hasn't fired yet, so no response is sent yet:
        self.assertEqual(len(response), 0)
        # Now we fire the Deferred with an exception:
        result.errback(ZeroDivisionError())

        # 500 response code:
        self.assertEqual(len(response), 1)
        self.assertEqual(response[0].code, 500)
        # The error was logged using twisted.python.log.err():
        excs = self.flushLoggedErrors(ZeroDivisionError)
        self.assertEqual(len(excs), 1)
    def test_11_handlerException(self):
        """
        If the handler throws an exception, L{HTTP.requestReceived} writes a
        response with error code 500 (internal server error), and the
        exception is logged.
        """
        def handler(method, path, headers, body):
            raise RuntimeError("I am a buggy handler!")

        protocol = HTTP(handler, reactor=task.Clock())
        response = []
        protocol._writeResponse = lambda r: response.append(r)

        protocol.requestReceived("GET", "/", [], "")
        # We don't assert anything on the body of the response; if you're
        # feeling ambitious you can include the text of the traceback in your
        # response:
        self.assertEqual(len(response), 1)
        self.assertEqual(response[0].code, 500)
        # You should log the error using twisted.python.log.err(). This makes
        # sure the logged error doesn't cause the test to fail:
        excs = self.flushLoggedErrors(RuntimeError)
        # And this asserts that you logged it, i.e. that there was one
        # RuntimeError logged:
        self.assertEqual(len(excs), 1)
    def test_09_badRequestResponse(self):
        """
        L{HTTP.badRequestReceived} writes a response with a 400 code ("Bad
        Client Request") using L{HTTP._writeResponse).
        """
        protocol = HTTP(None, reactor=task.Clock())
        response = []
        protocol._writeResponse = lambda r: response.append(r)

        protocol.badRequestReceived()
        self.assertResponsesEqual(response[0], Response(400, "", {}))
    def test_19_requestBodyToHandler(self):
        """
        If the HTTP request includes a body, it is passed to the handler
        function.
        """
        result = []
        def handler(method, path, headers, body):
            result.append(body)
            return Response(200, "hello", {})

        protocol = HTTP(handler, reactor=task.Clock())
        response = []
        protocol._writeResponse = lambda r: response.append(r)

        protocol.requestReceived("GET", "/", {}, "the body")
        self.assertEqual(result, ["the body"])
    def test_12_handlerReturnsDeferred(self):
        """
        If the handler returns a Deferred that fires with (code, body,
        headers), L{HTTP.requestReceived} writes it as a response using
        L{HTTP._writeResponse}.
        """
        # Handler that returns eventual result:
        result = defer.Deferred()
        def handler(method, path, headers, body):
            return result

        protocol = HTTP(handler, reactor=task.Clock())
        response = []
        protocol._writeResponse = lambda r: response.append(r)

        protocol.requestReceived("GET", "/", [], "")
        # Deferred hasn't fired yet, so no response is sent yet:
        self.assertEqual(len(response), 0)
        # Now we fire the Deferred, and response should be written:
        result.callback(Response(200, "response", {"key": "value"}))
        self.assertResponsesEqual(response[0],
                                  Response(200, "response", {"key": "value"}))