| 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 |