mirror of
https://github.com/flutter/flutter
synced 2024-10-13 11:42:54 +00:00
[flutter_tools] Hanlde OSError in places where we've seen it thrown (#52491)
This commit is contained in:
parent
183da8f837
commit
0cd2ece539
|
@ -78,6 +78,7 @@ export 'dart:io'
|
|||
IOSink,
|
||||
// Link NO! Use `file_system.dart`
|
||||
// NetworkInterface NO! Use `io.dart`
|
||||
OSError,
|
||||
pid,
|
||||
// Platform NO! use `platform.dart`
|
||||
Process,
|
||||
|
|
|
@ -319,7 +319,12 @@ class _DevFSHttpWriter {
|
|||
onError: (dynamic error) { globals.printTrace('error: $error'); },
|
||||
cancelOnError: true);
|
||||
break;
|
||||
} on Exception catch (error, trace) {
|
||||
} catch (error, trace) { // ignore: avoid_catches_without_on_clauses
|
||||
// We treat OSError as an Exception.
|
||||
// See: https://github.com/dart-lang/sdk/issues/40934
|
||||
if (error is! Exception && error is! OSError) {
|
||||
rethrow;
|
||||
}
|
||||
if (!_completer.isCompleted) {
|
||||
globals.printTrace('Error writing "$deviceUri" to DevFS: $error');
|
||||
if (retry > 0) {
|
||||
|
|
|
@ -58,10 +58,10 @@ class MDnsObservatoryDiscovery {
|
|||
try {
|
||||
await client.start();
|
||||
final List<PtrResourceRecord> pointerRecords = await client
|
||||
.lookup<PtrResourceRecord>(
|
||||
ResourceRecordQuery.serverPointer(dartObservatoryName),
|
||||
)
|
||||
.toList();
|
||||
.lookup<PtrResourceRecord>(
|
||||
ResourceRecordQuery.serverPointer(dartObservatoryName),
|
||||
)
|
||||
.toList();
|
||||
if (pointerRecords.isEmpty) {
|
||||
globals.printTrace('No pointer records found.');
|
||||
return null;
|
||||
|
@ -69,8 +69,8 @@ class MDnsObservatoryDiscovery {
|
|||
// We have no guarantee that we won't get multiple hits from the same
|
||||
// service on this.
|
||||
final Set<String> uniqueDomainNames = pointerRecords
|
||||
.map<String>((PtrResourceRecord record) => record.domainName)
|
||||
.toSet();
|
||||
.map<String>((PtrResourceRecord record) => record.domainName)
|
||||
.toSet();
|
||||
|
||||
String domainName;
|
||||
if (applicationId != null) {
|
||||
|
@ -98,10 +98,10 @@ class MDnsObservatoryDiscovery {
|
|||
globals.printTrace('Checking for available port on $domainName');
|
||||
// Here, if we get more than one, it should just be a duplicate.
|
||||
final List<SrvResourceRecord> srv = await client
|
||||
.lookup<SrvResourceRecord>(
|
||||
ResourceRecordQuery.service(domainName),
|
||||
)
|
||||
.toList();
|
||||
.lookup<SrvResourceRecord>(
|
||||
ResourceRecordQuery.service(domainName),
|
||||
)
|
||||
.toList();
|
||||
if (srv.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
@ -133,6 +133,11 @@ class MDnsObservatoryDiscovery {
|
|||
authCode += '/';
|
||||
}
|
||||
return MDnsObservatoryDiscoveryResult(srv.first.port, authCode);
|
||||
} on OSError catch (e) {
|
||||
// OSError is neither an Error nor and Exception, so we wrap it in a
|
||||
// SocketException and rethrow.
|
||||
// See: https://github.com/dart-lang/sdk/issues/40934
|
||||
throw SocketException('mdns query failed', osError: e);
|
||||
} finally {
|
||||
client.stop();
|
||||
}
|
||||
|
|
|
@ -109,59 +109,66 @@ void main() {
|
|||
HttpOverrides.global = savedHttpOverrides;
|
||||
});
|
||||
|
||||
testUsingContext('retry uploads when failure', () async {
|
||||
final File file = fs.file(fs.path.join(basePath, filePath));
|
||||
await file.parent.create(recursive: true);
|
||||
file.writeAsBytesSync(<int>[1, 2, 3]);
|
||||
// simulate package
|
||||
await _createPackage(fs, 'somepkg', 'somefile.txt');
|
||||
final List<dynamic> exceptions = <dynamic>[
|
||||
Exception('Connection resert by peer'),
|
||||
const OSError('Connection reset by peer'),
|
||||
];
|
||||
|
||||
final RealMockVMService vmService = RealMockVMService();
|
||||
final RealMockVM vm = RealMockVM();
|
||||
final Map<String, dynamic> response = <String, dynamic>{ 'uri': 'file://abc' };
|
||||
when(vm.createDevFS(any)).thenAnswer((Invocation invocation) {
|
||||
return Future<Map<String, dynamic>>.value(response);
|
||||
for (final dynamic exception in exceptions) {
|
||||
testUsingContext('retry uploads when failure: $exception', () async {
|
||||
final File file = fs.file(fs.path.join(basePath, filePath));
|
||||
await file.parent.create(recursive: true);
|
||||
file.writeAsBytesSync(<int>[1, 2, 3]);
|
||||
// simulate package
|
||||
await _createPackage(fs, 'somepkg', 'somefile.txt');
|
||||
|
||||
final RealMockVMService vmService = RealMockVMService();
|
||||
final RealMockVM vm = RealMockVM();
|
||||
final Map<String, dynamic> response = <String, dynamic>{ 'uri': 'file://abc' };
|
||||
when(vm.createDevFS(any)).thenAnswer((Invocation invocation) {
|
||||
return Future<Map<String, dynamic>>.value(response);
|
||||
});
|
||||
when(vmService.vm).thenReturn(vm);
|
||||
|
||||
reset(httpClient);
|
||||
|
||||
final MockHttpClientRequest httpRequest = MockHttpClientRequest();
|
||||
when(httpRequest.headers).thenReturn(MockHttpHeaders());
|
||||
when(httpClient.putUrl(any)).thenAnswer((Invocation invocation) {
|
||||
return Future<HttpClientRequest>.value(httpRequest);
|
||||
});
|
||||
final MockHttpClientResponse httpClientResponse = MockHttpClientResponse();
|
||||
int nRequest = 0;
|
||||
const int kFailedAttempts = 5;
|
||||
when(httpRequest.close()).thenAnswer((Invocation invocation) {
|
||||
if (nRequest++ < kFailedAttempts) {
|
||||
throw exception;
|
||||
}
|
||||
return Future<HttpClientResponse>.value(httpClientResponse);
|
||||
});
|
||||
|
||||
final DevFS devFS = DevFS(vmService, 'test', tempDir);
|
||||
await devFS.create();
|
||||
|
||||
final MockResidentCompiler residentCompiler = MockResidentCompiler();
|
||||
final UpdateFSReport report = await devFS.update(
|
||||
mainPath: 'lib/foo.txt',
|
||||
generator: residentCompiler,
|
||||
pathToReload: 'lib/foo.txt.dill',
|
||||
trackWidgetCreation: false,
|
||||
invalidatedFiles: <Uri>[],
|
||||
);
|
||||
|
||||
expect(report.syncedBytes, 22);
|
||||
expect(report.success, isTrue);
|
||||
verify(httpClient.putUrl(any)).called(kFailedAttempts + 1);
|
||||
verify(httpRequest.close()).called(kFailedAttempts + 1);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
HttpClientFactory: () => () => httpClient,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
when(vmService.vm).thenReturn(vm);
|
||||
|
||||
reset(httpClient);
|
||||
|
||||
final MockHttpClientRequest httpRequest = MockHttpClientRequest();
|
||||
when(httpRequest.headers).thenReturn(MockHttpHeaders());
|
||||
when(httpClient.putUrl(any)).thenAnswer((Invocation invocation) {
|
||||
return Future<HttpClientRequest>.value(httpRequest);
|
||||
});
|
||||
final MockHttpClientResponse httpClientResponse = MockHttpClientResponse();
|
||||
int nRequest = 0;
|
||||
const int kFailedAttempts = 5;
|
||||
when(httpRequest.close()).thenAnswer((Invocation invocation) {
|
||||
if (nRequest++ < kFailedAttempts) {
|
||||
throw Exception('Connection resert by peer');
|
||||
}
|
||||
return Future<HttpClientResponse>.value(httpClientResponse);
|
||||
});
|
||||
|
||||
final DevFS devFS = DevFS(vmService, 'test', tempDir);
|
||||
await devFS.create();
|
||||
|
||||
final MockResidentCompiler residentCompiler = MockResidentCompiler();
|
||||
final UpdateFSReport report = await devFS.update(
|
||||
mainPath: 'lib/foo.txt',
|
||||
generator: residentCompiler,
|
||||
pathToReload: 'lib/foo.txt.dill',
|
||||
trackWidgetCreation: false,
|
||||
invalidatedFiles: <Uri>[],
|
||||
);
|
||||
|
||||
expect(report.syncedBytes, 22);
|
||||
expect(report.success, isTrue);
|
||||
verify(httpClient.putUrl(any)).called(kFailedAttempts + 1);
|
||||
verify(httpRequest.close()).called(kFailedAttempts + 1);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
HttpClientFactory: () => () => httpClient,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
group('devfs remote', () {
|
||||
|
|
|
@ -192,6 +192,21 @@ void main() {
|
|||
final int port = (await portDiscovery.query(applicationId: 'bar'))?.port;
|
||||
expect(port, isNull);
|
||||
});
|
||||
|
||||
testUsingContext('Throws SocketException when client throws OSError on start', () async {
|
||||
final MDnsClient client = MockMDnsClient();
|
||||
when(client.start()).thenAnswer((_) {
|
||||
throw const OSError('Operation not suppoted on socket', 102);
|
||||
});
|
||||
|
||||
final MDnsObservatoryDiscovery portDiscovery = MDnsObservatoryDiscovery(
|
||||
mdnsClient: client,
|
||||
);
|
||||
expect(
|
||||
() async => await portDiscovery.query(),
|
||||
throwsA(isA<SocketException>()),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue