| 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 'dart:async'; | 5 import 'dart:async'; |
| 6 import 'dart:math'; | 6 import 'dart:math'; |
| 7 | 7 |
| 8 import "package:unittest/unittest.dart"; | 8 import "package:unittest/unittest.dart"; |
| 9 import "package:mime/mime.dart"; | 9 import "package:mime/mime.dart"; |
| 10 | 10 |
| 11 void _writeInChunks(List<int> data, | 11 void _writeInChunks(List<int> data, |
| 12 int chunkSize, | 12 int chunkSize, |
| 13 StreamController<List<int>> controller) { | 13 StreamController<List<int>> controller) { |
| 14 if (chunkSize == -1) chunkSize = data.length; | 14 if (chunkSize == -1) chunkSize = data.length; |
| 15 | 15 |
| 16 int written = 0; | 16 int written = 0; |
| 17 for (int pos = 0; pos < data.length; pos += chunkSize) { | 17 for (int pos = 0; pos < data.length; pos += chunkSize) { |
| 18 int remaining = data.length - pos; | 18 int remaining = data.length - pos; |
| 19 int writeLength = min(chunkSize, remaining); | 19 int writeLength = min(chunkSize, remaining); |
| 20 controller.add(data.sublist(pos, pos + writeLength)); | 20 controller.add(data.sublist(pos, pos + writeLength)); |
| 21 written += writeLength; | 21 written += writeLength; |
| 22 } | 22 } |
| 23 controller.close(); | 23 controller.close(); |
| 24 } | 24 } |
| 25 | 25 |
| 26 | 26 |
| 27 void _testParse(String message, | 27 enum TestMode { |
| 28 String boundary, | 28 IMMEDIATE_LISTEN, |
| 29 [List<Map> expectedHeaders, | 29 DELAY_LISTEN, |
| 30 List expectedParts, | 30 PAUSE_RESUME |
| 31 bool expectError = false]) { | 31 } |
| 32 |
| 33 void _runParseTest(String message, |
| 34 String boundary, |
| 35 TestMode mode, |
| 36 [List<Map> expectedHeaders, |
| 37 List expectedParts, |
| 38 bool expectError = false]) { |
| 32 Future testWrite(List<int> data, [int chunkSize = -1]) { | 39 Future testWrite(List<int> data, [int chunkSize = -1]) { |
| 33 StreamController controller = new StreamController(sync: true); | 40 StreamController controller = new StreamController(sync: true); |
| 34 | 41 |
| 35 var stream = controller.stream.transform( | 42 var stream = controller.stream.transform( |
| 36 new MimeMultipartTransformer(boundary)); | 43 new MimeMultipartTransformer(boundary)); |
| 37 int i = 0; | 44 int i = 0; |
| 38 var completer = new Completer(); | 45 var completer = new Completer(); |
| 39 var futures = []; | 46 var futures = []; |
| 40 stream.listen((multipart) { | 47 stream.listen((multipart) { |
| 41 int part = i++; | 48 int part = i++; |
| 42 if (expectedHeaders != null) { | 49 if (expectedHeaders != null) { |
| 43 expect(multipart.headers, equals(expectedHeaders[part])); | 50 expect(multipart.headers, equals(expectedHeaders[part])); |
| 44 } | 51 } |
| 45 futures.add(multipart.fold([], (buffer, data) => buffer..addAll(data)) | 52 switch (mode) { |
| 46 .then((data) { | 53 case TestMode.IMMEDIATE_LISTEN: |
| 47 if (expectedParts[part] != null) { | 54 futures.add(multipart.fold([], (buffer, data) => buffer..addAll(data)) |
| 48 expect(data, equals(expectedParts[part].codeUnits)); | 55 .then((data) { |
| 49 } | 56 if (expectedParts[part] != null) { |
| 57 expect(data, equals(expectedParts[part].codeUnits)); |
| 58 } |
| 59 })); |
| 60 break; |
| 61 |
| 62 case TestMode.DELAY_LISTEN: |
| 63 futures.add(new Future(() { |
| 64 return multipart.fold([], (buffer, data) => buffer..addAll(data)) |
| 65 .then((data) { |
| 66 if (expectedParts[part] != null) { |
| 67 expect(data, equals(expectedParts[part].codeUnits)); |
| 68 } |
| 69 }); |
| 50 })); | 70 })); |
| 71 break; |
| 72 |
| 73 case TestMode.PAUSE_RESUME: |
| 74 var completer = new Completer(); |
| 75 futures.add(completer.future); |
| 76 var buffer = []; |
| 77 var subscription; |
| 78 subscription = multipart.listen( |
| 79 (data) { |
| 80 buffer.addAll(data); |
| 81 subscription.pause(); |
| 82 new Future(() => subscription.resume()); |
| 83 }, |
| 84 onDone: () { |
| 85 if (expectedParts[part] != null) { |
| 86 expect(buffer, equals(expectedParts[part].codeUnits)); |
| 87 } |
| 88 completer.complete(); |
| 89 }); |
| 90 break; |
| 91 } |
| 51 }, onError: (error) { | 92 }, onError: (error) { |
| 52 if (!expectError) throw error; | 93 if (!expectError) throw error; |
| 53 }, onDone: () { | 94 }, onDone: () { |
| 54 if (expectedParts != null) { | 95 if (expectedParts != null) { |
| 55 expect(i, equals(expectedParts.length)); | 96 expect(i, equals(expectedParts.length)); |
| 56 } | 97 } |
| 57 Future.wait(futures).then(completer.complete); | 98 Future.wait(futures).then(completer.complete); |
| 58 }); | 99 }); |
| 59 | 100 |
| 60 _writeInChunks(data, chunkSize, controller); | 101 _writeInChunks(data, chunkSize, controller); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 expect(Future.wait([ | 196 expect(Future.wait([ |
| 156 testCompletePartAfterCancel(data, numPartsExpected), | 197 testCompletePartAfterCancel(data, numPartsExpected), |
| 157 testCompletePartAfterCancel(data, numPartsExpected, 10), | 198 testCompletePartAfterCancel(data, numPartsExpected, 10), |
| 158 testCompletePartAfterCancel(data, numPartsExpected, 2), | 199 testCompletePartAfterCancel(data, numPartsExpected, 2), |
| 159 testCompletePartAfterCancel(data, numPartsExpected, 1), | 200 testCompletePartAfterCancel(data, numPartsExpected, 1), |
| 160 ]), completes); | 201 ]), completes); |
| 161 }); | 202 }); |
| 162 } | 203 } |
| 163 } | 204 } |
| 164 | 205 |
| 206 void _testParse(String message, |
| 207 String boundary, |
| 208 [List<Map> expectedHeaders, |
| 209 List expectedParts, |
| 210 bool expectError = false]) { |
| 211 _runParseTest( |
| 212 message, boundary, TestMode.IMMEDIATE_LISTEN, |
| 213 expectedHeaders, expectedParts, expectError); |
| 214 _runParseTest( |
| 215 message, boundary, TestMode.DELAY_LISTEN, |
| 216 expectedHeaders, expectedParts, expectError); |
| 217 _runParseTest( |
| 218 message, boundary, TestMode.PAUSE_RESUME, |
| 219 expectedHeaders, expectedParts, expectError); |
| 220 } |
| 221 |
| 165 void _testParseValid() { | 222 void _testParseValid() { |
| 166 // Empty message from Chrome form post. | 223 // Empty message from Chrome form post. |
| 167 var message = '------WebKitFormBoundaryU3FBruSkJKG0Yor1--\r\n'; | 224 var message = '------WebKitFormBoundaryU3FBruSkJKG0Yor1--\r\n'; |
| 168 _testParse(message, "----WebKitFormBoundaryU3FBruSkJKG0Yor1", [], []); | 225 _testParse(message, "----WebKitFormBoundaryU3FBruSkJKG0Yor1", [], []); |
| 169 | 226 |
| 170 // Sample from Wikipedia. | 227 // Sample from Wikipedia. |
| 171 message = """ | 228 message = """ |
| 172 This is a message with multiple parts in MIME format.\r | 229 This is a message with multiple parts in MIME format.\r |
| 173 --frontier\r | 230 --frontier\r |
| 174 Content-Type: text/plain\r | 231 Content-Type: text/plain\r |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 399 \r | 456 \r |
| 400 Body2\r | 457 Body2\r |
| 401 --xxx\r\n"""; | 458 --xxx\r\n"""; |
| 402 _testParse(message, "xxx", null, [null, null], true); | 459 _testParse(message, "xxx", null, [null, null], true); |
| 403 } | 460 } |
| 404 | 461 |
| 405 void main() { | 462 void main() { |
| 406 _testParseValid(); | 463 _testParseValid(); |
| 407 _testParseInvalid(); | 464 _testParseInvalid(); |
| 408 } | 465 } |
| OLD | NEW |