Add catch for SocketException and tests for exception handling on fetchUrl. (#16569)

This commit is contained in:
jcollins-g 2018-04-16 14:02:07 -07:00 committed by GitHub
parent c103fd0c02
commit 85be28d36b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 4 deletions

View file

@ -48,6 +48,9 @@ Future<List<int>> _attempt(Uri url) async {
'URL: $url',
exitCode: kNetworkProblemExitCode,
);
} on SocketException catch (error) {
printTrace('Download error: $error');
return null;
}
final HttpClientResponse response = await request.close();
if (response.statusCode != 200) {

View file

@ -17,8 +17,8 @@ void main() {
new FakeAsync().run((FakeAsync time) {
fetchUrl(Uri.parse('http://example.invalid/')).then((List<int> value) {
error = 'test completed unexpectedly';
}, onError: (dynamic error) {
error = 'test failed unexpectedly';
}, onError: (dynamic exception) {
error = 'test failed unexpectedly: $exception';
});
expect(testLogger.statusText, '');
time.elapse(const Duration(milliseconds: 10000));
@ -40,8 +40,8 @@ void main() {
new FakeAsync().run((FakeAsync time) {
fetchUrl(Uri.parse('http://example.invalid/')).then((List<int> value) {
error = 'test completed unexpectedly';
}, onError: (dynamic error) {
error = 'test failed unexpectedly';
}, onError: (dynamic exception) {
error = 'test failed unexpectedly: $exception';
});
expect(testLogger.statusText, '');
time.elapse(const Duration(milliseconds: 10000));
@ -57,6 +57,68 @@ void main() {
}, overrides: <Type, Generator>{
HttpClientFactory: () => () => new MockHttpClient(200),
});
testUsingContext('retry from SocketException', () async {
String error;
new FakeAsync().run((FakeAsync time) {
fetchUrl(Uri.parse('http://example.invalid/')).then((List<int> value) {
error = 'test completed unexpectedly';
}, onError: (dynamic exception) {
error = 'test failed unexpectedly: $exception';
});
expect(testLogger.statusText, '');
time.elapse(const Duration(milliseconds: 10000));
expect(testLogger.statusText,
'Download failed -- attempting retry 1 in 1 second...\n'
'Download failed -- attempting retry 2 in 2 seconds...\n'
'Download failed -- attempting retry 3 in 4 seconds...\n'
'Download failed -- attempting retry 4 in 8 seconds...\n'
);
});
expect(testLogger.errorText, isEmpty);
expect(error, isNull);
expect(testLogger.traceText, contains('Download error: SocketException'));
}, overrides: <Type, Generator>{
HttpClientFactory: () => () => new MockHttpClientThrowing(
const io.SocketException('test exception handling'),
),
});
testUsingContext('no retry from HandshakeException', () async {
String error;
new FakeAsync().run((FakeAsync time) {
fetchUrl(Uri.parse('http://example.invalid/')).then((List<int> value) {
error = 'test completed unexpectedly';
}, onError: (dynamic exception) {
error = 'test failed: $exception';
});
expect(testLogger.statusText, '');
time.elapse(const Duration(milliseconds: 10000));
expect(testLogger.statusText, '');
});
expect(error, startsWith('test failed'));
expect(testLogger.traceText, contains('HandshakeException'));
}, overrides: <Type, Generator>{
HttpClientFactory: () => () => new MockHttpClientThrowing(
const io.HandshakeException('test exception handling'),
),
});
}
class MockHttpClientThrowing implements io.HttpClient {
MockHttpClientThrowing(this.exception);
final Exception exception;
@override
Future<io.HttpClientRequest> getUrl(Uri url) async {
throw exception;
}
@override
dynamic noSuchMethod(Invocation invocation) {
throw 'io.HttpClient - $invocation';
}
}
class MockHttpClient implements io.HttpClient {