httputil_test.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 
00004 from __future__ import absolute_import, division, print_function, with_statement
00005 from tornado.httputil import url_concat, parse_multipart_form_data, HTTPHeaders, format_timestamp
00006 from tornado.escape import utf8
00007 from tornado.log import gen_log
00008 from tornado.testing import ExpectLog
00009 from tornado.test.util import unittest
00010 
00011 import datetime
00012 import logging
00013 import time
00014 
00015 
00016 class TestUrlConcat(unittest.TestCase):
00017 
00018     def test_url_concat_no_query_params(self):
00019         url = url_concat(
00020             "https://localhost/path",
00021             [('y', 'y'), ('z', 'z')],
00022         )
00023         self.assertEqual(url, "https://localhost/path?y=y&z=z")
00024 
00025     def test_url_concat_encode_args(self):
00026         url = url_concat(
00027             "https://localhost/path",
00028             [('y', '/y'), ('z', 'z')],
00029         )
00030         self.assertEqual(url, "https://localhost/path?y=%2Fy&z=z")
00031 
00032     def test_url_concat_trailing_q(self):
00033         url = url_concat(
00034             "https://localhost/path?",
00035             [('y', 'y'), ('z', 'z')],
00036         )
00037         self.assertEqual(url, "https://localhost/path?y=y&z=z")
00038 
00039     def test_url_concat_q_with_no_trailing_amp(self):
00040         url = url_concat(
00041             "https://localhost/path?x",
00042             [('y', 'y'), ('z', 'z')],
00043         )
00044         self.assertEqual(url, "https://localhost/path?x&y=y&z=z")
00045 
00046     def test_url_concat_trailing_amp(self):
00047         url = url_concat(
00048             "https://localhost/path?x&",
00049             [('y', 'y'), ('z', 'z')],
00050         )
00051         self.assertEqual(url, "https://localhost/path?x&y=y&z=z")
00052 
00053     def test_url_concat_mult_params(self):
00054         url = url_concat(
00055             "https://localhost/path?a=1&b=2",
00056             [('y', 'y'), ('z', 'z')],
00057         )
00058         self.assertEqual(url, "https://localhost/path?a=1&b=2&y=y&z=z")
00059 
00060     def test_url_concat_no_params(self):
00061         url = url_concat(
00062             "https://localhost/path?r=1&t=2",
00063             [],
00064         )
00065         self.assertEqual(url, "https://localhost/path?r=1&t=2")
00066 
00067 
00068 class MultipartFormDataTest(unittest.TestCase):
00069     def test_file_upload(self):
00070         data = b"""\
00071 --1234
00072 Content-Disposition: form-data; name="files"; filename="ab.txt"
00073 
00074 Foo
00075 --1234--""".replace(b"\n", b"\r\n")
00076         args = {}
00077         files = {}
00078         parse_multipart_form_data(b"1234", data, args, files)
00079         file = files["files"][0]
00080         self.assertEqual(file["filename"], "ab.txt")
00081         self.assertEqual(file["body"], b"Foo")
00082 
00083     def test_unquoted_names(self):
00084         # quotes are optional unless special characters are present
00085         data = b"""\
00086 --1234
00087 Content-Disposition: form-data; name=files; filename=ab.txt
00088 
00089 Foo
00090 --1234--""".replace(b"\n", b"\r\n")
00091         args = {}
00092         files = {}
00093         parse_multipart_form_data(b"1234", data, args, files)
00094         file = files["files"][0]
00095         self.assertEqual(file["filename"], "ab.txt")
00096         self.assertEqual(file["body"], b"Foo")
00097 
00098     def test_special_filenames(self):
00099         filenames = ['a;b.txt',
00100                      'a"b.txt',
00101                      'a";b.txt',
00102                      'a;"b.txt',
00103                      'a";";.txt',
00104                      'a\\"b.txt',
00105                      'a\\b.txt',
00106                      ]
00107         for filename in filenames:
00108             logging.debug("trying filename %r", filename)
00109             data = """\
00110 --1234
00111 Content-Disposition: form-data; name="files"; filename="%s"
00112 
00113 Foo
00114 --1234--""" % filename.replace('\\', '\\\\').replace('"', '\\"')
00115             data = utf8(data.replace("\n", "\r\n"))
00116             args = {}
00117             files = {}
00118             parse_multipart_form_data(b"1234", data, args, files)
00119             file = files["files"][0]
00120             self.assertEqual(file["filename"], filename)
00121             self.assertEqual(file["body"], b"Foo")
00122 
00123     def test_boundary_starts_and_ends_with_quotes(self):
00124         data = b'''\
00125 --1234
00126 Content-Disposition: form-data; name="files"; filename="ab.txt"
00127 
00128 Foo
00129 --1234--'''.replace(b"\n", b"\r\n")
00130         args = {}
00131         files = {}
00132         parse_multipart_form_data(b'"1234"', data, args, files)
00133         file = files["files"][0]
00134         self.assertEqual(file["filename"], "ab.txt")
00135         self.assertEqual(file["body"], b"Foo")
00136 
00137     def test_missing_headers(self):
00138         data = b'''\
00139 --1234
00140 
00141 Foo
00142 --1234--'''.replace(b"\n", b"\r\n")
00143         args = {}
00144         files = {}
00145         with ExpectLog(gen_log, "multipart/form-data missing headers"):
00146             parse_multipart_form_data(b"1234", data, args, files)
00147         self.assertEqual(files, {})
00148 
00149     def test_invalid_content_disposition(self):
00150         data = b'''\
00151 --1234
00152 Content-Disposition: invalid; name="files"; filename="ab.txt"
00153 
00154 Foo
00155 --1234--'''.replace(b"\n", b"\r\n")
00156         args = {}
00157         files = {}
00158         with ExpectLog(gen_log, "Invalid multipart/form-data"):
00159             parse_multipart_form_data(b"1234", data, args, files)
00160         self.assertEqual(files, {})
00161 
00162     def test_line_does_not_end_with_correct_line_break(self):
00163         data = b'''\
00164 --1234
00165 Content-Disposition: form-data; name="files"; filename="ab.txt"
00166 
00167 Foo--1234--'''.replace(b"\n", b"\r\n")
00168         args = {}
00169         files = {}
00170         with ExpectLog(gen_log, "Invalid multipart/form-data"):
00171             parse_multipart_form_data(b"1234", data, args, files)
00172         self.assertEqual(files, {})
00173 
00174     def test_content_disposition_header_without_name_parameter(self):
00175         data = b"""\
00176 --1234
00177 Content-Disposition: form-data; filename="ab.txt"
00178 
00179 Foo
00180 --1234--""".replace(b"\n", b"\r\n")
00181         args = {}
00182         files = {}
00183         with ExpectLog(gen_log, "multipart/form-data value missing name"):
00184             parse_multipart_form_data(b"1234", data, args, files)
00185         self.assertEqual(files, {})
00186 
00187     def test_data_after_final_boundary(self):
00188         # The spec requires that data after the final boundary be ignored.
00189         # http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html
00190         # In practice, some libraries include an extra CRLF after the boundary.
00191         data = b"""\
00192 --1234
00193 Content-Disposition: form-data; name="files"; filename="ab.txt"
00194 
00195 Foo
00196 --1234--
00197 """.replace(b"\n", b"\r\n")
00198         args = {}
00199         files = {}
00200         parse_multipart_form_data(b"1234", data, args, files)
00201         file = files["files"][0]
00202         self.assertEqual(file["filename"], "ab.txt")
00203         self.assertEqual(file["body"], b"Foo")
00204 
00205 
00206 class HTTPHeadersTest(unittest.TestCase):
00207     def test_multi_line(self):
00208         # Lines beginning with whitespace are appended to the previous line
00209         # with any leading whitespace replaced by a single space.
00210         # Note that while multi-line headers are a part of the HTTP spec,
00211         # their use is strongly discouraged.
00212         data = """\
00213 Foo: bar
00214  baz
00215 Asdf: qwer
00216 \tzxcv
00217 Foo: even
00218      more
00219      lines
00220 """.replace("\n", "\r\n")
00221         headers = HTTPHeaders.parse(data)
00222         self.assertEqual(headers["asdf"], "qwer zxcv")
00223         self.assertEqual(headers.get_list("asdf"), ["qwer zxcv"])
00224         self.assertEqual(headers["Foo"], "bar baz,even more lines")
00225         self.assertEqual(headers.get_list("foo"), ["bar baz", "even more lines"])
00226         self.assertEqual(sorted(list(headers.get_all())),
00227                          [("Asdf", "qwer zxcv"),
00228                           ("Foo", "bar baz"),
00229                           ("Foo", "even more lines")])
00230 
00231 
00232 class FormatTimestampTest(unittest.TestCase):
00233     # Make sure that all the input types are supported.
00234     TIMESTAMP = 1359312200.503611
00235     EXPECTED = 'Sun, 27 Jan 2013 18:43:20 GMT'
00236 
00237     def check(self, value):
00238         self.assertEqual(format_timestamp(value), self.EXPECTED)
00239 
00240     def test_unix_time_float(self):
00241         self.check(self.TIMESTAMP)
00242 
00243     def test_unix_time_int(self):
00244         self.check(int(self.TIMESTAMP))
00245 
00246     def test_struct_time(self):
00247         self.check(time.gmtime(self.TIMESTAMP))
00248 
00249     def test_time_tuple(self):
00250         tup = tuple(time.gmtime(self.TIMESTAMP))
00251         self.assertEqual(9, len(tup))
00252         self.check(tup)
00253 
00254     def test_datetime(self):
00255         self.check(datetime.datetime.utcfromtimestamp(self.TIMESTAMP))


rosbridge_server
Author(s): Jonathan Mace
autogenerated on Thu Aug 27 2015 14:50:39