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, |
| 12 int chunkSize, |
| 13 StreamController<List<int>> controller) { |
| 14 if (chunkSize == -1) chunkSize = data.length; |
| 15 |
| 16 int written = 0; |
| 17 for (int pos = 0; pos < data.length; pos += chunkSize) { |
| 18 int remaining = data.length - pos; |
| 19 int writeLength = min(chunkSize, remaining); |
| 20 controller.add(data.sublist(pos, pos + writeLength)); |
| 21 written += writeLength; |
| 22 } |
| 23 controller.close(); |
| 24 } |
| 25 |
| 26 |
11 void _testParse(String message, | 27 void _testParse(String message, |
12 String boundary, | 28 String boundary, |
13 [List<Map> expectedHeaders, | 29 [List<Map> expectedHeaders, |
14 List expectedParts, | 30 List expectedParts, |
15 bool expectError = false]) { | 31 bool expectError = false]) { |
16 Future testWrite(List<int> data, [int chunkSize = -1]) { | 32 Future testWrite(List<int> data, [int chunkSize = -1]) { |
17 StreamController controller = new StreamController(sync: true); | 33 StreamController controller = new StreamController(sync: true); |
18 | 34 |
19 var stream = controller.stream.transform( | 35 var stream = controller.stream.transform( |
20 new MimeMultipartTransformer(boundary)); | 36 new MimeMultipartTransformer(boundary)); |
(...skipping 13 matching lines...) Expand all Loading... |
34 })); | 50 })); |
35 }, onError: (error) { | 51 }, onError: (error) { |
36 if (!expectError) throw error; | 52 if (!expectError) throw error; |
37 }, onDone: () { | 53 }, onDone: () { |
38 if (expectedParts != null) { | 54 if (expectedParts != null) { |
39 expect(i, equals(expectedParts.length)); | 55 expect(i, equals(expectedParts.length)); |
40 } | 56 } |
41 Future.wait(futures).then(completer.complete); | 57 Future.wait(futures).then(completer.complete); |
42 }); | 58 }); |
43 | 59 |
44 if (chunkSize == -1) chunkSize = data.length; | 60 _writeInChunks(data, chunkSize, controller); |
45 | |
46 int written = 0; | |
47 for (int pos = 0; pos < data.length; pos += chunkSize) { | |
48 int remaining = data.length - pos; | |
49 int writeLength = min(chunkSize, remaining); | |
50 controller.add(data.sublist(pos, pos + writeLength)); | |
51 written += writeLength; | |
52 } | |
53 controller.close(); | |
54 | 61 |
55 return completer.future; | 62 return completer.future; |
56 } | 63 } |
| 64 |
| 65 Future testFirstPartOnly(List<int> data, [int chunkSize = -1]) { |
| 66 var completer = new Completer(); |
| 67 var controller = new StreamController(sync: true); |
| 68 |
| 69 var stream = controller.stream.transform( |
| 70 new MimeMultipartTransformer(boundary)); |
| 71 |
| 72 var subscription; |
| 73 subscription = stream.first.then((multipart) { |
| 74 if (expectedHeaders != null) { |
| 75 expect(multipart.headers, equals(expectedHeaders[0])); |
| 76 } |
| 77 return (multipart.fold([], (b, d) => b..addAll(d)).then((data) { |
| 78 if (expectedParts != null && expectedParts[0] != null) { |
| 79 expect(data, equals(expectedParts[0].codeUnits)); |
| 80 } |
| 81 })); |
| 82 }).then((_) { |
| 83 completer.complete(); |
| 84 }); |
| 85 |
| 86 _writeInChunks(data, chunkSize, controller); |
| 87 |
| 88 return completer.future; |
| 89 } |
| 90 |
| 91 Future testCompletePartAfterCancel(List<int> data, |
| 92 int parts, |
| 93 [int chunkSize = -1]) { |
| 94 var completer = new Completer(); |
| 95 var controller = new StreamController(sync: true); |
| 96 var stream = controller.stream.transform( |
| 97 new MimeMultipartTransformer(boundary)); |
| 98 var subscription; |
| 99 int i = 0; |
| 100 var futures = []; |
| 101 subscription = stream.listen((multipart) { |
| 102 int partIndex = i; |
| 103 |
| 104 if (partIndex >= parts) { |
| 105 throw 'Expected no more parts, but got one.'; |
| 106 } |
| 107 |
| 108 if (expectedHeaders != null) { |
| 109 expect(multipart.headers, equals(expectedHeaders[partIndex])); |
| 110 } |
| 111 futures.add((multipart.fold([], (b, d) => b..addAll(d)).then((data) { |
| 112 if (expectedParts != null && expectedParts[partIndex] != null) { |
| 113 expect(data, equals(expectedParts[partIndex].codeUnits)); |
| 114 } |
| 115 }))); |
| 116 |
| 117 if (partIndex == (parts - 1)) { |
| 118 subscription.cancel(); |
| 119 Future.wait(futures).then(completer.complete); |
| 120 } |
| 121 i++; |
| 122 }); |
| 123 |
| 124 _writeInChunks(data, chunkSize, controller); |
| 125 |
| 126 return completer.future; |
| 127 } |
57 | 128 |
58 // Test parsing the data three times delivering the data in | 129 // Test parsing the data three times delivering the data in |
59 // different chunks. | 130 // different chunks. |
60 List<int> data = message.codeUnits; | 131 List<int> data = message.codeUnits; |
61 test('test', () { | 132 test('test', () { |
62 expect(Future.wait([ | 133 expect(Future.wait([ |
63 testWrite(data), | 134 testWrite(data), |
64 testWrite(data, 10), | 135 testWrite(data, 10), |
65 testWrite(data, 2), | 136 testWrite(data, 2), |
66 testWrite(data, 1)]), | 137 testWrite(data, 1), |
67 completes); | 138 ]), completes); |
68 }); | 139 }); |
| 140 |
| 141 if (expectedParts.length > 0) { |
| 142 test('test-first-part-only', () { |
| 143 expect(Future.wait([ |
| 144 testFirstPartOnly(data), |
| 145 testFirstPartOnly(data, 10), |
| 146 testFirstPartOnly(data, 2), |
| 147 testFirstPartOnly(data, 1), |
| 148 ]), completes); |
| 149 }); |
| 150 |
| 151 test('test-n-parts-only', () { |
| 152 int numPartsExpected = expectedParts.length - 1; |
| 153 if (numPartsExpected == 0) numPartsExpected = 1; |
| 154 |
| 155 expect(Future.wait([ |
| 156 testCompletePartAfterCancel(data, numPartsExpected), |
| 157 testCompletePartAfterCancel(data, numPartsExpected, 10), |
| 158 testCompletePartAfterCancel(data, numPartsExpected, 2), |
| 159 testCompletePartAfterCancel(data, numPartsExpected, 1), |
| 160 ]), completes); |
| 161 }); |
| 162 } |
69 } | 163 } |
70 | 164 |
71 void _testParseValid() { | 165 void _testParseValid() { |
72 // Empty message from Chrome form post. | 166 // Empty message from Chrome form post. |
73 var message = '------WebKitFormBoundaryU3FBruSkJKG0Yor1--\r\n'; | 167 var message = '------WebKitFormBoundaryU3FBruSkJKG0Yor1--\r\n'; |
74 _testParse(message, "----WebKitFormBoundaryU3FBruSkJKG0Yor1", [], []); | 168 _testParse(message, "----WebKitFormBoundaryU3FBruSkJKG0Yor1", [], []); |
75 | 169 |
76 // Sample from Wikipedia. | 170 // Sample from Wikipedia. |
77 message = """ | 171 message = """ |
78 This is a message with multiple parts in MIME format.\r | 172 This is a message with multiple parts in MIME format.\r |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 \r | 399 \r |
306 Body2\r | 400 Body2\r |
307 --xxx\r\n"""; | 401 --xxx\r\n"""; |
308 _testParse(message, "xxx", null, [null, null], true); | 402 _testParse(message, "xxx", null, [null, null], true); |
309 } | 403 } |
310 | 404 |
311 void main() { | 405 void main() { |
312 _testParseValid(); | 406 _testParseValid(); |
313 _testParseInvalid(); | 407 _testParseInvalid(); |
314 } | 408 } |
OLD | NEW |