From 171da0489fd6a1b4b99c4d5c1dd2af3faf13294f Mon Sep 17 00:00:00 2001 From: Ryan Macnak Date: Tue, 22 Nov 2016 16:52:21 -0800 Subject: [PATCH] Fuchsia sockets: - Remove CheckConnect. - Enable NODELAY. - Add testSimpleReadWriteClose to hello_fuchsia_test. Add stub implementation of OS::MaxRSS so Observatory can load without crashing the target VM. R=asiva@google.com Review URL: https://codereview.chromium.org/2523133002 . --- runtime/bin/socket_fuchsia.cc | 33 ---- runtime/tests/vm/dart/hello_fuchsia_test.dart | 155 +++++++++++++++++- runtime/vm/os_fuchsia.cc | 2 +- 3 files changed, 150 insertions(+), 40 deletions(-) diff --git a/runtime/bin/socket_fuchsia.cc b/runtime/bin/socket_fuchsia.cc index 0109bea3290..2443ee3fe69 100644 --- a/runtime/bin/socket_fuchsia.cc +++ b/runtime/bin/socket_fuchsia.cc @@ -95,39 +95,11 @@ static intptr_t Create(const RawAddr& addr) { } -static intptr_t CheckConnect(intptr_t fd) { - int val; - socklen_t vallen = sizeof(val); - LOG_INFO("CheckConnect: calling getsockopt(%ld)\n", fd); - intptr_t result = getsockopt(fd, SOL_SOCKET, SO_ERROR, &val, &vallen); - if (result != 0) { - FATAL1("CheckConnect: getsockopt(%ld) failed\n", fd); - } else if (vallen != sizeof(val)) { - FATAL1("CheckConnect: getsockopt(%ld) vallen != sizeof(val)!?!?\n", fd); - } else if (val != 0) { - LOG_ERR("CheckConnect: getsockopt(%ld) val = %d\n", fd, val); - return val; - } - LOG_INFO("CheckConnect: getsockopt(%ld) connected\n", fd); - return 0; -} - - static intptr_t Connect(intptr_t fd, const RawAddr& addr) { LOG_INFO("Connect: calling connect(%ld)\n", fd); intptr_t result = NO_RETRY_EXPECTED( connect(fd, &addr.addr, SocketAddress::GetAddrLength(addr))); if ((result == 0) || (errno == EINPROGRESS)) { - LOG_INFO("Connect: connect(%ld) succeeded\n", fd); - intptr_t error = 0; - // TODO(US-87): When the issue is resolved this check is no longer needed. - while ((error = CheckConnect(fd)) != 0) { - if (error != EINPROGRESS) { - errno = error; - FDUtils::SaveErrorAndClose(fd); - return -1; - } - } return fd; } LOG_ERR("Connect: connect(%ld) failed\n", fd); @@ -489,15 +461,10 @@ bool Socket::GetNoDelay(intptr_t fd, bool* enabled) { bool Socket::SetNoDelay(intptr_t fd, bool enabled) { -// TODO(US-94): Enable. -#if 0 int on = enabled ? 1 : 0; return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&on), sizeof(on))) == 0; -#else - return true; -#endif } diff --git a/runtime/tests/vm/dart/hello_fuchsia_test.dart b/runtime/tests/vm/dart/hello_fuchsia_test.dart index 100cb04cd2c..e29fb3ed906 100644 --- a/runtime/tests/vm/dart/hello_fuchsia_test.dart +++ b/runtime/tests/vm/dart/hello_fuchsia_test.dart @@ -45,7 +45,145 @@ testSimpleConnect() async { await socket.close(); } -testSimpleReadWrite({bool dropReads}) async { +testSimpleReadWriteClose() async { + // This test creates a server and a client connects. The client then + // writes and the server echos. When the client finishes fully reading the + // echo, it closes the socket. When the server receives the close event, it + // closes its end of the socket too. + + const messageSize = 1000; + int serverReadCount = 0; + int clientReadCount = 0; + + List createTestData() { + return new List.generate(messageSize, (index) => index & 0xff); + } + + void verifyTestData(List data) { + assert(messageSize == data.length); + List expected = createTestData(); + for (int i = 0; i < messageSize; i++) { + assert(expected[i] == data[i]); + } + } + + var server = await RawServerSocket.bind(InternetAddress.LOOPBACK_IP_V4, 0); + server.listen((client) { + int bytesRead = 0; + int bytesWritten = 0; + bool closedEventReceived = false; + List data = new List(messageSize); + bool doneReading = false; + + client.writeEventsEnabled = false; + client.listen((event) { + switch (event) { + case RawSocketEvent.READ: + if (doneReading) { + break; + } + print("client READ event bytesRead = $bytesRead"); + assert(bytesWritten == 0); + assert(client.available() > 0); + var buffer = client.read(200); + print("client READ event: read ${buffer.length} more bytes"); + data.setRange(bytesRead, bytesRead + buffer.length, buffer); + bytesRead += buffer.length; + if (bytesRead == data.length) { + verifyTestData(data); + print("client READ event. Done reading, enabling writes"); + client.writeEventsEnabled = true; + doneReading = true; + } + break; + case RawSocketEvent.WRITE: + assert(!client.writeEventsEnabled); + bytesWritten += client.write( + data, bytesWritten, data.length - bytesWritten); + print("client WRITE event: $bytesWritten written"); + if (bytesWritten < data.length) { + client.writeEventsEnabled = true; + } + if (bytesWritten == data.length) { + print("client WRITE event: done writing."); + } + break; + case RawSocketEvent.READ_CLOSED: + print("client READ_CLOSED event"); + client.close(); + server.close(); + break; + case RawSocketEvent.CLOSED: + assert(!closedEventReceived); + print("client CLOSED event"); + closedEventReceived = true; + break; + default: throw "Unexpected event $event"; + } + }, + onError: (e) { print("client ERROR $e"); }, + onDone: () {assert(closedEventReceived);}); + }); + + { + var completer = new Completer(); + var socket = await RawSocket.connect("127.0.0.1", server.port); + int bytesRead = 0; + int bytesWritten = 0; + bool closedEventReceived = false; + List data = createTestData(); + + socket.listen((event) { + switch (event) { + case RawSocketEvent.READ: + assert(socket.available() > 0); + print("server READ event: ${bytesRead} read"); + var buffer = socket.read(); + print("server READ event: read ${buffer.length} more bytes"); + data.setRange(bytesRead, bytesRead + buffer.length, buffer); + bytesRead += buffer.length; + if (bytesRead == messageSize) { + print("server READ event: done reading"); + socket.close(); + } + break; + case RawSocketEvent.WRITE: + assert(bytesRead == 0); + assert(!socket.writeEventsEnabled); + bytesWritten += socket.write( + data, bytesWritten, data.length - bytesWritten); + print("server WRITE event: ${bytesWritten} written"); + if (bytesWritten < data.length) { + socket.writeEventsEnabled = true; + } else { + print("server WRITE event: done writing"); + data = new List(messageSize); + } + break; + case RawSocketEvent.READ_CLOSED: + print("server READ_CLOSED event"); + verifyTestData(data); + socket.close(); + break; + case RawSocketEvent.CLOSED: + assert(!closedEventReceived); + print("server CLOSED event"); + closedEventReceived = true; + break; + default: throw "Unexpected event $event"; + } + }, + onError: (e) { print("server ERROR $e"); }, + onDone: () { + assert(closedEventReceived); + completer.complete(null); + }); + + return completer.future; + } +} + +testSimpleReadWriteShutdown({bool dropReads}) async { // 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 @@ -199,8 +337,9 @@ Future testGoogleUrl(SecurityContext context, String outcome) async { // built-in root certificate authority. try { // First, check if the lookup works. - await InternetAddress.lookup('www.google.com'); - var request = await client.getUrl(Uri.parse('http://www.google.com')); + var address = await InternetAddress.lookup('www.google.com'); + print(address); + var request = await client.getUrl(Uri.parse('http://www.google.com/')); request.followRedirects = false; var response = await request.close(); assert('pass' == outcome); @@ -230,10 +369,14 @@ main() async { await testSimpleConnect(); print("testSimpleConnect done"); + print("testSimpleReadWriteClose"); + await testSimpleReadWriteClose(); + print("testSimpleReadWriteClose done"); + // TODO(US-81): Enable. - // print("testSimpleReadWrite"); - // await testSimpleReadWrite(dropReads: false); - // print("testSimpleReadWrite done"); + // print("testSimpleReadWriteShutdown"); + // await testSimpleReadWriteShutdown(dropReads: false); + // print("testSimpleReadWriteShutdown done"); print("testGoogleUrl"); await testGoogleUrl(null, 'pass'); diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc index 65e743caee2..d6b96711ece 100644 --- a/runtime/vm/os_fuchsia.cc +++ b/runtime/vm/os_fuchsia.cc @@ -157,7 +157,7 @@ int OS::NumberOfAvailableProcessors() { uintptr_t OS::MaxRSS() { - UNIMPLEMENTED(); + // TODO(US-95): Implement. return 0; }