| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 import 'dart:async'; | 5 import 'dart:async'; |
| 6 import 'dart:math'; | 6 import 'dart:math'; |
| 7 | 7 |
| 8 import "package:test/test.dart"; | 8 import "package:test/test.dart"; |
| 9 import "package:mime/mime.dart"; | 9 import "package:mime/mime.dart"; |
| 10 | 10 |
| 11 void _writeInChunks(List<int> data, | 11 void _writeInChunks( |
| 12 int chunkSize, | 12 List<int> data, int chunkSize, StreamController<List<int>> controller) { |
| 13 StreamController<List<int>> controller) { | |
| 14 if (chunkSize == -1) chunkSize = data.length; | 13 if (chunkSize == -1) chunkSize = data.length; |
| 15 | 14 |
| 16 int written = 0; | 15 int written = 0; |
| 17 for (int pos = 0; pos < data.length; pos += chunkSize) { | 16 for (int pos = 0; pos < data.length; pos += chunkSize) { |
| 18 int remaining = data.length - pos; | 17 int remaining = data.length - pos; |
| 19 int writeLength = min(chunkSize, remaining); | 18 int writeLength = min(chunkSize, remaining); |
| 20 controller.add(data.sublist(pos, pos + writeLength)); | 19 controller.add(data.sublist(pos, pos + writeLength)); |
| 21 written += writeLength; | 20 written += writeLength; |
| 22 } | 21 } |
| 23 controller.close(); | 22 controller.close(); |
| 24 } | 23 } |
| 25 | 24 |
| 25 enum TestMode { IMMEDIATE_LISTEN, DELAY_LISTEN, PAUSE_RESUME } |
| 26 | 26 |
| 27 enum TestMode { | 27 void _runParseTest(String message, String boundary, TestMode mode, |
| 28 IMMEDIATE_LISTEN, | 28 [List<Map> expectedHeaders, List expectedParts, bool expectError = false]) { |
| 29 DELAY_LISTEN, | |
| 30 PAUSE_RESUME | |
| 31 } | |
| 32 | |
| 33 void _runParseTest(String message, | |
| 34 String boundary, | |
| 35 TestMode mode, | |
| 36 [List<Map> expectedHeaders, | |
| 37 List expectedParts, | |
| 38 bool expectError = false]) { | |
| 39 Future testWrite(List<int> data, [int chunkSize = -1]) { | 29 Future testWrite(List<int> data, [int chunkSize = -1]) { |
| 40 StreamController controller = new StreamController(sync: true); | 30 StreamController controller = new StreamController(sync: true); |
| 41 | 31 |
| 42 var stream = controller.stream.transform( | 32 var stream = |
| 43 new MimeMultipartTransformer(boundary)); | 33 controller.stream.transform(new MimeMultipartTransformer(boundary)); |
| 44 int i = 0; | 34 int i = 0; |
| 45 var completer = new Completer(); | 35 var completer = new Completer(); |
| 46 var futures = []; | 36 var futures = []; |
| 47 stream.listen((multipart) { | 37 stream.listen((multipart) { |
| 48 int part = i++; | 38 int part = i++; |
| 49 if (expectedHeaders != null) { | 39 if (expectedHeaders != null) { |
| 50 expect(multipart.headers, equals(expectedHeaders[part])); | 40 expect(multipart.headers, equals(expectedHeaders[part])); |
| 51 } | 41 } |
| 52 switch (mode) { | 42 switch (mode) { |
| 53 case TestMode.IMMEDIATE_LISTEN: | 43 case TestMode.IMMEDIATE_LISTEN: |
| 54 futures.add(multipart.fold([], (buffer, data) => buffer..addAll(data)) | 44 futures.add(multipart.fold([], (buffer, data) => buffer..addAll(data)) |
| 55 .then((data) { | 45 .then((data) { |
| 56 if (expectedParts[part] != null) { | 46 if (expectedParts[part] != null) { |
| 57 expect(data, equals(expectedParts[part].codeUnits)); | 47 expect(data, equals(expectedParts[part].codeUnits)); |
| 58 } | 48 } |
| 59 })); | 49 })); |
| 60 break; | 50 break; |
| 61 | 51 |
| 62 case TestMode.DELAY_LISTEN: | 52 case TestMode.DELAY_LISTEN: |
| 63 futures.add(new Future(() { | 53 futures.add(new Future(() { |
| 64 return multipart.fold([], (buffer, data) => buffer..addAll(data)) | 54 return multipart.fold([], (buffer, data) => buffer..addAll(data)) |
| 65 .then((data) { | 55 .then((data) { |
| 66 if (expectedParts[part] != null) { | 56 if (expectedParts[part] != null) { |
| 67 expect(data, equals(expectedParts[part].codeUnits)); | 57 expect(data, equals(expectedParts[part].codeUnits)); |
| 68 } | 58 } |
| 69 }); | 59 }); |
| 70 })); | 60 })); |
| 71 break; | 61 break; |
| 72 | 62 |
| 73 case TestMode.PAUSE_RESUME: | 63 case TestMode.PAUSE_RESUME: |
| 74 var completer = new Completer(); | 64 var completer = new Completer(); |
| 75 futures.add(completer.future); | 65 futures.add(completer.future); |
| 76 var buffer = []; | 66 var buffer = []; |
| 77 var subscription; | 67 var subscription; |
| 78 subscription = multipart.listen( | 68 subscription = multipart.listen((data) { |
| 79 (data) { | 69 buffer.addAll(data); |
| 80 buffer.addAll(data); | 70 subscription.pause(); |
| 81 subscription.pause(); | 71 new Future(() => subscription.resume()); |
| 82 new Future(() => subscription.resume()); | 72 }, onDone: () { |
| 83 }, | 73 if (expectedParts[part] != null) { |
| 84 onDone: () { | 74 expect(buffer, equals(expectedParts[part].codeUnits)); |
| 85 if (expectedParts[part] != null) { | 75 } |
| 86 expect(buffer, equals(expectedParts[part].codeUnits)); | 76 completer.complete(); |
| 87 } | 77 }); |
| 88 completer.complete(); | |
| 89 }); | |
| 90 break; | 78 break; |
| 91 } | 79 } |
| 92 }, onError: (error) { | 80 }, onError: (error) { |
| 93 if (!expectError) throw error; | 81 if (!expectError) throw error; |
| 94 }, onDone: () { | 82 }, onDone: () { |
| 95 if (expectedParts != null) { | 83 if (expectedParts != null) { |
| 96 expect(i, equals(expectedParts.length)); | 84 expect(i, equals(expectedParts.length)); |
| 97 } | 85 } |
| 98 Future.wait(futures).then(completer.complete); | 86 Future.wait(futures).then(completer.complete); |
| 99 }); | 87 }); |
| 100 | 88 |
| 101 _writeInChunks(data, chunkSize, controller); | 89 _writeInChunks(data, chunkSize, controller); |
| 102 | 90 |
| 103 return completer.future; | 91 return completer.future; |
| 104 } | 92 } |
| 105 | 93 |
| 106 Future testFirstPartOnly(List<int> data, [int chunkSize = -1]) { | 94 Future testFirstPartOnly(List<int> data, [int chunkSize = -1]) { |
| 107 var completer = new Completer(); | 95 var completer = new Completer(); |
| 108 var controller = new StreamController(sync: true); | 96 var controller = new StreamController(sync: true); |
| 109 | 97 |
| 110 var stream = controller.stream.transform( | 98 var stream = |
| 111 new MimeMultipartTransformer(boundary)); | 99 controller.stream.transform(new MimeMultipartTransformer(boundary)); |
| 112 | 100 |
| 113 var subscription; | 101 var subscription; |
| 114 subscription = stream.first.then((multipart) { | 102 subscription = stream.first.then((multipart) { |
| 115 if (expectedHeaders != null) { | 103 if (expectedHeaders != null) { |
| 116 expect(multipart.headers, equals(expectedHeaders[0])); | 104 expect(multipart.headers, equals(expectedHeaders[0])); |
| 117 } | 105 } |
| 118 return (multipart.fold([], (b, d) => b..addAll(d)).then((data) { | 106 return (multipart.fold([], (b, d) => b..addAll(d)).then((data) { |
| 119 if (expectedParts != null && expectedParts[0] != null) { | 107 if (expectedParts != null && expectedParts[0] != null) { |
| 120 expect(data, equals(expectedParts[0].codeUnits)); | 108 expect(data, equals(expectedParts[0].codeUnits)); |
| 121 } | 109 } |
| 122 })); | 110 })); |
| 123 }).then((_) { | 111 }).then((_) { |
| 124 completer.complete(); | 112 completer.complete(); |
| 125 }); | 113 }); |
| 126 | 114 |
| 127 _writeInChunks(data, chunkSize, controller); | 115 _writeInChunks(data, chunkSize, controller); |
| 128 | 116 |
| 129 return completer.future; | 117 return completer.future; |
| 130 } | 118 } |
| 131 | 119 |
| 132 Future testCompletePartAfterCancel(List<int> data, | 120 Future testCompletePartAfterCancel(List<int> data, int parts, |
| 133 int parts, | 121 [int chunkSize = -1]) { |
| 134 [int chunkSize = -1]) { | |
| 135 var completer = new Completer(); | 122 var completer = new Completer(); |
| 136 var controller = new StreamController(sync: true); | 123 var controller = new StreamController(sync: true); |
| 137 var stream = controller.stream.transform( | 124 var stream = |
| 138 new MimeMultipartTransformer(boundary)); | 125 controller.stream.transform(new MimeMultipartTransformer(boundary)); |
| 139 var subscription; | 126 var subscription; |
| 140 int i = 0; | 127 int i = 0; |
| 141 var futures = []; | 128 var futures = []; |
| 142 subscription = stream.listen((multipart) { | 129 subscription = stream.listen((multipart) { |
| 143 int partIndex = i; | 130 int partIndex = i; |
| 144 | 131 |
| 145 if (partIndex >= parts) { | 132 if (partIndex >= parts) { |
| 146 throw 'Expected no more parts, but got one.'; | 133 throw 'Expected no more parts, but got one.'; |
| 147 } | 134 } |
| 148 | 135 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 164 | 151 |
| 165 _writeInChunks(data, chunkSize, controller); | 152 _writeInChunks(data, chunkSize, controller); |
| 166 | 153 |
| 167 return completer.future; | 154 return completer.future; |
| 168 } | 155 } |
| 169 | 156 |
| 170 // Test parsing the data three times delivering the data in | 157 // Test parsing the data three times delivering the data in |
| 171 // different chunks. | 158 // different chunks. |
| 172 List<int> data = message.codeUnits; | 159 List<int> data = message.codeUnits; |
| 173 test('test', () { | 160 test('test', () { |
| 174 expect(Future.wait([ | 161 expect( |
| 175 testWrite(data), | 162 Future.wait([ |
| 176 testWrite(data, 10), | 163 testWrite(data), |
| 177 testWrite(data, 2), | 164 testWrite(data, 10), |
| 178 testWrite(data, 1), | 165 testWrite(data, 2), |
| 179 ]), completes); | 166 testWrite(data, 1), |
| 167 ]), |
| 168 completes); |
| 180 }); | 169 }); |
| 181 | 170 |
| 182 if (expectedParts.length > 0) { | 171 if (expectedParts.length > 0) { |
| 183 test('test-first-part-only', () { | 172 test('test-first-part-only', () { |
| 184 expect(Future.wait([ | 173 expect( |
| 185 testFirstPartOnly(data), | 174 Future.wait([ |
| 186 testFirstPartOnly(data, 10), | 175 testFirstPartOnly(data), |
| 187 testFirstPartOnly(data, 2), | 176 testFirstPartOnly(data, 10), |
| 188 testFirstPartOnly(data, 1), | 177 testFirstPartOnly(data, 2), |
| 189 ]), completes); | 178 testFirstPartOnly(data, 1), |
| 179 ]), |
| 180 completes); |
| 190 }); | 181 }); |
| 191 | 182 |
| 192 test('test-n-parts-only', () { | 183 test('test-n-parts-only', () { |
| 193 int numPartsExpected = expectedParts.length - 1; | 184 int numPartsExpected = expectedParts.length - 1; |
| 194 if (numPartsExpected == 0) numPartsExpected = 1; | 185 if (numPartsExpected == 0) numPartsExpected = 1; |
| 195 | 186 |
| 196 expect(Future.wait([ | 187 expect( |
| 197 testCompletePartAfterCancel(data, numPartsExpected), | 188 Future.wait([ |
| 198 testCompletePartAfterCancel(data, numPartsExpected, 10), | 189 testCompletePartAfterCancel(data, numPartsExpected), |
| 199 testCompletePartAfterCancel(data, numPartsExpected, 2), | 190 testCompletePartAfterCancel(data, numPartsExpected, 10), |
| 200 testCompletePartAfterCancel(data, numPartsExpected, 1), | 191 testCompletePartAfterCancel(data, numPartsExpected, 2), |
| 201 ]), completes); | 192 testCompletePartAfterCancel(data, numPartsExpected, 1), |
| 193 ]), |
| 194 completes); |
| 202 }); | 195 }); |
| 203 } | 196 } |
| 204 } | 197 } |
| 205 | 198 |
| 206 void _testParse(String message, | 199 void _testParse(String message, String boundary, |
| 207 String boundary, | 200 [List<Map> expectedHeaders, List expectedParts, bool expectError = false]) { |
| 208 [List<Map> expectedHeaders, | 201 _runParseTest(message, boundary, TestMode.IMMEDIATE_LISTEN, expectedHeaders, |
| 209 List expectedParts, | 202 expectedParts, expectError); |
| 210 bool expectError = false]) { | 203 _runParseTest(message, boundary, TestMode.DELAY_LISTEN, expectedHeaders, |
| 211 _runParseTest( | 204 expectedParts, expectError); |
| 212 message, boundary, TestMode.IMMEDIATE_LISTEN, | 205 _runParseTest(message, boundary, TestMode.PAUSE_RESUME, expectedHeaders, |
| 213 expectedHeaders, expectedParts, expectError); | 206 expectedParts, expectError); |
| 214 _runParseTest( | |
| 215 message, boundary, TestMode.DELAY_LISTEN, | |
| 216 expectedHeaders, expectedParts, expectError); | |
| 217 _runParseTest( | |
| 218 message, boundary, TestMode.PAUSE_RESUME, | |
| 219 expectedHeaders, expectedParts, expectError); | |
| 220 } | 207 } |
| 221 | 208 |
| 222 void _testParseValid() { | 209 void _testParseValid() { |
| 223 // Empty message from Chrome form post. | 210 // Empty message from Chrome form post. |
| 224 var message = '------WebKitFormBoundaryU3FBruSkJKG0Yor1--\r\n'; | 211 var message = '------WebKitFormBoundaryU3FBruSkJKG0Yor1--\r\n'; |
| 225 _testParse(message, "----WebKitFormBoundaryU3FBruSkJKG0Yor1", [], []); | 212 _testParse(message, "----WebKitFormBoundaryU3FBruSkJKG0Yor1", [], []); |
| 226 | 213 |
| 227 // Sample from Wikipedia. | 214 // Sample from Wikipedia. |
| 228 message = """ | 215 message = """ |
| 229 This is a message with multiple parts in MIME format.\r | 216 This is a message with multiple parts in MIME format.\r |
| 230 --frontier\r | 217 --frontier\r |
| 231 Content-Type: text/plain\r | 218 Content-Type: text/plain\r |
| 232 \r | 219 \r |
| 233 This is the body of the message.\r | 220 This is the body of the message.\r |
| 234 --frontier\r | 221 --frontier\r |
| 235 Content-Type: application/octet-stream\r | 222 Content-Type: application/octet-stream\r |
| 236 Content-Transfer-Encoding: base64\r | 223 Content-Transfer-Encoding: base64\r |
| 237 \r | 224 \r |
| 238 PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg | 225 PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg |
| 239 Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg=\r | 226 Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg=\r |
| 240 --frontier--\r\n"""; | 227 --frontier--\r\n"""; |
| 241 var headers1 = <String, String>{"content-type": "text/plain"}; | 228 var headers1 = <String, String>{"content-type": "text/plain"}; |
| 242 var headers2 = <String, String>{"content-type": "application/octet-stream", | 229 var headers2 = <String, String>{ |
| 243 "content-transfer-encoding": "base64"}; | 230 "content-type": "application/octet-stream", |
| 231 "content-transfer-encoding": "base64" |
| 232 }; |
| 244 var body1 = "This is the body of the message."; | 233 var body1 = "This is the body of the message."; |
| 245 var body2 = """ | 234 var body2 = """ |
| 246 PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg | 235 PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg |
| 247 Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg="""; | 236 Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg="""; |
| 248 _testParse(message, "frontier", [headers1, headers2], [body1, body2]); | 237 _testParse(message, "frontier", [headers1, headers2], [body1, body2]); |
| 249 | 238 |
| 250 // Sample from HTML 4.01 Specification. | 239 // Sample from HTML 4.01 Specification. |
| 251 message = """ | 240 message = """ |
| 252 \r\n--AaB03x\r | 241 \r\n--AaB03x\r |
| 253 Content-Disposition: form-data; name=\"submit-name\"\r | 242 Content-Disposition: form-data; name=\"submit-name\"\r |
| 254 \r | 243 \r |
| 255 Larry\r | 244 Larry\r |
| 256 --AaB03x\r | 245 --AaB03x\r |
| 257 Content-Disposition: form-data; name=\"files\"; filename=\"file1.txt\"\r | 246 Content-Disposition: form-data; name=\"files\"; filename=\"file1.txt\"\r |
| 258 Content-Type: text/plain\r | 247 Content-Type: text/plain\r |
| 259 \r | 248 \r |
| 260 ... contents of file1.txt ...\r | 249 ... contents of file1.txt ...\r |
| 261 --AaB03x--\r\n"""; | 250 --AaB03x--\r\n"""; |
| 262 headers1 = <String, String>{ | 251 headers1 = <String, String>{ |
| 263 "content-disposition": "form-data; name=\"submit-name\""}; | 252 "content-disposition": "form-data; name=\"submit-name\"" |
| 253 }; |
| 264 headers2 = <String, String>{ | 254 headers2 = <String, String>{ |
| 265 "content-type": "text/plain", | 255 "content-type": "text/plain", |
| 266 "content-disposition": "form-data; name=\"files\"; filename=\"file1.txt\"" | 256 "content-disposition": "form-data; name=\"files\"; filename=\"file1.txt\"" |
| 267 }; | 257 }; |
| 268 body1 = "Larry"; | 258 body1 = "Larry"; |
| 269 body2 = "... contents of file1.txt ..."; | 259 body2 = "... contents of file1.txt ..."; |
| 270 _testParse(message, "AaB03x", [headers1, headers2], [body1, body2]); | 260 _testParse(message, "AaB03x", [headers1, headers2], [body1, body2]); |
| 271 | 261 |
| 272 // Longer form from submitting the following from Chrome. | 262 // Longer form from submitting the following from Chrome. |
| 273 // | 263 // |
| 274 // <html> | 264 // <html> |
| 275 // <body> | 265 // <body> |
| 276 // <FORM action="http://127.0.0.1:1234/" | 266 // <FORM action="http://127.0.0.1:1234/" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 299 ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r | 289 ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r |
| 300 Content-Disposition: form-data; name=\"checkbox_input\"\r | 290 Content-Disposition: form-data; name=\"checkbox_input\"\r |
| 301 \r | 291 \r |
| 302 on\r | 292 on\r |
| 303 ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r | 293 ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r |
| 304 Content-Disposition: form-data; name=\"radio_input\"\r | 294 Content-Disposition: form-data; name=\"radio_input\"\r |
| 305 \r | 295 \r |
| 306 on\r | 296 on\r |
| 307 ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB--\r\n"""; | 297 ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB--\r\n"""; |
| 308 headers1 = <String, String>{ | 298 headers1 = <String, String>{ |
| 309 "content-disposition": "form-data; name=\"text_input\""}; | 299 "content-disposition": "form-data; name=\"text_input\"" |
| 300 }; |
| 310 headers2 = <String, String>{ | 301 headers2 = <String, String>{ |
| 311 "content-disposition": "form-data; name=\"password_input\""}; | 302 "content-disposition": "form-data; name=\"password_input\"" |
| 303 }; |
| 312 var headers3 = <String, String>{ | 304 var headers3 = <String, String>{ |
| 313 "content-disposition": "form-data; name=\"checkbox_input\""}; | 305 "content-disposition": "form-data; name=\"checkbox_input\"" |
| 306 }; |
| 314 var headers4 = <String, String>{ | 307 var headers4 = <String, String>{ |
| 315 "content-disposition": "form-data; name=\"radio_input\""}; | 308 "content-disposition": "form-data; name=\"radio_input\"" |
| 309 }; |
| 316 body1 = "text"; | 310 body1 = "text"; |
| 317 body2 = "password"; | 311 body2 = "password"; |
| 318 var body3 = "on"; | 312 var body3 = "on"; |
| 319 var body4 = "on"; | 313 var body4 = "on"; |
| 320 _testParse(message, | 314 _testParse(message, "----WebKitFormBoundaryQ3cgYAmGRF8yOeYB", |
| 321 "----WebKitFormBoundaryQ3cgYAmGRF8yOeYB", | 315 [headers1, headers2, headers3, headers4], [body1, body2, body3, body4]); |
| 322 [headers1, headers2, headers3, headers4], | |
| 323 [body1, body2, body3, body4]); | |
| 324 | 316 |
| 325 // Same form from Firefox. | 317 // Same form from Firefox. |
| 326 message = """ | 318 message = """ |
| 327 \r\n-----------------------------52284550912143824192005403738\r | 319 \r\n-----------------------------52284550912143824192005403738\r |
| 328 Content-Disposition: form-data; name=\"text_input\"\r | 320 Content-Disposition: form-data; name=\"text_input\"\r |
| 329 \r | 321 \r |
| 330 text\r | 322 text\r |
| 331 -----------------------------52284550912143824192005403738\r | 323 -----------------------------52284550912143824192005403738\r |
| 332 Content-Disposition: form-data; name=\"password_input\"\r | 324 Content-Disposition: form-data; name=\"password_input\"\r |
| 333 \r | 325 \r |
| 334 password\r | 326 password\r |
| 335 -----------------------------52284550912143824192005403738\r | 327 -----------------------------52284550912143824192005403738\r |
| 336 Content-Disposition: form-data; name=\"checkbox_input\"\r | 328 Content-Disposition: form-data; name=\"checkbox_input\"\r |
| 337 \r | 329 \r |
| 338 on\r | 330 on\r |
| 339 -----------------------------52284550912143824192005403738\r | 331 -----------------------------52284550912143824192005403738\r |
| 340 Content-Disposition: form-data; name=\"radio_input\"\r | 332 Content-Disposition: form-data; name=\"radio_input\"\r |
| 341 \r | 333 \r |
| 342 on\r | 334 on\r |
| 343 -----------------------------52284550912143824192005403738--\r\n"""; | 335 -----------------------------52284550912143824192005403738--\r\n"""; |
| 344 _testParse(message, | 336 _testParse( |
| 345 "---------------------------52284550912143824192005403738", | 337 message, |
| 346 [headers1, headers2, headers3, headers4], | 338 "---------------------------52284550912143824192005403738", |
| 347 [body1, body2, body3, body4]); | 339 [headers1, headers2, headers3, headers4], |
| 340 [body1, body2, body3, body4]); |
| 348 | 341 |
| 349 // And Internet Explorer | 342 // And Internet Explorer |
| 350 message = """ | 343 message = """ |
| 351 \r\n-----------------------------7dc8f38c60326\r | 344 \r\n-----------------------------7dc8f38c60326\r |
| 352 Content-Disposition: form-data; name=\"text_input\"\r | 345 Content-Disposition: form-data; name=\"text_input\"\r |
| 353 \r | 346 \r |
| 354 text\r | 347 text\r |
| 355 -----------------------------7dc8f38c60326\r | 348 -----------------------------7dc8f38c60326\r |
| 356 Content-Disposition: form-data; name=\"password_input\"\r | 349 Content-Disposition: form-data; name=\"password_input\"\r |
| 357 \r | 350 \r |
| 358 password\r | 351 password\r |
| 359 -----------------------------7dc8f38c60326\r | 352 -----------------------------7dc8f38c60326\r |
| 360 Content-Disposition: form-data; name=\"checkbox_input\"\r | 353 Content-Disposition: form-data; name=\"checkbox_input\"\r |
| 361 \r | 354 \r |
| 362 on\r | 355 on\r |
| 363 -----------------------------7dc8f38c60326\r | 356 -----------------------------7dc8f38c60326\r |
| 364 Content-Disposition: form-data; name=\"radio_input\"\r | 357 Content-Disposition: form-data; name=\"radio_input\"\r |
| 365 \r | 358 \r |
| 366 on\r | 359 on\r |
| 367 -----------------------------7dc8f38c60326--\r\n"""; | 360 -----------------------------7dc8f38c60326--\r\n"""; |
| 368 _testParse(message, | 361 _testParse(message, "---------------------------7dc8f38c60326", |
| 369 "---------------------------7dc8f38c60326", | 362 [headers1, headers2, headers3, headers4], [body1, body2, body3, body4]); |
| 370 [headers1, headers2, headers3, headers4], | |
| 371 [body1, body2, body3, body4]); | |
| 372 | 363 |
| 373 // Test boundary prefix inside prefix and content. | 364 // Test boundary prefix inside prefix and content. |
| 374 message = """ | 365 message = """ |
| 375 -\r | 366 -\r |
| 376 --\r | 367 --\r |
| 377 --b\r | 368 --b\r |
| 378 --bo\r | 369 --bo\r |
| 379 --bou\r | 370 --bou\r |
| 380 --boun\r | 371 --boun\r |
| 381 --bound\r | 372 --bound\r |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 \r | 447 \r |
| 457 Body2\r | 448 Body2\r |
| 458 --xxx\r\n"""; | 449 --xxx\r\n"""; |
| 459 _testParse(message, "xxx", null, [null, null], true); | 450 _testParse(message, "xxx", null, [null, null], true); |
| 460 } | 451 } |
| 461 | 452 |
| 462 void main() { | 453 void main() { |
| 463 _testParseValid(); | 454 _testParseValid(); |
| 464 _testParseInvalid(); | 455 _testParseInvalid(); |
| 465 } | 456 } |
| OLD | NEW |