Unverified Commit a204f038 authored by Dan Field's avatar Dan Field Committed by GitHub

Null safe migration for fuchsia_remote_debug_protocol (#74762)

parent d546e1d3
......@@ -10,14 +10,13 @@ import 'package:vm_service/vm_service.dart' as vms;
import '../common/logging.dart';
const Duration _kConnectTimeout = Duration(seconds: 3);
const Duration _kRpcTimeout = Duration(seconds: 5);
final Logger _log = Logger('DartVm');
/// Signature of an asynchronous function for establishing a [vms.VmService]
/// connection to a [Uri].
typedef RpcPeerConnectionFunction = Future<vms.VmService> Function(
Uri uri, {
Duration timeout,
required Duration timeout,
});
/// [DartVm] uses this function to connect to the Dart VM on Fuchsia.
......@@ -34,7 +33,7 @@ Future<vms.VmService> _waitAndConnect(
Duration timeout = _kConnectTimeout,
}) async {
int attempts = 0;
WebSocket socket;
late WebSocket socket;
while (true) {
try {
socket = await WebSocket.connect(uri.toString());
......@@ -56,7 +55,7 @@ Future<vms.VmService> _waitAndConnect(
await service.getVersion();
return service;
} catch (e) {
await socket?.close();
await socket.close();
if (attempts > 5) {
_log.warning('It is taking an unusually long time to connect to the VM...');
}
......@@ -112,9 +111,6 @@ class DartVm {
}
final vms.VmService service = await fuchsiaVmServiceConnectionFunction(uri, timeout: timeout);
if (service == null) {
return null;
}
return DartVm._(service, uri);
}
......@@ -123,16 +119,13 @@ class DartVm {
/// This is not limited to Isolates running Flutter, but to any Isolate on the
/// VM. Therefore, the [pattern] argument should be written to exclude
/// matching unintended isolates.
Future<List<IsolateRef>> getMainIsolatesByPattern(
Pattern pattern, {
Duration timeout = _kRpcTimeout,
}) async {
Future<List<IsolateRef>> getMainIsolatesByPattern(Pattern pattern) async {
final vms.VM vmRef = await _vmService.getVM();
final List<IsolateRef> result = <IsolateRef>[];
for (final vms.IsolateRef isolateRef in vmRef.isolates) {
if (pattern.matchAsPrefix(isolateRef.name) != null) {
for (final vms.IsolateRef isolateRef in vmRef.isolates!) {
if (pattern.matchAsPrefix(isolateRef.name!) != null) {
_log.fine('Found Isolate matching "$pattern": "${isolateRef.name}"');
result.add(IsolateRef._fromJson(isolateRef.json, this));
result.add(IsolateRef._fromJson(isolateRef.json!, this));
}
}
return result;
......@@ -145,16 +138,11 @@ class DartVm {
/// the flutter view's name), then the flutter view's ID will be added
/// instead. If none of these things can be found (isolate has no name or the
/// flutter view has no ID), then the result will not be added to the list.
Future<List<FlutterView>> getAllFlutterViews({
Duration timeout = _kRpcTimeout,
}) async {
Future<List<FlutterView>> getAllFlutterViews() async {
final List<FlutterView> views = <FlutterView>[];
final vms.Response rpcResponse = await _vmService.callMethod('_flutter.listViews');
for (final Map<String, dynamic> jsonView in (rpcResponse.json['views'] as List<dynamic>).cast<Map<String, dynamic>>()) {
final FlutterView flutterView = FlutterView._fromJson(jsonView);
if (flutterView != null) {
views.add(flutterView);
}
for (final Map<String, dynamic> jsonView in (rpcResponse.json!['views'] as List<dynamic>).cast<Map<String, dynamic>>()) {
views.add(FlutterView._fromJson(jsonView));
}
return views;
}
......@@ -190,25 +178,25 @@ class FlutterView {
/// All other cases return a [FlutterView] instance. The name of the
/// view may be null, but the id will always be set.
factory FlutterView._fromJson(Map<String, dynamic> json) {
final Map<String, dynamic> isolate = json['isolate'] as Map<String, dynamic>;
final String id = json['id'] as String;
String name;
final Map<String, dynamic>? isolate = json['isolate'] as Map<String, dynamic>?;
final String? id = json['id'] as String?;
String? name;
if (id == null) {
throw RpcFormatError(
'Unable to find view name for the following JSON structure "$json"');
}
if (isolate != null) {
name = isolate['name'] as String;
name = isolate['name'] as String?;
if (name == null) {
throw RpcFormatError('Unable to find name for isolate "$isolate"');
}
}
if (id == null) {
throw RpcFormatError(
'Unable to find view name for the following JSON structure "$json"');
}
return FlutterView._(name, id);
}
/// Determines the name of the isolate associated with this view. If there is
/// no associated isolate, this will be set to the view's ID.
final String _name;
final String? _name;
/// The ID of the Flutter view.
final String _id;
......@@ -219,7 +207,7 @@ class FlutterView {
/// Returns the name of the [FlutterView].
///
/// May be null if there is no associated isolate.
String get name => _name;
String? get name => _name;
}
/// This is a wrapper class for the `@Isolate` RPC object.
......@@ -233,9 +221,9 @@ class IsolateRef {
IsolateRef._(this.name, this.number, this.dartVm);
factory IsolateRef._fromJson(Map<String, dynamic> json, DartVm dartVm) {
final String number = json['number'] as String;
final String name = json['name'] as String;
final String type = json['type'] as String;
final String? number = json['number'] as String?;
final String? name = json['name'] as String?;
final String? type = json['type'] as String?;
if (type == null) {
throw RpcFormatError('Unable to find type within JSON "$json"');
}
......
......@@ -44,7 +44,7 @@ class SshCommandRunner {
/// IPv4 nor IPv6. When connecting to a link local address (`fe80::` is
/// usually at the start of the address), an interface should be supplied.
SshCommandRunner({
this.address,
required this.address,
this.interface = '',
this.sshConfigPath,
}) : _processManager = const LocalProcessManager() {
......@@ -55,7 +55,7 @@ class SshCommandRunner {
@visibleForTesting
SshCommandRunner.withProcessManager(
this._processManager, {
this.address,
required this.address,
this.interface = '',
this.sshConfigPath,
}) {
......@@ -70,7 +70,7 @@ class SshCommandRunner {
final String address;
/// The path to the SSH config (optional).
final String sshConfigPath;
final String? sshConfigPath;
/// The name of the machine's network interface (for use with IPv6
/// connections. Ignored otherwise).
......@@ -84,7 +84,7 @@ class SshCommandRunner {
final List<String> args = <String>[
'ssh',
if (sshConfigPath != null)
...<String>['-F', sshConfigPath],
...<String>['-F', sshConfigPath!],
if (isIpV6Address(address))
...<String>['-6', if (interface.isEmpty) address else '$address%$interface']
else
......
......@@ -5,7 +5,7 @@ homepage: http://flutter.dev
author: Flutter Authors <flutter-dev@googlegroups.com>
environment:
sdk: ">=2.2.2 <3.0.0"
sdk: '>=2.12.0-0 <3.0.0'
dependencies:
process: 4.0.0-nullsafety.4
......
......@@ -11,9 +11,9 @@ import 'common.dart';
void main() {
group('FuchsiaRemoteConnection.connect', () {
List<FakePortForwarder> forwardedPorts;
late List<FakePortForwarder> forwardedPorts;
List<FakeVmService> fakeVmServices;
List<Uri> uriConnections;
late List<Uri> uriConnections;
setUp(() {
final List<Map<String, dynamic>> flutterViewCannedResponses =
......@@ -63,7 +63,7 @@ void main() {
uriConnections = <Uri>[];
Future<vms.VmService> fakeVmConnectionFunction(
Uri uri, {
Duration timeout,
Duration? timeout,
}) {
return Future<vms.VmService>(() async {
final FakeVmService service = FakeVmService();
......@@ -89,8 +89,8 @@ void main() {
Future<PortForwarder> fakePortForwardingFunction(
String address,
int remotePort, [
String interface = '',
String configFile,
String? interface = '',
String? configFile,
]) {
return Future<PortForwarder>(() {
final FakePortForwarder pf = FakePortForwarder();
......@@ -156,8 +156,8 @@ void main() {
Future<PortForwarder> fakePortForwardingFunction(
String address,
int remotePort, [
String interface = '',
String configFile,
String? interface = '',
String? configFile,
]) {
return Future<PortForwarder>(() {
final FakePortForwarder pf = FakePortForwarder();
......@@ -223,8 +223,8 @@ void main() {
Future<PortForwarder> fakePortForwardingFunction(
String address,
int remotePort, [
String interface = '',
String configFile,
String? interface = '',
String? configFile,
]) {
return Future<PortForwarder>(() {
final FakePortForwarder pf = FakePortForwarder();
......@@ -296,24 +296,24 @@ void main() {
}
class FakeSshCommandRunner extends Fake implements SshCommandRunner {
List<String> findResponse;
List<String> lsResponse;
List<String>? findResponse;
List<String>? lsResponse;
@override
Future<List<String>> run(String command) async {
if (command.startsWith('/bin/find')) {
return findResponse;
return findResponse!;
}
if (command.startsWith('/bin/ls')) {
return lsResponse;
return lsResponse!;
}
throw UnimplementedError(command);
}
@override
String interface;
String interface = '';
@override
String address;
String address = '';
@override
String get sshConfigPath => '~/.ssh';
......@@ -321,13 +321,13 @@ class FakeSshCommandRunner extends Fake implements SshCommandRunner {
class FakePortForwarder extends Fake implements PortForwarder {
@override
int port;
int port = 0;
@override
int remotePort;
int remotePort = 0;
@override
String openPortAddress;
String? openPortAddress;
bool stopped = false;
@override
......@@ -338,7 +338,7 @@ class FakePortForwarder extends Fake implements PortForwarder {
class FakeVmService extends Fake implements vms.VmService {
bool disposed = false;
vms.Response flutterListViews;
vms.Response? flutterListViews;
@override
Future<void> dispose() async {
......@@ -346,15 +346,15 @@ class FakeVmService extends Fake implements vms.VmService {
}
@override
Future<vms.Response> callMethod(String method, {String isolateId, Map<String, dynamic> args}) async {
Future<vms.Response> callMethod(String method, {String? isolateId, Map<String, dynamic>? args}) async {
if (method == '_flutter.listViews') {
return flutterListViews;
return flutterListViews!;
}
throw UnimplementedError(method);
}
@override
Future<void> onDone;
Future<void> onDone = Future<void>.value();
@override
Future<vms.Version> getVersion() async {
......
......@@ -16,24 +16,11 @@ void main() {
restoreVmServiceConnectionFunction();
});
test('null connector', () async {
Future<vms.VmService> fakeServiceFunction(
Uri uri, {
Duration timeout,
}) {
return Future<vms.VmService>(() => null);
}
fuchsiaVmServiceConnectionFunction = fakeServiceFunction;
expect(await DartVm.connect(Uri.parse('http://this.whatever/ws')),
equals(null));
});
test('disconnect closes peer', () async {
final FakeVmService service = FakeVmService();
Future<vms.VmService> fakeServiceFunction(
Uri uri, {
Duration timeout,
Duration? timeout,
}) {
return Future<vms.VmService>(() => service);
}
......@@ -47,7 +34,7 @@ void main() {
});
group('DartVm.getAllFlutterViews', () {
FakeVmService fakeService;
late FakeVmService fakeService;
setUp(() {
fakeService = FakeVmService();
......@@ -91,7 +78,7 @@ void main() {
Future<vms.VmService> fakeVmConnectionFunction(
Uri uri, {
Duration timeout,
Duration? timeout,
}) {
fakeService.flutterListViews = vms.Response.parse(flutterViewCannedResponses);
return Future<vms.VmService>(() => fakeService);
......@@ -147,7 +134,7 @@ void main() {
Future<vms.VmService> fakeVmConnectionFunction(
Uri uri, {
Duration timeout,
Duration? timeout,
}) {
fakeService.flutterListViews = vms.Response.parse(flutterViewCannedResponses);
return Future<vms.VmService>(() => fakeService);
......@@ -194,7 +181,7 @@ void main() {
Future<vms.VmService> fakeVmConnectionFunction(
Uri uri, {
Duration timeout,
Duration? timeout,
}) {
fakeService.flutterListViews = vms.Response.parse(flutterViewCannedResponseMissingId);
return Future<vms.VmService>(() => fakeService);
......@@ -219,33 +206,33 @@ void main() {
'id': 'isolates/1',
'name': 'file://thingThatWillNotMatch:main()',
'number': '1',
}),
})!,
vms.IsolateRef.parse(<String, dynamic>{
'type': '@Isolate',
'fixedId': 'true',
'id': 'isolates/2',
'name': '0:dart_name_pattern()',
'number': '2',
}),
})!,
vms.IsolateRef.parse(<String, dynamic>{
'type': '@Isolate',
'fixedId': 'true',
'id': 'isolates/3',
'name': 'flutterBinary.cmx',
'number': '3',
}),
})!,
vms.IsolateRef.parse(<String, dynamic>{
'type': '@Isolate',
'fixedId': 'true',
'id': 'isolates/4',
'name': '0:some_other_dart_name_pattern()',
'number': '4',
}),
})!,
];
Future<vms.VmService> fakeVmConnectionFunction(
Uri uri, {
Duration timeout,
Duration? timeout,
}) {
fakeService.vm = FakeVM(isolates: isolates);
return Future<vms.VmService>(() => fakeService);
......@@ -279,7 +266,7 @@ void main() {
Future<vms.VmService> fakeVmConnectionFunction(
Uri uri, {
Duration timeout,
Duration? timeout,
}) {
fakeService.flutterListViews = vms.Response.parse(flutterViewCannedResponseMissingIsolateName);
return Future<vms.VmService>(() => fakeService);
......@@ -300,11 +287,11 @@ void main() {
class FakeVmService extends Fake implements vms.VmService {
bool disposed = false;
vms.Response flutterListViews;
vms.VM vm;
vms.Response? flutterListViews;
vms.VM? vm;
@override
Future<vms.VM> getVM() async => vm;
Future<vms.VM> getVM() async => vm!;
@override
Future<void> dispose() async {
......@@ -312,15 +299,15 @@ class FakeVmService extends Fake implements vms.VmService {
}
@override
Future<vms.Response> callMethod(String method, {String isolateId, Map<String, dynamic> args}) async {
Future<vms.Response> callMethod(String method, {String? isolateId, Map<String, dynamic>? args}) async {
if (method == '_flutter.listViews') {
return flutterListViews;
return flutterListViews!;
}
throw UnimplementedError(method);
}
@override
Future<void> onDone;
Future<void> onDone = Future<void>.value();
}
class FakeVM extends Fake implements vms.VM {
......@@ -329,5 +316,5 @@ class FakeVM extends Fake implements vms.VM {
});
@override
List<vms.IsolateRef> isolates;
List<vms.IsolateRef>? isolates;
}
......@@ -33,8 +33,8 @@ void main() {
});
group('SshCommandRunner.run', () {
FakeProcessManager fakeProcessManager;
FakeProcessResult fakeProcessResult;
late FakeProcessManager fakeProcessManager;
late FakeProcessResult fakeProcessResult;
SshCommandRunner runner;
setUp(() {
......@@ -103,10 +103,10 @@ void main() {
);
fakeProcessResult.stdout = 'somestuff';
await runner.run('ls /whatever');
final List<String> passedCommand = fakeProcessManager.runCommands.single as List<String>;
final List<String?> passedCommand = fakeProcessManager.runCommands.single as List<String?>;
expect(passedCommand, contains('-F'));
final int indexOfFlag = passedCommand.indexOf('-F');
final String passedConfig = passedCommand[indexOfFlag + 1];
final String? passedConfig = passedCommand[indexOfFlag + 1];
expect(passedConfig, config);
});
......@@ -118,7 +118,7 @@ void main() {
);
fakeProcessResult.stdout = 'somestuff';
await runner.run('ls /whatever');
final List<String> passedCommand = fakeProcessManager.runCommands.single as List<String>;
final List<String?> passedCommand = fakeProcessManager.runCommands.single as List<String?>;
final int indexOfFlag = passedCommand.indexOf('-F');
expect(indexOfFlag, equals(-1));
});
......@@ -126,21 +126,21 @@ void main() {
}
class FakeProcessManager extends Fake implements ProcessManager {
FakeProcessResult fakeResult;
FakeProcessResult? fakeResult;
List<List<dynamic>> runCommands = <List<dynamic>>[];
@override
Future<ProcessResult> run(List<dynamic> command, {
String workingDirectory,
Map<String, String> environment,
String? workingDirectory,
Map<String, String>? environment,
bool includeParentEnvironment = true,
bool runInShell = false,
Encoding stdoutEncoding = systemEncoding,
Encoding stderrEncoding = systemEncoding,
}) async {
runCommands.add(command);
return fakeResult;
return fakeResult!;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment