Chromium Code Reviews| 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) { |
| 50 })); | 57 expect(data, equals(expectedParts[part].codeUnits)); |
| 58 } | |
| 59 })); | |
| 60 break; | |
| 61 | |
| 62 case TestMode.DELAY_LISTEN: | |
| 63 var completer = new Completer(); | |
| 64 futures.add(completer.future); | |
| 65 new Future(() { | |
| 66 multipart.fold([], (buffer, data) => buffer..addAll(data)) | |
| 67 .then((data) { | |
| 68 if (expectedParts[part] != null) { | |
| 69 expect(data, equals(expectedParts[part].codeUnits)); | |
| 70 } | |
| 71 completer.complete(); | |
| 72 }); | |
| 73 }); | |
|
kustermann
2015/02/17 17:08:03
You don't need a completer here. Doing futures.add
Søren Gjesse
2015/02/18 07:27:18
Done.
| |
| 74 break; | |
| 75 | |
| 76 case TestMode.PAUSE_RESUME: | |
| 77 var completer = new Completer(); | |
| 78 futures.add(completer.future); | |
| 79 var buffer = []; | |
| 80 var subscription; | |
| 81 subscription = multipart.listen( | |
| 82 (data) { | |
| 83 buffer.addAll(data); | |
| 84 subscription.pause(); | |
| 85 new Future(() => subscription.resume()); | |
| 86 }, | |
| 87 onDone: () { | |
| 88 if (expectedParts[part] != null) { | |
| 89 expect(buffer, equals(expectedParts[part].codeUnits)); | |
| 90 } | |
| 91 completer.complete(); | |
| 92 }); | |
| 93 break; | |
| 94 } | |
| 51 }, onError: (error) { | 95 }, onError: (error) { |
| 52 if (!expectError) throw error; | 96 if (!expectError) throw error; |
| 53 }, onDone: () { | 97 }, onDone: () { |
| 54 if (expectedParts != null) { | 98 if (expectedParts != null) { |
| 55 expect(i, equals(expectedParts.length)); | 99 expect(i, equals(expectedParts.length)); |
| 56 } | 100 } |
| 57 Future.wait(futures).then(completer.complete); | 101 Future.wait(futures).then(completer.complete); |
| 58 }); | 102 }); |
| 59 | 103 |
| 60 _writeInChunks(data, chunkSize, controller); | 104 _writeInChunks(data, chunkSize, controller); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 155 expect(Future.wait([ | 199 expect(Future.wait([ |
| 156 testCompletePartAfterCancel(data, numPartsExpected), | 200 testCompletePartAfterCancel(data, numPartsExpected), |
| 157 testCompletePartAfterCancel(data, numPartsExpected, 10), | 201 testCompletePartAfterCancel(data, numPartsExpected, 10), |
| 158 testCompletePartAfterCancel(data, numPartsExpected, 2), | 202 testCompletePartAfterCancel(data, numPartsExpected, 2), |
| 159 testCompletePartAfterCancel(data, numPartsExpected, 1), | 203 testCompletePartAfterCancel(data, numPartsExpected, 1), |
| 160 ]), completes); | 204 ]), completes); |
| 161 }); | 205 }); |
| 162 } | 206 } |
| 163 } | 207 } |
| 164 | 208 |
| 209 void _testParse(String message, | |
| 210 String boundary, | |
| 211 [List<Map> expectedHeaders, | |
| 212 List expectedParts, | |
| 213 bool expectError = false]) { | |
| 214 _runParseTest( | |
| 215 message, boundary, TestMode.IMMEDIATE_LISTEN, | |
| 216 expectedHeaders, expectedParts, expectError); | |
| 217 _runParseTest( | |
| 218 message, boundary, TestMode.DELAY_LISTEN, | |
| 219 expectedHeaders, expectedParts, expectError); | |
| 220 _runParseTest( | |
| 221 message, boundary, TestMode.PAUSE_RESUME, | |
| 222 expectedHeaders, expectedParts, expectError); | |
| 223 } | |
| 224 | |
| 165 void _testParseValid() { | 225 void _testParseValid() { |
| 166 // Empty message from Chrome form post. | 226 // Empty message from Chrome form post. |
| 167 var message = '------WebKitFormBoundaryU3FBruSkJKG0Yor1--\r\n'; | 227 var message = '------WebKitFormBoundaryU3FBruSkJKG0Yor1--\r\n'; |
| 168 _testParse(message, "----WebKitFormBoundaryU3FBruSkJKG0Yor1", [], []); | 228 _testParse(message, "----WebKitFormBoundaryU3FBruSkJKG0Yor1", [], []); |
| 169 | 229 |
| 170 // Sample from Wikipedia. | 230 // Sample from Wikipedia. |
| 171 message = """ | 231 message = """ |
| 172 This is a message with multiple parts in MIME format.\r | 232 This is a message with multiple parts in MIME format.\r |
| 173 --frontier\r | 233 --frontier\r |
| 174 Content-Type: text/plain\r | 234 Content-Type: text/plain\r |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 399 \r | 459 \r |
| 400 Body2\r | 460 Body2\r |
| 401 --xxx\r\n"""; | 461 --xxx\r\n"""; |
| 402 _testParse(message, "xxx", null, [null, null], true); | 462 _testParse(message, "xxx", null, [null, null], true); |
| 403 } | 463 } |
| 404 | 464 |
| 405 void main() { | 465 void main() { |
| 406 _testParseValid(); | 466 _testParseValid(); |
| 407 _testParseInvalid(); | 467 _testParseInvalid(); |
| 408 } | 468 } |
| OLD | NEW |