| Index: tests/standalone/io/raw_socket_test.dart
|
| diff --git a/tests/standalone/io/raw_socket_test.dart b/tests/standalone/io/raw_socket_test.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d14dc9e7d9a5429ea3c5c8b11f8b93a278de1c69
|
| --- /dev/null
|
| +++ b/tests/standalone/io/raw_socket_test.dart
|
| @@ -0,0 +1,412 @@
|
| +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +//
|
| +// VMOptions=
|
| +// VMOptions=--short_socket_read
|
| +// VMOptions=--short_socket_write
|
| +// VMOptions=--short_socket_read --short_socket_write
|
| +
|
| +import "dart:async";
|
| +import "dart:io";
|
| +import "dart:isolate";
|
| +
|
| +void testArguments() {
|
| + Expect.throws(() => RawServerSocket.bind("127.0.0.1", 65536));
|
| + Expect.throws(() => RawServerSocket.bind("127.0.0.1", -1));
|
| + Expect.throws(() => RawServerSocket.bind("127.0.0.1", 0, -1));
|
| +}
|
| +
|
| +void testSimpleBind() {
|
| + ReceivePort port = new ReceivePort();
|
| + RawServerSocket.bind().then((s) {
|
| + Expect.isTrue(s.port > 0);
|
| + port.close();
|
| + });
|
| +}
|
| +
|
| +void testInvalidBind() {
|
| + int count = 0;
|
| + ReceivePort port = new ReceivePort();
|
| + port.receive((_, __) { count++; if (count == 3) port.close(); });
|
| +
|
| + // Bind to a unknown DNS name.
|
| + RawServerSocket.bind("ko.faar.__hest__")
|
| + .then((_) { Expect.fail("Failure expected"); } )
|
| + .catchError((e) {
|
| + Expect.isTrue(e.error is SocketIOException);
|
| + port.toSendPort().send(1);
|
| + });
|
| +
|
| + // Bind to an unavaliable IP-address.
|
| + RawServerSocket.bind("8.8.8.8")
|
| + .then((_) { Expect.fail("Failure expected"); } )
|
| + .catchError((e) {
|
| + Expect.isTrue(e.error is SocketIOException);
|
| + port.toSendPort().send(1);
|
| + });
|
| +
|
| + // Bind to a port already in use.
|
| + // Either an error or a successful bind is allowed.
|
| + // Windows platforms allow multiple binding to the same socket, with
|
| + // unpredictable results.
|
| + RawServerSocket.bind("127.0.0.1")
|
| + .then((s) {
|
| + RawServerSocket.bind("127.0.0.1", s.port)
|
| + .then((t) {
|
| + Expect.equals('windows', Platform.operatingSystem);
|
| + Expect.equals(s.port, t.port);
|
| + port.toSendPort().send(1);
|
| + })
|
| + .catchError((e) {
|
| + Expect.notEquals('windows', Platform.operatingSystem);
|
| + Expect.isTrue(e.error is SocketIOException);
|
| + port.toSendPort().send(1);
|
| + });
|
| + });
|
| +}
|
| +
|
| +void testSimpleConnect() {
|
| + ReceivePort port = new ReceivePort();
|
| + RawServerSocket.bind().then((server) {
|
| + server.listen((_) { });
|
| + RawSocket.connect("127.0.0.1", server.port).then((_) {
|
| + server.close();
|
| + port.close();
|
| + });
|
| + });
|
| +}
|
| +
|
| +void testCloseOneEnd(String toClose) {
|
| + ReceivePort port = new ReceivePort();
|
| + Completer serverDone = new Completer();
|
| + Completer serverEndDone = new Completer();
|
| + Completer clientEndDone = new Completer();
|
| + Future.wait([serverDone.future, serverEndDone.future, clientEndDone.future])
|
| + .then((_) {
|
| + port.close();
|
| + });
|
| + RawServerSocket.bind().then((server) {
|
| + server.listen((serverConnection) {
|
| + serverConnection.listen((event) {
|
| + if (toClose == "server" || event == RawSocketEvent.READ_CLOSED) {
|
| + serverConnection.shutdown(SocketDirection.SEND);
|
| + }
|
| + },
|
| + onDone: () {
|
| + serverEndDone.complete(null);
|
| + });
|
| + },
|
| + onDone:() {
|
| + serverDone.complete(null);
|
| + });
|
| + RawSocket.connect("127.0.0.1", server.port).then((clientConnection) {
|
| + clientConnection.listen((event){
|
| + if (toClose == "client" || event == RawSocketEvent.READ_CLOSED) {
|
| + clientConnection.shutdown(SocketDirection.SEND);
|
| + }
|
| + },
|
| + onDone: () {
|
| + clientEndDone.complete(null);
|
| + server.close();
|
| + });
|
| + });
|
| + });
|
| +}
|
| +
|
| +void testServerListenAfterConnect() {
|
| + ReceivePort port = new ReceivePort();
|
| + RawServerSocket.bind().then((server) {
|
| + Expect.isTrue(server.port > 0);
|
| + RawSocket.connect("127.0.0.1", server.port).then((_) {
|
| + server.listen((_) {
|
| + server.close();
|
| + port.close();
|
| + });
|
| + });
|
| + });
|
| +}
|
| +
|
| +void testSimpleReadWrite() {
|
| + // This test creates a server and a client connects. The client then
|
| + // writes and the server echos. When the server has finished its
|
| + // echo it half-closes. When the client gets the close event is
|
| + // closes fully.
|
| + ReceivePort port = new ReceivePort();
|
| +
|
| + const messageSize = 1000;
|
| +
|
| + List<int> createTestData() {
|
| + List<int> data = new List.fixedLength(messageSize);
|
| + for (int i = 0; i < messageSize; i++) {
|
| + data[i] = i & 0xff;
|
| + }
|
| + return data;
|
| + }
|
| +
|
| + void verifyTestData(List<int> data) {
|
| + Expect.equals(messageSize, data.length);
|
| + List<int> expected = createTestData();
|
| + for (int i = 0; i < messageSize; i++) {
|
| + Expect.equals(expected[i], data[i]);
|
| + }
|
| + }
|
| +
|
| + RawServerSocket.bind().then((server) {
|
| + server.listen((client) {
|
| + int bytesRead = 0;
|
| + int bytesWritten = 0;
|
| + List<int> data = new List.fixedLength(messageSize);
|
| +
|
| + client.writeEventsEnabled = false;
|
| + client.listen((event) {
|
| + switch (event) {
|
| + case RawSocketEvent.READ:
|
| + Expect.isTrue(bytesWritten == 0);
|
| + Expect.isTrue(client.available() > 0);
|
| + var buffer = client.read();
|
| + data.setRange(bytesRead, buffer.length, buffer);
|
| + bytesRead += buffer.length;
|
| + if (bytesRead == data.length) {
|
| + verifyTestData(data);
|
| + client.writeEventsEnabled = true;
|
| + }
|
| + break;
|
| + case RawSocketEvent.WRITE:
|
| + Expect.isFalse(client.writeEventsEnabled);
|
| + bytesWritten += client.write(
|
| + data, bytesWritten, data.length - bytesWritten);
|
| + if (bytesWritten < data.length) {
|
| + client.writeEventsEnabled = true;
|
| + }
|
| + if (bytesWritten == data.length) {
|
| + client.shutdown(SocketDirection.SEND);
|
| + }
|
| + break;
|
| + case RawSocketEvent.READ_CLOSED:
|
| + server.close();
|
| + break;
|
| + default: throw "Unexpected event $event";
|
| + }
|
| + });
|
| + });
|
| +
|
| + RawSocket.connect("127.0.0.1", server.port).then((socket) {
|
| + int bytesRead = 0;
|
| + int bytesWritten = 0;
|
| + List<int> data = createTestData();
|
| +
|
| + socket.listen((event) {
|
| + switch (event) {
|
| + case RawSocketEvent.READ:
|
| + Expect.isTrue(socket.available() > 0);
|
| + var buffer = socket.read();
|
| + data.setRange(bytesRead, buffer.length, buffer);
|
| + bytesRead += buffer.length;
|
| + break;
|
| + case RawSocketEvent.WRITE:
|
| + Expect.isTrue(bytesRead == 0);
|
| + Expect.isFalse(socket.writeEventsEnabled);
|
| + bytesWritten += socket.write(
|
| + data, bytesWritten, data.length - bytesWritten);
|
| + if (bytesWritten < data.length) {
|
| + socket.writeEventsEnabled = true;
|
| + } else {
|
| + data = new List.fixedLength(messageSize);
|
| + }
|
| + break;
|
| + case RawSocketEvent.READ_CLOSED:
|
| + verifyTestData(data);
|
| + socket.close();
|
| + break;
|
| + default: throw "Unexpected event $event";
|
| + }
|
| + },
|
| + onDone: () => port.close());
|
| + });
|
| + });
|
| +}
|
| +
|
| +testPauseServerSocket() {
|
| + const int socketCount = 10;
|
| + var acceptCount = 0;
|
| + var resumed = false;
|
| +
|
| + ReceivePort port = new ReceivePort();
|
| +
|
| + RawServerSocket.bind().then((server) {
|
| + Expect.isTrue(server.port > 0);
|
| + var subscription = server.listen((_) {
|
| + Expect.isTrue(resumed);
|
| + if (++acceptCount == socketCount) {
|
| + server.close();
|
| + port.close();
|
| + }
|
| + });
|
| +
|
| + // Pause the server socket subscription and resume it after having
|
| + // connected a number client sockets. Then connect more client
|
| + // sockets.
|
| + subscription.pause();
|
| + var connectCount = 0;
|
| + for (int i = 0; i <= socketCount / 2; i++) {
|
| + RawSocket.connect("127.0.0.1", server.port).then((_) {
|
| + if (++connectCount == socketCount / 2) {
|
| + subscription.resume();
|
| + resumed = true;
|
| + for (int i = connectCount; i < socketCount; i++) {
|
| + RawSocket.connect("127.0.0.1", server.port).then((_) {});
|
| + }
|
| + }
|
| + });
|
| + }
|
| + });
|
| +}
|
| +
|
| +testCancelResubscribeServerSocket() {
|
| + const int socketCount = 10;
|
| + var acceptCount = 0;
|
| + var doneCount = 0;
|
| + var closeCount = 0;
|
| + var errorCount = 0;
|
| +
|
| + ReceivePort port = new ReceivePort();
|
| +
|
| + RawServerSocket.bind().then((server) {
|
| + Expect.isTrue(server.port > 0);
|
| +
|
| + void checkDone() {
|
| + if (doneCount == socketCount &&
|
| + closeCount + errorCount == socketCount) {
|
| + port.close();
|
| + }
|
| + }
|
| +
|
| + // Subscribe the server socket. Then cancel subscription and
|
| + // subscribe again.
|
| + var subscription;
|
| + subscription = server.listen((client) {
|
| + if (++acceptCount == socketCount / 2) {
|
| + subscription.cancel();
|
| + new Timer(0, (_) {
|
| + subscription = server.listen((_) {
|
| + // Close on cancel, so no more events.
|
| + Expect.fail("Event after closed through cancel");
|
| + });
|
| + });
|
| + }
|
| + // Close the client socket.
|
| + client.close();
|
| + });
|
| +
|
| + // Connect a number of sockets.
|
| + for (int i = 0; i < socketCount; i++) {
|
| + RawSocket.connect("127.0.0.1", server.port).then((socket) {
|
| + socket.writeEventsEnabled = false;
|
| + var subscription;
|
| + subscription = socket.listen((event) {
|
| + Expect.equals(RawSocketEvent.READ_CLOSED, event);
|
| + socket.close();
|
| + closeCount++;
|
| + checkDone();
|
| + },
|
| + onDone: () { doneCount++; checkDone(); },
|
| + onError: (e) { errorCount++; checkDone(); });
|
| + });
|
| + }
|
| + });
|
| +}
|
| +
|
| +testPauseSocket() {
|
| + const messageSize = 1000;
|
| + const loopCount = 10;
|
| + Completer connected = new Completer();
|
| + int pauseResumeCount = 0;
|
| + int bytesWritten = 0;
|
| + int bytesRead = 0;
|
| + var writeSubscription;
|
| + var readSubscription;
|
| +
|
| + ReceivePort port = new ReceivePort();
|
| +
|
| + RawServerSocket.bind().then((server) {
|
| + Expect.isTrue(server.port > 0);
|
| + server.listen((client) {
|
| + List<int> data = new List.fixedLength(messageSize, fill: 0);
|
| + writeSubscription = client.listen((event) {
|
| + switch (event) {
|
| + case RawSocketEvent.READ:
|
| + throw "Unexpected read event";
|
| + case RawSocketEvent.WRITE:
|
| + if (pauseResumeCount == loopCount) return;
|
| + Expect.isFalse(client.writeEventsEnabled);
|
| + Expect.equals(0, bytesRead); // Checks that reader is paused.
|
| + bytesWritten += client.write(
|
| + data, bytesWritten, data.length - bytesWritten);
|
| + // Ensure all data is written. When done disable the write
|
| + // event and resume the receiver.
|
| + if (bytesWritten == data.length) {
|
| + writeSubscription.pause();
|
| + bytesWritten = 0;
|
| + connected.future.then((_) { readSubscription.resume(); });
|
| + }
|
| + client.writeEventsEnabled = true;
|
| + break;
|
| + case RawSocketEvent.READ_CLOSED:
|
| + client.close();
|
| + server.close();
|
| + break;
|
| + default: throw "Unexpected event $event";
|
| + }
|
| + });
|
| + });
|
| +
|
| + RawSocket.connect("127.0.0.1", server.port).then((socket) {
|
| + socket.writeEventsEnabled = false;
|
| + readSubscription = socket.listen((event) {
|
| + switch (event) {
|
| + case RawSocketEvent.READ:
|
| + Expect.equals(0, bytesWritten); // Checks that writer is paused.
|
| + Expect.isTrue(socket.available() > 0);
|
| + var buffer = socket.read();
|
| + bytesRead += buffer.length;
|
| + // Ensure all data is read. When done pause and resume the sender
|
| + if (bytesRead == messageSize) {
|
| + if (++pauseResumeCount == loopCount) {
|
| + socket.close();
|
| + port.close();
|
| + } else {
|
| + readSubscription.pause();
|
| + }
|
| + // Always resume writer as it needs the read closed
|
| + // event when done.
|
| + bytesRead = 0;
|
| + writeSubscription.resume();
|
| + }
|
| + break;
|
| + case RawSocketEvent.WRITE:
|
| + throw "Unexpected write event";
|
| + case RawSocketEvent.READ_CLOSED:
|
| + throw "Unexpected close event";
|
| + default: throw "Unexpected event $event";
|
| + }
|
| + });
|
| + readSubscription.pause();
|
| + connected.complete(true);
|
| + });
|
| + });
|
| +}
|
| +
|
| +main() {
|
| + testArguments();
|
| + testSimpleBind();
|
| + testCloseOneEnd("client");
|
| + testCloseOneEnd("server");
|
| + testInvalidBind();
|
| + testSimpleConnect();
|
| + testServerListenAfterConnect();
|
| + testSimpleReadWrite();
|
| + testPauseServerSocket();
|
| + testCancelResubscribeServerSocket();
|
| + testPauseSocket();
|
| +}
|
|
|