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 "package:unittest/unittest.dart"; | |
6 import "package:mime/mime.dart"; | |
7 import 'dart:async'; | 5 import 'dart:async'; |
8 import 'dart:math'; | 6 import 'dart:math'; |
9 | 7 |
10 void testParse(String message, | 8 import "package:unittest/unittest.dart"; |
| 9 import "package:mime/mime.dart"; |
| 10 |
| 11 void _testParse(String message, |
11 String boundary, | 12 String boundary, |
12 [List<Map> expectedHeaders, | 13 [List<Map> expectedHeaders, |
13 List expectedParts, | 14 List expectedParts, |
14 bool expectError = false]) { | 15 bool expectError = false]) { |
15 Future testWrite(List<int> data, [int chunkSize = -1]) { | 16 Future testWrite(List<int> data, [int chunkSize = -1]) { |
16 StreamController controller = new StreamController(sync: true); | 17 StreamController controller = new StreamController(sync: true); |
17 | 18 |
18 var stream = controller.stream.transform( | 19 var stream = controller.stream.transform( |
19 new MimeMultipartTransformer(boundary)); | 20 new MimeMultipartTransformer(boundary)); |
20 int i = 0; | 21 int i = 0; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 test('test', () { | 61 test('test', () { |
61 expect(Future.wait([ | 62 expect(Future.wait([ |
62 testWrite(data), | 63 testWrite(data), |
63 testWrite(data, 10), | 64 testWrite(data, 10), |
64 testWrite(data, 2), | 65 testWrite(data, 2), |
65 testWrite(data, 1)]), | 66 testWrite(data, 1)]), |
66 completes); | 67 completes); |
67 }); | 68 }); |
68 } | 69 } |
69 | 70 |
70 void testParseValid() { | 71 void _testParseValid() { |
71 String message; | |
72 Map headers; | |
73 Map headers1; | |
74 Map headers2; | |
75 Map headers3; | |
76 Map headers4; | |
77 String body1; | |
78 String body2; | |
79 String body3; | |
80 String body4; | |
81 | |
82 // Sample from Wikipedia. | 72 // Sample from Wikipedia. |
83 message = """ | 73 var message = """ |
84 This is a message with multiple parts in MIME format.\r | 74 This is a message with multiple parts in MIME format.\r |
85 --frontier\r | 75 --frontier\r |
86 Content-Type: text/plain\r | 76 Content-Type: text/plain\r |
87 \r | 77 \r |
88 This is the body of the message.\r | 78 This is the body of the message.\r |
89 --frontier\r | 79 --frontier\r |
90 Content-Type: application/octet-stream\r | 80 Content-Type: application/octet-stream\r |
91 Content-Transfer-Encoding: base64\r | 81 Content-Transfer-Encoding: base64\r |
92 \r | 82 \r |
93 PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg | 83 PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg |
94 Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg=\r | 84 Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg=\r |
95 --frontier--\r\n"""; | 85 --frontier--\r\n"""; |
96 headers1 = <String, String>{"content-type": "text/plain"}; | 86 var headers1 = <String, String>{"content-type": "text/plain"}; |
97 headers2 = <String, String>{"content-type": "application/octet-stream", | 87 var headers2 = <String, String>{"content-type": "application/octet-stream", |
98 "content-transfer-encoding": "base64"}; | 88 "content-transfer-encoding": "base64"}; |
99 body1 = "This is the body of the message."; | 89 var body1 = "This is the body of the message."; |
100 body2 = """ | 90 var body2 = """ |
101 PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg | 91 PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg |
102 Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg="""; | 92 Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg="""; |
103 testParse(message, "frontier", [headers1, headers2], [body1, body2]); | 93 _testParse(message, "frontier", [headers1, headers2], [body1, body2]); |
104 | 94 |
105 // Sample from HTML 4.01 Specification. | 95 // Sample from HTML 4.01 Specification. |
106 message = """ | 96 message = """ |
107 \r\n--AaB03x\r | 97 \r\n--AaB03x\r |
108 Content-Disposition: form-data; name=\"submit-name\"\r | 98 Content-Disposition: form-data; name=\"submit-name\"\r |
109 \r | 99 \r |
110 Larry\r | 100 Larry\r |
111 --AaB03x\r | 101 --AaB03x\r |
112 Content-Disposition: form-data; name=\"files\"; filename=\"file1.txt\"\r | 102 Content-Disposition: form-data; name=\"files\"; filename=\"file1.txt\"\r |
113 Content-Type: text/plain\r | 103 Content-Type: text/plain\r |
114 \r | 104 \r |
115 ... contents of file1.txt ...\r | 105 ... contents of file1.txt ...\r |
116 --AaB03x--\r\n"""; | 106 --AaB03x--\r\n"""; |
117 headers1 = <String, String>{ | 107 headers1 = <String, String>{ |
118 "content-disposition": "form-data; name=\"submit-name\""}; | 108 "content-disposition": "form-data; name=\"submit-name\""}; |
119 headers2 = <String, String>{ | 109 headers2 = <String, String>{ |
120 "content-type": "text/plain", | 110 "content-type": "text/plain", |
121 "content-disposition": "form-data; name=\"files\"; filename=\"file1.txt\"" | 111 "content-disposition": "form-data; name=\"files\"; filename=\"file1.txt\"" |
122 }; | 112 }; |
123 body1 = "Larry"; | 113 body1 = "Larry"; |
124 body2 = "... contents of file1.txt ..."; | 114 body2 = "... contents of file1.txt ..."; |
125 testParse(message, "AaB03x", [headers1, headers2], [body1, body2]); | 115 _testParse(message, "AaB03x", [headers1, headers2], [body1, body2]); |
126 | 116 |
127 // Longer form from submitting the following from Chrome. | 117 // Longer form from submitting the following from Chrome. |
128 // | 118 // |
129 // <html> | 119 // <html> |
130 // <body> | 120 // <body> |
131 // <FORM action="http://127.0.0.1:1234/" | 121 // <FORM action="http://127.0.0.1:1234/" |
132 // enctype="multipart/form-data" | 122 // enctype="multipart/form-data" |
133 // method="post"> | 123 // method="post"> |
134 // <P> | 124 // <P> |
135 // Text: <INPUT type="text" name="text_input"> | 125 // Text: <INPUT type="text" name="text_input"> |
(...skipping 21 matching lines...) Expand all Loading... |
157 on\r | 147 on\r |
158 ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r | 148 ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r |
159 Content-Disposition: form-data; name=\"radio_input\"\r | 149 Content-Disposition: form-data; name=\"radio_input\"\r |
160 \r | 150 \r |
161 on\r | 151 on\r |
162 ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB--\r\n"""; | 152 ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB--\r\n"""; |
163 headers1 = <String, String>{ | 153 headers1 = <String, String>{ |
164 "content-disposition": "form-data; name=\"text_input\""}; | 154 "content-disposition": "form-data; name=\"text_input\""}; |
165 headers2 = <String, String>{ | 155 headers2 = <String, String>{ |
166 "content-disposition": "form-data; name=\"password_input\""}; | 156 "content-disposition": "form-data; name=\"password_input\""}; |
167 headers3 = <String, String>{ | 157 var headers3 = <String, String>{ |
168 "content-disposition": "form-data; name=\"checkbox_input\""}; | 158 "content-disposition": "form-data; name=\"checkbox_input\""}; |
169 headers4 = <String, String>{ | 159 var headers4 = <String, String>{ |
170 "content-disposition": "form-data; name=\"radio_input\""}; | 160 "content-disposition": "form-data; name=\"radio_input\""}; |
171 body1 = "text"; | 161 body1 = "text"; |
172 body2 = "password"; | 162 body2 = "password"; |
173 body3 = "on"; | 163 var body3 = "on"; |
174 body4 = "on"; | 164 var body4 = "on"; |
175 testParse(message, | 165 _testParse(message, |
176 "----WebKitFormBoundaryQ3cgYAmGRF8yOeYB", | 166 "----WebKitFormBoundaryQ3cgYAmGRF8yOeYB", |
177 [headers1, headers2, headers3, headers4], | 167 [headers1, headers2, headers3, headers4], |
178 [body1, body2, body3, body4]); | 168 [body1, body2, body3, body4]); |
179 | 169 |
180 // Same form from Firefox. | 170 // Same form from Firefox. |
181 message = """ | 171 message = """ |
182 \r\n-----------------------------52284550912143824192005403738\r | 172 \r\n-----------------------------52284550912143824192005403738\r |
183 Content-Disposition: form-data; name=\"text_input\"\r | 173 Content-Disposition: form-data; name=\"text_input\"\r |
184 \r | 174 \r |
185 text\r | 175 text\r |
186 -----------------------------52284550912143824192005403738\r | 176 -----------------------------52284550912143824192005403738\r |
187 Content-Disposition: form-data; name=\"password_input\"\r | 177 Content-Disposition: form-data; name=\"password_input\"\r |
188 \r | 178 \r |
189 password\r | 179 password\r |
190 -----------------------------52284550912143824192005403738\r | 180 -----------------------------52284550912143824192005403738\r |
191 Content-Disposition: form-data; name=\"checkbox_input\"\r | 181 Content-Disposition: form-data; name=\"checkbox_input\"\r |
192 \r | 182 \r |
193 on\r | 183 on\r |
194 -----------------------------52284550912143824192005403738\r | 184 -----------------------------52284550912143824192005403738\r |
195 Content-Disposition: form-data; name=\"radio_input\"\r | 185 Content-Disposition: form-data; name=\"radio_input\"\r |
196 \r | 186 \r |
197 on\r | 187 on\r |
198 -----------------------------52284550912143824192005403738--\r\n"""; | 188 -----------------------------52284550912143824192005403738--\r\n"""; |
199 testParse(message, | 189 _testParse(message, |
200 "---------------------------52284550912143824192005403738", | 190 "---------------------------52284550912143824192005403738", |
201 [headers1, headers2, headers3, headers4], | 191 [headers1, headers2, headers3, headers4], |
202 [body1, body2, body3, body4]); | 192 [body1, body2, body3, body4]); |
203 | 193 |
204 // And Internet Explorer | 194 // And Internet Explorer |
205 message = """ | 195 message = """ |
206 \r\n-----------------------------7dc8f38c60326\r | 196 \r\n-----------------------------7dc8f38c60326\r |
207 Content-Disposition: form-data; name=\"text_input\"\r | 197 Content-Disposition: form-data; name=\"text_input\"\r |
208 \r | 198 \r |
209 text\r | 199 text\r |
210 -----------------------------7dc8f38c60326\r | 200 -----------------------------7dc8f38c60326\r |
211 Content-Disposition: form-data; name=\"password_input\"\r | 201 Content-Disposition: form-data; name=\"password_input\"\r |
212 \r | 202 \r |
213 password\r | 203 password\r |
214 -----------------------------7dc8f38c60326\r | 204 -----------------------------7dc8f38c60326\r |
215 Content-Disposition: form-data; name=\"checkbox_input\"\r | 205 Content-Disposition: form-data; name=\"checkbox_input\"\r |
216 \r | 206 \r |
217 on\r | 207 on\r |
218 -----------------------------7dc8f38c60326\r | 208 -----------------------------7dc8f38c60326\r |
219 Content-Disposition: form-data; name=\"radio_input\"\r | 209 Content-Disposition: form-data; name=\"radio_input\"\r |
220 \r | 210 \r |
221 on\r | 211 on\r |
222 -----------------------------7dc8f38c60326--\r\n"""; | 212 -----------------------------7dc8f38c60326--\r\n"""; |
223 testParse(message, | 213 _testParse(message, |
224 "---------------------------7dc8f38c60326", | 214 "---------------------------7dc8f38c60326", |
225 [headers1, headers2, headers3, headers4], | 215 [headers1, headers2, headers3, headers4], |
226 [body1, body2, body3, body4]); | 216 [body1, body2, body3, body4]); |
227 | 217 |
228 // Test boundary prefix inside prefix and content. | 218 // Test boundary prefix inside prefix and content. |
229 message = """ | 219 message = """ |
230 -\r | 220 -\r |
231 --\r | 221 --\r |
232 --b\r | 222 --b\r |
233 --bo\r | 223 --bo\r |
(...skipping 20 matching lines...) Expand all Loading... |
254 --boundar\r | 244 --boundar\r |
255 --bounda\r | 245 --bounda\r |
256 --bound\r | 246 --bound\r |
257 --boun\r | 247 --boun\r |
258 --bou\r | 248 --bou\r |
259 --bo\r | 249 --bo\r |
260 --b\r\r\r\r | 250 --b\r\r\r\r |
261 --\r\r\r | 251 --\r\r\r |
262 -\r\r | 252 -\r\r |
263 --boundary--\r\n"""; | 253 --boundary--\r\n"""; |
264 headers = <String, String>{"content-type": "text/plain"}; | 254 var headers = <String, String>{"content-type": "text/plain"}; |
265 body1 = """ | 255 body1 = """ |
266 -\r | 256 -\r |
267 --\r | 257 --\r |
268 --b\r | 258 --b\r |
269 --bo\r | 259 --bo\r |
270 --bou\r | 260 --bou\r |
271 --boun\r | 261 --boun\r |
272 --bound\r\r | 262 --bound\r\r |
273 --bounda\r\r\r | 263 --bounda\r\r\r |
274 --boundar\r\r\r"""; | 264 --boundar\r\r\r"""; |
275 body2 = """ | 265 body2 = """ |
276 --boundar\r | 266 --boundar\r |
277 --bounda\r | 267 --bounda\r |
278 --bound\r | 268 --bound\r |
279 --boun\r | 269 --boun\r |
280 --bou\r | 270 --bou\r |
281 --bo\r | 271 --bo\r |
282 --b\r\r\r\r | 272 --b\r\r\r\r |
283 --\r\r\r | 273 --\r\r\r |
284 -\r"""; | 274 -\r"""; |
285 testParse(message, "boundary", [headers, headers], [body1, body2]); | 275 _testParse(message, "boundary", [headers, headers], [body1, body2]); |
286 | 276 |
287 // Without initial CRLF. | 277 // Without initial CRLF. |
288 message = """ | 278 message = """ |
289 --xxx\r | 279 --xxx\r |
290 \r | 280 \r |
291 \r | 281 \r |
292 Body 1\r | 282 Body 1\r |
293 --xxx\r | 283 --xxx\r |
294 \r | 284 \r |
295 \r | 285 \r |
296 Body2\r | 286 Body2\r |
297 --xxx--\r\n"""; | 287 --xxx--\r\n"""; |
298 testParse(message, "xxx", null, ["\r\nBody 1", "\r\nBody2"]); | 288 _testParse(message, "xxx", null, ["\r\nBody 1", "\r\nBody2"]); |
299 } | 289 } |
300 | 290 |
301 void testParseInvalid() { | 291 void _testParseInvalid() { |
302 String message; | |
303 | |
304 // Missing end boundary. | 292 // Missing end boundary. |
305 message = """ | 293 var message = """ |
306 \r | 294 \r |
307 --xxx\r | 295 --xxx\r |
308 \r | 296 \r |
309 \r | 297 \r |
310 Body 1\r | 298 Body 1\r |
311 --xxx\r | 299 --xxx\r |
312 \r | 300 \r |
313 \r | 301 \r |
314 Body2\r | 302 Body2\r |
315 --xxx\r\n"""; | 303 --xxx\r\n"""; |
316 testParse(message, "xxx", null, [null, null], true); | 304 _testParse(message, "xxx", null, [null, null], true); |
317 } | 305 } |
318 | 306 |
319 void main() { | 307 void main() { |
320 testParseValid(); | 308 _testParseValid(); |
321 testParseInvalid(); | 309 _testParseInvalid(); |
322 } | 310 } |
OLD | NEW |