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

Side by Side Diff: tests/standalone/io/mime_multipart_parser_test.dart

Issue 10441021: Implement a MIME multipart parser (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 7 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
OLDNEW
(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 }
OLDNEW
« runtime/bin/mime_multipart_parser.dart ('K') | « runtime/bin/mime_multipart_parser.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698