Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 #source("../../../runtime/bin/http_parser.dart"); | |
| 6 #source("../../../runtime/bin/mime_multipart_parser.dart"); | |
| 7 | |
| 8 void testParse(String message, | |
| 9 String boundary, | |
| 10 List<Map> expectedHeaders, | |
| 11 List expectedParts) { | |
| 12 _MimeMultipartParser parser; | |
| 13 int partCount; | |
| 14 Map headers; | |
| 15 List<int> currentPart; | |
| 16 bool lastPartCalled; | |
| 17 | |
| 18 void reset() { | |
| 19 parser = new _MimeMultipartParser(boundary); | |
| 20 parser.partStart = (f, v) { | |
| 21 }; | |
| 22 parser.headerReceived = (f, v) { | |
| 23 headers[f] = v; | |
| 24 }; | |
| 25 parser.headersComplete = () { | |
| 26 expectedHeaders[partCount].forEach( | |
| 27 (String name, String value) => | |
|
Mads Ager (google)
2012/05/25 08:11:58
I would use the braces for this multi-line closure
Søren Gjesse
2012/05/25 11:57:06
Used {}s.
| |
| 28 Expect.equals(value, headers[name])); | |
| 29 }; | |
| 30 parser.partDataReceived = (List<int> data) { | |
| 31 if (currentPart == null) currentPart = new List<int>(); | |
| 32 currentPart.addAll(data); | |
| 33 }; | |
| 34 parser.partEnd = (lastPart) { | |
| 35 Expect.isFalse(lastPartCalled); | |
| 36 lastPartCalled = lastPart; | |
| 37 if (expectedParts[partCount] != null) { | |
| 38 List<int> expectedPart; | |
| 39 if (expectedParts[partCount] is String) { | |
| 40 expectedPart = expectedParts[partCount].charCodes(); | |
| 41 } else { | |
| 42 expectedPart = expectedParts[partCount]; | |
| 43 } | |
| 44 Expect.listEquals(expectedPart, currentPart); | |
| 45 } | |
| 46 currentPart = null; | |
| 47 partCount++; | |
| 48 if (lastPart) Expect.equals(expectedParts.length, partCount); | |
| 49 }; | |
| 50 | |
| 51 partCount = 0; | |
| 52 headers = new Map(); | |
| 53 currentPart = null; | |
| 54 lastPartCalled = false; | |
| 55 } | |
| 56 | |
| 57 void testWrite(List<int> data, [int chunkSize = -1]) { | |
| 58 if (chunkSize == -1) chunkSize = data.length; | |
| 59 reset(); | |
| 60 int written = 0; | |
| 61 int unparsed; | |
| 62 for (int pos = 0; pos < data.length; pos += chunkSize) { | |
| 63 int remaining = data.length - pos; | |
| 64 int writeLength = Math.min(chunkSize, remaining); | |
| 65 written += writeLength; | |
| 66 int parsed = | |
| 67 parser.update(data.getRange(pos, writeLength), 0, writeLength); | |
| 68 unparsed = writeLength - parsed; | |
| 69 Expect.equals(0, unparsed); | |
| 70 } | |
| 71 Expect.isTrue(lastPartCalled); | |
| 72 } | |
| 73 | |
| 74 // Test parsing the data three times delivering the data in | |
| 75 // different chunks. | |
| 76 List<int> data = message.charCodes(); | |
| 77 //testWrite(data); | |
|
Mads Ager (google)
2012/05/25 08:11:58
Code in comment.
Søren Gjesse
2012/05/25 11:57:06
Un-commented.
| |
| 78 testWrite(data, 10); | |
| 79 testWrite(data, 2); | |
| 80 testWrite(data, 1); | |
| 81 } | |
| 82 | |
| 83 void testParseValid() { | |
| 84 String message; | |
| 85 Map headers; | |
| 86 Map headers1; | |
| 87 Map headers2; | |
| 88 Map headers3; | |
| 89 Map headers4; | |
| 90 String body1; | |
| 91 String body2; | |
| 92 String body3; | |
| 93 String body4; | |
| 94 | |
| 95 // Sample from Wikipedia. | |
| 96 message = """ | |
| 97 This is a message with multiple parts in MIME format.\r | |
| 98 --frontier\r | |
| 99 Content-Type: text/plain\r | |
| 100 \r | |
| 101 This is the body of the message.\r | |
| 102 --frontier\r | |
| 103 Content-Type: application/octet-stream\r | |
| 104 Content-Transfer-Encoding: base64\r | |
| 105 \r | |
| 106 PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg | |
| 107 Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg=\r | |
| 108 --frontier--\r\n"""; | |
| 109 headers1 = <String>{"content-type": "text/plain"}; | |
| 110 headers2 = <String>{"content-type": "application/octet-stream", | |
| 111 "content-transfer-encoding": "base64"}; | |
| 112 body1 = "This is the body of the message."; | |
| 113 body2 = """ | |
| 114 PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg | |
| 115 Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg="""; | |
| 116 //testParse(message, "frontier", [headers1, headers2], [body1, body2]); | |
| 117 | |
| 118 // Sample from HTML 4.01 Specification. | |
| 119 message = """ | |
| 120 \r\n--AaB03x\r | |
| 121 Content-Disposition: form-data; name=\"submit-name\"\r | |
| 122 \r | |
| 123 Larry\r | |
| 124 --AaB03x\r | |
| 125 Content-Disposition: form-data; name=\"files\"; filename=\"file1.txt\"\r | |
| 126 Content-Type: text/plain\r | |
| 127 \r | |
| 128 ... contents of file1.txt ...\r | |
| 129 --AaB03x--\r\n"""; | |
| 130 headers1 = <String>{"content-disposition": "form-data; name=\"submit-name\""}; | |
| 131 headers2 = <String>{ | |
| 132 "content-type": "text/plain", | |
| 133 "content-disposition": "form-data; name=\"files\"; filename=\"file1.txt\"" | |
| 134 }; | |
| 135 body1 = "Larry"; | |
| 136 body2 = "... contents of file1.txt ..."; | |
| 137 testParse(message, "AaB03x", [headers1, headers2], [body1, body2]); | |
| 138 | |
| 139 // Longer form from submitting the following from Chrome. | |
| 140 // | |
| 141 // <html> | |
| 142 // <body> | |
| 143 // <FORM action="http://127.0.0.1:1234/" | |
| 144 // enctype="multipart/form-data" | |
| 145 // method="post"> | |
| 146 // <P> | |
| 147 // Text: <INPUT type="text" name="text_input"> | |
| 148 // Password: <INPUT type="password" name="password_input"> | |
| 149 // Checkbox: <INPUT type="checkbox" name="checkbox_input"> | |
| 150 // Radio: <INPUT type="radio" name="radio_input"> | |
| 151 // Send <INPUT type="submit"> | |
| 152 // </P> | |
| 153 // </FORM> | |
| 154 // </body> | |
| 155 // </html> | |
| 156 | |
| 157 message = """ | |
| 158 \r\n------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r | |
| 159 Content-Disposition: form-data; name=\"text_input\"\r | |
| 160 \r | |
| 161 text\r | |
| 162 ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r | |
| 163 Content-Disposition: form-data; name=\"password_input\"\r | |
| 164 \r | |
| 165 password\r | |
| 166 ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r | |
| 167 Content-Disposition: form-data; name=\"checkbox_input\"\r | |
| 168 \r | |
| 169 on\r | |
| 170 ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r | |
| 171 Content-Disposition: form-data; name=\"radio_input\"\r | |
| 172 \r | |
| 173 on\r | |
| 174 ------WebKitFormBoundaryQ3cgYAmGRF8yOeYB--\r\n"""; | |
| 175 headers1 = <String>{"content-disposition": "form-data; name=\"text_input\""}; | |
| 176 headers2 = | |
| 177 <String>{"content-disposition": "form-data; name=\"password_input\""}; | |
| 178 headers3 = | |
| 179 <String>{"content-disposition": "form-data; name=\"checkbox_input\""}; | |
| 180 headers4 = <String>{"content-disposition": "form-data; name=\"radio_input\""}; | |
| 181 body1 = "text"; | |
| 182 body2 = "password"; | |
| 183 body3 = "on"; | |
| 184 body4 = "on"; | |
| 185 testParse(message, | |
| 186 "----webkitformboundaryq3cgyamgrf8yoeyb", | |
| 187 [headers1, headers2, headers3, headers4], | |
| 188 [body1, body2, body3, body4]); | |
| 189 | |
| 190 // Same form from Firefox. | |
| 191 message = """ | |
| 192 \r\n-----------------------------52284550912143824192005403738\r | |
| 193 Content-Disposition: form-data; name=\"text_input\"\r | |
| 194 \r | |
| 195 text\r | |
| 196 -----------------------------52284550912143824192005403738\r | |
| 197 Content-Disposition: form-data; name=\"password_input\"\r | |
| 198 \r | |
| 199 password\r | |
| 200 -----------------------------52284550912143824192005403738\r | |
| 201 Content-Disposition: form-data; name=\"checkbox_input\"\r | |
| 202 \r | |
| 203 on\r | |
| 204 -----------------------------52284550912143824192005403738\r | |
| 205 Content-Disposition: form-data; name=\"radio_input\"\r | |
| 206 \r | |
| 207 on\r | |
| 208 -----------------------------52284550912143824192005403738--\r\n"""; | |
| 209 testParse(message, | |
| 210 "---------------------------52284550912143824192005403738", | |
| 211 [headers1, headers2, headers3, headers4], | |
| 212 [body1, body2, body3, body4]); | |
| 213 | |
| 214 // And Internet Explorer | |
| 215 message = """ | |
| 216 \r\n-----------------------------7dc8f38c60326\r | |
| 217 Content-Disposition: form-data; name=\"text_input\"\r | |
| 218 \r | |
| 219 text\r | |
| 220 -----------------------------7dc8f38c60326\r | |
| 221 Content-Disposition: form-data; name=\"password_input\"\r | |
| 222 \r | |
| 223 password\r | |
| 224 -----------------------------7dc8f38c60326\r | |
| 225 Content-Disposition: form-data; name=\"checkbox_input\"\r | |
| 226 \r | |
| 227 on\r | |
| 228 -----------------------------7dc8f38c60326\r | |
| 229 Content-Disposition: form-data; name=\"radio_input\"\r | |
| 230 \r | |
| 231 on\r | |
| 232 -----------------------------7dc8f38c60326--\r\n"""; | |
| 233 testParse(message, | |
| 234 "---------------------------7dc8f38c60326", | |
| 235 [headers1, headers2, headers3, headers4], | |
| 236 [body1, body2, body3, body4]); | |
| 237 | |
| 238 // Test boundary prefix inside prefix and content. | |
| 239 message = """ | |
| 240 -\r | |
| 241 --\r | |
| 242 --b\r | |
| 243 --bo\r | |
| 244 --bou\r | |
| 245 --boun\r | |
| 246 --bound\r | |
| 247 --bounda\r | |
| 248 --boundar\r | |
| 249 --boundary\r | |
| 250 Content-Type: text/plain\r | |
| 251 \r | |
| 252 -\r | |
| 253 --\r | |
| 254 --b\r | |
| 255 --bo\r | |
| 256 --bou\r | |
| 257 --boun\r | |
| 258 --bound\r\r | |
| 259 --bounda\r\r\r | |
| 260 --boundar\r\r\r\r | |
| 261 --boundary\r | |
| 262 Content-Type: text/plain\r | |
| 263 \r | |
| 264 --boundar\r | |
| 265 --bounda\r | |
| 266 --bound\r | |
| 267 --boun\r | |
| 268 --bou\r | |
| 269 --bo\r | |
| 270 --b\r\r\r\r | |
| 271 --\r\r\r | |
| 272 -\r\r | |
| 273 --boundary--\r\n"""; | |
| 274 headers = <String>{"content-type": "text/plain"}; | |
| 275 body1 = """ | |
| 276 -\r | |
| 277 --\r | |
| 278 --b\r | |
| 279 --bo\r | |
| 280 --bou\r | |
| 281 --boun\r | |
| 282 --bound\r\r | |
| 283 --bounda\r\r\r | |
| 284 --boundar\r\r\r"""; | |
| 285 body2 = """ | |
| 286 --boundar\r | |
| 287 --bounda\r | |
| 288 --bound\r | |
| 289 --boun\r | |
| 290 --bou\r | |
| 291 --bo\r | |
| 292 --b\r\r\r\r | |
| 293 --\r\r\r | |
| 294 -\r"""; | |
| 295 testParse(message, "boundary", [headers, headers], [body1, body2]); | |
| 296 } | |
| 297 | |
| 298 void testParseInvalid() { | |
|
Mads Ager (google)
2012/05/25 08:11:58
You should add some tests here? :-)
Søren Gjesse
2012/05/25 11:57:06
Done.
| |
| 299 } | |
| 300 | |
| 301 void main() { | |
| 302 testParseValid(); | |
| 303 } | |
| OLD | NEW |