| 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 |