OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | |
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. | |
4 | |
5 import 'dart:async'; | |
6 | |
7 import 'package:unittest/src/util/multi_channel.dart'; | |
8 import 'package:unittest/unittest.dart'; | |
9 | |
10 import 'utils.dart'; | |
11 | |
12 void main() { | |
13 var oneToTwo; | |
14 var twoToOne; | |
15 var channel1; | |
16 var channel2; | |
17 setUp(() { | |
18 oneToTwo = new StreamController(); | |
19 twoToOne = new StreamController(); | |
20 channel1 = new MultiChannel(twoToOne.stream, oneToTwo.sink); | |
21 channel2 = new MultiChannel(oneToTwo.stream, twoToOne.sink); | |
22 }); | |
23 | |
24 group("the default virtual channel", () { | |
25 test("begins connected", () { | |
26 var first = true; | |
27 channel2.stream.listen(expectAsync((message) { | |
28 if (first) { | |
29 expect(message, equals("hello")); | |
30 first = false; | |
31 } else { | |
32 expect(message, equals("world")); | |
33 } | |
34 }, count: 2)); | |
35 | |
36 channel1.sink.add("hello"); | |
37 channel1.sink.add("world"); | |
38 }); | |
39 | |
40 test("closes the remote virtual channel when it closes", () { | |
41 expect(channel2.stream.toList(), completion(isEmpty)); | |
42 expect(channel2.sink.done, completes); | |
43 | |
44 channel1.sink.close(); | |
45 }); | |
46 | |
47 test("closes the local virtual channel when it closes", () { | |
48 expect(channel1.stream.toList(), completion(isEmpty)); | |
49 expect(channel1.sink.done, completes); | |
50 | |
51 channel1.sink.close(); | |
52 }); | |
53 | |
54 test("doesn't closes the local virtual channel when the stream " | |
55 "subscription is canceled", () { | |
56 channel1.sink.done.then(expectAsync((_) {}, count: 0)); | |
57 | |
58 channel1.stream.listen((_) {}).cancel(); | |
59 | |
60 // Ensure that there's enough time for the channel to close if it's going | |
61 // to. | |
62 return pumpEventQueue(); | |
63 }); | |
64 | |
65 test("closes the underlying channel when it closes without any other " | |
66 "virtual channels", () { | |
67 expect(oneToTwo.done, completes); | |
68 expect(twoToOne.done, completes); | |
69 | |
70 channel1.sink.close(); | |
71 }); | |
72 | |
73 test("doesn't close the underlying channel when it closes with other " | |
74 "virtual channels", () { | |
75 oneToTwo.done.then(expectAsync((_) {}, count: 0)); | |
76 twoToOne.done.then(expectAsync((_) {}, count: 0)); | |
77 | |
78 // Establish another virtual connection which should keep the underlying | |
79 // connection open. | |
80 channel2.virtualChannel(channel1.virtualChannel().id); | |
81 channel1.sink.close(); | |
82 | |
83 // Ensure that there's enough time for the underlying channel to complete | |
84 // if it's going to. | |
85 return pumpEventQueue(); | |
86 }); | |
87 }); | |
88 | |
89 group("a locally-created virtual channel", () { | |
90 var virtual1; | |
91 var virtual2; | |
92 setUp(() { | |
93 virtual1 = channel1.virtualChannel(); | |
94 virtual2 = channel2.virtualChannel(virtual1.id); | |
95 }); | |
96 | |
97 test("sends messages only to the other virtual channel", () { | |
98 var first = true; | |
99 virtual2.stream.listen(expectAsync((message) { | |
100 if (first) { | |
101 expect(message, equals("hello")); | |
102 first = false; | |
103 } else { | |
104 expect(message, equals("world")); | |
105 } | |
106 }, count: 2)); | |
107 | |
108 // No other virtual channels should receive the message. | |
109 for (var i = 0; i < 10; i++) { | |
110 var virtual = channel2.virtualChannel(channel1.virtualChannel().id); | |
111 virtual.stream.listen(expectAsync((_) {}, count: 0)); | |
112 } | |
113 channel2.stream.listen(expectAsync((_) {}, count: 0)); | |
114 | |
115 virtual1.sink.add("hello"); | |
116 virtual1.sink.add("world"); | |
117 }); | |
118 | |
119 test("closes the remote virtual channel when it closes", () { | |
120 expect(virtual2.stream.toList(), completion(isEmpty)); | |
121 expect(virtual2.sink.done, completes); | |
122 | |
123 virtual1.sink.close(); | |
124 }); | |
125 | |
126 test("closes the local virtual channel when it closes", () { | |
127 expect(virtual1.stream.toList(), completion(isEmpty)); | |
128 expect(virtual1.sink.done, completes); | |
129 | |
130 virtual1.sink.close(); | |
131 }); | |
132 | |
133 test("doesn't closes the local virtual channel when the stream " | |
134 "subscription is canceled", () { | |
135 virtual1.sink.done.then(expectAsync((_) {}, count: 0)); | |
136 virtual1.stream.listen((_) {}).cancel(); | |
137 | |
138 // Ensure that there's enough time for the channel to close if it's going | |
139 // to. | |
140 return pumpEventQueue(); | |
141 }); | |
142 | |
143 test("closes the underlying channel when it closes without any other " | |
144 "virtual channels", () { | |
145 // First close the default channel so we can test the new channel as the | |
146 // last living virtual channel. | |
147 channel1.sink.close(); | |
148 return channel2.stream.toList().then((_) { | |
149 expect(oneToTwo.done, completes); | |
150 expect(twoToOne.done, completes); | |
151 | |
152 virtual1.sink.close(); | |
153 }); | |
154 }); | |
155 | |
156 test("doesn't close the underlying channel when it closes with other " | |
157 "virtual channels", () { | |
158 oneToTwo.done.then(expectAsync((_) {}, count: 0)); | |
159 twoToOne.done.then(expectAsync((_) {}, count: 0)); | |
160 | |
161 virtual1.sink.close(); | |
162 | |
163 // Ensure that there's enough time for the underlying channel to complete | |
164 // if it's going to. | |
165 return pumpEventQueue(); | |
166 }); | |
167 | |
168 test("doesn't conflict with a remote virtual channel", () { | |
169 var virtual3 = channel2.virtualChannel(); | |
170 var virtual4 = channel1.virtualChannel(virtual3.id); | |
171 | |
172 // This is an implementation detail, but we assert it here to make sure | |
173 // we're properly testing two channels with the same id. | |
174 expect(virtual1.id, equals(virtual3.id)); | |
175 | |
176 virtual2.stream.listen( | |
177 expectAsync((message) => expect(message, equals("hello")))); | |
178 virtual4.stream.listen( | |
179 expectAsync((message) => expect(message, equals("goodbye")))); | |
180 | |
181 virtual1.sink.add("hello"); | |
182 virtual3.sink.add("goodbye"); | |
183 }); | |
184 }); | |
185 | |
186 group("a remotely-created virtual channel", () { | |
187 var virtual1; | |
188 var virtual2; | |
189 setUp(() { | |
190 virtual1 = channel1.virtualChannel(); | |
191 virtual2 = channel2.virtualChannel(virtual1.id); | |
192 }); | |
193 | |
194 test("sends messages only to the other virtual channel", () { | |
195 var first = true; | |
196 virtual1.stream.listen(expectAsync((message) { | |
197 if (first) { | |
198 expect(message, equals("hello")); | |
199 first = false; | |
200 } else { | |
201 expect(message, equals("world")); | |
202 } | |
203 }, count: 2)); | |
204 | |
205 // No other virtual channels should receive the message. | |
206 for (var i = 0; i < 10; i++) { | |
207 var virtual = channel2.virtualChannel(channel1.virtualChannel().id); | |
208 virtual.stream.listen(expectAsync((_) {}, count: 0)); | |
209 } | |
210 channel1.stream.listen(expectAsync((_) {}, count: 0)); | |
211 | |
212 virtual2.sink.add("hello"); | |
213 virtual2.sink.add("world"); | |
214 }); | |
215 | |
216 test("closes the remote virtual channel when it closes", () { | |
217 expect(virtual1.stream.toList(), completion(isEmpty)); | |
218 expect(virtual1.sink.done, completes); | |
219 | |
220 virtual2.sink.close(); | |
221 }); | |
222 | |
223 test("closes the local virtual channel when it closes", () { | |
224 expect(virtual2.stream.toList(), completion(isEmpty)); | |
225 expect(virtual2.sink.done, completes); | |
226 | |
227 virtual2.sink.close(); | |
228 }); | |
229 | |
230 test("doesn't closes the local virtual channel when the stream " | |
231 "subscription is canceled", () { | |
232 virtual2.sink.done.then(expectAsync((_) {}, count: 0)); | |
233 virtual2.stream.listen((_) {}).cancel(); | |
234 | |
235 // Ensure that there's enough time for the channel to close if it's going | |
236 // to. | |
237 return pumpEventQueue(); | |
238 }); | |
239 | |
240 test("closes the underlying channel when it closes without any other " | |
241 "virtual channels", () { | |
242 // First close the default channel so we can test the new channel as the | |
243 // last living virtual channel. | |
244 channel2.sink.close(); | |
245 return channel1.stream.toList().then((_) { | |
246 expect(oneToTwo.done, completes); | |
247 expect(twoToOne.done, completes); | |
248 | |
249 virtual2.sink.close(); | |
250 }); | |
251 }); | |
252 | |
253 test("doesn't close the underlying channel when it closes with other " | |
254 "virtual channels", () { | |
255 oneToTwo.done.then(expectAsync((_) {}, count: 0)); | |
256 twoToOne.done.then(expectAsync((_) {}, count: 0)); | |
257 | |
258 virtual2.sink.close(); | |
259 | |
260 // Ensure that there's enough time for the underlying channel to complete | |
261 // if it's going to. | |
262 return pumpEventQueue(); | |
263 }); | |
264 | |
265 test("doesn't allow another virtual channel with the same id", () { | |
266 expect(() => channel2.virtualChannel(virtual1.id), | |
267 throwsArgumentError); | |
268 }); | |
269 }); | |
270 | |
271 group("when the underlying stream", () { | |
272 var virtual1; | |
273 var virtual2; | |
274 setUp(() { | |
275 virtual1 = channel1.virtualChannel(); | |
276 virtual2 = channel2.virtualChannel(virtual1.id); | |
277 }); | |
278 | |
279 test("closes, all virtual channels close", () { | |
280 expect(channel1.stream.toList(), completion(isEmpty)); | |
281 expect(channel1.sink.done, completes); | |
282 expect(channel2.stream.toList(), completion(isEmpty)); | |
283 expect(channel2.sink.done, completes); | |
284 expect(virtual1.stream.toList(), completion(isEmpty)); | |
285 expect(virtual1.sink.done, completes); | |
286 expect(virtual2.stream.toList(), completion(isEmpty)); | |
287 expect(virtual2.sink.done, completes); | |
288 | |
289 oneToTwo.close(); | |
290 }); | |
291 | |
292 test("closes, no more virtual channels may be created", () { | |
293 expect(channel1.sink.done.then((_) => channel1.virtualChannel()), | |
294 throwsStateError); | |
295 expect(channel2.sink.done.then((_) => channel2.virtualChannel()), | |
296 throwsStateError); | |
297 | |
298 oneToTwo.close(); | |
299 }); | |
300 | |
301 test("emits an error, the error is sent only to the default channel", () { | |
302 channel1.stream.listen(expectAsync((_) {}, count: 0), | |
303 onError: expectAsync((error) => expect(error, equals("oh no")))); | |
304 virtual1.stream.listen(expectAsync((_) {}, count: 0), | |
305 onError: expectAsync((_) {}, count: 0)); | |
306 | |
307 twoToOne.addError("oh no"); | |
308 }); | |
309 }); | |
310 } | |
OLD | NEW |