Null safe migration for fuchsia_remote_debug_protocol (#74762)
This commit is contained in:
parent
d546e1d311
commit
a204f038fc
@ -10,14 +10,13 @@ import 'package:vm_service/vm_service.dart' as vms;
|
|||||||
import '../common/logging.dart';
|
import '../common/logging.dart';
|
||||||
|
|
||||||
const Duration _kConnectTimeout = Duration(seconds: 3);
|
const Duration _kConnectTimeout = Duration(seconds: 3);
|
||||||
const Duration _kRpcTimeout = Duration(seconds: 5);
|
|
||||||
final Logger _log = Logger('DartVm');
|
final Logger _log = Logger('DartVm');
|
||||||
|
|
||||||
/// Signature of an asynchronous function for establishing a [vms.VmService]
|
/// Signature of an asynchronous function for establishing a [vms.VmService]
|
||||||
/// connection to a [Uri].
|
/// connection to a [Uri].
|
||||||
typedef RpcPeerConnectionFunction = Future<vms.VmService> Function(
|
typedef RpcPeerConnectionFunction = Future<vms.VmService> Function(
|
||||||
Uri uri, {
|
Uri uri, {
|
||||||
Duration timeout,
|
required Duration timeout,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// [DartVm] uses this function to connect to the Dart VM on Fuchsia.
|
/// [DartVm] uses this function to connect to the Dart VM on Fuchsia.
|
||||||
@ -34,7 +33,7 @@ Future<vms.VmService> _waitAndConnect(
|
|||||||
Duration timeout = _kConnectTimeout,
|
Duration timeout = _kConnectTimeout,
|
||||||
}) async {
|
}) async {
|
||||||
int attempts = 0;
|
int attempts = 0;
|
||||||
WebSocket socket;
|
late WebSocket socket;
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
socket = await WebSocket.connect(uri.toString());
|
socket = await WebSocket.connect(uri.toString());
|
||||||
@ -56,7 +55,7 @@ Future<vms.VmService> _waitAndConnect(
|
|||||||
await service.getVersion();
|
await service.getVersion();
|
||||||
return service;
|
return service;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await socket?.close();
|
await socket.close();
|
||||||
if (attempts > 5) {
|
if (attempts > 5) {
|
||||||
_log.warning('It is taking an unusually long time to connect to the VM...');
|
_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);
|
final vms.VmService service = await fuchsiaVmServiceConnectionFunction(uri, timeout: timeout);
|
||||||
if (service == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return DartVm._(service, uri);
|
return DartVm._(service, uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,16 +119,13 @@ class DartVm {
|
|||||||
/// This is not limited to Isolates running Flutter, but to any Isolate on the
|
/// This is not limited to Isolates running Flutter, but to any Isolate on the
|
||||||
/// VM. Therefore, the [pattern] argument should be written to exclude
|
/// VM. Therefore, the [pattern] argument should be written to exclude
|
||||||
/// matching unintended isolates.
|
/// matching unintended isolates.
|
||||||
Future<List<IsolateRef>> getMainIsolatesByPattern(
|
Future<List<IsolateRef>> getMainIsolatesByPattern(Pattern pattern) async {
|
||||||
Pattern pattern, {
|
|
||||||
Duration timeout = _kRpcTimeout,
|
|
||||||
}) async {
|
|
||||||
final vms.VM vmRef = await _vmService.getVM();
|
final vms.VM vmRef = await _vmService.getVM();
|
||||||
final List<IsolateRef> result = <IsolateRef>[];
|
final List<IsolateRef> result = <IsolateRef>[];
|
||||||
for (final vms.IsolateRef isolateRef in vmRef.isolates) {
|
for (final vms.IsolateRef isolateRef in vmRef.isolates!) {
|
||||||
if (pattern.matchAsPrefix(isolateRef.name) != null) {
|
if (pattern.matchAsPrefix(isolateRef.name!) != null) {
|
||||||
_log.fine('Found Isolate matching "$pattern": "${isolateRef.name}"');
|
_log.fine('Found Isolate matching "$pattern": "${isolateRef.name}"');
|
||||||
result.add(IsolateRef._fromJson(isolateRef.json, this));
|
result.add(IsolateRef._fromJson(isolateRef.json!, this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -145,16 +138,11 @@ class DartVm {
|
|||||||
/// the flutter view's name), then the flutter view's ID will be added
|
/// 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
|
/// 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.
|
/// flutter view has no ID), then the result will not be added to the list.
|
||||||
Future<List<FlutterView>> getAllFlutterViews({
|
Future<List<FlutterView>> getAllFlutterViews() async {
|
||||||
Duration timeout = _kRpcTimeout,
|
|
||||||
}) async {
|
|
||||||
final List<FlutterView> views = <FlutterView>[];
|
final List<FlutterView> views = <FlutterView>[];
|
||||||
final vms.Response rpcResponse = await _vmService.callMethod('_flutter.listViews');
|
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>>()) {
|
for (final Map<String, dynamic> jsonView in (rpcResponse.json!['views'] as List<dynamic>).cast<Map<String, dynamic>>()) {
|
||||||
final FlutterView flutterView = FlutterView._fromJson(jsonView);
|
views.add(FlutterView._fromJson(jsonView));
|
||||||
if (flutterView != null) {
|
|
||||||
views.add(flutterView);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return views;
|
return views;
|
||||||
}
|
}
|
||||||
@ -190,25 +178,25 @@ class FlutterView {
|
|||||||
/// All other cases return a [FlutterView] instance. The name of the
|
/// All other cases return a [FlutterView] instance. The name of the
|
||||||
/// view may be null, but the id will always be set.
|
/// view may be null, but the id will always be set.
|
||||||
factory FlutterView._fromJson(Map<String, dynamic> json) {
|
factory FlutterView._fromJson(Map<String, dynamic> json) {
|
||||||
final Map<String, dynamic> isolate = json['isolate'] as Map<String, dynamic>;
|
final Map<String, dynamic>? isolate = json['isolate'] as Map<String, dynamic>?;
|
||||||
final String id = json['id'] as String;
|
final String? id = json['id'] as String?;
|
||||||
String name;
|
String? name;
|
||||||
if (isolate != null) {
|
|
||||||
name = isolate['name'] as String;
|
|
||||||
if (name == null) {
|
|
||||||
throw RpcFormatError('Unable to find name for isolate "$isolate"');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
throw RpcFormatError(
|
throw RpcFormatError(
|
||||||
'Unable to find view name for the following JSON structure "$json"');
|
'Unable to find view name for the following JSON structure "$json"');
|
||||||
}
|
}
|
||||||
|
if (isolate != null) {
|
||||||
|
name = isolate['name'] as String?;
|
||||||
|
if (name == null) {
|
||||||
|
throw RpcFormatError('Unable to find name for isolate "$isolate"');
|
||||||
|
}
|
||||||
|
}
|
||||||
return FlutterView._(name, id);
|
return FlutterView._(name, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines the name of the isolate associated with this view. If there is
|
/// 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.
|
/// no associated isolate, this will be set to the view's ID.
|
||||||
final String _name;
|
final String? _name;
|
||||||
|
|
||||||
/// The ID of the Flutter view.
|
/// The ID of the Flutter view.
|
||||||
final String _id;
|
final String _id;
|
||||||
@ -219,7 +207,7 @@ class FlutterView {
|
|||||||
/// Returns the name of the [FlutterView].
|
/// Returns the name of the [FlutterView].
|
||||||
///
|
///
|
||||||
/// May be null if there is no associated isolate.
|
/// 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.
|
/// This is a wrapper class for the `@Isolate` RPC object.
|
||||||
@ -233,9 +221,9 @@ class IsolateRef {
|
|||||||
IsolateRef._(this.name, this.number, this.dartVm);
|
IsolateRef._(this.name, this.number, this.dartVm);
|
||||||
|
|
||||||
factory IsolateRef._fromJson(Map<String, dynamic> json, DartVm dartVm) {
|
factory IsolateRef._fromJson(Map<String, dynamic> json, DartVm dartVm) {
|
||||||
final String number = json['number'] as String;
|
final String? number = json['number'] as String?;
|
||||||
final String name = json['name'] as String;
|
final String? name = json['name'] as String?;
|
||||||
final String type = json['type'] as String;
|
final String? type = json['type'] as String?;
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
throw RpcFormatError('Unable to find type within JSON "$json"');
|
throw RpcFormatError('Unable to find type within JSON "$json"');
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,8 @@ final Logger _log = Logger('FuchsiaRemoteConnection');
|
|||||||
typedef PortForwardingFunction = Future<PortForwarder> Function(
|
typedef PortForwardingFunction = Future<PortForwarder> Function(
|
||||||
String address,
|
String address,
|
||||||
int remotePort, [
|
int remotePort, [
|
||||||
String interface,
|
String? interface,
|
||||||
String configFile,
|
String? configFile,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/// The function for forwarding the local machine's ports to a remote Fuchsia
|
/// The function for forwarding the local machine's ports to a remote Fuchsia
|
||||||
@ -83,7 +83,7 @@ enum DartVmEventType {
|
|||||||
/// Specifies the type of the event (whether the VM has started or has stopped),
|
/// Specifies the type of the event (whether the VM has started or has stopped),
|
||||||
/// and contains the service port of the VM as well as a URL to connect to it.
|
/// and contains the service port of the VM as well as a URL to connect to it.
|
||||||
class DartVmEvent {
|
class DartVmEvent {
|
||||||
DartVmEvent._({this.eventType, this.servicePort, this.uri});
|
DartVmEvent._({required this.eventType, required this.servicePort, required this.uri});
|
||||||
|
|
||||||
/// The URL used to connect to the Dart VM.
|
/// The URL used to connect to the Dart VM.
|
||||||
final Uri uri;
|
final Uri uri;
|
||||||
@ -121,13 +121,13 @@ class FuchsiaRemoteConnection {
|
|||||||
|
|
||||||
/// A broadcast stream that emits events relating to Dart VM's as they update.
|
/// A broadcast stream that emits events relating to Dart VM's as they update.
|
||||||
Stream<DartVmEvent> get onDartVmEvent => _onDartVmEvent;
|
Stream<DartVmEvent> get onDartVmEvent => _onDartVmEvent;
|
||||||
Stream<DartVmEvent> _onDartVmEvent;
|
late Stream<DartVmEvent> _onDartVmEvent;
|
||||||
final StreamController<DartVmEvent> _dartVmEventController =
|
final StreamController<DartVmEvent> _dartVmEventController =
|
||||||
StreamController<DartVmEvent>();
|
StreamController<DartVmEvent>();
|
||||||
|
|
||||||
/// VM service cache to avoid repeating handshakes across function
|
/// VM service cache to avoid repeating handshakes across function
|
||||||
/// calls. Keys a URI to a DartVm connection instance.
|
/// calls. Keys a URI to a DartVm connection instance.
|
||||||
final Map<Uri, DartVm> _dartVmCache = <Uri, DartVm>{};
|
final Map<Uri, DartVm?> _dartVmCache = <Uri, DartVm?>{};
|
||||||
|
|
||||||
/// Same as [FuchsiaRemoteConnection.connect] albeit with a provided
|
/// Same as [FuchsiaRemoteConnection.connect] albeit with a provided
|
||||||
/// [SshCommandRunner] instance.
|
/// [SshCommandRunner] instance.
|
||||||
@ -188,9 +188,9 @@ class FuchsiaRemoteConnection {
|
|||||||
/// In the event that `FUCHSIA_SSH_CONFIG` is set in the environment, that
|
/// In the event that `FUCHSIA_SSH_CONFIG` is set in the environment, that
|
||||||
/// will be used when `sshConfigPath` isn't supplied.
|
/// will be used when `sshConfigPath` isn't supplied.
|
||||||
static Future<FuchsiaRemoteConnection> connect([
|
static Future<FuchsiaRemoteConnection> connect([
|
||||||
String address,
|
String? address,
|
||||||
String interface = '',
|
String interface = '',
|
||||||
String sshConfigPath,
|
String? sshConfigPath,
|
||||||
]) async {
|
]) async {
|
||||||
address ??= Platform.environment['FUCHSIA_DEVICE_URL'];
|
address ??= Platform.environment['FUCHSIA_DEVICE_URL'];
|
||||||
sshConfigPath ??= Platform.environment['FUCHSIA_SSH_CONFIG'];
|
sshConfigPath ??= Platform.environment['FUCHSIA_SSH_CONFIG'];
|
||||||
@ -210,7 +210,7 @@ class FuchsiaRemoteConnection {
|
|||||||
SshCommandRunner(
|
SshCommandRunner(
|
||||||
address: address,
|
address: address,
|
||||||
interface: interface,
|
interface: interface,
|
||||||
sshConfigPath: sshConfigPath,
|
sshConfigPath: sshConfigPath!,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -225,14 +225,14 @@ class FuchsiaRemoteConnection {
|
|||||||
// Closes VM service first to ensure that the connection is closed cleanly
|
// Closes VM service first to ensure that the connection is closed cleanly
|
||||||
// on the target before shutting down the forwarding itself.
|
// on the target before shutting down the forwarding itself.
|
||||||
final Uri uri = _getDartVmUri(pf);
|
final Uri uri = _getDartVmUri(pf);
|
||||||
final DartVm vmService = _dartVmCache[uri];
|
final DartVm? vmService = _dartVmCache[uri];
|
||||||
_dartVmCache[uri] = null;
|
_dartVmCache[uri] = null;
|
||||||
await vmService?.stop();
|
await vmService?.stop();
|
||||||
await pf.stop();
|
await pf.stop();
|
||||||
}
|
}
|
||||||
for (final PortForwarder pf in _dartVmPortMap.values) {
|
for (final PortForwarder pf in _dartVmPortMap.values) {
|
||||||
final Uri uri = _getDartVmUri(pf);
|
final Uri uri = _getDartVmUri(pf);
|
||||||
final DartVm vmService = _dartVmCache[uri];
|
final DartVm? vmService = _dartVmCache[uri];
|
||||||
_dartVmCache[uri] = null;
|
_dartVmCache[uri] = null;
|
||||||
await vmService?.stop();
|
await vmService?.stop();
|
||||||
await pf.stop();
|
await pf.stop();
|
||||||
@ -250,7 +250,7 @@ class FuchsiaRemoteConnection {
|
|||||||
/// (possible when the Isolate we're attempting to connect to is in the only
|
/// (possible when the Isolate we're attempting to connect to is in the only
|
||||||
/// instance of the Dart VM and its service port has not yet opened).
|
/// instance of the Dart VM and its service port has not yet opened).
|
||||||
Future<List<IsolateRef>> _waitForMainIsolatesByPattern([
|
Future<List<IsolateRef>> _waitForMainIsolatesByPattern([
|
||||||
Pattern pattern,
|
Pattern? pattern,
|
||||||
Duration timeout = _kIsolateFindTimeout,
|
Duration timeout = _kIsolateFindTimeout,
|
||||||
Duration vmConnectionTimeout = _kDartVmConnectionTimeout,
|
Duration vmConnectionTimeout = _kDartVmConnectionTimeout,
|
||||||
]) async {
|
]) async {
|
||||||
@ -260,12 +260,10 @@ class FuchsiaRemoteConnection {
|
|||||||
if (event.eventType == DartVmEventType.started) {
|
if (event.eventType == DartVmEventType.started) {
|
||||||
_log.fine('New VM found on port: ${event.servicePort}. Searching '
|
_log.fine('New VM found on port: ${event.servicePort}. Searching '
|
||||||
'for Isolate: $pattern');
|
'for Isolate: $pattern');
|
||||||
final DartVm vmService = await _getDartVm(event.uri,
|
final DartVm? vmService = await _getDartVm(event.uri,
|
||||||
timeout: _kDartVmConnectionTimeout);
|
timeout: _kDartVmConnectionTimeout);
|
||||||
// If the VM service is null, set the result to the empty list.
|
// If the VM service is null, set the result to the empty list.
|
||||||
final List<IsolateRef> result = await vmService
|
final List<IsolateRef> result = await vmService?.getMainIsolatesByPattern(pattern!) ?? <IsolateRef>[];
|
||||||
?.getMainIsolatesByPattern(pattern, timeout: timeout) ??
|
|
||||||
<IsolateRef>[];
|
|
||||||
if (result.isNotEmpty) {
|
if (result.isNotEmpty) {
|
||||||
if (!completer.isCompleted) {
|
if (!completer.isCompleted) {
|
||||||
completer.complete(result);
|
completer.complete(result);
|
||||||
@ -308,7 +306,7 @@ class FuchsiaRemoteConnection {
|
|||||||
final List<Future<List<IsolateRef>>> isolates =
|
final List<Future<List<IsolateRef>>> isolates =
|
||||||
<Future<List<IsolateRef>>>[];
|
<Future<List<IsolateRef>>>[];
|
||||||
for (final PortForwarder fp in _dartVmPortMap.values) {
|
for (final PortForwarder fp in _dartVmPortMap.values) {
|
||||||
final DartVm vmService =
|
final DartVm? vmService =
|
||||||
await _getDartVm(_getDartVmUri(fp), timeout: vmConnectionTimeout);
|
await _getDartVm(_getDartVmUri(fp), timeout: vmConnectionTimeout);
|
||||||
if (vmService == null) {
|
if (vmService == null) {
|
||||||
continue;
|
continue;
|
||||||
@ -393,7 +391,7 @@ class FuchsiaRemoteConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final PortForwarder pf in _dartVmPortMap.values) {
|
for (final PortForwarder pf in _dartVmPortMap.values) {
|
||||||
final DartVm service = await _getDartVm(_getDartVmUri(pf));
|
final DartVm? service = await _getDartVm(_getDartVmUri(pf));
|
||||||
if (service == null) {
|
if (service == null) {
|
||||||
await shutDownPortForwarder(pf);
|
await shutDownPortForwarder(pf);
|
||||||
} else {
|
} else {
|
||||||
@ -405,11 +403,11 @@ class FuchsiaRemoteConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Uri _getDartVmUri(PortForwarder pf) {
|
Uri _getDartVmUri(PortForwarder pf) {
|
||||||
String addr;
|
String? addr;
|
||||||
if (pf.openPortAddress == null) {
|
if (pf.openPortAddress == null) {
|
||||||
addr = _useIpV6 ? '[$_ipv6Loopback]' : _ipv4Loopback;
|
addr = _useIpV6 ? '[$_ipv6Loopback]' : _ipv4Loopback;
|
||||||
} else {
|
} else {
|
||||||
addr = isIpV6Address(pf.openPortAddress)
|
addr = isIpV6Address(pf.openPortAddress!)
|
||||||
? '[${pf.openPortAddress}]'
|
? '[${pf.openPortAddress}]'
|
||||||
: pf.openPortAddress;
|
: pf.openPortAddress;
|
||||||
}
|
}
|
||||||
@ -421,7 +419,7 @@ class FuchsiaRemoteConnection {
|
|||||||
///
|
///
|
||||||
/// Returns null if either there is an [HttpException] or a
|
/// Returns null if either there is an [HttpException] or a
|
||||||
/// [TimeoutException], else a [DartVm] instance.
|
/// [TimeoutException], else a [DartVm] instance.
|
||||||
Future<DartVm> _getDartVm(
|
Future<DartVm?> _getDartVm(
|
||||||
Uri uri, {
|
Uri uri, {
|
||||||
Duration timeout = _kDartVmConnectionTimeout,
|
Duration timeout = _kDartVmConnectionTimeout,
|
||||||
}) async {
|
}) async {
|
||||||
@ -462,7 +460,7 @@ class FuchsiaRemoteConnection {
|
|||||||
_dartVmEventController.add(DartVmEvent._(
|
_dartVmEventController.add(DartVmEvent._(
|
||||||
eventType: DartVmEventType.started,
|
eventType: DartVmEventType.started,
|
||||||
servicePort: servicePort,
|
servicePort: servicePort,
|
||||||
uri: _getDartVmUri(_dartVmPortMap[servicePort]),
|
uri: _getDartVmUri(_dartVmPortMap[servicePort]!),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -488,9 +486,9 @@ class FuchsiaRemoteConnection {
|
|||||||
Future<void> _forwardOpenPortsToDeviceServicePorts() async {
|
Future<void> _forwardOpenPortsToDeviceServicePorts() async {
|
||||||
await stop();
|
await stop();
|
||||||
final List<int> servicePorts = await getDeviceServicePorts();
|
final List<int> servicePorts = await getDeviceServicePorts();
|
||||||
final List<PortForwarder> forwardedVmServicePorts =
|
final List<PortForwarder?> forwardedVmServicePorts =
|
||||||
await Future.wait<PortForwarder>(
|
await Future.wait<PortForwarder?>(
|
||||||
servicePorts.map<Future<PortForwarder>>((int deviceServicePort) {
|
servicePorts.map<Future<PortForwarder?>>((int deviceServicePort) {
|
||||||
return fuchsiaPortForwardingFunction(
|
return fuchsiaPortForwardingFunction(
|
||||||
_sshCommandRunner.address,
|
_sshCommandRunner.address,
|
||||||
deviceServicePort,
|
deviceServicePort,
|
||||||
@ -498,9 +496,9 @@ class FuchsiaRemoteConnection {
|
|||||||
_sshCommandRunner.sshConfigPath);
|
_sshCommandRunner.sshConfigPath);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
for (final PortForwarder pf in forwardedVmServicePorts) {
|
for (final PortForwarder? pf in forwardedVmServicePorts) {
|
||||||
// TODO(awdavies): Handle duplicates.
|
// TODO(awdavies): Handle duplicates.
|
||||||
_dartVmPortMap[pf.remotePort] = pf;
|
_dartVmPortMap[pf!.remotePort] = pf;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't queue events, since this is the initial forwarding.
|
// Don't queue events, since this is the initial forwarding.
|
||||||
@ -530,7 +528,7 @@ class FuchsiaRemoteConnection {
|
|||||||
if (line == '') {
|
if (line == '') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final int port = int.tryParse(line);
|
final int? port = int.tryParse(line);
|
||||||
if (port != null) {
|
if (port != null) {
|
||||||
ports.add(port);
|
ports.add(port);
|
||||||
}
|
}
|
||||||
@ -552,7 +550,7 @@ abstract class PortForwarder {
|
|||||||
|
|
||||||
/// The address on which the open port is accessible. Defaults to null to
|
/// The address on which the open port is accessible. Defaults to null to
|
||||||
/// indicate local loopback.
|
/// indicate local loopback.
|
||||||
String get openPortAddress => null;
|
String? get openPortAddress => null;
|
||||||
|
|
||||||
/// The destination port on the other end of the port forwarding tunnel.
|
/// The destination port on the other end of the port forwarding tunnel.
|
||||||
int get remotePort;
|
int get remotePort;
|
||||||
@ -577,8 +575,8 @@ class _SshPortForwarder implements PortForwarder {
|
|||||||
final String _remoteAddress;
|
final String _remoteAddress;
|
||||||
final int _remotePort;
|
final int _remotePort;
|
||||||
final ServerSocket _localSocket;
|
final ServerSocket _localSocket;
|
||||||
final String _sshConfigPath;
|
final String? _sshConfigPath;
|
||||||
final String _interface;
|
final String? _interface;
|
||||||
final bool _ipV6;
|
final bool _ipV6;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -595,15 +593,15 @@ class _SshPortForwarder implements PortForwarder {
|
|||||||
static Future<_SshPortForwarder> start(
|
static Future<_SshPortForwarder> start(
|
||||||
String address,
|
String address,
|
||||||
int remotePort, [
|
int remotePort, [
|
||||||
String interface,
|
String? interface,
|
||||||
String sshConfigPath,
|
String? sshConfigPath,
|
||||||
]) async {
|
]) async {
|
||||||
final bool isIpV6 = isIpV6Address(address);
|
final bool isIpV6 = isIpV6Address(address);
|
||||||
final ServerSocket localSocket = await _createLocalSocket();
|
final ServerSocket? localSocket = await _createLocalSocket();
|
||||||
if (localSocket == null || localSocket.port == 0) {
|
if (localSocket == null || localSocket.port == 0) {
|
||||||
_log.warning('_SshPortForwarder failed to find a local port for '
|
_log.warning('_SshPortForwarder failed to find a local port for '
|
||||||
'$address:$remotePort');
|
'$address:$remotePort');
|
||||||
return null;
|
throw StateError('Unable to create a socket or no available ports.');
|
||||||
}
|
}
|
||||||
// TODO(awdavies): The square-bracket enclosure for using the IPv6 loopback
|
// TODO(awdavies): The square-bracket enclosure for using the IPv6 loopback
|
||||||
// didn't appear to work, but when assigning to the IPv4 loopback device,
|
// didn't appear to work, but when assigning to the IPv4 loopback device,
|
||||||
@ -614,7 +612,7 @@ class _SshPortForwarder implements PortForwarder {
|
|||||||
final String formattedForwardingUrl =
|
final String formattedForwardingUrl =
|
||||||
'${localSocket.port}:$_ipv4Loopback:$remotePort';
|
'${localSocket.port}:$_ipv4Loopback:$remotePort';
|
||||||
final String targetAddress =
|
final String targetAddress =
|
||||||
isIpV6 && interface.isNotEmpty ? '$address%$interface' : address;
|
isIpV6 && interface!.isNotEmpty ? '$address%$interface' : address;
|
||||||
const String dummyRemoteCommand = 'true';
|
const String dummyRemoteCommand = 'true';
|
||||||
final List<String> command = <String>[
|
final List<String> command = <String>[
|
||||||
'ssh',
|
'ssh',
|
||||||
@ -636,7 +634,7 @@ class _SshPortForwarder implements PortForwarder {
|
|||||||
_log.fine("'${command.join(' ')}' exited with exit code "
|
_log.fine("'${command.join(' ')}' exited with exit code "
|
||||||
'${processResult.exitCode}');
|
'${processResult.exitCode}');
|
||||||
if (processResult.exitCode != 0) {
|
if (processResult.exitCode != 0) {
|
||||||
return null;
|
throw StateError('Unable to start port forwarding');
|
||||||
}
|
}
|
||||||
final _SshPortForwarder result = _SshPortForwarder._(
|
final _SshPortForwarder result = _SshPortForwarder._(
|
||||||
address, remotePort, localSocket, interface, sshConfigPath, isIpV6);
|
address, remotePort, localSocket, interface, sshConfigPath, isIpV6);
|
||||||
@ -653,13 +651,13 @@ class _SshPortForwarder implements PortForwarder {
|
|||||||
// uses the IPv4 loopback.
|
// uses the IPv4 loopback.
|
||||||
final String formattedForwardingUrl =
|
final String formattedForwardingUrl =
|
||||||
'${_localSocket.port}:$_ipv4Loopback:$_remotePort';
|
'${_localSocket.port}:$_ipv4Loopback:$_remotePort';
|
||||||
final String targetAddress = _ipV6 && _interface.isNotEmpty
|
final String targetAddress = _ipV6 && _interface!.isNotEmpty
|
||||||
? '$_remoteAddress%$_interface'
|
? '$_remoteAddress%$_interface'
|
||||||
: _remoteAddress;
|
: _remoteAddress;
|
||||||
final List<String> command = <String>[
|
final List<String?> command = <String?>[
|
||||||
'ssh',
|
'ssh',
|
||||||
if (_sshConfigPath != null)
|
if (_sshConfigPath != null)
|
||||||
...<String>['-F', _sshConfigPath],
|
...<String?>['-F', _sshConfigPath],
|
||||||
'-O',
|
'-O',
|
||||||
'cancel',
|
'cancel',
|
||||||
'-L',
|
'-L',
|
||||||
@ -680,7 +678,7 @@ class _SshPortForwarder implements PortForwarder {
|
|||||||
///
|
///
|
||||||
/// If successful returns a valid [ServerSocket] (which must be disconnected
|
/// If successful returns a valid [ServerSocket] (which must be disconnected
|
||||||
/// later).
|
/// later).
|
||||||
static Future<ServerSocket> _createLocalSocket() async {
|
static Future<ServerSocket?> _createLocalSocket() async {
|
||||||
ServerSocket s;
|
ServerSocket s;
|
||||||
try {
|
try {
|
||||||
s = await ServerSocket.bind(_ipv4Loopback, 0);
|
s = await ServerSocket.bind(_ipv4Loopback, 0);
|
||||||
|
@ -44,7 +44,7 @@ class SshCommandRunner {
|
|||||||
/// IPv4 nor IPv6. When connecting to a link local address (`fe80::` is
|
/// IPv4 nor IPv6. When connecting to a link local address (`fe80::` is
|
||||||
/// usually at the start of the address), an interface should be supplied.
|
/// usually at the start of the address), an interface should be supplied.
|
||||||
SshCommandRunner({
|
SshCommandRunner({
|
||||||
this.address,
|
required this.address,
|
||||||
this.interface = '',
|
this.interface = '',
|
||||||
this.sshConfigPath,
|
this.sshConfigPath,
|
||||||
}) : _processManager = const LocalProcessManager() {
|
}) : _processManager = const LocalProcessManager() {
|
||||||
@ -55,7 +55,7 @@ class SshCommandRunner {
|
|||||||
@visibleForTesting
|
@visibleForTesting
|
||||||
SshCommandRunner.withProcessManager(
|
SshCommandRunner.withProcessManager(
|
||||||
this._processManager, {
|
this._processManager, {
|
||||||
this.address,
|
required this.address,
|
||||||
this.interface = '',
|
this.interface = '',
|
||||||
this.sshConfigPath,
|
this.sshConfigPath,
|
||||||
}) {
|
}) {
|
||||||
@ -70,7 +70,7 @@ class SshCommandRunner {
|
|||||||
final String address;
|
final String address;
|
||||||
|
|
||||||
/// The path to the SSH config (optional).
|
/// 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
|
/// The name of the machine's network interface (for use with IPv6
|
||||||
/// connections. Ignored otherwise).
|
/// connections. Ignored otherwise).
|
||||||
@ -84,7 +84,7 @@ class SshCommandRunner {
|
|||||||
final List<String> args = <String>[
|
final List<String> args = <String>[
|
||||||
'ssh',
|
'ssh',
|
||||||
if (sshConfigPath != null)
|
if (sshConfigPath != null)
|
||||||
...<String>['-F', sshConfigPath],
|
...<String>['-F', sshConfigPath!],
|
||||||
if (isIpV6Address(address))
|
if (isIpV6Address(address))
|
||||||
...<String>['-6', if (interface.isEmpty) address else '$address%$interface']
|
...<String>['-6', if (interface.isEmpty) address else '$address%$interface']
|
||||||
else
|
else
|
||||||
|
@ -5,7 +5,7 @@ homepage: http://flutter.dev
|
|||||||
author: Flutter Authors <flutter-dev@googlegroups.com>
|
author: Flutter Authors <flutter-dev@googlegroups.com>
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.2.2 <3.0.0"
|
sdk: '>=2.12.0-0 <3.0.0'
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
process: 4.0.0-nullsafety.4
|
process: 4.0.0-nullsafety.4
|
||||||
|
@ -11,9 +11,9 @@ import 'common.dart';
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
group('FuchsiaRemoteConnection.connect', () {
|
group('FuchsiaRemoteConnection.connect', () {
|
||||||
List<FakePortForwarder> forwardedPorts;
|
late List<FakePortForwarder> forwardedPorts;
|
||||||
List<FakeVmService> fakeVmServices;
|
List<FakeVmService> fakeVmServices;
|
||||||
List<Uri> uriConnections;
|
late List<Uri> uriConnections;
|
||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
final List<Map<String, dynamic>> flutterViewCannedResponses =
|
final List<Map<String, dynamic>> flutterViewCannedResponses =
|
||||||
@ -63,7 +63,7 @@ void main() {
|
|||||||
uriConnections = <Uri>[];
|
uriConnections = <Uri>[];
|
||||||
Future<vms.VmService> fakeVmConnectionFunction(
|
Future<vms.VmService> fakeVmConnectionFunction(
|
||||||
Uri uri, {
|
Uri uri, {
|
||||||
Duration timeout,
|
Duration? timeout,
|
||||||
}) {
|
}) {
|
||||||
return Future<vms.VmService>(() async {
|
return Future<vms.VmService>(() async {
|
||||||
final FakeVmService service = FakeVmService();
|
final FakeVmService service = FakeVmService();
|
||||||
@ -89,8 +89,8 @@ void main() {
|
|||||||
Future<PortForwarder> fakePortForwardingFunction(
|
Future<PortForwarder> fakePortForwardingFunction(
|
||||||
String address,
|
String address,
|
||||||
int remotePort, [
|
int remotePort, [
|
||||||
String interface = '',
|
String? interface = '',
|
||||||
String configFile,
|
String? configFile,
|
||||||
]) {
|
]) {
|
||||||
return Future<PortForwarder>(() {
|
return Future<PortForwarder>(() {
|
||||||
final FakePortForwarder pf = FakePortForwarder();
|
final FakePortForwarder pf = FakePortForwarder();
|
||||||
@ -156,8 +156,8 @@ void main() {
|
|||||||
Future<PortForwarder> fakePortForwardingFunction(
|
Future<PortForwarder> fakePortForwardingFunction(
|
||||||
String address,
|
String address,
|
||||||
int remotePort, [
|
int remotePort, [
|
||||||
String interface = '',
|
String? interface = '',
|
||||||
String configFile,
|
String? configFile,
|
||||||
]) {
|
]) {
|
||||||
return Future<PortForwarder>(() {
|
return Future<PortForwarder>(() {
|
||||||
final FakePortForwarder pf = FakePortForwarder();
|
final FakePortForwarder pf = FakePortForwarder();
|
||||||
@ -223,8 +223,8 @@ void main() {
|
|||||||
Future<PortForwarder> fakePortForwardingFunction(
|
Future<PortForwarder> fakePortForwardingFunction(
|
||||||
String address,
|
String address,
|
||||||
int remotePort, [
|
int remotePort, [
|
||||||
String interface = '',
|
String? interface = '',
|
||||||
String configFile,
|
String? configFile,
|
||||||
]) {
|
]) {
|
||||||
return Future<PortForwarder>(() {
|
return Future<PortForwarder>(() {
|
||||||
final FakePortForwarder pf = FakePortForwarder();
|
final FakePortForwarder pf = FakePortForwarder();
|
||||||
@ -296,24 +296,24 @@ void main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class FakeSshCommandRunner extends Fake implements SshCommandRunner {
|
class FakeSshCommandRunner extends Fake implements SshCommandRunner {
|
||||||
List<String> findResponse;
|
List<String>? findResponse;
|
||||||
List<String> lsResponse;
|
List<String>? lsResponse;
|
||||||
@override
|
@override
|
||||||
Future<List<String>> run(String command) async {
|
Future<List<String>> run(String command) async {
|
||||||
if (command.startsWith('/bin/find')) {
|
if (command.startsWith('/bin/find')) {
|
||||||
return findResponse;
|
return findResponse!;
|
||||||
}
|
}
|
||||||
if (command.startsWith('/bin/ls')) {
|
if (command.startsWith('/bin/ls')) {
|
||||||
return lsResponse;
|
return lsResponse!;
|
||||||
}
|
}
|
||||||
throw UnimplementedError(command);
|
throw UnimplementedError(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String interface;
|
String interface = '';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String address;
|
String address = '';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get sshConfigPath => '~/.ssh';
|
String get sshConfigPath => '~/.ssh';
|
||||||
@ -321,13 +321,13 @@ class FakeSshCommandRunner extends Fake implements SshCommandRunner {
|
|||||||
|
|
||||||
class FakePortForwarder extends Fake implements PortForwarder {
|
class FakePortForwarder extends Fake implements PortForwarder {
|
||||||
@override
|
@override
|
||||||
int port;
|
int port = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int remotePort;
|
int remotePort = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String openPortAddress;
|
String? openPortAddress;
|
||||||
|
|
||||||
bool stopped = false;
|
bool stopped = false;
|
||||||
@override
|
@override
|
||||||
@ -338,7 +338,7 @@ class FakePortForwarder extends Fake implements PortForwarder {
|
|||||||
|
|
||||||
class FakeVmService extends Fake implements vms.VmService {
|
class FakeVmService extends Fake implements vms.VmService {
|
||||||
bool disposed = false;
|
bool disposed = false;
|
||||||
vms.Response flutterListViews;
|
vms.Response? flutterListViews;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
@ -346,15 +346,15 @@ class FakeVmService extends Fake implements vms.VmService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@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') {
|
if (method == '_flutter.listViews') {
|
||||||
return flutterListViews;
|
return flutterListViews!;
|
||||||
}
|
}
|
||||||
throw UnimplementedError(method);
|
throw UnimplementedError(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> onDone;
|
Future<void> onDone = Future<void>.value();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<vms.Version> getVersion() async {
|
Future<vms.Version> getVersion() async {
|
||||||
|
@ -16,24 +16,11 @@ void main() {
|
|||||||
restoreVmServiceConnectionFunction();
|
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 {
|
test('disconnect closes peer', () async {
|
||||||
final FakeVmService service = FakeVmService();
|
final FakeVmService service = FakeVmService();
|
||||||
Future<vms.VmService> fakeServiceFunction(
|
Future<vms.VmService> fakeServiceFunction(
|
||||||
Uri uri, {
|
Uri uri, {
|
||||||
Duration timeout,
|
Duration? timeout,
|
||||||
}) {
|
}) {
|
||||||
return Future<vms.VmService>(() => service);
|
return Future<vms.VmService>(() => service);
|
||||||
}
|
}
|
||||||
@ -47,7 +34,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
group('DartVm.getAllFlutterViews', () {
|
group('DartVm.getAllFlutterViews', () {
|
||||||
FakeVmService fakeService;
|
late FakeVmService fakeService;
|
||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
fakeService = FakeVmService();
|
fakeService = FakeVmService();
|
||||||
@ -91,7 +78,7 @@ void main() {
|
|||||||
|
|
||||||
Future<vms.VmService> fakeVmConnectionFunction(
|
Future<vms.VmService> fakeVmConnectionFunction(
|
||||||
Uri uri, {
|
Uri uri, {
|
||||||
Duration timeout,
|
Duration? timeout,
|
||||||
}) {
|
}) {
|
||||||
fakeService.flutterListViews = vms.Response.parse(flutterViewCannedResponses);
|
fakeService.flutterListViews = vms.Response.parse(flutterViewCannedResponses);
|
||||||
return Future<vms.VmService>(() => fakeService);
|
return Future<vms.VmService>(() => fakeService);
|
||||||
@ -147,7 +134,7 @@ void main() {
|
|||||||
|
|
||||||
Future<vms.VmService> fakeVmConnectionFunction(
|
Future<vms.VmService> fakeVmConnectionFunction(
|
||||||
Uri uri, {
|
Uri uri, {
|
||||||
Duration timeout,
|
Duration? timeout,
|
||||||
}) {
|
}) {
|
||||||
fakeService.flutterListViews = vms.Response.parse(flutterViewCannedResponses);
|
fakeService.flutterListViews = vms.Response.parse(flutterViewCannedResponses);
|
||||||
return Future<vms.VmService>(() => fakeService);
|
return Future<vms.VmService>(() => fakeService);
|
||||||
@ -194,7 +181,7 @@ void main() {
|
|||||||
|
|
||||||
Future<vms.VmService> fakeVmConnectionFunction(
|
Future<vms.VmService> fakeVmConnectionFunction(
|
||||||
Uri uri, {
|
Uri uri, {
|
||||||
Duration timeout,
|
Duration? timeout,
|
||||||
}) {
|
}) {
|
||||||
fakeService.flutterListViews = vms.Response.parse(flutterViewCannedResponseMissingId);
|
fakeService.flutterListViews = vms.Response.parse(flutterViewCannedResponseMissingId);
|
||||||
return Future<vms.VmService>(() => fakeService);
|
return Future<vms.VmService>(() => fakeService);
|
||||||
@ -219,33 +206,33 @@ void main() {
|
|||||||
'id': 'isolates/1',
|
'id': 'isolates/1',
|
||||||
'name': 'file://thingThatWillNotMatch:main()',
|
'name': 'file://thingThatWillNotMatch:main()',
|
||||||
'number': '1',
|
'number': '1',
|
||||||
}),
|
})!,
|
||||||
vms.IsolateRef.parse(<String, dynamic>{
|
vms.IsolateRef.parse(<String, dynamic>{
|
||||||
'type': '@Isolate',
|
'type': '@Isolate',
|
||||||
'fixedId': 'true',
|
'fixedId': 'true',
|
||||||
'id': 'isolates/2',
|
'id': 'isolates/2',
|
||||||
'name': '0:dart_name_pattern()',
|
'name': '0:dart_name_pattern()',
|
||||||
'number': '2',
|
'number': '2',
|
||||||
}),
|
})!,
|
||||||
vms.IsolateRef.parse(<String, dynamic>{
|
vms.IsolateRef.parse(<String, dynamic>{
|
||||||
'type': '@Isolate',
|
'type': '@Isolate',
|
||||||
'fixedId': 'true',
|
'fixedId': 'true',
|
||||||
'id': 'isolates/3',
|
'id': 'isolates/3',
|
||||||
'name': 'flutterBinary.cmx',
|
'name': 'flutterBinary.cmx',
|
||||||
'number': '3',
|
'number': '3',
|
||||||
}),
|
})!,
|
||||||
vms.IsolateRef.parse(<String, dynamic>{
|
vms.IsolateRef.parse(<String, dynamic>{
|
||||||
'type': '@Isolate',
|
'type': '@Isolate',
|
||||||
'fixedId': 'true',
|
'fixedId': 'true',
|
||||||
'id': 'isolates/4',
|
'id': 'isolates/4',
|
||||||
'name': '0:some_other_dart_name_pattern()',
|
'name': '0:some_other_dart_name_pattern()',
|
||||||
'number': '4',
|
'number': '4',
|
||||||
}),
|
})!,
|
||||||
];
|
];
|
||||||
|
|
||||||
Future<vms.VmService> fakeVmConnectionFunction(
|
Future<vms.VmService> fakeVmConnectionFunction(
|
||||||
Uri uri, {
|
Uri uri, {
|
||||||
Duration timeout,
|
Duration? timeout,
|
||||||
}) {
|
}) {
|
||||||
fakeService.vm = FakeVM(isolates: isolates);
|
fakeService.vm = FakeVM(isolates: isolates);
|
||||||
return Future<vms.VmService>(() => fakeService);
|
return Future<vms.VmService>(() => fakeService);
|
||||||
@ -279,7 +266,7 @@ void main() {
|
|||||||
|
|
||||||
Future<vms.VmService> fakeVmConnectionFunction(
|
Future<vms.VmService> fakeVmConnectionFunction(
|
||||||
Uri uri, {
|
Uri uri, {
|
||||||
Duration timeout,
|
Duration? timeout,
|
||||||
}) {
|
}) {
|
||||||
fakeService.flutterListViews = vms.Response.parse(flutterViewCannedResponseMissingIsolateName);
|
fakeService.flutterListViews = vms.Response.parse(flutterViewCannedResponseMissingIsolateName);
|
||||||
return Future<vms.VmService>(() => fakeService);
|
return Future<vms.VmService>(() => fakeService);
|
||||||
@ -300,11 +287,11 @@ void main() {
|
|||||||
|
|
||||||
class FakeVmService extends Fake implements vms.VmService {
|
class FakeVmService extends Fake implements vms.VmService {
|
||||||
bool disposed = false;
|
bool disposed = false;
|
||||||
vms.Response flutterListViews;
|
vms.Response? flutterListViews;
|
||||||
vms.VM vm;
|
vms.VM? vm;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<vms.VM> getVM() async => vm;
|
Future<vms.VM> getVM() async => vm!;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
@ -312,15 +299,15 @@ class FakeVmService extends Fake implements vms.VmService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@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') {
|
if (method == '_flutter.listViews') {
|
||||||
return flutterListViews;
|
return flutterListViews!;
|
||||||
}
|
}
|
||||||
throw UnimplementedError(method);
|
throw UnimplementedError(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> onDone;
|
Future<void> onDone = Future<void>.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeVM extends Fake implements vms.VM {
|
class FakeVM extends Fake implements vms.VM {
|
||||||
@ -329,5 +316,5 @@ class FakeVM extends Fake implements vms.VM {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<vms.IsolateRef> isolates;
|
List<vms.IsolateRef>? isolates;
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,8 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
group('SshCommandRunner.run', () {
|
group('SshCommandRunner.run', () {
|
||||||
FakeProcessManager fakeProcessManager;
|
late FakeProcessManager fakeProcessManager;
|
||||||
FakeProcessResult fakeProcessResult;
|
late FakeProcessResult fakeProcessResult;
|
||||||
SshCommandRunner runner;
|
SshCommandRunner runner;
|
||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
@ -103,10 +103,10 @@ void main() {
|
|||||||
);
|
);
|
||||||
fakeProcessResult.stdout = 'somestuff';
|
fakeProcessResult.stdout = 'somestuff';
|
||||||
await runner.run('ls /whatever');
|
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'));
|
expect(passedCommand, contains('-F'));
|
||||||
final int indexOfFlag = passedCommand.indexOf('-F');
|
final int indexOfFlag = passedCommand.indexOf('-F');
|
||||||
final String passedConfig = passedCommand[indexOfFlag + 1];
|
final String? passedConfig = passedCommand[indexOfFlag + 1];
|
||||||
expect(passedConfig, config);
|
expect(passedConfig, config);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
fakeProcessResult.stdout = 'somestuff';
|
fakeProcessResult.stdout = 'somestuff';
|
||||||
await runner.run('ls /whatever');
|
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');
|
final int indexOfFlag = passedCommand.indexOf('-F');
|
||||||
expect(indexOfFlag, equals(-1));
|
expect(indexOfFlag, equals(-1));
|
||||||
});
|
});
|
||||||
@ -126,21 +126,21 @@ void main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class FakeProcessManager extends Fake implements ProcessManager {
|
class FakeProcessManager extends Fake implements ProcessManager {
|
||||||
FakeProcessResult fakeResult;
|
FakeProcessResult? fakeResult;
|
||||||
|
|
||||||
List<List<dynamic>> runCommands = <List<dynamic>>[];
|
List<List<dynamic>> runCommands = <List<dynamic>>[];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<ProcessResult> run(List<dynamic> command, {
|
Future<ProcessResult> run(List<dynamic> command, {
|
||||||
String workingDirectory,
|
String? workingDirectory,
|
||||||
Map<String, String> environment,
|
Map<String, String>? environment,
|
||||||
bool includeParentEnvironment = true,
|
bool includeParentEnvironment = true,
|
||||||
bool runInShell = false,
|
bool runInShell = false,
|
||||||
Encoding stdoutEncoding = systemEncoding,
|
Encoding stdoutEncoding = systemEncoding,
|
||||||
Encoding stderrEncoding = systemEncoding,
|
Encoding stderrEncoding = systemEncoding,
|
||||||
}) async {
|
}) async {
|
||||||
runCommands.add(command);
|
runCommands.add(command);
|
||||||
return fakeResult;
|
return fakeResult!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user