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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: tests/standalone/io/mime_multipart_parser_test.dart
diff --git a/tests/standalone/io/mime_multipart_parser_test.dart b/tests/standalone/io/mime_multipart_parser_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..3abc5a2687415eaa4d92d72f5abc46df6c827799
--- /dev/null
+++ b/tests/standalone/io/mime_multipart_parser_test.dart
@@ -0,0 +1,303 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#source("../../../runtime/bin/http_parser.dart");
+#source("../../../runtime/bin/mime_multipart_parser.dart");
+
+void testParse(String message,
+ String boundary,
+ List<Map> expectedHeaders,
+ List expectedParts) {
+ _MimeMultipartParser parser;
+ int partCount;
+ Map headers;
+ List<int> currentPart;
+ bool lastPartCalled;
+
+ void reset() {
+ parser = new _MimeMultipartParser(boundary);
+ parser.partStart = (f, v) {
+ };
+ parser.headerReceived = (f, v) {
+ headers[f] = v;
+ };
+ parser.headersComplete = () {
+ expectedHeaders[partCount].forEach(
+ (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.
+ Expect.equals(value, headers[name]));
+ };
+ parser.partDataReceived = (List<int> data) {
+ if (currentPart == null) currentPart = new List<int>();
+ currentPart.addAll(data);
+ };
+ parser.partEnd = (lastPart) {
+ Expect.isFalse(lastPartCalled);
+ lastPartCalled = lastPart;
+ if (expectedParts[partCount] != null) {
+ List<int> expectedPart;
+ if (expectedParts[partCount] is String) {
+ expectedPart = expectedParts[partCount].charCodes();
+ } else {
+ expectedPart = expectedParts[partCount];
+ }
+ Expect.listEquals(expectedPart, currentPart);
+ }
+ currentPart = null;
+ partCount++;
+ if (lastPart) Expect.equals(expectedParts.length, partCount);
+ };
+
+ partCount = 0;
+ headers = new Map();
+ currentPart = null;
+ lastPartCalled = false;
+ }
+
+ void testWrite(List<int> data, [int chunkSize = -1]) {
+ if (chunkSize == -1) chunkSize = data.length;
+ reset();
+ int written = 0;
+ int unparsed;
+ for (int pos = 0; pos < data.length; pos += chunkSize) {
+ int remaining = data.length - pos;
+ int writeLength = Math.min(chunkSize, remaining);
+ written += writeLength;
+ int parsed =
+ parser.update(data.getRange(pos, writeLength), 0, writeLength);
+ unparsed = writeLength - parsed;
+ Expect.equals(0, unparsed);
+ }
+ Expect.isTrue(lastPartCalled);
+ }
+
+ // Test parsing the data three times delivering the data in
+ // different chunks.
+ List<int> data = message.charCodes();
+ //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.
+ testWrite(data, 10);
+ testWrite(data, 2);
+ testWrite(data, 1);
+}
+
+void testParseValid() {
+ String message;
+ Map headers;
+ Map headers1;
+ Map headers2;
+ Map headers3;
+ Map headers4;
+ String body1;
+ String body2;
+ String body3;
+ String body4;
+
+ // Sample from Wikipedia.
+ message = """
+This is a message with multiple parts in MIME format.\r
+--frontier\r
+Content-Type: text/plain\r
+\r
+This is the body of the message.\r
+--frontier\r
+Content-Type: application/octet-stream\r
+Content-Transfer-Encoding: base64\r
+\r
+PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg
+Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg=\r
+--frontier--\r\n""";
+ headers1 = <String>{"content-type": "text/plain"};
+ headers2 = <String>{"content-type": "application/octet-stream",
+ "content-transfer-encoding": "base64"};
+ body1 = "This is the body of the message.";
+ body2 = """
+PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg
+Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg=""";
+ //testParse(message, "frontier", [headers1, headers2], [body1, body2]);
+
+ // Sample from HTML 4.01 Specification.
+ message = """
+\r\n--AaB03x\r
+Content-Disposition: form-data; name=\"submit-name\"\r
+\r
+Larry\r
+--AaB03x\r
+Content-Disposition: form-data; name=\"files\"; filename=\"file1.txt\"\r
+Content-Type: text/plain\r
+\r
+... contents of file1.txt ...\r
+--AaB03x--\r\n""";
+ headers1 = <String>{"content-disposition": "form-data; name=\"submit-name\""};
+ headers2 = <String>{
+ "content-type": "text/plain",
+ "content-disposition": "form-data; name=\"files\"; filename=\"file1.txt\""
+ };
+ body1 = "Larry";
+ body2 = "... contents of file1.txt ...";
+ testParse(message, "AaB03x", [headers1, headers2], [body1, body2]);
+
+ // Longer form from submitting the following from Chrome.
+ //
+ // <html>
+ // <body>
+ // <FORM action="http://127.0.0.1:1234/"
+ // enctype="multipart/form-data"
+ // method="post">
+ // <P>
+ // Text: <INPUT type="text" name="text_input">
+ // Password: <INPUT type="password" name="password_input">
+ // Checkbox: <INPUT type="checkbox" name="checkbox_input">
+ // Radio: <INPUT type="radio" name="radio_input">
+ // Send <INPUT type="submit">
+ // </P>
+ // </FORM>
+ // </body>
+ // </html>
+
+ message = """
+\r\n------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r
+Content-Disposition: form-data; name=\"text_input\"\r
+\r
+text\r
+------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r
+Content-Disposition: form-data; name=\"password_input\"\r
+\r
+password\r
+------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r
+Content-Disposition: form-data; name=\"checkbox_input\"\r
+\r
+on\r
+------WebKitFormBoundaryQ3cgYAmGRF8yOeYB\r
+Content-Disposition: form-data; name=\"radio_input\"\r
+\r
+on\r
+------WebKitFormBoundaryQ3cgYAmGRF8yOeYB--\r\n""";
+ headers1 = <String>{"content-disposition": "form-data; name=\"text_input\""};
+ headers2 =
+ <String>{"content-disposition": "form-data; name=\"password_input\""};
+ headers3 =
+ <String>{"content-disposition": "form-data; name=\"checkbox_input\""};
+ headers4 = <String>{"content-disposition": "form-data; name=\"radio_input\""};
+ body1 = "text";
+ body2 = "password";
+ body3 = "on";
+ body4 = "on";
+ testParse(message,
+ "----webkitformboundaryq3cgyamgrf8yoeyb",
+ [headers1, headers2, headers3, headers4],
+ [body1, body2, body3, body4]);
+
+ // Same form from Firefox.
+ message = """
+\r\n-----------------------------52284550912143824192005403738\r
+Content-Disposition: form-data; name=\"text_input\"\r
+\r
+text\r
+-----------------------------52284550912143824192005403738\r
+Content-Disposition: form-data; name=\"password_input\"\r
+\r
+password\r
+-----------------------------52284550912143824192005403738\r
+Content-Disposition: form-data; name=\"checkbox_input\"\r
+\r
+on\r
+-----------------------------52284550912143824192005403738\r
+Content-Disposition: form-data; name=\"radio_input\"\r
+\r
+on\r
+-----------------------------52284550912143824192005403738--\r\n""";
+ testParse(message,
+ "---------------------------52284550912143824192005403738",
+ [headers1, headers2, headers3, headers4],
+ [body1, body2, body3, body4]);
+
+ // And Internet Explorer
+ message = """
+\r\n-----------------------------7dc8f38c60326\r
+Content-Disposition: form-data; name=\"text_input\"\r
+\r
+text\r
+-----------------------------7dc8f38c60326\r
+Content-Disposition: form-data; name=\"password_input\"\r
+\r
+password\r
+-----------------------------7dc8f38c60326\r
+Content-Disposition: form-data; name=\"checkbox_input\"\r
+\r
+on\r
+-----------------------------7dc8f38c60326\r
+Content-Disposition: form-data; name=\"radio_input\"\r
+\r
+on\r
+-----------------------------7dc8f38c60326--\r\n""";
+ testParse(message,
+ "---------------------------7dc8f38c60326",
+ [headers1, headers2, headers3, headers4],
+ [body1, body2, body3, body4]);
+
+ // Test boundary prefix inside prefix and content.
+ message = """
+-\r
+--\r
+--b\r
+--bo\r
+--bou\r
+--boun\r
+--bound\r
+--bounda\r
+--boundar\r
+--boundary\r
+Content-Type: text/plain\r
+\r
+-\r
+--\r
+--b\r
+--bo\r
+--bou\r
+--boun\r
+--bound\r\r
+--bounda\r\r\r
+--boundar\r\r\r\r
+--boundary\r
+Content-Type: text/plain\r
+\r
+--boundar\r
+--bounda\r
+--bound\r
+--boun\r
+--bou\r
+--bo\r
+--b\r\r\r\r
+--\r\r\r
+-\r\r
+--boundary--\r\n""";
+ headers = <String>{"content-type": "text/plain"};
+ body1 = """
+-\r
+--\r
+--b\r
+--bo\r
+--bou\r
+--boun\r
+--bound\r\r
+--bounda\r\r\r
+--boundar\r\r\r""";
+ body2 = """
+--boundar\r
+--bounda\r
+--bound\r
+--boun\r
+--bou\r
+--bo\r
+--b\r\r\r\r
+--\r\r\r
+-\r""";
+ testParse(message, "boundary", [headers, headers], [body1, body2]);
+}
+
+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.
+}
+
+void main() {
+ testParseValid();
+}
« 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