diff --git a/packages/flutter_tools/bin/fuchsia_attach.dart b/packages/flutter_tools/bin/fuchsia_attach.dart index 71c0d9f613e..0180b73f925 100644 --- a/packages/flutter_tools/bin/fuchsia_attach.dart +++ b/packages/flutter_tools/bin/fuchsia_attach.dart @@ -41,6 +41,7 @@ Future main(List args) async { final String buildDirectory = argResults['build-dir']; final File frontendServer = fs.file('$buildDirectory/host_x64/gen/third_party/flutter/frontend_server/frontend_server_tool.snapshot'); final File sshConfig = fs.file('$buildDirectory/ssh-keys/ssh_config'); + final File devFinder = fs.file('$buildDirectory/host_x64/dev_finder'); final File platformKernelDill = fs.file('$buildDirectory/flutter_runner_patched_sdk/platform_strong.dill'); final File flutterPatchedSdk = fs.file('$buildDirectory/flutter_runner_patched_sdk'); final String packages = '$buildDirectory/dartlang/gen/$path/${name}_dart_library.packages'; @@ -91,7 +92,7 @@ Future main(List args) async { muteCommandLogging: false, verboseHelp: false, overrides: { - FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig), + FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig, devFinder: devFinder), Artifacts: () => OverrideArtifacts( parent: CachedArtifacts(), frontendServer: frontendServer, diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart index be89010182f..ed48b22fe5a 100644 --- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart @@ -108,12 +108,8 @@ class FuchsiaDevices extends PollingDeviceDiscovery { if (!fuchsiaWorkflow.canListDevices) { return []; } - final String text = await fuchsiaSdk.netls(); - final List devices = []; - for (String name in parseFuchsiaDeviceOutput(text)) { - final String id = await fuchsiaSdk.netaddr(); - devices.add(FuchsiaDevice(id, name: name)); - } + final String text = await fuchsiaSdk.listDevices(); + final List devices = parseListDevices(text); return devices; } @@ -121,24 +117,18 @@ class FuchsiaDevices extends PollingDeviceDiscovery { Future> getDiagnostics() async => const []; } -/// Parses output from the netls tool into fuchsia devices names. -/// -/// Example output: -/// $ ./netls -/// > device liliac-shore-only-last (fe80::82e4:da4d:fe81:227d/3) @visibleForTesting -List parseFuchsiaDeviceOutput(String text) { - final List names = []; +List parseListDevices(String text) { + final List devices = []; for (String rawLine in text.trim().split('\n')) { final String line = rawLine.trim(); - if (!line.startsWith('device')) - continue; - // ['device', 'device name', '(id)'] + // ['ip', 'device name'] final List words = line.split(' '); final String name = words[1]; - names.add(name); + final String id = words[0]; + devices.add(FuchsiaDevice(id, name: name)); } - return names; + return devices; } class FuchsiaDevice extends Device { diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart index 63f91e136aa..86f5220b485 100644 --- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart @@ -9,7 +9,6 @@ import '../base/common.dart'; 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'; @@ -24,21 +23,15 @@ FuchsiaArtifacts get fuchsiaArtifacts => context[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 _netaddrCommand = ['fx', 'netaddr', '--fuchsia', '--nowait']; - static const List _netlsCommand = ['fx', 'netls', '--nowait']; static const List _syslogCommand = ['fx', 'syslog', '--clock', 'Local']; - /// Invokes the `netaddr` command. - /// - /// This returns the network address of an attached fuchsia device. Does - /// not currently support multiple attached devices. - /// /// Example output: - /// $ fx netaddr --fuchsia --nowait - /// > fe80::9aaa:fcff:fe60:d3af%eth1 - Future netaddr() async { + /// $ dev_finder list -full + /// > 192.168.42.56 paper-pulp-bush-angel + Future listDevices() async { try { - final RunResult process = await runAsync(_netaddrCommand); + final String path = fuchsiaArtifacts.devFinder.absolute.path; + final RunResult process = await runAsync([path, 'list', '-full']); return process.stdout.trim(); } on ArgumentError catch (exception) { throwToolExit('$exception'); @@ -69,49 +62,18 @@ class FuchsiaSdk { } return null; } - - /// Invokes the `netls` command. - /// - /// This lists attached fuchsia devices with their name and address. Does - /// not currently support multiple attached devices. - /// - /// Example output: - /// $ fx netls --nowait - /// > device liliac-shore-only-last (fe80::82e4:da4d:fe81:227d/3) - Future netls() async { - try { - final RunResult process = await runAsync(_netlsCommand); - return process.stdout; - } on ArgumentError catch (exception) { - throwToolExit('$exception'); - } - return null; - } } /// Fuchsia-specific artifacts used to interact with a device. class FuchsiaArtifacts { /// Creates a new [FuchsiaArtifacts]. - /// - /// May optionally provide a file `sshConfig` file. - FuchsiaArtifacts({File sshConfig}) - : _sshConfig = sshConfig; + FuchsiaArtifacts({this.sshConfig, this.devFinder}); /// The location of the SSH configuration file used to interact with a - /// fuchsia device. - /// - /// Requires the env variable `BUILD_DIR` to be set if not provided by - /// the constructor. - File get sshConfig { - if (_sshConfig == null) { - final String buildDirectory = platform.environment['BUILD_DIR']; - if (buildDirectory == null) { - throwToolExit('BUILD_DIR must be supplied to locate SSH keys. For example:\n' - ' export BUILD_DIR=path/to/fuchsia/out/x64\n'); - } - _sshConfig = fs.file('$buildDirectory/ssh-keys/ssh_config'); - } - return _sshConfig; - } - File _sshConfig; + /// Fuchsia device. + final File sshConfig; + + /// The location of the dev finder tool used to locate connected + /// Fuchsia devices. + final File devFinder; } diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_workflow.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_workflow.dart index 797837678bb..a0d3022482d 100644 --- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_workflow.dart +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_workflow.dart @@ -3,9 +3,9 @@ // found in the LICENSE file. import '../base/context.dart'; -import '../base/os.dart'; import '../base/platform.dart'; import '../doctor.dart'; +import 'fuchsia_sdk.dart'; /// The [FuchsiaWorkflow] instance. FuchsiaWorkflow get fuchsiaWorkflow => context[FuchsiaWorkflow]; @@ -21,12 +21,12 @@ class FuchsiaWorkflow implements Workflow { @override bool get canListDevices { - return os.which('fx') != null; + return fuchsiaArtifacts.devFinder != null; } @override bool get canLaunchDevices { - return os.which('fx') != null; + return fuchsiaArtifacts.devFinder != null && fuchsiaArtifacts.sshConfig != null; } @override diff --git a/packages/flutter_tools/test/fuchsia/fuchsa_device_test.dart b/packages/flutter_tools/test/fuchsia/fuchsa_device_test.dart index fb192f0a4e0..51521920422 100644 --- a/packages/flutter_tools/test/fuchsia/fuchsa_device_test.dart +++ b/packages/flutter_tools/test/fuchsia/fuchsa_device_test.dart @@ -29,12 +29,13 @@ void main() { expect(device.name, name); }); - test('parse netls log output', () { - const String example = 'device lilia-shore-only-last (fe80::0000:a00a:f00f:2002/3)'; - final List names = parseFuchsiaDeviceOutput(example); + test('parse dev_finder output', () { + const String example = '192.168.42.56 paper-pulp-bush-angel'; + final List names = parseListDevices(example); expect(names.length, 1); - expect(names.first, 'lilia-shore-only-last'); + expect(names.first.name, 'paper-pulp-bush-angel'); + expect(names.first.id, '192.168.42.56'); }); test('default capabilities', () async { @@ -50,7 +51,6 @@ void main() { group('displays friendly error when', () { final MockProcessManager mockProcessManager = MockProcessManager(); final MockProcessResult mockProcessResult = MockProcessResult(); - final MockFuchsiaArtifacts mockFuchsiaArtifacts = MockFuchsiaArtifacts(); final MockFile mockFile = MockFile(); when(mockProcessManager.run( any, @@ -60,23 +60,9 @@ void main() { when(mockProcessResult.exitCode).thenReturn(1); when(mockProcessResult.stdout).thenReturn(''); when(mockProcessResult.stderr).thenReturn(''); - when(mockFuchsiaArtifacts.sshConfig).thenReturn(mockFile); when(mockFile.absolute).thenReturn(mockFile); when(mockFile.path).thenReturn(''); - testUsingContext('No BUILD_DIR set', () async { - final FuchsiaDevice device = FuchsiaDevice('id'); - ToolExit toolExit; - try { - await device.servicePorts(); - } on ToolExit catch (err) { - toolExit = err; - } - expect(toolExit.message, contains('BUILD_DIR must be supplied to locate SSH keys')); - }, overrides: { - ProcessManager: () => mockProcessManager, - }); - final MockProcessManager emptyStdoutProcessManager = MockProcessManager(); final MockProcessResult emptyStdoutProcessResult = MockProcessResult(); when(emptyStdoutProcessManager.run( @@ -99,7 +85,10 @@ void main() { expect(toolExit.message, contains('No Dart Observatories found. Are you running a debug build?')); }, overrides: { ProcessManager: () => emptyStdoutProcessManager, - FuchsiaArtifacts: () => mockFuchsiaArtifacts, + FuchsiaArtifacts: () => FuchsiaArtifacts( + sshConfig: mockFile, + devFinder: mockFile, + ), }); group('device logs', () { @@ -211,8 +200,6 @@ void main() { }); } -class MockFuchsiaArtifacts extends Mock implements FuchsiaArtifacts {} - class MockProcessManager extends Mock implements ProcessManager {} class MockProcessResult extends Mock implements ProcessResult {} diff --git a/packages/flutter_tools/test/fuchsia/fuchsia_workflow_test.dart b/packages/flutter_tools/test/fuchsia/fuchsia_workflow_test.dart index 974c55f37d4..f7c2a4cf9dc 100644 --- a/packages/flutter_tools/test/fuchsia/fuchsia_workflow_test.dart +++ b/packages/flutter_tools/test/fuchsia/fuchsia_workflow_test.dart @@ -4,6 +4,7 @@ import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/os.dart'; +import 'package:flutter_tools/src/fuchsia/fuchsia_sdk.dart'; import 'package:flutter_tools/src/fuchsia/fuchsia_workflow.dart'; import 'package:mockito/mockito.dart'; @@ -14,28 +15,34 @@ class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {} class MockFile extends Mock implements File {} void main() { - bool fxPresent = false; - final MockOperatingSystemUtils utils = MockOperatingSystemUtils(); - final MockFile file = MockFile(); - when(utils.which('fx')).thenAnswer((Invocation _) => fxPresent ? file : null); - group('android workflow', () { - testUsingContext('can not list and launch devices if there is no `fx` command', () { - fxPresent = false; + 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', () { expect(fuchsiaWorkflow.canLaunchDevices, false); expect(fuchsiaWorkflow.canListDevices, false); expect(fuchsiaWorkflow.canListEmulators, false); }, overrides: { - OperatingSystemUtils: () => utils, + FuchsiaArtifacts: () => FuchsiaArtifacts(devFinder: null, sshConfig: null), + }); + + 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: { + FuchsiaArtifacts: () => FuchsiaArtifacts(devFinder: devFinder, sshConfig: null), }); testUsingContext('can list and launch devices supported if there is a `fx` command', () { - fxPresent = true; expect(fuchsiaWorkflow.canLaunchDevices, true); expect(fuchsiaWorkflow.canListDevices, true); expect(fuchsiaWorkflow.canListEmulators, false); }, overrides: { - OperatingSystemUtils: () => utils, + FuchsiaArtifacts: () => FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig), }); }); }