Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Side by Side Diff: tests/standalone/src/io/HttpParserTest.dart

Issue 9704009: Support parsing HTTP responses where the body length is not known (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« runtime/bin/http_parser.dart ('K') | « runtime/bin/http_parser.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #source("../../../../runtime/bin/http_parser.dart"); 5 #source("../../../../runtime/bin/http_parser.dart");
6 6
7 class HttpParserTest { 7 class HttpParserTest {
8 static void runAllTests() { 8 static void runAllTests() {
9 testParseRequest(); 9 testParseRequest();
10 testParseResponse(); 10 testParseResponse();
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 testWrite(requestData, 10); 94 testWrite(requestData, 10);
95 testWrite(requestData, 1); 95 testWrite(requestData, 1);
96 } 96 }
97 97
98 static void _testParseResponse(String response, 98 static void _testParseResponse(String response,
99 int expectedStatusCode, 99 int expectedStatusCode,
100 String expectedReasonPhrase, 100 String expectedReasonPhrase,
101 [int expectedContentLength = 0, 101 [int expectedContentLength = 0,
102 int expectedBytesReceived = 0, 102 int expectedBytesReceived = 0,
103 Map expectedHeaders = null, 103 Map expectedHeaders = null,
104 bool chunked = false]) { 104 bool chunked = false,
105 bool close = false]) {
105 _HttpParser httpParser; 106 _HttpParser httpParser;
106 bool headersCompleteCalled; 107 bool headersCompleteCalled;
107 bool dataEndCalled; 108 bool dataEndCalled;
108 int statusCode; 109 int statusCode;
109 String reasonPhrase; 110 String reasonPhrase;
110 Map headers; 111 Map headers;
111 int contentLength; 112 int contentLength;
112 int bytesReceived; 113 int bytesReceived;
113 114
114 void reset() { 115 void reset() {
115 httpParser = new _HttpParser(); 116 httpParser = new _HttpParser();
116 httpParser.requestStart = (m, u) => Expect.fail("Expected response"); 117 httpParser.requestStart = (m, u) => Expect.fail("Expected response");
117 httpParser.responseStart = (s, r) { 118 httpParser.responseStart = (s, r) {
118 statusCode = s; 119 statusCode = s;
119 reasonPhrase = r; 120 reasonPhrase = r;
120 }; 121 };
121 httpParser.headerReceived = (f, v) { 122 httpParser.headerReceived = (f, v) {
122 Expect.isFalse(headersCompleteCalled); 123 Expect.isFalse(headersCompleteCalled);
123 headers[f] = v; 124 headers[f] = v;
124 }; 125 };
125 httpParser.headersComplete = () { 126 httpParser.headersComplete = () {
126 Expect.isFalse(headersCompleteCalled); 127 Expect.isFalse(headersCompleteCalled);
127 if (!chunked) { 128 if (!chunked && !close) {
128 Expect.equals(expectedContentLength, httpParser.contentLength); 129 Expect.equals(expectedContentLength, httpParser.contentLength);
129 } else { 130 } else {
130 Expect.equals(-1, httpParser.contentLength); 131 Expect.equals(-1, httpParser.contentLength);
131 } 132 }
132 if (expectedHeaders != null) { 133 if (expectedHeaders != null) {
133 expectedHeaders.forEach((String name, String value) { 134 expectedHeaders.forEach((String name, String value) {
134 Expect.equals(value, headers[name]); 135 Expect.equals(value, headers[name]);
135 }); 136 });
136 } 137 }
137 headersCompleteCalled = true; 138 headersCompleteCalled = true;
(...skipping 21 matching lines...) Expand all
159 } 160 }
160 161
161 void testWrite(List<int> requestData, [int chunkSize = -1]) { 162 void testWrite(List<int> requestData, [int chunkSize = -1]) {
162 if (chunkSize == -1) chunkSize = requestData.length; 163 if (chunkSize == -1) chunkSize = requestData.length;
163 reset(); 164 reset();
164 for (int pos = 0; pos < requestData.length; pos += chunkSize) { 165 for (int pos = 0; pos < requestData.length; pos += chunkSize) {
165 int remaining = requestData.length - pos; 166 int remaining = requestData.length - pos;
166 int writeLength = Math.min(chunkSize, remaining); 167 int writeLength = Math.min(chunkSize, remaining);
167 httpParser.writeList(requestData, pos, writeLength); 168 httpParser.writeList(requestData, pos, writeLength);
168 } 169 }
170 if (close) httpParser.connectionClosed();
169 checkExpectations(); 171 checkExpectations();
170 } 172 }
171 173
172 void testWriteAll(List<int> requestData) { 174 void testWriteAll(List<int> requestData) {
173 reset(); 175 reset();
174 httpParser.writeList(requestData, 0, requestData.length); 176 httpParser.writeList(requestData, 0, requestData.length);
175 checkExpectations(); 177 checkExpectations();
176 } 178 }
177 179
178 // Test parsing the request three times delivering the data in 180 // Test parsing the request three times delivering the data in
179 // different chunks. 181 // different chunks.
180 List<int> responseData = response.charCodes(); 182 List<int> responseData = response.charCodes();
181 testWrite(responseData); 183 testWrite(responseData);
182 testWrite(responseData, 10); 184 testWrite(responseData, 10);
183 testWrite(responseData, 1); 185 testWrite(responseData, 1);
184 } 186 }
185 187
186 static void testParseRequest() { 188 static void testParseRequest() {
187 String request; 189 String request;
188 Map headers; 190 Map headers;
189 request = "GET / HTTP/1.1\r\n\r\n"; 191 request = "GET / HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
190 _testParseRequest(request, "GET", "/"); 192 _testParseRequest(request, "GET", "/");
191 193
192 request = "POST / HTTP/1.1\r\n\r\n"; 194 request = "POST / HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
193 _testParseRequest(request, "POST", "/"); 195 _testParseRequest(request, "POST", "/");
194 196
195 request = "GET /index.html HTTP/1.1\r\n\r\n"; 197 request = "GET /index.html HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
196 _testParseRequest(request, "GET", "/index.html"); 198 _testParseRequest(request, "GET", "/index.html");
197 199
198 request = "POST /index.html HTTP/1.1\r\n\r\n"; 200 request = "POST /index.html HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
199 _testParseRequest(request, "POST", "/index.html"); 201 _testParseRequest(request, "POST", "/index.html");
200 202
201 request = "H /index.html HTTP/1.1\r\n\r\n"; 203 request = "H /index.html HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
202 _testParseRequest(request, "H", "/index.html"); 204 _testParseRequest(request, "H", "/index.html");
203 205
204 request = "HT /index.html HTTP/1.1\r\n\r\n"; 206 request = "HT /index.html HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
205 _testParseRequest(request, "HT", "/index.html"); 207 _testParseRequest(request, "HT", "/index.html");
206 208
207 request = "HTT /index.html HTTP/1.1\r\n\r\n"; 209 request = "HTT /index.html HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
208 _testParseRequest(request, "HTT", "/index.html"); 210 _testParseRequest(request, "HTT", "/index.html");
209 211
210 request = "HTTP /index.html HTTP/1.1\r\n\r\n"; 212 request = "HTTP /index.html HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
211 _testParseRequest(request, "HTTP", "/index.html"); 213 _testParseRequest(request, "HTTP", "/index.html");
212 214
213 request = """ 215 request = """
214 POST /test HTTP/1.1\r 216 POST /test HTTP/1.1\r
215 AAA: AAA\r 217 AAA: AAA\r
216 Content-Length: 0\r 218 Content-Length: 0\r
217 \r 219 \r
218 """; 220 """;
219 _testParseRequest(request, "POST", "/test"); 221 _testParseRequest(request, "POST", "/test");
220 222
221 request = """ 223 request = """
222 POST /test HTTP/1.1\r 224 POST /test HTTP/1.1\r
223 content-length: 0\r 225 content-length: 0\r
224 \r 226 \r
225 """; 227 """;
226 _testParseRequest(request, "POST", "/test"); 228 _testParseRequest(request, "POST", "/test");
227 229
228 request = """ 230 request = """
229 POST /test HTTP/1.1\r 231 POST /test HTTP/1.1\r
232 Content-Length: 0\r
230 Header-A: AAA\r 233 Header-A: AAA\r
231 X-Header-B: bbb\r 234 X-Header-B: bbb\r
232 \r 235 \r
233 """; 236 """;
234 headers = new Map(); 237 headers = new Map();
235 headers["header-a"] = "AAA"; 238 headers["header-a"] = "AAA";
236 headers["x-header-b"] = "bbb"; 239 headers["x-header-b"] = "bbb";
237 _testParseRequest(request, "POST", "/test", 0, 0, headers); 240 _testParseRequest(request, "POST", "/test", expectedHeaders: headers);
238 241
239 request = """ 242 request = """
240 POST /test HTTP/1.1\r 243 POST /test HTTP/1.1\r
244 Content-Length: 0\r
241 Header-A: AAA\r 245 Header-A: AAA\r
242 X-Header-B:\t \t bbb\r 246 X-Header-B:\t \t bbb\r
243 \r 247 \r
244 """; 248 """;
245 headers = new Map(); 249 headers = new Map();
246 headers["header-a"] = "AAA"; 250 headers["header-a"] = "AAA";
247 headers["x-header-b"] = "bbb"; 251 headers["x-header-b"] = "bbb";
248 _testParseRequest(request, "POST", "/test", 0, 0, headers); 252 _testParseRequest(request, "POST", "/test", expectedHeaders: headers);
249 253
250 request = """ 254 request = """
251 POST /test HTTP/1.1\r 255 POST /test HTTP/1.1\r
256 Content-Length: 0\r
252 Header-A: AA\r 257 Header-A: AA\r
253 A\r 258 A\r
254 X-Header-B: b\r 259 X-Header-B: b\r
255 b\r 260 b\r
256 \t b\r 261 \t b\r
257 \r 262 \r
258 """; 263 """;
259 headers = new Map(); 264 headers = new Map();
260 headers["header-a"] = "AAA"; 265 headers["header-a"] = "AAA";
261 headers["x-header-b"] = "bbb"; 266 headers["x-header-b"] = "bbb";
262 _testParseRequest(request, "POST", "/test", 0, 0, headers); 267 _testParseRequest(request, "POST", "/test", expectedHeaders: headers);
263 268
264 request = """ 269 request = """
265 POST /test HTTP/1.1\r 270 POST /test HTTP/1.1\r
266 Content-Length: 10\r 271 Content-Length: 10\r
267 \r 272 \r
268 0123456789"""; 273 0123456789""";
269 _testParseRequest(request, "POST", "/test", 10, 10); 274 _testParseRequest(request,
275 "POST",
276 "/test",
277 expectedContentLength: 10,
278 expectedBytesReceived: 10);
270 279
271 // Test chunked encoding. 280 // Test chunked encoding.
272 request = """ 281 request = """
273 POST /test HTTP/1.1\r 282 POST /test HTTP/1.1\r
274 Transfer-Encoding: chunked\r 283 Transfer-Encoding: chunked\r
275 \r 284 \r
276 5\r 285 5\r
277 01234\r 286 01234\r
278 5\r 287 5\r
279 56789\r 288 56789\r
280 0\r\n\r\n"""; 289 0\r\n\r\n""";
281 _testParseRequest(request, "POST", "/test", -1, 10, null, true); 290 _testParseRequest(request,
291 "POST",
292 "/test",
293 expectedContentLength: -1,
294 expectedBytesReceived: 10,
295 chunked: true);
282 296
283 // Test mixing chunked encoding and content length (content length 297 // Test mixing chunked encoding and content length (content length
284 // is ignored). 298 // is ignored).
285 request = """ 299 request = """
286 POST /test HTTP/1.1\r 300 POST /test HTTP/1.1\r
287 Content-Length: 7\r 301 Content-Length: 7\r
288 Transfer-Encoding: chunked\r 302 Transfer-Encoding: chunked\r
289 \r 303 \r
290 5\r 304 5\r
291 01234\r 305 01234\r
292 5\r 306 5\r
293 56789\r 307 56789\r
294 0\r\n\r\n"""; 308 0\r\n\r\n""";
295 _testParseRequest(request, "POST", "/test", -1, 10, null, true); 309 _testParseRequest(request,
310 "POST",
311 "/test",
312 expectedContentLength: -1,
313 expectedBytesReceived: 10,
314 chunked: true);
296 315
297 // Test mixing chunked encoding and content length (content length 316 // Test mixing chunked encoding and content length (content length
298 // is ignored). 317 // is ignored).
299 request = """ 318 request = """
300 POST /test HTTP/1.1\r 319 POST /test HTTP/1.1\r
301 Transfer-Encoding: chunked\r 320 Transfer-Encoding: chunked\r
302 Content-Length: 3\r 321 Content-Length: 3\r
303 \r 322 \r
304 5\r 323 5\r
305 01234\r 324 01234\r
306 5\r 325 5\r
307 56789\r 326 56789\r
308 0\r\n\r\n"""; 327 0\r\n\r\n""";
309 _testParseRequest(request, "POST", "/test", -1, 10, null, true); 328 _testParseRequest(request,
329 "POST",
330 "/test",
331 expectedContentLength: -1,
332 expectedBytesReceived: 10,
333 chunked: true);
310 334
311 // Test upper and lower case hex digits in chunked encoding. 335 // Test upper and lower case hex digits in chunked encoding.
312 request = """ 336 request = """
313 POST /test HTTP/1.1\r 337 POST /test HTTP/1.1\r
314 Transfer-Encoding: chunked\r 338 Transfer-Encoding: chunked\r
315 \r 339 \r
316 1E\r 340 1E\r
317 012345678901234567890123456789\r 341 012345678901234567890123456789\r
318 1e\r 342 1e\r
319 012345678901234567890123456789\r 343 012345678901234567890123456789\r
320 0\r\n\r\n"""; 344 0\r\n\r\n""";
321 _testParseRequest(request, "POST", "/test", -1, 60, null, true); 345 _testParseRequest(request,
346 "POST",
347 "/test",
348 expectedContentLength: -1,
349 expectedBytesReceived: 60,
350 chunked: true);
322 } 351 }
323 352
324 static void testParseResponse() { 353 static void testParseResponse() {
325 String response; 354 String response;
326 Map headers; 355 Map headers;
327 response = "HTTP/1.1 200 OK\r\n\r\n"; 356 response = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n";
328 _testParseResponse(response, 200, "OK"); 357 _testParseResponse(response, 200, "OK");
329 358
330 response = "HTTP/1.1 404 Not found\r\n\r\n"; 359 response = "HTTP/1.1 404 Not found\r\nContent-Length: 0\r\n\r\n";
331 _testParseResponse(response, 404, "Not found"); 360 _testParseResponse(response, 404, "Not found");
332 361
333 response = "HTTP/1.1 500 Server error\r\n\r\n"; 362 response = "HTTP/1.1 500 Server error\r\nContent-Length: 0\r\n\r\n";
334 _testParseResponse(response, 500, "Server error"); 363 _testParseResponse(response, 500, "Server error");
335 364
336 // Test content. 365 // Test content.
337 response = """ 366 response = """
338 HTTP/1.1 200 OK\r 367 HTTP/1.1 200 OK\r
339 Content-Length: 20\r 368 Content-Length: 20\r
340 \r 369 \r
341 01234567890123456789"""; 370 01234567890123456789""";
342 371
343 _testParseResponse(response, 200, "OK", 20, 20); 372 _testParseResponse(response,
373 200,
374 "OK",
375 expectedContentLength: 20,
376 expectedBytesReceived: 20);
377
344 // Test upper and lower case hex digits in chunked encoding. 378 // Test upper and lower case hex digits in chunked encoding.
345 response = """ 379 response = """
346 HTTP/1.1 200 OK\r 380 HTTP/1.1 200 OK\r
347 Transfer-Encoding: chunked\r 381 Transfer-Encoding: chunked\r
348 \r 382 \r
349 1A\r 383 1A\r
350 01234567890123456789012345\r 384 01234567890123456789012345\r
351 1f\r 385 1f\r
352 0123456789012345678901234567890\r 386 0123456789012345678901234567890\r
353 0\r\n\r\n"""; 387 0\r\n\r\n""";
354 _testParseResponse(response, 200, "OK", -1, 57, null, true); 388 _testParseResponse(response,
389 200,
390 "OK",
391 expectedContentLength: -1,
392 expectedBytesReceived: 57,
393 chunked: true);
394
395 // Test HTTP response without any transfer length indications
396 // where closing the connections indicated end of body.
397 response = """
398 HTTP/1.1 200 OK\r
399 \r
400 01234567890123456789012345
401 0123456789012345678901234567890
402 """;
403 _testParseResponse(response,
404 200,
405 "OK",
406 expectedContentLength: -1,
407 expectedBytesReceived: 59,
408 close: true);
355 } 409 }
356 } 410 }
357 411
358 412
359 void main() { 413 void main() {
360 HttpParserTest.runAllTests(); 414 HttpParserTest.runAllTests();
361 } 415 }
OLDNEW
« runtime/bin/http_parser.dart ('K') | « runtime/bin/http_parser.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698