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 |