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