Add assert method to check a response for spec conformance

Similarly to the method for checking HTTP requests for spec conformance,
we're adding a method to do the same for HTTP responses. This one is a bit
less exciting because we're testing raw HTTP responses.
This commit is contained in:
Maik Hoepfel 2017-03-22 16:57:43 +08:00
parent 250f0e30c3
commit f35ad20748
2 changed files with 36 additions and 4 deletions

View File

@ -73,8 +73,8 @@ def _build_request(method, path, params=None, headers=None, body=None):
quoted_path += b'?' + parse.urlencode(params)
request = method.encode('ascii') + b' ' + quoted_path + b" HTTP/1.1\r\n"
for k, v in headers:
request += k.encode('ascii') + b': ' + v.encode('ascii') + b"\r\n"
for name, value in headers:
request += header_line(name, value)
request += b'\r\n'
@ -84,6 +84,13 @@ def _build_request(method, path, params=None, headers=None, body=None):
return request
def header_line(name, value):
"""
Given a header name and value, returns the line to use in a HTTP request or response.
"""
return name.encode('ascii') + b': ' + value.encode('ascii') + b"\r\n"
def _run_through_daphne(request, channel_name):
"""
Returns Daphne's channel message for a given request.

View File

@ -4,12 +4,13 @@ Contains a test case class to allow verifying ASGI messages
from __future__ import unicode_literals
from collections import defaultdict
import six
import socket
from six.moves.urllib import parse
import socket
import unittest
from . import factories
class ASGITestCase(unittest.TestCase):
"""
@ -122,3 +123,27 @@ class ASGITestCase(unittest.TestCase):
self.assertIsInstance(server_host, six.text_type)
self.assert_is_ip_address(server_host)
self.assertIsInstance(server_port, int)
def assert_valid_http_response_message(self, message, response):
self.assertTrue(message)
self.assertTrue(response.startswith(b'HTTP'))
status_code_bytes = six.text_type(message['status']).encode('ascii')
self.assertIn(status_code_bytes, response)
if 'content' in message:
self.assertIn(message['content'], response)
# Check that headers are in the given order.
# N.b. HTTP spec only enforces that the order of header values is kept, but
# the ASGI spec requires that order of all headers is kept. This code
# checks conformance with the stricter ASGI spec.
if 'headers' in message:
for name, value in message['headers']:
expected_header = factories.header_line(name, value)
# Daphne or Twisted turn our lower cased header names ('foo-bar') into title
# case ('Foo-Bar'). So technically we want to to match that the header name is
# present while ignoring casing, and want to ensure the value is present without
# altered casing. The approach below does this well enough.
self.assertIn(expected_header.lower(), response.lower())
self.assertIn(value.encode('ascii'), response)