mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Reland: Switch to dev_finder (#26250)
This commit is contained in:
parent
6f1d10b71a
commit
32041c0c9c
@ -41,6 +41,7 @@ Future<void> main(List<String> args) async {
|
|||||||
final String buildDirectory = argResults['build-dir'];
|
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 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 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 platformKernelDill = fs.file('$buildDirectory/flutter_runner_patched_sdk/platform_strong.dill');
|
||||||
final File flutterPatchedSdk = fs.file('$buildDirectory/flutter_runner_patched_sdk');
|
final File flutterPatchedSdk = fs.file('$buildDirectory/flutter_runner_patched_sdk');
|
||||||
final String packages = '$buildDirectory/dartlang/gen/$path/${name}_dart_library.packages';
|
final String packages = '$buildDirectory/dartlang/gen/$path/${name}_dart_library.packages';
|
||||||
@ -91,7 +92,7 @@ Future<void> main(List<String> args) async {
|
|||||||
muteCommandLogging: false,
|
muteCommandLogging: false,
|
||||||
verboseHelp: false,
|
verboseHelp: false,
|
||||||
overrides: <Type, Generator>{
|
overrides: <Type, Generator>{
|
||||||
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
|
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig, devFinder: devFinder),
|
||||||
Artifacts: () => OverrideArtifacts(
|
Artifacts: () => OverrideArtifacts(
|
||||||
parent: CachedArtifacts(),
|
parent: CachedArtifacts(),
|
||||||
frontendServer: frontendServer,
|
frontendServer: frontendServer,
|
||||||
|
@ -108,12 +108,8 @@ class FuchsiaDevices extends PollingDeviceDiscovery {
|
|||||||
if (!fuchsiaWorkflow.canListDevices) {
|
if (!fuchsiaWorkflow.canListDevices) {
|
||||||
return <Device>[];
|
return <Device>[];
|
||||||
}
|
}
|
||||||
final String text = await fuchsiaSdk.netls();
|
final String text = await fuchsiaSdk.listDevices();
|
||||||
final List<FuchsiaDevice> devices = <FuchsiaDevice>[];
|
final List<FuchsiaDevice> devices = parseListDevices(text);
|
||||||
for (String name in parseFuchsiaDeviceOutput(text)) {
|
|
||||||
final String id = await fuchsiaSdk.netaddr();
|
|
||||||
devices.add(FuchsiaDevice(id, name: name));
|
|
||||||
}
|
|
||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,24 +117,18 @@ class FuchsiaDevices extends PollingDeviceDiscovery {
|
|||||||
Future<List<String>> getDiagnostics() async => const <String>[];
|
Future<List<String>> getDiagnostics() async => const <String>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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
|
@visibleForTesting
|
||||||
List<String> parseFuchsiaDeviceOutput(String text) {
|
List<FuchsiaDevice> parseListDevices(String text) {
|
||||||
final List<String> names = <String>[];
|
final List<FuchsiaDevice> devices = <FuchsiaDevice>[];
|
||||||
for (String rawLine in text.trim().split('\n')) {
|
for (String rawLine in text.trim().split('\n')) {
|
||||||
final String line = rawLine.trim();
|
final String line = rawLine.trim();
|
||||||
if (!line.startsWith('device'))
|
// ['ip', 'device name']
|
||||||
continue;
|
|
||||||
// ['device', 'device name', '(id)']
|
|
||||||
final List<String> words = line.split(' ');
|
final List<String> words = line.split(' ');
|
||||||
final String name = words[1];
|
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 {
|
class FuchsiaDevice extends Device {
|
||||||
|
@ -9,7 +9,6 @@ import '../base/common.dart';
|
|||||||
import '../base/context.dart';
|
import '../base/context.dart';
|
||||||
import '../base/file_system.dart';
|
import '../base/file_system.dart';
|
||||||
import '../base/io.dart';
|
import '../base/io.dart';
|
||||||
import '../base/platform.dart';
|
|
||||||
import '../base/process.dart';
|
import '../base/process.dart';
|
||||||
import '../base/process_manager.dart';
|
import '../base/process_manager.dart';
|
||||||
|
|
||||||
@ -24,21 +23,15 @@ FuchsiaArtifacts get fuchsiaArtifacts => context[FuchsiaArtifacts];
|
|||||||
/// This workflow assumes development within the fuchsia source tree,
|
/// This workflow assumes development within the fuchsia source tree,
|
||||||
/// including a working fx command-line tool in the user's PATH.
|
/// including a working fx command-line tool in the user's PATH.
|
||||||
class FuchsiaSdk {
|
class FuchsiaSdk {
|
||||||
static const List<String> _netaddrCommand = <String>['fx', 'netaddr', '--fuchsia', '--nowait'];
|
|
||||||
static const List<String> _netlsCommand = <String>['fx', 'netls', '--nowait'];
|
|
||||||
static const List<String> _syslogCommand = <String>['fx', 'syslog', '--clock', 'Local'];
|
static const List<String> _syslogCommand = <String>['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:
|
/// Example output:
|
||||||
/// $ fx netaddr --fuchsia --nowait
|
/// $ dev_finder list -full
|
||||||
/// > fe80::9aaa:fcff:fe60:d3af%eth1
|
/// > 192.168.42.56 paper-pulp-bush-angel
|
||||||
Future<String> netaddr() async {
|
Future<String> listDevices() async {
|
||||||
try {
|
try {
|
||||||
final RunResult process = await runAsync(_netaddrCommand);
|
final String path = fuchsiaArtifacts.devFinder.absolute.path;
|
||||||
|
final RunResult process = await runAsync(<String>[path, 'list', '-full']);
|
||||||
return process.stdout.trim();
|
return process.stdout.trim();
|
||||||
} on ArgumentError catch (exception) {
|
} on ArgumentError catch (exception) {
|
||||||
throwToolExit('$exception');
|
throwToolExit('$exception');
|
||||||
@ -69,49 +62,18 @@ class FuchsiaSdk {
|
|||||||
}
|
}
|
||||||
return null;
|
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<String> 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.
|
/// Fuchsia-specific artifacts used to interact with a device.
|
||||||
class FuchsiaArtifacts {
|
class FuchsiaArtifacts {
|
||||||
/// Creates a new [FuchsiaArtifacts].
|
/// Creates a new [FuchsiaArtifacts].
|
||||||
///
|
FuchsiaArtifacts({this.sshConfig, this.devFinder});
|
||||||
/// May optionally provide a file `sshConfig` file.
|
|
||||||
FuchsiaArtifacts({File sshConfig})
|
|
||||||
: _sshConfig = sshConfig;
|
|
||||||
|
|
||||||
/// The location of the SSH configuration file used to interact with a
|
/// The location of the SSH configuration file used to interact with a
|
||||||
/// fuchsia device.
|
/// Fuchsia device.
|
||||||
///
|
final File sshConfig;
|
||||||
/// Requires the env variable `BUILD_DIR` to be set if not provided by
|
|
||||||
/// the constructor.
|
/// The location of the dev finder tool used to locate connected
|
||||||
File get sshConfig {
|
/// Fuchsia devices.
|
||||||
if (_sshConfig == null) {
|
final File devFinder;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import '../base/context.dart';
|
import '../base/context.dart';
|
||||||
import '../base/os.dart';
|
|
||||||
import '../base/platform.dart';
|
import '../base/platform.dart';
|
||||||
import '../doctor.dart';
|
import '../doctor.dart';
|
||||||
|
import 'fuchsia_sdk.dart';
|
||||||
|
|
||||||
/// The [FuchsiaWorkflow] instance.
|
/// The [FuchsiaWorkflow] instance.
|
||||||
FuchsiaWorkflow get fuchsiaWorkflow => context[FuchsiaWorkflow];
|
FuchsiaWorkflow get fuchsiaWorkflow => context[FuchsiaWorkflow];
|
||||||
@ -21,12 +21,12 @@ class FuchsiaWorkflow implements Workflow {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool get canListDevices {
|
bool get canListDevices {
|
||||||
return os.which('fx') != null;
|
return fuchsiaArtifacts.devFinder != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool get canLaunchDevices {
|
bool get canLaunchDevices {
|
||||||
return os.which('fx') != null;
|
return fuchsiaArtifacts.devFinder != null && fuchsiaArtifacts.sshConfig != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -29,12 +29,13 @@ void main() {
|
|||||||
expect(device.name, name);
|
expect(device.name, name);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('parse netls log output', () {
|
test('parse dev_finder output', () {
|
||||||
const String example = 'device lilia-shore-only-last (fe80::0000:a00a:f00f:2002/3)';
|
const String example = '192.168.42.56 paper-pulp-bush-angel';
|
||||||
final List<String> names = parseFuchsiaDeviceOutput(example);
|
final List<FuchsiaDevice> names = parseListDevices(example);
|
||||||
|
|
||||||
expect(names.length, 1);
|
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 {
|
test('default capabilities', () async {
|
||||||
@ -50,7 +51,6 @@ void main() {
|
|||||||
group('displays friendly error when', () {
|
group('displays friendly error when', () {
|
||||||
final MockProcessManager mockProcessManager = MockProcessManager();
|
final MockProcessManager mockProcessManager = MockProcessManager();
|
||||||
final MockProcessResult mockProcessResult = MockProcessResult();
|
final MockProcessResult mockProcessResult = MockProcessResult();
|
||||||
final MockFuchsiaArtifacts mockFuchsiaArtifacts = MockFuchsiaArtifacts();
|
|
||||||
final MockFile mockFile = MockFile();
|
final MockFile mockFile = MockFile();
|
||||||
when(mockProcessManager.run(
|
when(mockProcessManager.run(
|
||||||
any,
|
any,
|
||||||
@ -60,23 +60,9 @@ void main() {
|
|||||||
when(mockProcessResult.exitCode).thenReturn(1);
|
when(mockProcessResult.exitCode).thenReturn(1);
|
||||||
when<String>(mockProcessResult.stdout).thenReturn('');
|
when<String>(mockProcessResult.stdout).thenReturn('');
|
||||||
when<String>(mockProcessResult.stderr).thenReturn('');
|
when<String>(mockProcessResult.stderr).thenReturn('');
|
||||||
when(mockFuchsiaArtifacts.sshConfig).thenReturn(mockFile);
|
|
||||||
when(mockFile.absolute).thenReturn(mockFile);
|
when(mockFile.absolute).thenReturn(mockFile);
|
||||||
when(mockFile.path).thenReturn('');
|
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: <Type, Generator>{
|
|
||||||
ProcessManager: () => mockProcessManager,
|
|
||||||
});
|
|
||||||
|
|
||||||
final MockProcessManager emptyStdoutProcessManager = MockProcessManager();
|
final MockProcessManager emptyStdoutProcessManager = MockProcessManager();
|
||||||
final MockProcessResult emptyStdoutProcessResult = MockProcessResult();
|
final MockProcessResult emptyStdoutProcessResult = MockProcessResult();
|
||||||
when(emptyStdoutProcessManager.run(
|
when(emptyStdoutProcessManager.run(
|
||||||
@ -99,7 +85,10 @@ void main() {
|
|||||||
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>{
|
}, overrides: <Type, Generator>{
|
||||||
ProcessManager: () => emptyStdoutProcessManager,
|
ProcessManager: () => emptyStdoutProcessManager,
|
||||||
FuchsiaArtifacts: () => mockFuchsiaArtifacts,
|
FuchsiaArtifacts: () => FuchsiaArtifacts(
|
||||||
|
sshConfig: mockFile,
|
||||||
|
devFinder: mockFile,
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
group('device logs', () {
|
group('device logs', () {
|
||||||
@ -211,8 +200,6 @@ void main() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockFuchsiaArtifacts extends Mock implements FuchsiaArtifacts {}
|
|
||||||
|
|
||||||
class MockProcessManager extends Mock implements ProcessManager {}
|
class MockProcessManager extends Mock implements ProcessManager {}
|
||||||
|
|
||||||
class MockProcessResult extends Mock implements ProcessResult {}
|
class MockProcessResult extends Mock implements ProcessResult {}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
import 'package:flutter_tools/src/base/file_system.dart';
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
import 'package:flutter_tools/src/base/os.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:flutter_tools/src/fuchsia/fuchsia_workflow.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
import 'package:mockito/mockito.dart';
|
||||||
|
|
||||||
@ -14,28 +15,34 @@ class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {}
|
|||||||
class MockFile extends Mock implements File {}
|
class MockFile extends Mock implements File {}
|
||||||
|
|
||||||
void main() {
|
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', () {
|
group('android workflow', () {
|
||||||
testUsingContext('can not list and launch devices if there is no `fx` command', () {
|
final MockFile devFinder = MockFile();
|
||||||
fxPresent = false;
|
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.canLaunchDevices, false);
|
||||||
expect(fuchsiaWorkflow.canListDevices, false);
|
expect(fuchsiaWorkflow.canListDevices, false);
|
||||||
expect(fuchsiaWorkflow.canListEmulators, false);
|
expect(fuchsiaWorkflow.canListEmulators, false);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
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: <Type, Generator>{
|
||||||
|
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 if there is a `fx` command', () {
|
||||||
fxPresent = true;
|
|
||||||
expect(fuchsiaWorkflow.canLaunchDevices, true);
|
expect(fuchsiaWorkflow.canLaunchDevices, true);
|
||||||
expect(fuchsiaWorkflow.canListDevices, true);
|
expect(fuchsiaWorkflow.canListDevices, true);
|
||||||
expect(fuchsiaWorkflow.canListEmulators, false);
|
expect(fuchsiaWorkflow.canListEmulators, false);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
OperatingSystemUtils: () => utils,
|
FuchsiaArtifacts: () => FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user