mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
[fuchsia] Add support for the 'device' command using the SDK (#31910)
This commit is contained in:
parent
06973f58a7
commit
6a69f8c98c
@ -1 +1 @@
|
||||
Ow5Xdviq7OwKr7XNuf-Bw0nBMeAr849mFn7gc_RUpzUC
|
||||
mfXzGfxNWcf6BHsv083b56vQcj96yCo0exBFBdjE4gMC
|
||||
|
@ -72,7 +72,7 @@ Future<T> runInContext<T>(
|
||||
DoctorValidatorsProvider: () => DoctorValidatorsProvider.defaultInstance,
|
||||
EmulatorManager: () => EmulatorManager(),
|
||||
FuchsiaSdk: () => FuchsiaSdk(),
|
||||
FuchsiaArtifacts: () => FuchsiaArtifacts(),
|
||||
FuchsiaArtifacts: () => FuchsiaArtifacts.find(),
|
||||
FuchsiaWorkflow: () => FuchsiaWorkflow(),
|
||||
Flags: () => const EmptyFlags(),
|
||||
FlutterVersion: () => FlutterVersion(const SystemClock()),
|
||||
|
@ -35,7 +35,8 @@ Future<VMService> _kDefaultFuchsiaIsolateDiscoveryConnector(Uri uri) {
|
||||
class _FuchsiaLogReader extends DeviceLogReader {
|
||||
_FuchsiaLogReader(this._device, [this._app]);
|
||||
|
||||
static final RegExp _flutterLogOutput = RegExp(r'INFO: \w+\(flutter\): ');
|
||||
// \S matches non-whitespace characters.
|
||||
static final RegExp _flutterLogOutput = RegExp(r'INFO: \S+\(flutter\): ');
|
||||
|
||||
FuchsiaDevice _device;
|
||||
ApplicationPackage _app;
|
||||
@ -46,7 +47,7 @@ class _FuchsiaLogReader extends DeviceLogReader {
|
||||
Stream<String> _logLines;
|
||||
@override
|
||||
Stream<String> get logLines {
|
||||
_logLines ??= _processLogs(fuchsiaSdk.syslogs());
|
||||
_logLines ??= _processLogs(fuchsiaSdk.syslogs(_device.id));
|
||||
return _logLines;
|
||||
}
|
||||
|
||||
@ -57,8 +58,8 @@ class _FuchsiaLogReader extends DeviceLogReader {
|
||||
// Determine if line comes from flutter, and optionally whether it matches
|
||||
// the correct fuchsia module.
|
||||
final RegExp matchRegExp = _app == null
|
||||
? _flutterLogOutput
|
||||
: RegExp('INFO: ${_app.name}\\(flutter\\): ');
|
||||
? _flutterLogOutput
|
||||
: RegExp('INFO: ${_app.name}\\(flutter\\): ');
|
||||
return Stream<String>.eventTransformed(
|
||||
lines,
|
||||
(Sink<String> outout) => _FuchsiaLogSink(outout, matchRegExp, startTime),
|
||||
@ -90,16 +91,19 @@ class _FuchsiaLogSink implements EventSink<String> {
|
||||
if (logTime.millisecondsSinceEpoch < _startTime.millisecondsSinceEpoch) {
|
||||
return;
|
||||
}
|
||||
_outputSink.add('[${logTime.toLocal()}] Flutter: ${line.split(_matchRegExp).last}');
|
||||
_outputSink.add(
|
||||
'[${logTime.toLocal()}] Flutter: ${line.split(_matchRegExp).last}');
|
||||
}
|
||||
|
||||
@override
|
||||
void addError(Object error, [ StackTrace stackTrace ]) {
|
||||
void addError(Object error, [StackTrace stackTrace]) {
|
||||
_outputSink.addError(error, stackTrace);
|
||||
}
|
||||
|
||||
@override
|
||||
void close() { _outputSink.close(); }
|
||||
void close() {
|
||||
_outputSink.close();
|
||||
}
|
||||
}
|
||||
|
||||
class FuchsiaDevices extends PollingDeviceDiscovery {
|
||||
@ -146,7 +150,7 @@ List<FuchsiaDevice> parseListDevices(String text) {
|
||||
}
|
||||
|
||||
class FuchsiaDevice extends Device {
|
||||
FuchsiaDevice(String id, { this.name }) : super(id);
|
||||
FuchsiaDevice(String id, {this.name}) : super(id);
|
||||
|
||||
@override
|
||||
bool get supportsHotReload => true;
|
||||
@ -191,7 +195,8 @@ class FuchsiaDevice extends Device {
|
||||
bool prebuiltApplication = false,
|
||||
bool usesTerminalUi = true,
|
||||
bool ipv6 = false,
|
||||
}) => Future<void>.error('unimplemented');
|
||||
}) =>
|
||||
Future<void>.error('unimplemented');
|
||||
|
||||
@override
|
||||
Future<bool> stopApp(ApplicationPackage app) async {
|
||||
@ -206,15 +211,17 @@ class FuchsiaDevice extends Device {
|
||||
Future<String> get sdkNameAndVersion async => 'Fuchsia';
|
||||
|
||||
@override
|
||||
DeviceLogReader getLogReader({ ApplicationPackage app }) => _logReader ??= _FuchsiaLogReader(this, app);
|
||||
DeviceLogReader getLogReader({ApplicationPackage app}) =>
|
||||
_logReader ??= _FuchsiaLogReader(this, app);
|
||||
_FuchsiaLogReader _logReader;
|
||||
|
||||
@override
|
||||
DevicePortForwarder get portForwarder => _portForwarder ??= _FuchsiaPortForwarder(this);
|
||||
DevicePortForwarder get portForwarder =>
|
||||
_portForwarder ??= _FuchsiaPortForwarder(this);
|
||||
_FuchsiaPortForwarder _portForwarder;
|
||||
|
||||
@override
|
||||
void clearLogs() { }
|
||||
void clearLogs() {}
|
||||
|
||||
@override
|
||||
bool get supportsScreenshot => false;
|
||||
@ -234,7 +241,8 @@ class FuchsiaDevice extends Device {
|
||||
Future<List<int>> servicePorts() async {
|
||||
final String findOutput = await shell('find /hub -name vmservice-port');
|
||||
if (findOutput.trim() == '') {
|
||||
throwToolExit('No Dart Observatories found. Are you running a debug build?');
|
||||
throwToolExit(
|
||||
'No Dart Observatories found. Are you running a debug build?');
|
||||
return null;
|
||||
}
|
||||
final List<int> ports = <int>[];
|
||||
@ -259,9 +267,15 @@ class FuchsiaDevice extends Device {
|
||||
/// Run `command` on the Fuchsia device shell.
|
||||
Future<String> shell(String command) async {
|
||||
final RunResult result = await runAsync(<String>[
|
||||
'ssh', '-F', fuchsiaArtifacts.sshConfig.absolute.path, id, command]);
|
||||
'ssh',
|
||||
'-F',
|
||||
fuchsiaArtifacts.sshConfig.absolute.path,
|
||||
id,
|
||||
command
|
||||
]);
|
||||
if (result.exitCode != 0) {
|
||||
throwToolExit('Command failed: $command\nstdout: ${result.stdout}\nstderr: ${result.stderr}');
|
||||
throwToolExit(
|
||||
'Command failed: $command\nstdout: ${result.stdout}\nstderr: ${result.stderr}');
|
||||
return null;
|
||||
}
|
||||
return result.stdout;
|
||||
@ -302,7 +316,9 @@ class FuchsiaDevice extends Device {
|
||||
return null;
|
||||
}
|
||||
|
||||
FuchsiaIsolateDiscoveryProtocol getIsolateDiscoveryProtocol(String isolateName) => FuchsiaIsolateDiscoveryProtocol(this, isolateName);
|
||||
FuchsiaIsolateDiscoveryProtocol getIsolateDiscoveryProtocol(
|
||||
String isolateName) =>
|
||||
FuchsiaIsolateDiscoveryProtocol(this, isolateName);
|
||||
|
||||
@override
|
||||
bool isSupportedForProject(FlutterProject flutterProject) => true;
|
||||
@ -341,6 +357,7 @@ class FuchsiaIsolateDiscoveryProtocol {
|
||||
return uri;
|
||||
});
|
||||
}
|
||||
|
||||
Uri _uri;
|
||||
|
||||
void dispose() {
|
||||
@ -379,8 +396,8 @@ class FuchsiaIsolateDiscoveryProtocol {
|
||||
final Uri address = flutterView.owner.vmService.httpAddress;
|
||||
if (flutterView.uiIsolate.name.contains(_isolateName)) {
|
||||
_foundUri.complete(_device.ipv6
|
||||
? Uri.parse('http://[$_ipv6Loopback]:${address.port}/')
|
||||
: Uri.parse('http://$_ipv4Loopback:${address.port}/'));
|
||||
? Uri.parse('http://[$_ipv6Loopback]:${address.port}/')
|
||||
: Uri.parse('http://$_ipv4Loopback:${address.port}/'));
|
||||
_status.stop();
|
||||
return;
|
||||
}
|
||||
@ -402,13 +419,22 @@ class _FuchsiaPortForwarder extends DevicePortForwarder {
|
||||
final Map<int, Process> _processes = <int, Process>{};
|
||||
|
||||
@override
|
||||
Future<int> forward(int devicePort, { int hostPort }) async {
|
||||
Future<int> forward(int devicePort, {int hostPort}) async {
|
||||
hostPort ??= await _findPort();
|
||||
// Note: the provided command works around a bug in -N, see US-515
|
||||
// for more explanation.
|
||||
final List<String> command = <String>[
|
||||
'ssh', '-6', '-F', fuchsiaArtifacts.sshConfig.absolute.path, '-nNT', '-vvv', '-f',
|
||||
'-L', '$hostPort:$_ipv4Loopback:$devicePort', device.id, 'true',
|
||||
'ssh',
|
||||
'-6',
|
||||
'-F',
|
||||
fuchsiaArtifacts.sshConfig.absolute.path,
|
||||
'-nNT',
|
||||
'-vvv',
|
||||
'-f',
|
||||
'-L',
|
||||
'$hostPort:$_ipv4Loopback:$devicePort',
|
||||
device.id,
|
||||
'true',
|
||||
];
|
||||
final Process process = await processManager.start(command);
|
||||
unawaited(process.exitCode.then((int exitCode) {
|
||||
@ -431,8 +457,16 @@ class _FuchsiaPortForwarder extends DevicePortForwarder {
|
||||
final Process process = _processes.remove(forwardedPort.hostPort);
|
||||
process?.kill();
|
||||
final List<String> command = <String>[
|
||||
'ssh', '-F', fuchsiaArtifacts.sshConfig.absolute.path, '-O', 'cancel', '-vvv',
|
||||
'-L', '${forwardedPort.hostPort}:$_ipv4Loopback:${forwardedPort.devicePort}', device.id];
|
||||
'ssh',
|
||||
'-F',
|
||||
fuchsiaArtifacts.sshConfig.absolute.path,
|
||||
'-O',
|
||||
'cancel',
|
||||
'-vvv',
|
||||
'-L',
|
||||
'${forwardedPort.hostPort}:$_ipv4Loopback:${forwardedPort.devicePort}',
|
||||
device.id
|
||||
];
|
||||
final ProcessResult result = await processManager.run(command);
|
||||
if (result.exitCode != 0) {
|
||||
throwToolExit(result.stderr);
|
||||
@ -449,8 +483,9 @@ class _FuchsiaPortForwarder extends DevicePortForwarder {
|
||||
// Failures are signaled by a return value of 0 from this function.
|
||||
printTrace('_findPort failed: $e');
|
||||
}
|
||||
if (serverSocket != null)
|
||||
if (serverSocket != null) {
|
||||
await serverSocket.close();
|
||||
}
|
||||
return port;
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,10 @@ import 'dart:async';
|
||||
import '../base/context.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../base/io.dart';
|
||||
import '../base/platform.dart';
|
||||
import '../base/process.dart';
|
||||
import '../base/process_manager.dart';
|
||||
import '../cache.dart';
|
||||
import '../convert.dart';
|
||||
import '../globals.dart';
|
||||
|
||||
@ -23,8 +25,6 @@ FuchsiaArtifacts get fuchsiaArtifacts => context.get<FuchsiaArtifacts>();
|
||||
/// This workflow assumes development within the fuchsia source tree,
|
||||
/// including a working fx command-line tool in the user's PATH.
|
||||
class FuchsiaSdk {
|
||||
static const List<String> _syslogCommand = <String>['fx', 'syslog', '--clock', 'Local'];
|
||||
|
||||
/// Example output:
|
||||
/// $ dev_finder list -full
|
||||
/// > 192.168.42.56 paper-pulp-bush-angel
|
||||
@ -42,19 +42,33 @@ class FuchsiaSdk {
|
||||
/// Returns the fuchsia system logs for an attached device.
|
||||
///
|
||||
/// Does not currently support multiple attached devices.
|
||||
Stream<String> syslogs() {
|
||||
Stream<String> syslogs(String id) {
|
||||
Process process;
|
||||
try {
|
||||
final StreamController<String> controller = StreamController<String>(onCancel: () {
|
||||
final StreamController<String> controller =
|
||||
StreamController<String>(onCancel: () {
|
||||
process.kill();
|
||||
});
|
||||
processManager.start(_syslogCommand).then((Process newProcess) {
|
||||
if (fuchsiaArtifacts.sshConfig == null) {
|
||||
return null;
|
||||
}
|
||||
const String remoteCommand = 'log_listener --clock Local';
|
||||
final List<String> cmd = <String>[
|
||||
'ssh',
|
||||
'-F',
|
||||
fuchsiaArtifacts.sshConfig.absolute.path,
|
||||
id,
|
||||
remoteCommand
|
||||
];
|
||||
processManager.start(cmd).then((Process newProcess) {
|
||||
if (controller.isClosed) {
|
||||
return;
|
||||
}
|
||||
process = newProcess;
|
||||
process.exitCode.whenComplete(controller.close);
|
||||
controller.addStream(process.stdout.transform(utf8.decoder).transform(const LineSplitter()));
|
||||
controller.addStream(process.stdout
|
||||
.transform(utf8.decoder)
|
||||
.transform(const LineSplitter()));
|
||||
});
|
||||
return controller.stream;
|
||||
} catch (exception) {
|
||||
@ -69,6 +83,35 @@ class FuchsiaArtifacts {
|
||||
/// Creates a new [FuchsiaArtifacts].
|
||||
FuchsiaArtifacts({this.sshConfig, this.devFinder});
|
||||
|
||||
/// Creates a new [FuchsiaArtifacts] using the cached Fuchsia SDK.
|
||||
///
|
||||
/// Finds tools under bin/cache/artifacts/fuchsia/tools.
|
||||
/// Queries environment variables (first FUCHSIA_BUILD_DIR, then
|
||||
/// FUCHSIA_SSH_CONFIG) to find the ssh configuration needed to talk to
|
||||
/// a device.
|
||||
factory FuchsiaArtifacts.find() {
|
||||
final String fuchsia = Cache.instance.getArtifactDirectory('fuchsia').path;
|
||||
final String tools = fs.path.join(fuchsia, 'tools');
|
||||
|
||||
// If FUCHSIA_BUILD_DIR is defined, then look for the ssh_config dir
|
||||
// relative to it. Next, if FUCHSIA_SSH_CONFIG is defined, then use it.
|
||||
// TODO(zra): Consider passing the ssh config path in with a flag.
|
||||
File sshConfig;
|
||||
if (platform.environment.containsKey(_kFuchsiaBuildDir)) {
|
||||
sshConfig = fs.file(fs.path.join(
|
||||
platform.environment[_kFuchsiaSshConfig], 'ssh-keys', 'ssh_config'));
|
||||
} else if (platform.environment.containsKey(_kFuchsiaSshConfig)) {
|
||||
sshConfig = fs.file(platform.environment[_kFuchsiaSshConfig]);
|
||||
}
|
||||
return FuchsiaArtifacts(
|
||||
sshConfig: sshConfig,
|
||||
devFinder: fs.file(fs.path.join(tools, 'dev_finder')),
|
||||
);
|
||||
}
|
||||
|
||||
static const String _kFuchsiaSshConfig = 'FUCHSIA_SSH_CONFIG';
|
||||
static const String _kFuchsiaBuildDir = 'FUCHSIA_BUILD_DIR';
|
||||
|
||||
/// The location of the SSH configuration file used to interact with a
|
||||
/// Fuchsia device.
|
||||
final File sshConfig;
|
||||
|
@ -66,7 +66,8 @@ void main() {
|
||||
any,
|
||||
environment: anyNamed('environment'),
|
||||
workingDirectory: anyNamed('workingDirectory'),
|
||||
)).thenAnswer((Invocation invocation) => Future<ProcessResult>.value(mockProcessResult));
|
||||
)).thenAnswer((Invocation invocation) =>
|
||||
Future<ProcessResult>.value(mockProcessResult));
|
||||
when(mockProcessResult.exitCode).thenReturn(1);
|
||||
when<String>(mockProcessResult.stdout).thenReturn('');
|
||||
when<String>(mockProcessResult.stderr).thenReturn('');
|
||||
@ -79,7 +80,8 @@ void main() {
|
||||
any,
|
||||
environment: anyNamed('environment'),
|
||||
workingDirectory: anyNamed('workingDirectory'),
|
||||
)).thenAnswer((Invocation invocation) => Future<ProcessResult>.value(emptyStdoutProcessResult));
|
||||
)).thenAnswer((Invocation invocation) =>
|
||||
Future<ProcessResult>.value(emptyStdoutProcessResult));
|
||||
when(emptyStdoutProcessResult.exitCode).thenReturn(0);
|
||||
when<String>(emptyStdoutProcessResult.stdout).thenReturn('');
|
||||
when<String>(emptyStdoutProcessResult.stderr).thenReturn('');
|
||||
@ -92,23 +94,26 @@ void main() {
|
||||
} on ToolExit catch (err) {
|
||||
toolExit = err;
|
||||
}
|
||||
expect(toolExit.message, contains('No Dart Observatories found. Are you running a debug build?'));
|
||||
expect(
|
||||
toolExit.message,
|
||||
contains(
|
||||
'No Dart Observatories found. Are you running a debug build?'));
|
||||
}, overrides: <Type, Generator>{
|
||||
ProcessManager: () => emptyStdoutProcessManager,
|
||||
FuchsiaArtifacts: () => FuchsiaArtifacts(
|
||||
sshConfig: mockFile,
|
||||
devFinder: mockFile,
|
||||
),
|
||||
sshConfig: mockFile,
|
||||
devFinder: mockFile,
|
||||
),
|
||||
});
|
||||
|
||||
group('device logs', () {
|
||||
const String exampleUtcLogs = '''
|
||||
[2018-11-09 01:27:45][3][297950920][log] INFO: example_app(flutter): Error doing thing
|
||||
[2018-11-09 01:27:45][3][297950920][log] INFO: example_app.cmx(flutter): Error doing thing
|
||||
[2018-11-09 01:27:58][46257][46269][foo] INFO: Using a thing
|
||||
[2018-11-09 01:29:58][46257][46269][foo] INFO: Blah blah blah
|
||||
[2018-11-09 01:29:58][46257][46269][foo] INFO: other_app(flutter): Do thing
|
||||
[2018-11-09 01:29:58][46257][46269][foo] INFO: other_app.cmx(flutter): Do thing
|
||||
[2018-11-09 01:30:02][41175][41187][bar] INFO: Invoking a bar
|
||||
[2018-11-09 01:30:12][52580][52983][log] INFO: example_app(flutter): Did thing this time
|
||||
[2018-11-09 01:30:12][52580][52983][log] INFO: example_app.cmx(flutter): Did thing this time
|
||||
|
||||
''';
|
||||
final MockProcessManager mockProcessManager = MockProcessManager();
|
||||
@ -116,11 +121,17 @@ void main() {
|
||||
Completer<int> exitCode;
|
||||
StreamController<List<int>> stdout;
|
||||
StreamController<List<int>> stderr;
|
||||
when(mockProcessManager.start(any)).thenAnswer((Invocation _) => Future<Process>.value(mockProcess));
|
||||
when(mockProcessManager.start(any))
|
||||
.thenAnswer((Invocation _) => Future<Process>.value(mockProcess));
|
||||
when(mockProcess.exitCode).thenAnswer((Invocation _) => exitCode.future);
|
||||
when(mockProcess.stdout).thenAnswer((Invocation _) => stdout.stream);
|
||||
when(mockProcess.stderr).thenAnswer((Invocation _) => stderr.stream);
|
||||
|
||||
final MockFile devFinder = MockFile();
|
||||
final MockFile sshConfig = MockFile();
|
||||
when(devFinder.absolute).thenReturn(devFinder);
|
||||
when(sshConfig.absolute).thenReturn(sshConfig);
|
||||
|
||||
setUp(() {
|
||||
stdout = StreamController<List<int>>(sync: true);
|
||||
stderr = StreamController<List<int>>(sync: true);
|
||||
@ -133,7 +144,8 @@ void main() {
|
||||
|
||||
testUsingContext('can be parsed for an app', () async {
|
||||
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
|
||||
final DeviceLogReader reader = device.getLogReader(app: FuchsiaModulePackage(name: 'example_app'));
|
||||
final DeviceLogReader reader = device.getLogReader(
|
||||
app: FuchsiaModulePackage(name: 'example_app.cmx'));
|
||||
final List<String> logLines = <String>[];
|
||||
final Completer<void> lock = Completer<void>();
|
||||
reader.logLines.listen((String line) {
|
||||
@ -155,11 +167,14 @@ void main() {
|
||||
}, overrides: <Type, Generator>{
|
||||
ProcessManager: () => mockProcessManager,
|
||||
SystemClock: () => SystemClock.fixed(DateTime(2018, 11, 9, 1, 25, 45)),
|
||||
FuchsiaArtifacts: () =>
|
||||
FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig),
|
||||
});
|
||||
|
||||
testUsingContext('cuts off prior logs', () async {
|
||||
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
|
||||
final DeviceLogReader reader = device.getLogReader(app: FuchsiaModulePackage(name: 'example_app'));
|
||||
final DeviceLogReader reader = device.getLogReader(
|
||||
app: FuchsiaModulePackage(name: 'example_app.cmx'));
|
||||
final List<String> logLines = <String>[];
|
||||
final Completer<void> lock = Completer<void>();
|
||||
reader.logLines.listen((String line) {
|
||||
@ -178,6 +193,8 @@ void main() {
|
||||
}, overrides: <Type, Generator>{
|
||||
ProcessManager: () => mockProcessManager,
|
||||
SystemClock: () => SystemClock.fixed(DateTime(2018, 11, 9, 1, 29, 45)),
|
||||
FuchsiaArtifacts: () =>
|
||||
FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig),
|
||||
});
|
||||
|
||||
testUsingContext('can be parsed for all apps', () async {
|
||||
@ -205,12 +222,15 @@ void main() {
|
||||
}, overrides: <Type, Generator>{
|
||||
ProcessManager: () => mockProcessManager,
|
||||
SystemClock: () => SystemClock.fixed(DateTime(2018, 11, 9, 1, 25, 45)),
|
||||
FuchsiaArtifacts: () =>
|
||||
FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group(FuchsiaIsolateDiscoveryProtocol, () {
|
||||
Future<Uri> findUri(List<MockFlutterView> views, String expectedIsolateName) {
|
||||
Future<Uri> findUri(
|
||||
List<MockFlutterView> views, String expectedIsolateName) {
|
||||
final MockPortForwarder portForwarder = MockPortForwarder();
|
||||
final MockVMService vmService = MockVMService();
|
||||
final MockVM vm = MockVM();
|
||||
@ -220,33 +240,43 @@ void main() {
|
||||
for (MockFlutterView view in views) {
|
||||
view.owner = vm;
|
||||
}
|
||||
final MockFuchsiaDevice fuchsiaDevice = MockFuchsiaDevice('123', portForwarder, false);
|
||||
final FuchsiaIsolateDiscoveryProtocol discoveryProtocol = FuchsiaIsolateDiscoveryProtocol(
|
||||
final MockFuchsiaDevice fuchsiaDevice =
|
||||
MockFuchsiaDevice('123', portForwarder, false);
|
||||
final FuchsiaIsolateDiscoveryProtocol discoveryProtocol =
|
||||
FuchsiaIsolateDiscoveryProtocol(
|
||||
fuchsiaDevice,
|
||||
expectedIsolateName,
|
||||
(Uri uri) async => vmService,
|
||||
true, // only poll once.
|
||||
);
|
||||
when(fuchsiaDevice.servicePorts()).thenAnswer((Invocation invocation) async => <int>[1]);
|
||||
when(portForwarder.forward(1)).thenAnswer((Invocation invocation) async => 2);
|
||||
when(vmService.getVM()).thenAnswer((Invocation invocation) => Future<void>.value(null));
|
||||
when(vmService.refreshViews()).thenAnswer((Invocation invocation) => Future<void>.value(null));
|
||||
when(fuchsiaDevice.servicePorts())
|
||||
.thenAnswer((Invocation invocation) async => <int>[1]);
|
||||
when(portForwarder.forward(1))
|
||||
.thenAnswer((Invocation invocation) async => 2);
|
||||
when(vmService.getVM())
|
||||
.thenAnswer((Invocation invocation) => Future<void>.value(null));
|
||||
when(vmService.refreshViews())
|
||||
.thenAnswer((Invocation invocation) => Future<void>.value(null));
|
||||
when(vmService.httpAddress).thenReturn(Uri.parse('example'));
|
||||
return discoveryProtocol.uri;
|
||||
}
|
||||
testUsingContext('can find flutter view with matching isolate name', () async {
|
||||
|
||||
testUsingContext('can find flutter view with matching isolate name',
|
||||
() async {
|
||||
const String expectedIsolateName = 'foobar';
|
||||
final Uri uri = await findUri(<MockFlutterView>[
|
||||
MockFlutterView(null), // no ui isolate.
|
||||
MockFlutterView(MockIsolate('wrong name')), // wrong name.
|
||||
MockFlutterView(MockIsolate(expectedIsolateName)), // matching name.
|
||||
], expectedIsolateName);
|
||||
expect(uri.toString(), 'http://${InternetAddress.loopbackIPv4.address}:0/');
|
||||
expect(
|
||||
uri.toString(), 'http://${InternetAddress.loopbackIPv4.address}:0/');
|
||||
}, overrides: <Type, Generator>{
|
||||
Logger: () => StdoutLogger(),
|
||||
});
|
||||
|
||||
testUsingContext('can handle flutter view without matching isolate name', () async {
|
||||
testUsingContext('can handle flutter view without matching isolate name',
|
||||
() async {
|
||||
const String expectedIsolateName = 'foobar';
|
||||
final Future<Uri> uri = findUri(<MockFlutterView>[
|
||||
MockFlutterView(null), // no ui isolate.
|
||||
|
@ -12,37 +12,47 @@ import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
|
||||
class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {}
|
||||
|
||||
class MockFile extends Mock implements File {}
|
||||
|
||||
void main() {
|
||||
group('android workflow', () {
|
||||
group('Fuchsia workflow', () {
|
||||
final MockFile devFinder = MockFile();
|
||||
final MockFile sshConfig = MockFile();
|
||||
when(devFinder.absolute).thenReturn(devFinder);
|
||||
when(sshConfig.absolute).thenReturn(sshConfig);
|
||||
|
||||
testUsingContext('can not list and launch devices if there is not ssh config and dev finder', () {
|
||||
testUsingContext(
|
||||
'can not list and launch devices if there is not ssh config and dev finder',
|
||||
() {
|
||||
expect(fuchsiaWorkflow.canLaunchDevices, false);
|
||||
expect(fuchsiaWorkflow.canListDevices, false);
|
||||
expect(fuchsiaWorkflow.canListEmulators, false);
|
||||
}, overrides: <Type, Generator>{
|
||||
FuchsiaArtifacts: () => FuchsiaArtifacts(devFinder: null, sshConfig: null),
|
||||
FuchsiaArtifacts: () =>
|
||||
FuchsiaArtifacts(devFinder: null, sshConfig: null),
|
||||
});
|
||||
|
||||
testUsingContext('can not list and launch devices if there is not ssh config and dev finder', () {
|
||||
testUsingContext(
|
||||
'can not list and launch devices if there is not ssh config and dev finder',
|
||||
() {
|
||||
expect(fuchsiaWorkflow.canLaunchDevices, false);
|
||||
expect(fuchsiaWorkflow.canListDevices, true);
|
||||
expect(fuchsiaWorkflow.canListEmulators, false);
|
||||
}, overrides: <Type, Generator>{
|
||||
FuchsiaArtifacts: () => FuchsiaArtifacts(devFinder: devFinder, sshConfig: null),
|
||||
FuchsiaArtifacts: () =>
|
||||
FuchsiaArtifacts(devFinder: devFinder, sshConfig: null),
|
||||
});
|
||||
|
||||
testUsingContext('can list and launch devices supported if there is a `fx` command', () {
|
||||
testUsingContext(
|
||||
'can list and launch devices supported with sufficient SDK artifacts',
|
||||
() {
|
||||
expect(fuchsiaWorkflow.canLaunchDevices, true);
|
||||
expect(fuchsiaWorkflow.canListDevices, true);
|
||||
expect(fuchsiaWorkflow.canListEmulators, false);
|
||||
}, overrides: <Type, Generator>{
|
||||
FuchsiaArtifacts: () => FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig),
|
||||
FuchsiaArtifacts: () =>
|
||||
FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user