OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 #library("http_parser_test.dart"); | |
6 #import("../../../chat/http.dart"); | |
7 | |
8 | |
9 class HTTPParserTest { | |
10 static void runAllTests() { | |
11 testParseRequest(); | |
12 testParseResponse(); | |
13 } | |
14 | |
15 static void _testParseRequest(String request, | |
16 String expectedMethod, | |
17 String expectedUri, | |
18 [int expectedContentLength = 0, | |
19 int expectedBytesReceived = 0, | |
20 Map expectedHeaders = null, | |
21 bool chunked = false]) { | |
22 HTTPParser httpParser; | |
23 bool headersCompleteCalled; | |
24 bool dataEndCalled; | |
25 String method; | |
26 String uri; | |
27 Map headers; | |
28 int contentLength; | |
29 int bytesReceived; | |
30 | |
31 void reset() { | |
32 httpParser = new HTTPParser(); | |
33 httpParser.requestStart = (m, u) { method = m; uri = u; }; | |
34 httpParser.responseStart = (s, r) { Expect.fail("Expected request"); }; | |
35 httpParser.headerReceived = | |
36 (f, v) { | |
37 Expect.isFalse(headersCompleteCalled); | |
38 headers[f] = v; | |
39 }; | |
40 httpParser.headersComplete = | |
41 () { | |
42 Expect.isFalse(headersCompleteCalled); | |
43 if (!chunked) { | |
44 Expect.equals(expectedContentLength, httpParser.contentLength); | |
45 } else { | |
46 Expect.equals(-1, httpParser.contentLength); | |
47 } | |
48 if (expectedHeaders != null) { | |
49 expectedHeaders.forEach( | |
50 (String name, String value) => | |
51 Expect.equals(value, headers[name])); | |
52 } | |
53 headersCompleteCalled = true; | |
54 }; | |
55 httpParser.dataReceived = | |
56 (List<int> data) { | |
57 Expect.isTrue(headersCompleteCalled); | |
58 bytesReceived += data.length; | |
59 }; | |
60 httpParser.dataEnd = () { dataEndCalled = true; }; | |
61 | |
62 headersCompleteCalled = false; | |
63 dataEndCalled = false; | |
64 method = null; | |
65 uri = null; | |
66 headers = new Map(); | |
67 bytesReceived = 0; | |
68 } | |
69 | |
70 void checkExpectations() { | |
71 Expect.equals(expectedMethod, method); | |
72 Expect.equals(expectedUri, uri); | |
73 Expect.isTrue(headersCompleteCalled); | |
74 Expect.equals(expectedBytesReceived, bytesReceived); | |
75 Expect.isTrue(dataEndCalled); | |
76 } | |
77 | |
78 void testWrite(List<int> requestData, [int chunkSize = -1]) { | |
79 if (chunkSize == -1) chunkSize = requestData.length; | |
80 reset(); | |
81 for (int pos = 0; pos < requestData.length; pos += chunkSize) { | |
82 int remaining = requestData.length - pos; | |
83 int writeLength = Math.min(chunkSize, remaining); | |
84 httpParser.writeList(requestData, pos, writeLength); | |
85 } | |
86 checkExpectations(); | |
87 } | |
88 | |
89 void testWriteAll(List<int> requestData) { | |
90 reset(); | |
91 httpParser.writeList(requestData, 0, requestData.length); | |
92 checkExpectations(); | |
93 } | |
94 | |
95 // Test parsing the request three times delivering the data in | |
96 // different chunks. | |
97 List<int> requestData = request.charCodes(); | |
98 testWrite(requestData); | |
99 testWrite(requestData, 10); | |
100 testWrite(requestData, 1); | |
101 } | |
102 | |
103 static void _testParseResponse(String response, | |
104 int expectedStatusCode, | |
105 String expectedReasonPhrase, | |
106 [int expectedContentLength = 0, | |
107 int expectedBytesReceived = 0, | |
108 Map expectedHeaders = null, | |
109 bool chunked = false]) { | |
110 HTTPParser httpParser; | |
111 bool headersCompleteCalled; | |
112 bool dataEndCalled; | |
113 int statusCode; | |
114 String reasonPhrase; | |
115 Map headers; | |
116 int contentLength; | |
117 int bytesReceived; | |
118 | |
119 void reset() { | |
120 httpParser = new HTTPParser(); | |
121 httpParser.requestStart = (m, u) { Expect.fail("Expected response"); }; | |
122 httpParser.responseStart = (s, r) { statusCode = s; reasonPhrase = r; }; | |
123 httpParser.headerReceived = | |
124 (f, v) { | |
125 Expect.isFalse(headersCompleteCalled); | |
126 headers[f] = v; | |
127 }; | |
128 httpParser.headersComplete = | |
129 () { | |
130 Expect.isFalse(headersCompleteCalled); | |
131 if (!chunked) { | |
132 Expect.equals(expectedContentLength, httpParser.contentLength); | |
133 } else { | |
134 Expect.equals(-1, httpParser.contentLength); | |
135 } | |
136 if (expectedHeaders != null) { | |
137 expectedHeaders.forEach( | |
138 (String name, String value) => | |
139 Expect.equals(value, headers[name])); | |
140 } | |
141 headersCompleteCalled = true; | |
142 }; | |
143 httpParser.dataReceived = | |
144 (List<int> data) { | |
145 Expect.isTrue(headersCompleteCalled); | |
146 bytesReceived += data.length; | |
147 }; | |
148 httpParser.dataEnd = () { dataEndCalled = true; }; | |
149 | |
150 headersCompleteCalled = false; | |
151 dataEndCalled = false; | |
152 statusCode = -1; | |
153 reasonPhrase = null; | |
154 headers = new Map(); | |
155 bytesReceived = 0; | |
156 } | |
157 | |
158 void checkExpectations() { | |
159 Expect.equals(expectedStatusCode, statusCode); | |
160 Expect.equals(expectedReasonPhrase, reasonPhrase); | |
161 Expect.isTrue(headersCompleteCalled); | |
162 Expect.equals(expectedBytesReceived, bytesReceived); | |
163 Expect.isTrue(dataEndCalled); | |
164 } | |
165 | |
166 void testWrite(List<int> requestData, [int chunkSize = -1]) { | |
167 if (chunkSize == -1) chunkSize = requestData.length; | |
168 reset(); | |
169 for (int pos = 0; pos < requestData.length; pos += chunkSize) { | |
170 int remaining = requestData.length - pos; | |
171 int writeLength = Math.min(chunkSize, remaining); | |
172 httpParser.writeList(requestData, pos, writeLength); | |
173 } | |
174 checkExpectations(); | |
175 } | |
176 | |
177 void testWriteAll(List<int> requestData) { | |
178 reset(); | |
179 httpParser.writeList(requestData, 0, requestData.length); | |
180 checkExpectations(); | |
181 } | |
182 | |
183 // Test parsing the request three times delivering the data in | |
184 // different chunks. | |
185 List<int> responseData = response.charCodes(); | |
186 testWrite(responseData); | |
187 testWrite(responseData, 10); | |
188 testWrite(responseData, 1); | |
189 } | |
190 | |
191 static void testParseRequest() { | |
192 String request; | |
193 Map headers; | |
194 request = "GET / HTTP/1.1\r\n\r\n"; | |
195 _testParseRequest(request, "GET", "/"); | |
196 | |
197 request = "POST / HTTP/1.1\r\n\r\n"; | |
198 _testParseRequest(request, "POST", "/"); | |
199 | |
200 request = "GET /index.html HTTP/1.1\r\n\r\n"; | |
201 _testParseRequest(request, "GET", "/index.html"); | |
202 | |
203 request = "POST /index.html HTTP/1.1\r\n\r\n"; | |
204 _testParseRequest(request, "POST", "/index.html"); | |
205 | |
206 request = "H /index.html HTTP/1.1\r\n\r\n"; | |
207 _testParseRequest(request, "H", "/index.html"); | |
208 | |
209 request = "HT /index.html HTTP/1.1\r\n\r\n"; | |
210 _testParseRequest(request, "HT", "/index.html"); | |
211 | |
212 request = "HTT /index.html HTTP/1.1\r\n\r\n"; | |
213 _testParseRequest(request, "HTT", "/index.html"); | |
214 | |
215 request = "HTTP /index.html HTTP/1.1\r\n\r\n"; | |
216 _testParseRequest(request, "HTTP", "/index.html"); | |
217 | |
218 request = """ | |
219 POST /test HTTP/1.1\r | |
220 AAA: AAA\r | |
221 Content-Length: 0\r | |
222 \r | |
223 """; | |
224 _testParseRequest(request, "POST", "/test"); | |
225 | |
226 request = """ | |
227 POST /test HTTP/1.1\r | |
228 content-length: 0\r | |
229 \r | |
230 """; | |
231 _testParseRequest(request, "POST", "/test"); | |
232 | |
233 request = """ | |
234 POST /test HTTP/1.1\r | |
235 Header-A: AAA\r | |
236 X-Header-B: bbb\r | |
237 \r | |
238 """; | |
239 headers = new Map(); | |
240 headers["header-a"] = "AAA"; | |
241 headers["x-header-b"] = "bbb"; | |
242 _testParseRequest(request, "POST", "/test", 0, 0, headers); | |
243 | |
244 request = """ | |
245 POST /test HTTP/1.1\r | |
246 Header-A: AAA\r | |
247 X-Header-B:\t \t bbb\r | |
248 \r | |
249 """; | |
250 headers = new Map(); | |
251 headers["header-a"] = "AAA"; | |
252 headers["x-header-b"] = "bbb"; | |
253 _testParseRequest(request, "POST", "/test", 0, 0, headers); | |
254 | |
255 request = """ | |
256 POST /test HTTP/1.1\r | |
257 Header-A: AA\r | |
258 A\r | |
259 X-Header-B: b\r | |
260 b\r | |
261 \t b\r | |
262 \r | |
263 """; | |
264 headers = new Map(); | |
265 headers["header-a"] = "AAA"; | |
266 headers["x-header-b"] = "bbb"; | |
267 _testParseRequest(request, "POST", "/test", 0, 0, headers); | |
268 | |
269 request = """ | |
270 POST /test HTTP/1.1\r | |
271 Content-Length: 10\r | |
272 \r | |
273 0123456789"""; | |
274 _testParseRequest(request, "POST", "/test", 10, 10); | |
275 | |
276 // Test chunked encoding. | |
277 request = """ | |
278 POST /test HTTP/1.1\r | |
279 Transfer-Encoding: chunked\r | |
280 \r | |
281 5\r | |
282 01234\r | |
283 5\r | |
284 56789\r | |
285 0\r\n"""; | |
286 _testParseRequest(request, "POST", "/test", -1, 10, null, true); | |
287 | |
288 // Test mixing chunked encoding and content length (content length | |
289 // is ignored). | |
290 request = """ | |
291 POST /test HTTP/1.1\r | |
292 Content-Length: 7\r | |
293 Transfer-Encoding: chunked\r | |
294 \r | |
295 5\r | |
296 01234\r | |
297 5\r | |
298 56789\r | |
299 0\r\n"""; | |
300 _testParseRequest(request, "POST", "/test", -1, 10, null, true); | |
301 | |
302 // Test mixing chunked encoding and content length (content length | |
303 // is ignored). | |
304 request = """ | |
305 POST /test HTTP/1.1\r | |
306 Transfer-Encoding: chunked\r | |
307 Content-Length: 3\r | |
308 \r | |
309 5\r | |
310 01234\r | |
311 5\r | |
312 56789\r | |
313 0\r\n"""; | |
314 _testParseRequest(request, "POST", "/test", -1, 10, null, true); | |
315 | |
316 // Test upper and lower case hex digits in chunked encoding. | |
317 request = """ | |
318 POST /test HTTP/1.1\r | |
319 Transfer-Encoding: chunked\r | |
320 \r | |
321 1E\r | |
322 012345678901234567890123456789\r | |
323 1e\r | |
324 012345678901234567890123456789\r | |
325 0\r\n"""; | |
326 _testParseRequest(request, "POST", "/test", -1, 60, null, true); | |
327 } | |
328 | |
329 static void testParseResponse() { | |
330 String response; | |
331 Map headers; | |
332 response = "HTTP/1.1 200 OK\r\n\r\n"; | |
333 _testParseResponse(response, 200, "OK"); | |
334 | |
335 response = "HTTP/1.1 404 Not found\r\n\r\n"; | |
336 _testParseResponse(response, 404, "Not found"); | |
337 | |
338 response = "HTTP/1.1 500 Server error\r\n\r\n"; | |
339 _testParseResponse(response, 500, "Server error"); | |
340 | |
341 // Test content. | |
342 response = """ | |
343 HTTP/1.1 200 OK\r | |
344 Content-Length: 20\r | |
345 \r | |
346 01234567890123456789"""; | |
347 | |
348 _testParseResponse(response, 200, "OK", 20, 20); | |
349 // Test upper and lower case hex digits in chunked encoding. | |
350 response = """ | |
351 HTTP/1.1 200 OK\r | |
352 Transfer-Encoding: chunked\r | |
353 \r | |
354 1A\r | |
355 01234567890123456789012345\r | |
356 1f\r | |
357 0123456789012345678901234567890\r | |
358 0\r\n"""; | |
359 _testParseResponse(response, 200, "OK", -1, 57, null, true); | |
360 } | |
361 } | |
362 | |
363 | |
364 void main() { | |
365 HTTPParserTest.runAllTests(); | |
366 } | |
OLD | NEW |