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

Unified Diff: mojo/public/dart/third_party/mime/test/mime_multipart_transformer_test.dart

Issue 1346773002: Stop running pub get at gclient sync time and fix build bugs (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 3 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: mojo/public/dart/third_party/mime/test/mime_multipart_transformer_test.dart
diff --git a/mojo/public/dart/third_party/mime/test/mime_multipart_transformer_test.dart b/mojo/public/dart/third_party/mime/test/mime_multipart_transformer_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..50389998faa677b5f2cba98aa48e833cb6c30f35
--- /dev/null
+++ b/mojo/public/dart/third_party/mime/test/mime_multipart_transformer_test.dart
@@ -0,0 +1,465 @@
+// Copyright (c) 2013, 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.
+
+import 'dart:async';
+import 'dart:math';
+
+import "package:unittest/unittest.dart";
+import "package:mime/mime.dart";
+
+void _writeInChunks(List<int> data,
+ int chunkSize,
+ StreamController<List<int>> controller) {
+ if (chunkSize == -1) chunkSize = data.length;
+
+ int written = 0;
+ for (int pos = 0; pos < data.length; pos += chunkSize) {
+ int remaining = data.length - pos;
+ int writeLength = min(chunkSize, remaining);
+ controller.add(data.sublist(pos, pos + writeLength));
+ written += writeLength;
+ }
+ controller.close();
+}
+
+
+enum TestMode {
+ IMMEDIATE_LISTEN,
+ DELAY_LISTEN,
+ PAUSE_RESUME
+}
+
+void _runParseTest(String message,
+ String boundary,
+ TestMode mode,
+ [List<Map> expectedHeaders,
+ List expectedParts,
+ bool expectError = false]) {
+ Future testWrite(List<int> data, [int chunkSize = -1]) {
+ StreamController controller = new StreamController(sync: true);
+
+ var stream = controller.stream.transform(
+ new MimeMultipartTransformer(boundary));
+ int i = 0;
+ var completer = new Completer();
+ var futures = [];
+ stream.listen((multipart) {
+ int part = i++;
+ if (expectedHeaders != null) {
+ expect(multipart.headers, equals(expectedHeaders[part]));
+ }
+ switch (mode) {
+ case TestMode.IMMEDIATE_LISTEN:
+ futures.add(multipart.fold([], (buffer, data) => buffer..addAll(data))
+ .then((data) {
+ if (expectedParts[part] != null) {
+ expect(data, equals(expectedParts[part].codeUnits));
+ }
+ }));
+ break;
+
+ case TestMode.DELAY_LISTEN:
+ futures.add(new Future(() {
+ return multipart.fold([], (buffer, data) => buffer..addAll(data))
+ .then((data) {
+ if (expectedParts[part] != null) {
+ expect(data, equals(expectedParts[part].codeUnits));
+ }
+ });
+ }));
+ break;
+
+ case TestMode.PAUSE_RESUME:
+ var completer = new Completer();
+ futures.add(completer.future);
+ var buffer = [];
+ var subscription;
+ subscription = multipart.listen(
+ (data) {
+ buffer.addAll(data);
+ subscription.pause();
+ new Future(() => subscription.resume());
+ },
+ onDone: () {
+ if (expectedParts[part] != null) {
+ expect(buffer, equals(expectedParts[part].codeUnits));
+ }
+ completer.complete();
+ });
+ break;
+ }
+ }, onError: (error) {
+ if (!expectError) throw error;
+ }, onDone: () {
+ if (expectedParts != null) {
+ expect(i, equals(expectedParts.length));
+ }
+ Future.wait(futures).then(completer.complete);
+ });
+
+ _writeInChunks(data, chunkSize, controller);
+
+ return completer.future;
+ }
+
+ Future testFirstPartOnly(List<int> data, [int chunkSize = -1]) {
+ var completer = new Completer();
+ var controller = new StreamController(sync: true);
+
+ var stream = controller.stream.transform(
+ new MimeMultipartTransformer(boundary));
+
+ var subscription;
+ subscription = stream.first.then((multipart) {
+ if (expectedHeaders != null) {
+ expect(multipart.headers, equals(expectedHeaders[0]));
+ }
+ return (multipart.fold([], (b, d) => b..addAll(d)).then((data) {
+ if (expectedParts != null && expectedParts[0] != null) {
+ expect(data, equals(expectedParts[0].codeUnits));
+ }
+ }));
+ }).then((_) {
+ completer.complete();
+ });
+
+ _writeInChunks(data, chunkSize, controller);
+
+ return completer.future;
+ }
+
+ Future testCompletePartAfterCancel(List<int> data,
+ int parts,
+ [int chunkSize = -1]) {
+ var completer = new Completer();
+ var controller = new StreamController(sync: true);
+ var stream = controller.stream.transform(
+ new MimeMultipartTransformer(boundary));
+ var subscription;
+ int i = 0;
+ var futures = [];
+ subscription = stream.listen((multipart) {
+ int partIndex = i;
+
+ if (partIndex >= parts) {
+ throw 'Expected no more parts, but got one.';
+ }
+
+ if (expectedHeaders != null) {
+ expect(multipart.headers, equals(expectedHeaders[partIndex]));
+ }
+ futures.add((multipart.fold([], (b, d) => b..addAll(d)).then((data) {
+ if (expectedParts != null && expectedParts[partIndex] != null) {
+ expect(data, equals(expectedParts[partIndex].codeUnits));
+ }
+ })));
+
+ if (partIndex == (parts - 1)) {
+ subscription.cancel();
+ Future.wait(futures).then(completer.complete);
+ }
+ i++;
+ });
+
+ _writeInChunks(data, chunkSize, controller);
+
+ return completer.future;
+ }
+
+ // Test parsing the data three times delivering the data in
+ // different chunks.
+ List<int> data = message.codeUnits;
+ test('test', () {
+ expect(Future.wait([
+ testWrite(data),
+ testWrite(data, 10),
+ testWrite(data, 2),
+ testWrite(data, 1),
+ ]), completes);
+ });
+
+ if (expectedParts.length > 0) {
+ test('test-first-part-only', () {
+ expect(Future.wait([
+ testFirstPartOnly(data),
+ testFirstPartOnly(data, 10),
+ testFirstPartOnly(data, 2),
+ testFirstPartOnly(data, 1),
+ ]), completes);
+ });
+
+ test('test-n-parts-only', () {
+ int numPartsExpected = expectedParts.length - 1;
+ if (numPartsExpected == 0) numPartsExpected = 1;
+
+ expect(Future.wait([
+ testCompletePartAfterCancel(data, numPartsExpected),
+ testCompletePartAfterCancel(data, numPartsExpected, 10),
+ testCompletePartAfterCancel(data, numPartsExpected, 2),
+ testCompletePartAfterCancel(data, numPartsExpected, 1),
+ ]), completes);
+ });
+ }
+}
+
+void _testParse(String message,
+ String boundary,
+ [List<Map> expectedHeaders,
+ List expectedParts,
+ bool expectError = false]) {
+ _runParseTest(
+ message, boundary, TestMode.IMMEDIATE_LISTEN,
+ expectedHeaders, expectedParts, expectError);
+ _runParseTest(
+ message, boundary, TestMode.DELAY_LISTEN,
+ expectedHeaders, expectedParts, expectError);
+ _runParseTest(
+ message, boundary, TestMode.PAUSE_RESUME,
+ expectedHeaders, expectedParts, expectError);
+}
+
+void _testParseValid() {
+ // Empty message from Chrome form post.
+ var message = '------WebKitFormBoundaryU3FBruSkJKG0Yor1--\r\n';
+ _testParse(message, "----WebKitFormBoundaryU3FBruSkJKG0Yor1", [], []);
+
+ // 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""";
+ var headers1 = <String, String>{"content-type": "text/plain"};
+ var headers2 = <String, String>{"content-type": "application/octet-stream",
+ "content-transfer-encoding": "base64"};
+ var body1 = "This is the body of the message.";
+ var 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, String>{
+ "content-disposition": "form-data; name=\"submit-name\""};
+ headers2 = <String, 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, String>{
+ "content-disposition": "form-data; name=\"text_input\""};
+ headers2 = <String, String>{
+ "content-disposition": "form-data; name=\"password_input\""};
+ var headers3 = <String, String>{
+ "content-disposition": "form-data; name=\"checkbox_input\""};
+ var headers4 = <String, String>{
+ "content-disposition": "form-data; name=\"radio_input\""};
+ body1 = "text";
+ body2 = "password";
+ var body3 = "on";
+ var 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""";
+ var headers = <String, 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]);
+
+ // Without initial CRLF.
+ message = """
+--xxx\r
+\r
+\r
+Body 1\r
+--xxx\r
+\r
+\r
+Body2\r
+--xxx--\r\n""";
+ _testParse(message, "xxx", null, ["\r\nBody 1", "\r\nBody2"]);
+}
+
+void _testParseInvalid() {
+ // Missing end boundary.
+ var message = """
+\r
+--xxx\r
+\r
+\r
+Body 1\r
+--xxx\r
+\r
+\r
+Body2\r
+--xxx\r\n""";
+ _testParse(message, "xxx", null, [null, null], true);
+}
+
+void main() {
+ _testParseValid();
+ _testParseInvalid();
+}
« no previous file with comments | « mojo/public/dart/third_party/mime/pubspec.yaml ('k') | mojo/public/dart/third_party/mime/test/mime_type_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698