OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, 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 // VMOptions= | |
6 // VMOptions=--short_socket_read | |
7 // VMOptions=--short_socket_write | |
8 // VMOptions=--short_socket_read --short_socket_write | |
9 // | |
10 // Test socket close events. | |
11 | |
12 import 'dart:async'; | |
13 import 'dart:io'; | |
14 import 'dart:isolate'; | |
15 | |
16 const SERVERSHUTDOWN = -1; | |
17 const ITERATIONS = 10; | |
18 | |
19 | |
20 class SocketClose { | |
21 | |
22 SocketClose.start(this._mode, this._donePort) | |
23 : _receivePort = new ReceivePort(), | |
24 _sendPort = null, | |
25 _readBytes = 0, | |
26 _dataEvents = 0, | |
27 _closeEvents = 0, | |
28 _errorEvents = 0, | |
29 _iterations = 0 { | |
30 _sendPort = spawnFunction(startSocketCloseServer); | |
31 initialize(); | |
32 } | |
33 | |
34 void proceed() { | |
35 if (_iterations < ITERATIONS) { | |
36 Timer.run(sendData); | |
37 } else { | |
38 shutdown(); | |
39 } | |
40 } | |
41 | |
42 void sendData() { | |
43 | |
44 void dataHandler() { | |
45 switch (_mode) { | |
46 case 0: | |
47 case 1: | |
48 case 2: | |
49 Expect.fail("No data expected"); | |
50 break; | |
51 case 3: | |
52 case 4: | |
53 case 5: | |
54 case 6: | |
55 case 7: | |
56 case 8: | |
57 var read = _socket.inputStream.read(); | |
58 _readBytes += read.length; | |
59 if ((_readBytes % 5) == 0) { | |
60 _dataEvents++; | |
61 } | |
62 break; | |
63 default: | |
64 Expect.fail("Unknown test mode"); | |
65 } | |
66 } | |
67 | |
68 void closeHandler() { | |
69 _closeEvents++; | |
70 switch (_mode) { | |
71 case 0: | |
72 case 1: | |
73 break; | |
74 case 2: | |
75 case 3: | |
76 case 4: | |
77 _socket.outputStream.close(); | |
78 proceed(); | |
79 break; | |
80 case 5: | |
81 proceed(); | |
82 break; | |
83 case 6: | |
84 _socket.outputStream.close(); | |
85 proceed(); | |
86 break; | |
87 case 7: | |
88 case 8: | |
89 proceed(); | |
90 break; | |
91 default: | |
92 Expect.fail("Unknown test mode"); | |
93 } | |
94 } | |
95 | |
96 void errorHandler(Exception e) { | |
97 _errorEvents++; | |
98 _socket.close(); | |
99 } | |
100 | |
101 void connectHandler() { | |
102 _socket.inputStream.onData = dataHandler; | |
103 _socket.inputStream.onClosed = closeHandler; | |
104 _socket.onError = errorHandler; | |
105 | |
106 _iterations++; | |
107 switch (_mode) { | |
108 case 0: | |
109 _socket.inputStream.close(); | |
110 proceed(); | |
111 break; | |
112 case 1: | |
113 _socket.outputStream.write("Hello".charCodes); | |
114 _socket.outputStream.onNoPendingWrites = () { | |
115 _socket.inputStream.close(); | |
116 proceed(); | |
117 }; | |
118 break; | |
119 case 2: | |
120 case 3: | |
121 case 4: | |
122 _socket.outputStream.write("Hello".charCodes); | |
123 break; | |
124 case 5: | |
125 _socket.outputStream.write("Hello".charCodes); | |
126 _socket.outputStream.onNoPendingWrites = () { | |
127 _socket.outputStream.close(); | |
128 }; | |
129 break; | |
130 case 6: | |
131 _socket.outputStream.write("Hello".charCodes); | |
132 break; | |
133 case 7: | |
134 case 8: | |
135 _socket.outputStream.write("Hello".charCodes); | |
136 _socket.outputStream.onNoPendingWrites = () { | |
137 _socket.outputStream.close(); | |
138 }; | |
139 break; | |
140 default: | |
141 Expect.fail("Unknown test mode"); | |
142 } | |
143 } | |
144 | |
145 _socket = new Socket(SocketCloseServer.HOST, _port); | |
146 Expect.equals(true, _socket != null); | |
147 _socket.onConnect = connectHandler; | |
148 } | |
149 | |
150 void initialize() { | |
151 _receivePort.receive((var message, SendPort replyTo) { | |
152 _port = message; | |
153 proceed(); | |
154 }); | |
155 _sendPort.send(_mode, _receivePort.toSendPort()); | |
156 } | |
157 | |
158 void shutdown() { | |
159 _sendPort.send(SERVERSHUTDOWN, _receivePort.toSendPort()); | |
160 _receivePort.receive((message, ignore) { | |
161 _donePort.send(null); | |
162 _receivePort.close(); | |
163 }); | |
164 | |
165 switch (_mode) { | |
166 case 0: | |
167 case 1: | |
168 Expect.equals(0, _dataEvents); | |
169 Expect.equals(0, _closeEvents); | |
170 break; | |
171 case 2: | |
172 Expect.equals(0, _dataEvents); | |
173 Expect.equals(ITERATIONS, _closeEvents); | |
174 break; | |
175 case 3: | |
176 Expect.equals(ITERATIONS, _dataEvents); | |
177 Expect.equals(ITERATIONS, _closeEvents); | |
178 break; | |
179 case 4: | |
180 Expect.equals(ITERATIONS, _closeEvents); | |
181 break; | |
182 case 5: | |
183 case 6: | |
184 case 7: | |
185 case 8: | |
186 Expect.equals(ITERATIONS, _dataEvents); | |
187 Expect.equals(ITERATIONS, _closeEvents); | |
188 break; | |
189 default: | |
190 Expect.fail("Unknown test mode"); | |
191 } | |
192 Expect.equals(0, _errorEvents); | |
193 } | |
194 | |
195 int _port; | |
196 ReceivePort _receivePort; | |
197 SendPort _sendPort; | |
198 Socket _socket; | |
199 List<int> _buffer; | |
200 int _readBytes; | |
201 int _dataEvents; | |
202 int _closeEvents; | |
203 int _errorEvents; | |
204 int _iterations; | |
205 int _mode; | |
206 SendPort _donePort; | |
207 } | |
208 | |
209 | |
210 class ConnectionData { | |
211 ConnectionData(Socket this.connection) : readBytes = 0; | |
212 Socket connection; | |
213 int readBytes; | |
214 } | |
215 | |
216 | |
217 void startSocketCloseServer() { | |
218 var server = new SocketCloseServer(); | |
219 port.receive(server.dispatch); | |
220 } | |
221 | |
222 | |
223 class SocketCloseServer { | |
224 | |
225 static const HOST = "127.0.0.1"; | |
226 | |
227 SocketCloseServer() : super() {} | |
228 | |
229 void connectionHandler(ConnectionData data) { | |
230 var connection = data.connection; | |
231 | |
232 void readBytes(whenFiveBytes) { | |
233 var read = connection.inputStream.read(); | |
234 data.readBytes += read.length; | |
235 if (data.readBytes == 5) { | |
236 whenFiveBytes(); | |
237 } | |
238 } | |
239 | |
240 void dataHandler() { | |
241 switch (_mode) { | |
242 case 0: | |
243 Expect.fail("No data expected"); | |
244 break; | |
245 case 1: | |
246 readBytes(() { | |
247 _dataEvents++; | |
248 }); | |
249 break; | |
250 case 2: | |
251 readBytes(() { | |
252 _dataEvents++; | |
253 connection.inputStream.close(); | |
254 }); | |
255 break; | |
256 case 3: | |
257 readBytes(() { | |
258 _dataEvents++; | |
259 connection.outputStream.write("Hello".charCodes); | |
260 connection.outputStream.onNoPendingWrites = () { | |
261 connection.inputStream.close(); | |
262 }; | |
263 }); | |
264 break; | |
265 case 4: | |
266 readBytes(() { | |
267 _dataEvents++; | |
268 connection.outputStream.write("Hello".charCodes); | |
269 connection.inputStream.close(); | |
270 }); | |
271 break; | |
272 case 5: | |
273 readBytes(() { | |
274 _dataEvents++; | |
275 connection.outputStream.write("Hello".charCodes); | |
276 }); | |
277 break; | |
278 case 6: | |
279 case 7: | |
280 readBytes(() { | |
281 _dataEvents++; | |
282 connection.outputStream.write("Hello".charCodes); | |
283 connection.outputStream.onNoPendingWrites = () { | |
284 connection.outputStream.close(); | |
285 }; | |
286 }); | |
287 break; | |
288 case 8: | |
289 readBytes(() { | |
290 _dataEvents++; | |
291 connection.outputStream.write("Hello".charCodes); | |
292 connection.outputStream.close(); | |
293 }); | |
294 break; | |
295 default: | |
296 Expect.fail("Unknown test mode"); | |
297 } | |
298 } | |
299 | |
300 void closeHandler() { | |
301 _closeEvents++; | |
302 connection.outputStream.close(); | |
303 } | |
304 | |
305 void errorHandler(Exception e) { | |
306 Expect.fail("Socket error $e"); | |
307 } | |
308 | |
309 _iterations++; | |
310 | |
311 connection.inputStream.onData = dataHandler; | |
312 connection.inputStream.onClosed = closeHandler; | |
313 connection.onError = errorHandler; | |
314 } | |
315 | |
316 void errorHandlerServer(Exception e) { | |
317 Expect.fail("Server socket error"); | |
318 } | |
319 | |
320 waitForResult() { | |
321 // Make sure all iterations have been run. In multiple of these | |
322 // scenarios it is possible to get the SERVERSHUTDOWN message | |
323 // before we have received the last close event on the | |
324 // server. In these cases we wait for the correct number of | |
325 // close events. | |
326 if (_iterations == ITERATIONS && | |
327 (_closeEvents == ITERATIONS || | |
328 (_mode == 2 || _mode == 3 || _mode == 4))) { | |
329 switch (_mode) { | |
330 case 0: | |
331 Expect.equals(0, _dataEvents); | |
332 Expect.equals(ITERATIONS, _closeEvents); | |
333 break; | |
334 case 1: | |
335 Expect.equals(ITERATIONS, _dataEvents); | |
336 Expect.equals(ITERATIONS, _closeEvents); | |
337 break; | |
338 case 2: | |
339 case 3: | |
340 case 4: | |
341 Expect.equals(ITERATIONS, _dataEvents); | |
342 Expect.equals(0, _closeEvents); | |
343 break; | |
344 case 5: | |
345 case 6: | |
346 case 7: | |
347 case 8: | |
348 Expect.equals(ITERATIONS, _dataEvents); | |
349 Expect.equals(ITERATIONS, _closeEvents); | |
350 break; | |
351 default: | |
352 Expect.fail("Unknown test mode"); | |
353 } | |
354 Expect.equals(0, _errorEvents); | |
355 _server.close(); | |
356 port.close(); | |
357 _donePort.send(null); | |
358 } else { | |
359 new Timer(new Duration(milliseconds: 100), waitForResult); | |
360 } | |
361 } | |
362 | |
363 void dispatch(message, replyTo) { | |
364 _donePort = replyTo; | |
365 if (message != SERVERSHUTDOWN) { | |
366 _readBytes = 0; | |
367 _errorEvents = 0; | |
368 _dataEvents = 0; | |
369 _closeEvents = 0; | |
370 _iterations = 0; | |
371 _mode = message; | |
372 _server = new ServerSocket(HOST, 0, 10); | |
373 Expect.equals(true, _server != null); | |
374 _server.onConnection = (connection) { | |
375 var data = new ConnectionData(connection); | |
376 connectionHandler(data); | |
377 }; | |
378 _server.onError = errorHandlerServer; | |
379 replyTo.send(_server.port, null); | |
380 } else { | |
381 Timer.run(waitForResult); | |
382 } | |
383 } | |
384 | |
385 ServerSocket _server; | |
386 SendPort _donePort; | |
387 int _readBytes; | |
388 int _errorEvents; | |
389 int _dataEvents; | |
390 int _closeEvents; | |
391 int _iterations; | |
392 int _mode; | |
393 } | |
394 | |
395 | |
396 main() { | |
397 // Run the close test in these different "modes". | |
398 // 0: Client closes without sending at all. | |
399 // 1: Client sends and closes. | |
400 // 2: Client sends. Server closes. | |
401 // 3: Client sends. Server responds and closes. | |
402 // 4: Client sends. Server responds and closes without waiting for everything | |
403 // being sent. | |
404 // 5: Client sends and half-closes. Server responds and closes. | |
405 // 6: Client sends. Server responds and half closes. | |
406 // 7: Client sends and half-closes. Server responds and half closes. | |
407 // 8: Client sends and half-closes. Server responds and half closes without | |
408 // explicitly waiting for everything being sent. | |
409 var tests = 9; | |
410 var port = new ReceivePort(); | |
411 var completed = 0; | |
412 port.receive((message, ignore) { | |
413 if (++completed == tests) port.close(); | |
414 }); | |
415 for (var i = 0; i < tests; i++) { | |
416 new SocketClose.start(i, port.toSendPort()); | |
417 } | |
418 } | |
OLD | NEW |