[fuchsia] - migrate devicer discovery workflows to use ffx (#76241)
This commit is contained in:
parent
54455c706d
commit
f996033fcc
@ -13,7 +13,7 @@
|
||||
# The first and only parameter should be the path to the Fuchsia system image
|
||||
# tarball, e.g. `./run_fuchsia_tests.sh generic-x64.tgz`.
|
||||
#
|
||||
# This script expects `pm`, `device-finder`, and `fuchsia_ctl` to all be in the
|
||||
# This script expects `pm`, `ffx`, and `fuchsia_ctl` to all be in the
|
||||
# same directory as the script.
|
||||
#
|
||||
# This script also expects a private key available at:
|
||||
@ -44,7 +44,7 @@ fi
|
||||
# Wrapper function to pass common args to fuchsia_ctl.
|
||||
fuchsia_ctl() {
|
||||
$script_dir/fuchsia_ctl -d $device_name \
|
||||
--device-finder-path $script_dir/device-finder "$@"
|
||||
--ffx-path $script_dir/ffx "$@"
|
||||
}
|
||||
|
||||
reboot() {
|
||||
@ -115,6 +115,8 @@ EOF
|
||||
|
||||
export FUCHSIA_SSH_CONFIG=$script_dir/fuchsia_ssh_config
|
||||
|
||||
export FUCHSIA_ANALYTICS_DISABLED="1"
|
||||
|
||||
# Run the driver test
|
||||
echo "$(date) START:DRIVER_TEST -------------------------------------"
|
||||
flutter_dir=$script_dir/flutter
|
||||
|
@ -327,12 +327,12 @@ class FuchsiaDeviceDiscovery implements DeviceDiscovery {
|
||||
|
||||
FuchsiaDevice _workingDevice;
|
||||
|
||||
String get _devFinder {
|
||||
final String devFinder = path.join(getArtifactPath(), 'fuchsia', 'tools', 'device-finder');
|
||||
if (!File(devFinder).existsSync()) {
|
||||
throw FileSystemException("Couldn't find device-finder at location $devFinder");
|
||||
String get _ffx {
|
||||
final String ffx = path.join(getArtifactPath(), 'fuchsia', 'tools','x64', 'ffx');
|
||||
if (!File(ffx).existsSync()) {
|
||||
throw FileSystemException("Couldn't find ffx at location $ffx");
|
||||
}
|
||||
return devFinder;
|
||||
return ffx;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -378,7 +378,7 @@ class FuchsiaDeviceDiscovery implements DeviceDiscovery {
|
||||
|
||||
@override
|
||||
Future<List<String>> discoverDevices() async {
|
||||
final List<String> output = (await eval(_devFinder, <String>['list', '-full']))
|
||||
final List<String> output = (await eval(_ffx, <String>['target', 'list', '--format', 's']))
|
||||
.trim()
|
||||
.split('\n');
|
||||
|
||||
@ -396,16 +396,20 @@ class FuchsiaDeviceDiscovery implements DeviceDiscovery {
|
||||
final Map<String, HealthCheckResult> results = <String, HealthCheckResult>{};
|
||||
for (final String deviceId in await discoverDevices()) {
|
||||
try {
|
||||
StringBuffer stderr;
|
||||
final int resolveResult = await exec(
|
||||
_devFinder,
|
||||
_ffx,
|
||||
<String>[
|
||||
'resolve',
|
||||
'-device-limit',
|
||||
'1',
|
||||
'target',
|
||||
'list',
|
||||
'--format',
|
||||
'a',
|
||||
deviceId,
|
||||
]
|
||||
],
|
||||
stderr: stderr
|
||||
);
|
||||
if (resolveResult == 0) {
|
||||
final String stderrOutput = stderr.toString().trim();
|
||||
if (resolveResult == 0 && ! stderrOutput.contains('No devices found')) {
|
||||
results['fuchsia-device-$deviceId'] = HealthCheckResult.success();
|
||||
} else {
|
||||
results['fuchsia-device-$deviceId'] = HealthCheckResult.failure('Cannot resolve device $deviceId');
|
||||
|
@ -322,6 +322,7 @@ Future<int> exec(
|
||||
List<String> arguments, {
|
||||
Map<String, String> environment,
|
||||
bool canFail = false, // as in, whether failures are ok. False means that they are fatal.
|
||||
StringBuffer stderr, // if not null, the stderr will be written here
|
||||
String workingDirectory,
|
||||
}) async {
|
||||
return _execute(
|
||||
@ -329,6 +330,7 @@ Future<int> exec(
|
||||
arguments,
|
||||
environment: environment,
|
||||
canFail : canFail,
|
||||
stderr: stderr,
|
||||
workingDirectory: workingDirectory,
|
||||
);
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ final ArgParser parser = ArgParser()
|
||||
..addOption('entrypoint', defaultsTo: 'main.dart', help: 'The filename of the main method. Defaults to main.dart')
|
||||
..addOption('device', help: 'The device id to attach to')
|
||||
..addOption('dev-finder', help: 'The location of the device-finder binary')
|
||||
..addOption('ffx', help: 'The location of the ffx binary')
|
||||
..addFlag('verbose', negatable: true);
|
||||
|
||||
// Track the original working directory so that the tool can find the
|
||||
@ -48,6 +49,7 @@ Future<void> main(List<String> args) async {
|
||||
final File frontendServer = globals.fs.file('$buildDirectory/host_x64/gen/third_party/flutter/frontend_server/frontend_server_tool.snapshot');
|
||||
final File sshConfig = globals.fs.file('$buildDirectory/ssh-keys/ssh_config');
|
||||
final File devFinder = globals.fs.file(argResults['dev-finder']);
|
||||
final File ffx = globals.fs.file(argResults['ffx']);
|
||||
final File platformKernelDill = globals.fs.file('$buildDirectory/flutter_runner_patched_sdk/platform_strong.dill');
|
||||
final File flutterPatchedSdk = globals.fs.file('$buildDirectory/flutter_runner_patched_sdk');
|
||||
final String packages = '$buildDirectory/dartlang/gen/$path/${name}_dart_library.packages';
|
||||
@ -62,6 +64,10 @@ Future<void> main(List<String> args) async {
|
||||
print('Error: device-finder not found at ${devFinder.path}.');
|
||||
return 1;
|
||||
}
|
||||
if (!ffx.existsSync()) {
|
||||
print('Error: ffx not found at ${ffx.path}.');
|
||||
return 1;
|
||||
}
|
||||
if (!frontendServer.existsSync()) {
|
||||
print(
|
||||
'Error: frontend_server not found at ${frontendServer.path}. This '
|
||||
@ -107,7 +113,8 @@ Future<void> main(List<String> args) async {
|
||||
overrides: <Type, Generator>{
|
||||
FeatureFlags: () => const _FuchsiaFeatureFlags(),
|
||||
DeviceManager: () => _FuchsiaDeviceManager(),
|
||||
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig, devFinder: devFinder),
|
||||
FuchsiaArtifacts: () => FuchsiaArtifacts(
|
||||
sshConfig: sshConfig, devFinder: devFinder, ffx: ffx),
|
||||
Artifacts: () => OverrideArtifacts(
|
||||
parent: CachedArtifacts(
|
||||
fileSystem: globals.fs,
|
||||
|
@ -181,8 +181,11 @@ class FuchsiaDevices extends PollingDeviceDiscovery {
|
||||
if (!_fuchsiaWorkflow.canListDevices) {
|
||||
return <Device>[];
|
||||
}
|
||||
final List<String> text = (await _fuchsiaSdk.listDevices(timeout: timeout))
|
||||
?.split('\n');
|
||||
// TODO(omerlevran): Remove once soft transition is complete fxb/67602.
|
||||
final List<String> text = (await _fuchsiaSdk.listDevices(
|
||||
timeout: timeout,
|
||||
useDeviceFinder: _fuchsiaWorkflow.shouldUseDeviceFinder,
|
||||
))?.split('\n');
|
||||
if (text == null || text.isEmpty) {
|
||||
return <Device>[];
|
||||
}
|
||||
@ -208,9 +211,18 @@ class FuchsiaDevices extends PollingDeviceDiscovery {
|
||||
return null;
|
||||
}
|
||||
final String name = words[1];
|
||||
final String resolvedHost = await _fuchsiaSdk.fuchsiaDevFinder.resolve(
|
||||
name,
|
||||
);
|
||||
String resolvedHost;
|
||||
|
||||
// TODO(omerlevran): Remove once soft transition is complete fxb/67602.
|
||||
if (_fuchsiaWorkflow.shouldUseDeviceFinder) {
|
||||
// TODO(omerlevran): Add support for resolve on the FuchsiaSdk Object.
|
||||
resolvedHost = await _fuchsiaSdk.fuchsiaDevFinder.resolve(
|
||||
name,
|
||||
);
|
||||
} else {
|
||||
// TODO(omerlevran): Add support for resolve on the FuchsiaSdk Object.
|
||||
resolvedHost = await _fuchsiaSdk.fuchsiaFfx.resolve(name);
|
||||
}
|
||||
if (resolvedHost == null) {
|
||||
_logger.printError('Failed to resolve host for Fuchsia device `$name`');
|
||||
return null;
|
||||
|
101
packages/flutter_tools/lib/src/fuchsia/fuchsia_ffx.dart
Normal file
101
packages/flutter_tools/lib/src/fuchsia/fuchsia_ffx.dart
Normal file
@ -0,0 +1,101 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:process/process.dart';
|
||||
|
||||
import '../base/common.dart';
|
||||
import '../base/logger.dart';
|
||||
import '../base/process.dart';
|
||||
import 'fuchsia_sdk.dart';
|
||||
|
||||
// Usage: ffx [-c <config>] [-e <env>] [-t <target>] [-T <timeout>] [-v] [<command>] [<args>]
|
||||
|
||||
// Fuchsia's developer tool
|
||||
|
||||
// Options:
|
||||
// -c, --config override default configuration
|
||||
// -e, --env override default environment settings
|
||||
// -t, --target apply operations across single or multiple targets
|
||||
// -T, --timeout override default proxy timeout
|
||||
// -v, --verbose use verbose output
|
||||
// --help display usage information
|
||||
|
||||
// Commands:
|
||||
// config View and switch default and user configurations
|
||||
// daemon Interact with/control the ffx daemon
|
||||
// target Interact with a target device or emulator
|
||||
|
||||
/// A simple wrapper for the Fuchsia SDK's 'ffx' tool.
|
||||
class FuchsiaFfx {
|
||||
FuchsiaFfx({
|
||||
@required FuchsiaArtifacts fuchsiaArtifacts,
|
||||
@required Logger logger,
|
||||
@required ProcessManager processManager,
|
||||
}) : _fuchsiaArtifacts = fuchsiaArtifacts,
|
||||
_logger = logger,
|
||||
_processUtils =
|
||||
ProcessUtils(logger: logger, processManager: processManager);
|
||||
|
||||
final FuchsiaArtifacts _fuchsiaArtifacts;
|
||||
final Logger _logger;
|
||||
final ProcessUtils _processUtils;
|
||||
|
||||
/// Returns a list of attached devices as a list of strings with entries
|
||||
/// formatted as follows:
|
||||
///
|
||||
/// abcd::abcd:abc:abcd:abcd%qemu scare-cable-skip-joy
|
||||
Future<List<String>> list({Duration timeout}) async {
|
||||
if (_fuchsiaArtifacts.ffx == null || !_fuchsiaArtifacts.ffx.existsSync()) {
|
||||
throwToolExit('Fuchsia ffx tool not found.');
|
||||
}
|
||||
final List<String> command = <String>[
|
||||
_fuchsiaArtifacts.ffx.path,
|
||||
if (timeout != null)
|
||||
...<String>['-T', '${timeout.inSeconds}'],
|
||||
'target',
|
||||
'list',
|
||||
'--format',
|
||||
's'
|
||||
];
|
||||
final RunResult result = await _processUtils.run(command);
|
||||
if (result.exitCode != 0) {
|
||||
_logger.printError('ffx failed: ${result.stderr}');
|
||||
return null;
|
||||
}
|
||||
if (result.stderr.contains('No devices found')) {
|
||||
return null;
|
||||
}
|
||||
return result.stdout.split('\n');
|
||||
}
|
||||
|
||||
/// Returns the address of the named device.
|
||||
///
|
||||
/// The string [deviceName] should be the name of the device from the
|
||||
/// 'list' command, e.g. 'scare-cable-skip-joy'.
|
||||
Future<String> resolve(String deviceName) async {
|
||||
if (_fuchsiaArtifacts.ffx == null || !_fuchsiaArtifacts.ffx.existsSync()) {
|
||||
throwToolExit('Fuchsia ffx tool not found.');
|
||||
}
|
||||
final List<String> command = <String>[
|
||||
_fuchsiaArtifacts.ffx.path,
|
||||
'target',
|
||||
'list',
|
||||
'--format',
|
||||
'a',
|
||||
deviceName,
|
||||
];
|
||||
final RunResult result = await _processUtils.run(command);
|
||||
if (result.exitCode != 0) {
|
||||
_logger.printError('ffx failed: ${result.stderr}');
|
||||
return null;
|
||||
}
|
||||
if (result.stderr.contains('No devices found')) {
|
||||
return null;
|
||||
}
|
||||
return result.stdout.trim();
|
||||
}
|
||||
}
|
@ -106,7 +106,7 @@ class FuchsiaPM {
|
||||
///
|
||||
/// The argument [repoPath] should have previously been an argument to
|
||||
/// [newrepo]. The [host] should be the host reported by
|
||||
/// [FuchsiaDevFinder.resolve], and [port] should be an unused port for the
|
||||
/// [FuchsiaDevFinder.resolve] or [FuchsiaFfx.resolve] and [port] should be an unused port for the
|
||||
/// http server to bind.
|
||||
Future<Process> serve(String repoPath, String host, int port) async {
|
||||
if (globals.fuchsiaArtifacts.pm == null) {
|
||||
|
@ -14,6 +14,7 @@ import '../convert.dart';
|
||||
import '../globals.dart' as globals;
|
||||
|
||||
import 'fuchsia_dev_finder.dart';
|
||||
import 'fuchsia_ffx.dart';
|
||||
import 'fuchsia_kernel_compiler.dart';
|
||||
import 'fuchsia_pm.dart';
|
||||
|
||||
@ -48,18 +49,32 @@ class FuchsiaSdk {
|
||||
FuchsiaKernelCompiler get fuchsiaKernelCompiler =>
|
||||
_fuchsiaKernelCompiler ??= FuchsiaKernelCompiler();
|
||||
|
||||
/// Interface to the 'ffx' tool.
|
||||
FuchsiaFfx _fuchsiaFfx;
|
||||
FuchsiaFfx get fuchsiaFfx => _fuchsiaFfx ??= FuchsiaFfx(
|
||||
fuchsiaArtifacts: globals.fuchsiaArtifacts,
|
||||
logger: globals.logger,
|
||||
processManager: globals.processManager,
|
||||
);
|
||||
|
||||
/// Returns any attached devices is a newline-denominated String.
|
||||
///
|
||||
/// Example output:
|
||||
///
|
||||
/// $ device-finder list -full
|
||||
/// > 192.168.42.56 paper-pulp-bush-angel
|
||||
Future<String> listDevices({ Duration timeout }) async {
|
||||
if (globals.fuchsiaArtifacts.devFinder == null ||
|
||||
!globals.fuchsiaArtifacts.devFinder.existsSync()) {
|
||||
return null;
|
||||
/// Example output: abcd::abcd:abc:abcd:abcd%qemu scare-cable-skip-joy
|
||||
Future<String> listDevices({Duration timeout, bool useDeviceFinder = false}) async {
|
||||
List<String> devices;
|
||||
if (useDeviceFinder) {
|
||||
if (globals.fuchsiaArtifacts.devFinder == null ||
|
||||
!globals.fuchsiaArtifacts.devFinder.existsSync()) {
|
||||
return null;
|
||||
}
|
||||
devices = await fuchsiaDevFinder.list(timeout: timeout);
|
||||
} else {
|
||||
if (globals.fuchsiaArtifacts.ffx == null ||
|
||||
!globals.fuchsiaArtifacts.ffx.existsSync()) {
|
||||
return null;
|
||||
}
|
||||
devices = await fuchsiaFfx.list(timeout: timeout);
|
||||
}
|
||||
final List<String> devices = await fuchsiaDevFinder.list(timeout: timeout);
|
||||
if (devices == null) {
|
||||
return null;
|
||||
}
|
||||
@ -112,6 +127,7 @@ class FuchsiaArtifacts {
|
||||
FuchsiaArtifacts({
|
||||
this.sshConfig,
|
||||
this.devFinder,
|
||||
this.ffx,
|
||||
this.pm,
|
||||
});
|
||||
|
||||
@ -140,11 +156,13 @@ class FuchsiaArtifacts {
|
||||
final String fuchsia = globals.cache.getArtifactDirectory('fuchsia').path;
|
||||
final String tools = globals.fs.path.join(fuchsia, 'tools');
|
||||
final File devFinder = globals.fs.file(globals.fs.path.join(tools, 'device-finder'));
|
||||
final File ffx = globals.fs.file(globals.fs.path.join(tools, 'x64/ffx'));
|
||||
final File pm = globals.fs.file(globals.fs.path.join(tools, 'pm'));
|
||||
|
||||
return FuchsiaArtifacts(
|
||||
sshConfig: sshConfig,
|
||||
devFinder: devFinder.existsSync() ? devFinder : null,
|
||||
ffx: ffx.existsSync() ? ffx : null,
|
||||
pm: pm.existsSync() ? pm : null,
|
||||
);
|
||||
}
|
||||
@ -160,6 +178,10 @@ class FuchsiaArtifacts {
|
||||
/// Fuchsia devices.
|
||||
final File devFinder;
|
||||
|
||||
/// The location of the ffx tool used to locate connected
|
||||
/// Fuchsia devices.
|
||||
final File ffx;
|
||||
|
||||
/// The pm tool.
|
||||
final File pm;
|
||||
|
||||
|
@ -35,14 +35,29 @@ class FuchsiaWorkflow implements Workflow {
|
||||
@override
|
||||
bool get appliesToHostPlatform => _featureFlags.isFuchsiaEnabled && (_platform.isLinux || _platform.isMacOS);
|
||||
|
||||
bool get shouldUseDeviceFinder {
|
||||
final String useDeviceFinder = _platform.environment.containsKey('FUCHSIA_DISABLED_ffx_discovery')
|
||||
? _platform.environment['FUCHSIA_DISABLED_ffx_discovery'] : '0';
|
||||
if (useDeviceFinder == '1') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
bool get canListDevices {
|
||||
return _fuchsiaArtifacts.devFinder != null;
|
||||
if (shouldUseDeviceFinder) {
|
||||
return _fuchsiaArtifacts.devFinder != null;
|
||||
}
|
||||
return _fuchsiaArtifacts.ffx != null;
|
||||
}
|
||||
|
||||
@override
|
||||
bool get canLaunchDevices {
|
||||
return _fuchsiaArtifacts.devFinder != null && _fuchsiaArtifacts.sshConfig != null;
|
||||
if (shouldUseDeviceFinder) {
|
||||
return _fuchsiaArtifacts.devFinder != null && _fuchsiaArtifacts.sshConfig != null;
|
||||
}
|
||||
return _fuchsiaArtifacts.ffx != null && _fuchsiaArtifacts.sshConfig != null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -25,6 +25,7 @@ import 'package:flutter_tools/src/fuchsia/amber_ctl.dart';
|
||||
import 'package:flutter_tools/src/fuchsia/application_package.dart';
|
||||
import 'package:flutter_tools/src/fuchsia/fuchsia_dev_finder.dart';
|
||||
import 'package:flutter_tools/src/fuchsia/fuchsia_device.dart';
|
||||
import 'package:flutter_tools/src/fuchsia/fuchsia_ffx.dart';
|
||||
import 'package:flutter_tools/src/fuchsia/fuchsia_kernel_compiler.dart';
|
||||
import 'package:flutter_tools/src/fuchsia/fuchsia_pm.dart';
|
||||
import 'package:flutter_tools/src/fuchsia/fuchsia_sdk.dart';
|
||||
@ -103,17 +104,18 @@ void main() {
|
||||
expect(await fuchsiaDevices.pollingGetDevices(), isEmpty);
|
||||
});
|
||||
|
||||
testWithoutContext('can parse device-finder output for single device', () async {
|
||||
testWithoutContext('can parse ffx output for single device', () async {
|
||||
final MockFuchsiaWorkflow fuchsiaWorkflow = MockFuchsiaWorkflow();
|
||||
final MockFuchsiaSdk fuchsiaSdk = MockFuchsiaSdk();
|
||||
final FuchsiaDevices fuchsiaDevices = FuchsiaDevices(
|
||||
platform: FakePlatform(operatingSystem: 'linux'),
|
||||
platform: FakePlatform(operatingSystem: 'linux', environment: <String, String>{},),
|
||||
fuchsiaSdk: fuchsiaSdk,
|
||||
fuchsiaWorkflow: fuchsiaWorkflow,
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
when(fuchsiaWorkflow.shouldUseDeviceFinder).thenReturn(false);
|
||||
when(fuchsiaWorkflow.canListDevices).thenReturn(true);
|
||||
when(fuchsiaSdk.listDevices()).thenAnswer((Invocation invocation) async {
|
||||
when(fuchsiaSdk.listDevices(useDeviceFinder: false)).thenAnswer((Invocation invocation) async {
|
||||
return '2001:0db8:85a3:0000:0000:8a2e:0370:7334 paper-pulp-bush-angel';
|
||||
});
|
||||
|
||||
@ -123,7 +125,28 @@ void main() {
|
||||
expect(device.id, '192.168.42.10');
|
||||
});
|
||||
|
||||
testWithoutContext('can parse device-finder output for multiple devices', () async {
|
||||
testWithoutContext('can parse device-finder output for single device', () async {
|
||||
final MockFuchsiaWorkflow fuchsiaWorkflow = MockFuchsiaWorkflow();
|
||||
final MockFuchsiaSdk fuchsiaSdk = MockFuchsiaSdk();
|
||||
final FuchsiaDevices fuchsiaDevices = FuchsiaDevices(
|
||||
platform: FakePlatform(operatingSystem: 'linux', environment: <String, String>{'FUCHSIA_DISABLED_ffx_discovery': '1'},),
|
||||
fuchsiaSdk: fuchsiaSdk,
|
||||
fuchsiaWorkflow: fuchsiaWorkflow,
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
when(fuchsiaWorkflow.shouldUseDeviceFinder).thenReturn(true);
|
||||
when(fuchsiaWorkflow.canListDevices).thenReturn(true);
|
||||
when(fuchsiaSdk.listDevices(useDeviceFinder: true)).thenAnswer((Invocation invocation) async {
|
||||
return '2001:0db8:85a3:0000:0000:8a2e:0370:7334 paper-pulp-bush-angel';
|
||||
});
|
||||
|
||||
final Device device = (await fuchsiaDevices.pollingGetDevices()).single;
|
||||
|
||||
expect(device.name, 'paper-pulp-bush-angel');
|
||||
expect(device.id, '192.168.11.999');
|
||||
});
|
||||
|
||||
testWithoutContext('can parse ffx output for multiple devices', () async {
|
||||
final MockFuchsiaWorkflow fuchsiaWorkflow = MockFuchsiaWorkflow();
|
||||
final MockFuchsiaSdk fuchsiaSdk = MockFuchsiaSdk();
|
||||
final FuchsiaDevices fuchsiaDevices = FuchsiaDevices(
|
||||
@ -132,8 +155,9 @@ void main() {
|
||||
fuchsiaWorkflow: fuchsiaWorkflow,
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
when(fuchsiaWorkflow.shouldUseDeviceFinder).thenReturn(false);
|
||||
when(fuchsiaWorkflow.canListDevices).thenReturn(true);
|
||||
when(fuchsiaSdk.listDevices()).thenAnswer((Invocation invocation) async {
|
||||
when(fuchsiaSdk.listDevices(useDeviceFinder: false)).thenAnswer((Invocation invocation) async {
|
||||
return '2001:0db8:85a3:0000:0000:8a2e:0370:7334 paper-pulp-bush-angel\n'
|
||||
'2001:0db8:85a3:0000:0000:8a2e:0370:7335 foo-bar-fiz-buzz';
|
||||
});
|
||||
@ -146,7 +170,7 @@ void main() {
|
||||
expect(devices.last.id, '192.168.42.10');
|
||||
});
|
||||
|
||||
testWithoutContext('can parse junk output from the dev-finder', () async {
|
||||
testWithoutContext('can parse device-finder output for multiple devices', () async {
|
||||
final MockFuchsiaWorkflow fuchsiaWorkflow = MockFuchsiaWorkflow();
|
||||
final MockFuchsiaSdk fuchsiaSdk = MockFuchsiaSdk();
|
||||
final FuchsiaDevices fuchsiaDevices = FuchsiaDevices(
|
||||
@ -155,6 +179,31 @@ void main() {
|
||||
fuchsiaWorkflow: fuchsiaWorkflow,
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
when(fuchsiaWorkflow.shouldUseDeviceFinder).thenReturn(true);
|
||||
when(fuchsiaWorkflow.canListDevices).thenReturn(true);
|
||||
when(fuchsiaSdk.listDevices(useDeviceFinder: true)).thenAnswer((Invocation invocation) async {
|
||||
return '2001:0db8:85a3:0000:0000:8a2e:0370:7334 paper-pulp-bush-angel\n'
|
||||
'2001:0db8:85a3:0000:0000:8a2e:0370:7335 foo-bar-fiz-buzz';
|
||||
});
|
||||
|
||||
final List<Device> devices = await fuchsiaDevices.pollingGetDevices();
|
||||
|
||||
expect(devices.first.name, 'paper-pulp-bush-angel');
|
||||
expect(devices.first.id, '192.168.11.999');
|
||||
expect(devices.last.name, 'foo-bar-fiz-buzz');
|
||||
expect(devices.last.id, '192.168.11.999');
|
||||
});
|
||||
|
||||
testWithoutContext('can parse junk output from ffx', () async {
|
||||
final MockFuchsiaWorkflow fuchsiaWorkflow = MockFuchsiaWorkflow();
|
||||
final MockFuchsiaSdk fuchsiaSdk = MockFuchsiaSdk();
|
||||
final FuchsiaDevices fuchsiaDevices = FuchsiaDevices(
|
||||
platform: FakePlatform(operatingSystem: 'linux'),
|
||||
fuchsiaSdk: fuchsiaSdk,
|
||||
fuchsiaWorkflow: fuchsiaWorkflow,
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
when(fuchsiaWorkflow.shouldUseDeviceFinder).thenReturn(false);
|
||||
when(fuchsiaWorkflow.canListDevices).thenReturn(true);
|
||||
when(fuchsiaSdk.listDevices()).thenAnswer((Invocation invocation) async {
|
||||
return 'junk';
|
||||
@ -165,6 +214,26 @@ void main() {
|
||||
expect(devices, isEmpty);
|
||||
});
|
||||
|
||||
testWithoutContext('can parse junk output from device-finder', () async {
|
||||
final MockFuchsiaWorkflow fuchsiaWorkflow = MockFuchsiaWorkflow();
|
||||
final MockFuchsiaSdk fuchsiaSdk = MockFuchsiaSdk();
|
||||
final FuchsiaDevices fuchsiaDevices = FuchsiaDevices(
|
||||
platform: FakePlatform(operatingSystem: 'linux'),
|
||||
fuchsiaSdk: fuchsiaSdk,
|
||||
fuchsiaWorkflow: fuchsiaWorkflow,
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
when(fuchsiaWorkflow.shouldUseDeviceFinder).thenReturn(true);
|
||||
when(fuchsiaWorkflow.canListDevices).thenReturn(true);
|
||||
when(fuchsiaSdk.listDevices(useDeviceFinder: true)).thenAnswer((Invocation invocation) async {
|
||||
return 'junk';
|
||||
});
|
||||
|
||||
final List<Device> devices = await fuchsiaDevices.pollingGetDevices();
|
||||
|
||||
expect(devices, isEmpty);
|
||||
});
|
||||
|
||||
testUsingContext('disposing device disposes the portForwarder', () async {
|
||||
final MockPortForwarder mockPortForwarder = MockPortForwarder();
|
||||
final FuchsiaDevice device = FuchsiaDevice('123');
|
||||
@ -335,6 +404,7 @@ void main() {
|
||||
FuchsiaArtifacts: () => FuchsiaArtifacts(
|
||||
sshConfig: artifactFile,
|
||||
devFinder: artifactFile,
|
||||
ffx: artifactFile,
|
||||
),
|
||||
FuchsiaSdk: () => MockFuchsiaSdk(),
|
||||
});
|
||||
@ -355,6 +425,7 @@ void main() {
|
||||
StreamController<List<int>> stdout;
|
||||
StreamController<List<int>> stderr;
|
||||
File devFinder;
|
||||
File ffx;
|
||||
File sshConfig;
|
||||
|
||||
setUp(() {
|
||||
@ -370,6 +441,7 @@ void main() {
|
||||
when(mockProcess.stderr).thenAnswer((Invocation _) => stderr.stream);
|
||||
final FileSystem memoryFileSystem = MemoryFileSystem.test();
|
||||
devFinder = memoryFileSystem.file('device-finder')..writeAsStringSync('\n');
|
||||
ffx = memoryFileSystem.file('ffx')..writeAsStringSync('\n');
|
||||
sshConfig = memoryFileSystem.file('ssh_config')..writeAsStringSync('\n');
|
||||
});
|
||||
|
||||
@ -403,7 +475,7 @@ void main() {
|
||||
ProcessManager: () => mockProcessManager,
|
||||
SystemClock: () => SystemClock.fixed(DateTime(2018, 11, 9, 1, 25, 45)),
|
||||
FuchsiaArtifacts: () =>
|
||||
FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig),
|
||||
FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig, ffx: ffx),
|
||||
});
|
||||
|
||||
testUsingContext('cuts off prior logs', () async {
|
||||
@ -429,7 +501,7 @@ void main() {
|
||||
ProcessManager: () => mockProcessManager,
|
||||
SystemClock: () => SystemClock.fixed(DateTime(2018, 11, 9, 1, 29, 45)),
|
||||
FuchsiaArtifacts: () =>
|
||||
FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig),
|
||||
FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig, ffx: ffx),
|
||||
});
|
||||
|
||||
testUsingContext('can be parsed for all apps', () async {
|
||||
@ -458,7 +530,7 @@ void main() {
|
||||
ProcessManager: () => mockProcessManager,
|
||||
SystemClock: () => SystemClock.fixed(DateTime(2018, 11, 9, 1, 25, 45)),
|
||||
FuchsiaArtifacts: () =>
|
||||
FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig),
|
||||
FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig, ffx: ffx),
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1577,7 +1649,19 @@ class FailingKernelCompiler implements FuchsiaKernelCompiler {
|
||||
class FakeFuchsiaDevFinder implements FuchsiaDevFinder {
|
||||
@override
|
||||
Future<List<String>> list({ Duration timeout }) async {
|
||||
return <String>['192.168.42.172 scare-cable-skip-joy'];
|
||||
return <String>['192.168.11.999 scare-cable-device-finder'];
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> resolve(String deviceName) async {
|
||||
return '192.168.11.999';
|
||||
}
|
||||
}
|
||||
|
||||
class FakeFuchsiaFfx implements FuchsiaFfx {
|
||||
@override
|
||||
Future<List<String>> list({Duration timeout}) async {
|
||||
return <String>['192.168.42.172 scare-cable-skip-ffx'];
|
||||
}
|
||||
|
||||
@override
|
||||
@ -1591,9 +1675,11 @@ class MockFuchsiaSdk extends Mock implements FuchsiaSdk {
|
||||
FuchsiaPM pm,
|
||||
FuchsiaKernelCompiler compiler,
|
||||
FuchsiaDevFinder devFinder,
|
||||
FuchsiaFfx ffx,
|
||||
}) : fuchsiaPM = pm ?? FakeFuchsiaPM(),
|
||||
fuchsiaKernelCompiler = compiler ?? FakeFuchsiaKernelCompiler(),
|
||||
fuchsiaDevFinder = devFinder ?? FakeFuchsiaDevFinder();
|
||||
fuchsiaDevFinder = devFinder ?? FakeFuchsiaDevFinder(),
|
||||
fuchsiaFfx = ffx ?? FakeFuchsiaFfx();
|
||||
|
||||
@override
|
||||
final FuchsiaPM fuchsiaPM;
|
||||
@ -1603,6 +1689,9 @@ class MockFuchsiaSdk extends Mock implements FuchsiaSdk {
|
||||
|
||||
@override
|
||||
final FuchsiaDevFinder fuchsiaDevFinder;
|
||||
|
||||
@override
|
||||
final FuchsiaFfx fuchsiaFfx;
|
||||
}
|
||||
|
||||
class MockDartDevelopmentService extends Mock implements DartDevelopmentService {}
|
||||
|
@ -0,0 +1,138 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:file/file.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/fuchsia/fuchsia_ffx.dart';
|
||||
import 'package:flutter_tools/src/fuchsia/fuchsia_sdk.dart';
|
||||
import 'package:process/process.dart';
|
||||
import 'package:test/fake.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
|
||||
void main() {
|
||||
FakeFuchsiaArtifacts fakeFuchsiaArtifacts;
|
||||
BufferLogger logger;
|
||||
MemoryFileSystem memoryFileSystem;
|
||||
File ffx;
|
||||
|
||||
setUp(() {
|
||||
fakeFuchsiaArtifacts = FakeFuchsiaArtifacts();
|
||||
memoryFileSystem = MemoryFileSystem.test();
|
||||
logger = BufferLogger.test();
|
||||
ffx = memoryFileSystem.file('ffx');
|
||||
fakeFuchsiaArtifacts.ffx = ffx;
|
||||
});
|
||||
|
||||
group('ffx list', () {
|
||||
testWithoutContext('ffx not found', () {
|
||||
final FuchsiaFfx fuchsiaFfx = FuchsiaFfx(
|
||||
fuchsiaArtifacts: fakeFuchsiaArtifacts,
|
||||
logger: logger,
|
||||
processManager: FakeProcessManager.any(),
|
||||
);
|
||||
|
||||
expect(() async => await fuchsiaFfx.list(),
|
||||
throwsToolExit(message: 'Fuchsia ffx tool not found.'));
|
||||
});
|
||||
|
||||
testWithoutContext('no device found', () async {
|
||||
ffx.createSync();
|
||||
|
||||
final ProcessManager processManager =
|
||||
FakeProcessManager.list(<FakeCommand>[
|
||||
FakeCommand(
|
||||
command: <String>[ffx.path, 'target', 'list', '--format', 's'],
|
||||
exitCode: 0,
|
||||
stderr: 'No devices found.',
|
||||
),
|
||||
]);
|
||||
|
||||
final FuchsiaFfx fuchsiaFfx = FuchsiaFfx(
|
||||
fuchsiaArtifacts: fakeFuchsiaArtifacts,
|
||||
logger: logger,
|
||||
processManager: processManager,
|
||||
);
|
||||
|
||||
expect(await fuchsiaFfx.list(), isNull);
|
||||
expect(logger.errorText, isEmpty);
|
||||
});
|
||||
|
||||
testWithoutContext('error', () async {
|
||||
ffx.createSync();
|
||||
|
||||
final ProcessManager processManager =
|
||||
FakeProcessManager.list(<FakeCommand>[
|
||||
FakeCommand(
|
||||
command: <String>[ffx.path, 'target', 'list', '--format', 's'],
|
||||
exitCode: 1,
|
||||
stderr: 'unexpected error',
|
||||
),
|
||||
]);
|
||||
|
||||
final FuchsiaFfx fuchsiaFfx = FuchsiaFfx(
|
||||
fuchsiaArtifacts: fakeFuchsiaArtifacts,
|
||||
logger: logger,
|
||||
processManager: processManager,
|
||||
);
|
||||
|
||||
expect(await fuchsiaFfx.list(), isNull);
|
||||
expect(logger.errorText, contains('unexpected error'));
|
||||
});
|
||||
|
||||
testWithoutContext('devices found', () async {
|
||||
ffx.createSync();
|
||||
|
||||
final ProcessManager processManager =
|
||||
FakeProcessManager.list(<FakeCommand>[
|
||||
FakeCommand(
|
||||
command: <String>[ffx.path, 'target', 'list', '--format', 's'],
|
||||
exitCode: 0,
|
||||
stdout: 'device1\ndevice2',
|
||||
),
|
||||
]);
|
||||
|
||||
final FuchsiaFfx fuchsiaFfx = FuchsiaFfx(
|
||||
fuchsiaArtifacts: fakeFuchsiaArtifacts,
|
||||
logger: logger,
|
||||
processManager: processManager,
|
||||
);
|
||||
|
||||
expect(await fuchsiaFfx.list(), <String>['device1', 'device2']);
|
||||
expect(logger.errorText, isEmpty);
|
||||
});
|
||||
|
||||
testWithoutContext('timeout', () async {
|
||||
ffx.createSync();
|
||||
|
||||
final ProcessManager processManager =
|
||||
FakeProcessManager.list(<FakeCommand>[
|
||||
FakeCommand(
|
||||
command: <String>[ffx.path, '-T', '2', 'target', 'list', '--format', 's'],
|
||||
exitCode: 0,
|
||||
stdout: 'device1',
|
||||
),
|
||||
]);
|
||||
|
||||
final FuchsiaFfx fuchsiaFfx = FuchsiaFfx(
|
||||
fuchsiaArtifacts: fakeFuchsiaArtifacts,
|
||||
logger: logger,
|
||||
processManager: processManager,
|
||||
);
|
||||
|
||||
expect(await fuchsiaFfx.list(timeout: const Duration(seconds: 2)),
|
||||
<String>['device1']);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class FakeFuchsiaArtifacts extends Fake implements FuchsiaArtifacts {
|
||||
@override
|
||||
File ffx;
|
||||
}
|
@ -17,6 +17,7 @@ void main() {
|
||||
final FileSystem fileSystem = MemoryFileSystem.test();
|
||||
final File devFinder = fileSystem.file('dev_finder');
|
||||
final File sshConfig = fileSystem.file('ssh_config');
|
||||
final File ffx = fileSystem.file('ffx');
|
||||
|
||||
testWithoutContext('Fuchsia workflow does not apply to host platform if feature is disabled', () {
|
||||
final FuchsiaWorkflow fuchsiaWorkflow = FuchsiaWorkflow(
|
||||
@ -38,11 +39,11 @@ void main() {
|
||||
expect(fuchsiaWorkflow.appliesToHostPlatform, false);
|
||||
});
|
||||
|
||||
testWithoutContext('Fuchsia workflow can not list and launch devices if there is no ssh config and dev finder', () {
|
||||
testWithoutContext('Fuchsia workflow can not list and launch devices if there is no ffx when using default workflow', () {
|
||||
final FuchsiaWorkflow fuchsiaWorkflow = FuchsiaWorkflow(
|
||||
featureFlags: TestFeatureFlags(),
|
||||
fuchsiaArtifacts: FuchsiaArtifacts(devFinder: null, sshConfig: null),
|
||||
platform: FakePlatform(operatingSystem: 'linux'),
|
||||
fuchsiaArtifacts: FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig, ffx: null),
|
||||
platform: FakePlatform(operatingSystem: 'linux', environment: <String, String>{}),
|
||||
);
|
||||
|
||||
expect(fuchsiaWorkflow.canLaunchDevices, false);
|
||||
@ -50,11 +51,23 @@ void main() {
|
||||
expect(fuchsiaWorkflow.canListEmulators, false);
|
||||
});
|
||||
|
||||
testWithoutContext('Fuchsia workflow can not list and launch devices if there is no ssh config and dev finder', () {
|
||||
testWithoutContext('Fuchsia workflow can not list and launch devices if there is no dev finder when ffx is disabled', () {
|
||||
final FuchsiaWorkflow fuchsiaWorkflow = FuchsiaWorkflow(
|
||||
featureFlags: TestFeatureFlags(),
|
||||
fuchsiaArtifacts: FuchsiaArtifacts(devFinder: devFinder, sshConfig: null),
|
||||
platform: FakePlatform(operatingSystem: 'linux'),
|
||||
fuchsiaArtifacts: FuchsiaArtifacts(devFinder: null, sshConfig: sshConfig, ffx: ffx),
|
||||
platform: FakePlatform(operatingSystem: 'linux', environment: <String, String>{'FUCHSIA_DISABLED_ffx_discovery': '1'}),
|
||||
);
|
||||
|
||||
expect(fuchsiaWorkflow.canLaunchDevices, false);
|
||||
expect(fuchsiaWorkflow.canListDevices, false);
|
||||
expect(fuchsiaWorkflow.canListEmulators, false);
|
||||
});
|
||||
|
||||
testWithoutContext('Fuchsia workflow can not launch devices if there is no ssh config when using default workflow', () {
|
||||
final FuchsiaWorkflow fuchsiaWorkflow = FuchsiaWorkflow(
|
||||
featureFlags: TestFeatureFlags(),
|
||||
fuchsiaArtifacts: FuchsiaArtifacts(sshConfig: null, ffx: ffx),
|
||||
platform: FakePlatform(operatingSystem: 'linux', environment: <String, String>{}),
|
||||
);
|
||||
|
||||
expect(fuchsiaWorkflow.canLaunchDevices, false);
|
||||
@ -62,11 +75,35 @@ void main() {
|
||||
expect(fuchsiaWorkflow.canListEmulators, false);
|
||||
});
|
||||
|
||||
testWithoutContext('Fuchsia workflow can list and launch devices supported with sufficient SDK artifacts', () {
|
||||
testWithoutContext('Fuchsia workflow can not launch devices if there is no ssh config when ffx is disabled', () {
|
||||
final FuchsiaWorkflow fuchsiaWorkflow = FuchsiaWorkflow(
|
||||
featureFlags: TestFeatureFlags(),
|
||||
fuchsiaArtifacts: FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig),
|
||||
platform: FakePlatform(operatingSystem: 'linux'),
|
||||
fuchsiaArtifacts: FuchsiaArtifacts(sshConfig: null, devFinder: devFinder),
|
||||
platform: FakePlatform(operatingSystem: 'linux', environment: <String, String>{'FUCHSIA_DISABLED_ffx_discovery': '1'}),
|
||||
);
|
||||
|
||||
expect(fuchsiaWorkflow.canLaunchDevices, false);
|
||||
expect(fuchsiaWorkflow.canListDevices, true);
|
||||
expect(fuchsiaWorkflow.canListEmulators, false);
|
||||
});
|
||||
|
||||
testWithoutContext('Fuchsia workflow can list and launch devices supported with sufficient SDK artifacts when using default workflow', () {
|
||||
final FuchsiaWorkflow fuchsiaWorkflow = FuchsiaWorkflow(
|
||||
featureFlags: TestFeatureFlags(),
|
||||
fuchsiaArtifacts: FuchsiaArtifacts(devFinder: null, sshConfig: sshConfig, ffx: ffx),
|
||||
platform: FakePlatform(operatingSystem: 'linux', environment: <String, String>{}),
|
||||
);
|
||||
|
||||
expect(fuchsiaWorkflow.canLaunchDevices, true);
|
||||
expect(fuchsiaWorkflow.canListDevices, true);
|
||||
expect(fuchsiaWorkflow.canListEmulators, false);
|
||||
});
|
||||
|
||||
testWithoutContext('Fuchsia workflow can list and launch devices supported with sufficient SDK artifacts when ffx is disabled', () {
|
||||
final FuchsiaWorkflow fuchsiaWorkflow = FuchsiaWorkflow(
|
||||
featureFlags: TestFeatureFlags(),
|
||||
fuchsiaArtifacts: FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig, ffx: null),
|
||||
platform: FakePlatform(operatingSystem: 'linux', environment: <String, String>{'FUCHSIA_DISABLED_ffx_discovery': '1'}),
|
||||
);
|
||||
|
||||
expect(fuchsiaWorkflow.canLaunchDevices, true);
|
||||
@ -77,8 +114,8 @@ void main() {
|
||||
testWithoutContext('Fuchsia workflow can list and launch devices supported with sufficient SDK artifacts on macOS', () {
|
||||
final FuchsiaWorkflow fuchsiaWorkflow = FuchsiaWorkflow(
|
||||
featureFlags: TestFeatureFlags(),
|
||||
fuchsiaArtifacts: FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig),
|
||||
platform: FakePlatform(operatingSystem: 'macOS'),
|
||||
fuchsiaArtifacts: FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig, ffx: ffx),
|
||||
platform: FakePlatform(operatingSystem: 'macOS', environment: <String, String>{}),
|
||||
);
|
||||
|
||||
expect(fuchsiaWorkflow.canLaunchDevices, true);
|
||||
|
Loading…
x
Reference in New Issue
Block a user