dart-sdk/tests/standalone_2/io/http_shutdown_test.dart
Zach Anderson 0ccdc3ec38 Reland: [dart:io] Adds Socket.startConnect
This is a reland of https://dart-review.googlesource.com/c/sdk/+/62484
with the following changes:
- _NativeSocket.connect now drops references to pending sockets on
  an error or successful connection.
- eventhandlers are updated to ignore unset Dart ports on a close
  command.
- Test updated to account for new SocketException.

This is the second part of https://dart-review.googlesource.com/c/sdk/+/62484

This CL adds a startConnect method to Socket types that returns
a ConnectionTask object that can be cancelled. Cancelling
a ConnectionTask closes any sockets that were opened for the
connection attempt that are not yet connected to the host.

This allows a closing HttpClient to close sockets for pending
requests whose sockets weren't fully connected yet.

related https://github.com/flutter/flutter/issues/18617

Change-Id: I47fe3564e41197d622079aad4bb644bbdfe0bfe8
Reviewed-on: https://dart-review.googlesource.com/63040
Reviewed-by: Zach Anderson <zra@google.com>
Commit-Queue: Zach Anderson <zra@google.com>
2018-07-03 14:47:41 +00:00

195 lines
5.4 KiB
Dart

// 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 "package:expect/expect.dart";
void test1(int totalConnections) {
// Server which just closes immediately.
HttpServer.bind("127.0.0.1", 0).then((server) {
server.listen((HttpRequest request) {
request.response.close();
});
int count = 0;
HttpClient client = new HttpClient();
for (int i = 0; i < totalConnections; i++) {
client
.get("127.0.0.1", server.port, "/")
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
response.listen((_) {}, onDone: () {
count++;
if (count == totalConnections) {
client.close();
server.close();
}
});
});
}
});
}
void test2(int totalConnections, int outputStreamWrites) {
// Server which responds without waiting for request body.
HttpServer.bind("127.0.0.1", 0).then((server) {
server.listen((HttpRequest request) {
request.response.write("!dlrow ,olleH");
request.response.close();
});
int count = 0;
HttpClient client = new HttpClient();
for (int i = 0; i < totalConnections; i++) {
client
.get("127.0.0.1", server.port, "/")
.then((HttpClientRequest request) {
request.contentLength = -1;
for (int i = 0; i < outputStreamWrites; i++) {
request.write("Hello, world!");
}
request.done.catchError((_) {});
return request.close();
}).then((HttpClientResponse response) {
response.listen((_) {}, onDone: () {
count++;
if (count == totalConnections) {
client.close(force: true);
server.close();
}
}, onError: (e) {} /* ignore */);
}).catchError((error) {
count++;
if (count == totalConnections) {
client.close();
server.close();
}
});
}
});
}
void test3(int totalConnections) {
// Server which responds when request body has been received.
HttpServer.bind("127.0.0.1", 0).then((server) {
server.listen((HttpRequest request) {
request.listen((_) {}, onDone: () {
request.response.write("!dlrow ,olleH");
request.response.close();
});
});
int count = 0;
HttpClient client = new HttpClient();
for (int i = 0; i < totalConnections; i++) {
client
.get("127.0.0.1", server.port, "/")
.then((HttpClientRequest request) {
request.contentLength = -1;
request.write("Hello, world!");
return request.close();
}).then((HttpClientResponse response) {
response.listen((_) {}, onDone: () {
count++;
if (count == totalConnections) {
client.close();
server.close();
}
});
});
}
});
}
void test4() {
HttpServer.bind("127.0.0.1", 0).then((server) {
server.listen((var request) {
request.listen((_) {}, onDone: () {
new Timer.periodic(new Duration(milliseconds: 100), (timer) {
if (server.connectionsInfo().total == 0) {
server.close();
timer.cancel();
}
});
request.response.close();
});
});
var client = new HttpClient();
client
.get("127.0.0.1", server.port, "/")
.then((request) => request.close())
.then((response) {
response.listen((_) {}, onDone: () {
client.close();
});
});
});
}
void test5(int totalConnections) {
HttpServer.bind("127.0.0.1", 0).then((server) {
server.listen((request) {
request.listen((_) {}, onDone: () {
request.response.close();
request.response.done.catchError((e) {});
}, onError: (error) {});
}, onError: (error) {});
// Create a number of client requests and keep then active. Then
// close the client and wait for the server to lose all active
// connections.
var client = new HttpClient();
client.maxConnectionsPerHost = totalConnections;
for (int i = 0; i < totalConnections; i++) {
client
.post("127.0.0.1", server.port, "/")
.then((request) {
request.add([0]);
// TODO(sgjesse): Make this test work with
//request.response instead of request.close() return
//return request.response;
request.done.catchError((e) {});
return request.close();
})
.then((response) {})
.catchError((e) {},
test: (e) => e is HttpException || e is SocketException);
}
bool clientClosed = false;
new Timer.periodic(new Duration(milliseconds: 100), (timer) {
if (!clientClosed) {
if (server.connectionsInfo().total == totalConnections) {
clientClosed = true;
client.close(force: true);
}
} else {
if (server.connectionsInfo().total == 0) {
server.close();
timer.cancel();
}
}
});
});
}
void main() {
test1(1);
test1(10);
test2(1, 10);
test2(10, 10);
test2(10, 1000);
test3(1);
test3(10);
test4();
test5(1);
test5(10);
}