|
1 # :set encoding=utf8 |
|
2 |
|
3 """ |
|
4 Unit tests for qmsk.web.http |
|
5 """ |
|
6 |
|
7 import unittest |
|
8 from cStringIO import StringIO |
|
9 |
|
10 import http |
|
11 |
|
12 class TestHttpUtil (unittest.TestCase) : |
|
13 def test_request_url (self) : |
|
14 for env, url in ( |
|
15 ({ |
|
16 'wsgi.url_scheme': "https", |
|
17 'HTTP_HOST': "testhost", |
|
18 'REQUEST_URI': "/test" |
|
19 }, "https://testhost/test"), |
|
20 ({ |
|
21 'HTTP_HOST': "-" |
|
22 }, "[???]://-[???]") |
|
23 ) : |
|
24 self.assertEqual(http.request_url(env), url) |
|
25 |
|
26 class TestHttpRequest (unittest.TestCase) : |
|
27 def build_request (self, env_dict={}, **env_kw) : |
|
28 env = { |
|
29 'wsgi.url_scheme': "http", |
|
30 'HTTP_HOST': "testhost", |
|
31 'REQUEST_METHOD': "GET", |
|
32 } |
|
33 env.update(env_dict) |
|
34 env.update(env_kw) |
|
35 |
|
36 return http.Request(env) |
|
37 |
|
38 def test_site_host (self) : |
|
39 self.assertEqual(self.build_request(HTTP_HOST='testhost').site_host, "testhost") |
|
40 self.assertEqual(self.build_request(HTTP_HOST='testhost:13').site_host, "testhost:13") |
|
41 |
|
42 def test_site_root (self) : |
|
43 for script_name, site_root in ( |
|
44 ('', "" ), |
|
45 ('/foo', "" ), |
|
46 ('/foo/bar/', "/foo/bar" ), |
|
47 ) : |
|
48 self.assertEqual(self.build_request(SCRIPT_NAME=script_name).site_root, site_root) |
|
49 |
|
50 def test_get_page_name (self) : |
|
51 for path_info, page_name in ( |
|
52 ('', ""), |
|
53 ('/', ""), |
|
54 ('/foo1/bar', "foo1/bar"), |
|
55 ('/foo2/bar/', "foo2/bar/"), |
|
56 ('/foo3/bar/../', "foo3/"), |
|
57 ('/foo4/bar/..', "foo4"), |
|
58 ('//', ""), |
|
59 ) : |
|
60 self.assertEqual(self.build_request(PATH_INFO=path_info).get_page_name(), page_name) |
|
61 |
|
62 def _test_page_prefix (self, request_uri, path_info, page_prefix) : |
|
63 self.assertEqual(self.build_request(REQUEST_URI=request_uri, PATH_INFO=path_info).page_prefix, page_prefix) |
|
64 |
|
65 def test_page_prefix_empty (self) : |
|
66 self._test_page_prefix('', '', "") |
|
67 |
|
68 def test_page_prefix_root_dir (self) : |
|
69 self._test_page_prefix('/foo/', '/foo/', "") |
|
70 |
|
71 def test_page_prefix_cgi (self) : |
|
72 self._test_page_prefix('/foo.cgi/quux', '/quux', "/foo.cgi") |
|
73 |
|
74 def test_page_prefix_qargs (self) : |
|
75 self._test_page_prefix('/foo.cgi/?foo', '/', "/foo.cgi") |
|
76 |
|
77 def test_get_arg (self) : |
|
78 for query_string, key, value in ( |
|
79 ('', 'foo', None), |
|
80 ('foo', 'foo', ''), |
|
81 ('foo=', 'foo', ''), |
|
82 ('foo=bar', 'foo', 'bar'), |
|
83 ('foo=&bar=.', 'bar', '.'), |
|
84 ) : |
|
85 self.assertEqual(self.build_request(QUERY_STRING=query_string).get_arg(key, None), value) |
|
86 |
|
87 def test_get_args (self) : |
|
88 for query_string, keyvals in ( |
|
89 ('', []), |
|
90 ('foo1=&bar', [('foo1', ''), ('bar', '')]), |
|
91 ('foo2=bar', [('foo2', 'bar')]), |
|
92 ('foo3=bar&foo3', [('foo3', 'bar'), ('foo3', '')]), |
|
93 ) : |
|
94 self.assertEqual(self.build_request(QUERY_STRING=query_string).get_args(), keyvals) |
|
95 |
|
96 def _build_post (self, method='POST', **vals) : |
|
97 data = '&'.join('%s=%s' % kv for kv in vals.iteritems()) |
|
98 |
|
99 return self.build_request({'wsgi.input': StringIO(data)}, REQUEST_METHOD=method, CONTENT_TYPE='application/x-www-form-urlencoded') |
|
100 |
|
101 def test_is_post (self) : |
|
102 for request_method, bool in ( |
|
103 ('GET', False), |
|
104 ('POST', True), |
|
105 ('post', True), |
|
106 ) : |
|
107 self.assertEqual(self._build_post(method=request_method).is_post(), bool) |
|
108 |
|
109 def _test_post (self, **vals) : |
|
110 req = self._build_post(**vals) |
|
111 |
|
112 def test_post_empty (self) : |
|
113 req = self._build_post() |
|
114 |
|
115 self.assertTrue(req.is_post()) |
|
116 self.assertEqual(req.get_post('foo', None), None) |
|
117 |
|
118 def test_post_simple (self) : |
|
119 req = self._build_post(foo='bar') |
|
120 |
|
121 self.assertTrue(req.is_post()) |
|
122 self.assertEqual(req.get_post('foo', None), 'bar') |
|
123 |
|
124 class TestHttpResponse (unittest.TestCase) : |
|
125 def test_status (self) : |
|
126 response = http.Response(None, status='100 Continue') |
|
127 |
|
128 self.assertEqual(response.get_status(), '100 Continue') |
|
129 |
|
130 def test_data_empty (self) : |
|
131 self.assertEqual(http.Response(None).get_data(), '') |
|
132 |
|
133 def test_data_str (self) : |
|
134 self.assertEqual(http.Response('foo').get_data(), 'foo') |
|
135 |
|
136 def test_data_utf8 (self) : |
|
137 data = u'föö' |
|
138 |
|
139 self.assertEqual(http.Response(data).get_data(), data.encode('utf8')) |
|
140 |
|
141 def test_data_utf16 (self) : |
|
142 data = u'fåå' |
|
143 |
|
144 self.assertEqual(http.Response(data, charset='utf16').get_data(), data.encode('utf16')) |
|
145 |
|
146 def test_data_invalid (self) : |
|
147 data = 'fää' |
|
148 |
|
149 self.assertRaises(UnicodeDecodeError, http.Response(data).get_data) |
|
150 |
|
151 def test_data_binary (self) : |
|
152 data = '\x01\x00' |
|
153 |
|
154 self.assertEqual(http.Response(data, charset=None).get_data(), data) |
|
155 |
|
156 def test_content_type_none (self) : |
|
157 response = http.Response(None, content_type=None) |
|
158 |
|
159 self.assertEqual(response.get_headers(), []) |
|
160 |
|
161 def test_content_type_default (self) : |
|
162 self.assertEqual(http.Response(None).get_headers(), [('Content-type', "text/html; charset=\"UTF-8\"")]) |
|
163 |
|
164 def test_content_type_weird (self) : |
|
165 self.assertEqual(http.Response(None, content_type="foo/x-bar").get_headers(), [('Content-type', "foo/x-bar; charset=\"UTF-8\"")]) |
|
166 |
|
167 def test_content_type_charset (self) : |
|
168 self.assertEqual(http.Response(None, content_type="foo/x-bar", charset="---").get_headers(), [('Content-type', "foo/x-bar; charset=\"---\"")]) |
|
169 |
|
170 def _build_headers (self, tlist=None, **map) : |
|
171 response = http.Response(None) |
|
172 |
|
173 if tlist : |
|
174 for name, value, params in tlist : |
|
175 response.add_header(name, value, **params) |
|
176 |
|
177 for name, value in map.iteritems() : |
|
178 response.add_header(name, value) |
|
179 |
|
180 return response |
|
181 |
|
182 def test_headers_simple (self) : |
|
183 self.assertEqual(self._build_headers(**{'X-Foo': 'bar, never'}).get_headers(), [ |
|
184 ('Content-type', "text/html; charset=\"UTF-8\""), |
|
185 ('X-Foo', "bar, never") |
|
186 ]) |
|
187 |
|
188 def test_headers_params (self) : |
|
189 self.assertEqual(self._build_headers([('X-Bar', 'bar', dict(never='yes'))]).get_headers(), [ |
|
190 ('Content-type', "text/html; charset=\"UTF-8\""), |
|
191 ('X-Bar', "bar; never=\"yes\"") |
|
192 ]) |
|
193 |
|
194 def test_headers_multi (self) : |
|
195 self.assertEqual(self._build_headers([('X-Bar', 'bar', {}), ('X-bar', 'foo', {})]).get_headers(), [ |
|
196 ('Content-type', "text/html; charset=\"UTF-8\""), |
|
197 ('X-Bar', "bar"), |
|
198 ('X-bar', "foo"), |
|
199 ]) |
|
200 |
|
201 class TestHttpRedirect (unittest.TestCase) : |
|
202 def test_redirect (self) : |
|
203 response = http.Redirect('http://test/bar') |
|
204 |
|
205 self.assertEquals(response.get_status(), '302 Found') |
|
206 self.assertEquals(response.get_headers(), [('Location', 'http://test/bar')]) |
|
207 self.assertEquals(response.get_data(), '') |
|
208 |
|
209 |