Support for fuchsia device discovery, workflow, and sdk wrapper (#23282)

This commit is contained in:
Jonah Williams 2018-10-22 16:48:17 -07:00 committed by GitHub
parent 43c99404c5
commit b7c9c96c6b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 218 additions and 0 deletions

View file

@ -26,6 +26,8 @@ import 'devfs.dart';
import 'device.dart';
import 'doctor.dart';
import 'emulator.dart';
import 'fuchsia/fuchsia_sdk.dart';
import 'fuchsia/fuchsia_workflow.dart';
import 'ios/cocoapods.dart';
import 'ios/ios_workflow.dart';
import 'ios/mac.dart';
@ -62,6 +64,8 @@ Future<T> runInContext<T>(
Doctor: () => const Doctor(),
DoctorValidatorsProvider: () => DoctorValidatorsProvider.defaultInstance,
EmulatorManager: () => EmulatorManager(),
FuchsiaSdk: () => FuchsiaSdk(),
FuchsiaWorkflow: () => FuchsiaWorkflow(),
Flags: () => const EmptyFlags(),
FlutterVersion: () => FlutterVersion(const Clock()),
GenSnapshot: () => const GenSnapshot(),

View file

@ -11,6 +11,8 @@ import 'base/context.dart';
import 'base/file_system.dart';
import 'base/utils.dart';
import 'build_info.dart';
import 'fuchsia/fuchsia_device.dart';
import 'globals.dart';
import 'ios/devices.dart';
import 'ios/simulators.dart';
@ -27,6 +29,7 @@ class DeviceManager {
_deviceDiscoverers.add(AndroidDevices());
_deviceDiscoverers.add(IOSDevices());
_deviceDiscoverers.add(IOSSimulators());
_deviceDiscoverers.add(FuchsiaDevices());
_deviceDiscoverers.add(FlutterTesterDevices());
}

View file

@ -19,6 +19,7 @@ import 'base/utils.dart';
import 'base/version.dart';
import 'cache.dart';
import 'device.dart';
import 'fuchsia/fuchsia_workflow.dart';
import 'globals.dart';
import 'intellij/intellij.dart';
import 'ios/ios_workflow.dart';
@ -80,6 +81,9 @@ class _DefaultDoctorValidatorsProvider implements DoctorValidatorsProvider {
if (androidWorkflow.appliesToHostPlatform)
_workflows.add(androidWorkflow);
if (fuchsiaWorkflow.appliesToHostPlatform)
_workflows.add(fuchsiaWorkflow);
}
return _workflows;
}

View file

@ -4,10 +4,16 @@
import 'dart:async';
import 'package:meta/meta.dart';
import '../application_package.dart';
import '../base/platform.dart';
import '../build_info.dart';
import '../device.dart';
import 'fuchsia_sdk.dart';
import 'fuchsia_workflow.dart';
/// Read the log for a particular device.
class _FuchsiaLogReader extends DeviceLogReader {
_FuchsiaLogReader(this._device);
@ -27,6 +33,49 @@ class _FuchsiaLogReader extends DeviceLogReader {
String toString() => name;
}
class FuchsiaDevices extends PollingDeviceDiscovery {
FuchsiaDevices() : super('Fuchsia devices');
@override
bool get supportsPlatform => platform.isLinux || platform.isMacOS;
@override
bool get canListAnything => fuchsiaWorkflow.canListDevices;
@override
Future<List<Device>> pollingGetDevices() async {
if (!fuchsiaWorkflow.canListDevices) {
return <Device>[];
}
final String text = await fuchsiaSdk.netls();
return parseFuchsiaDeviceOutput(text);
}
@override
Future<List<String>> getDiagnostics() async => const <String>[];
}
/// Parses output from the netls tool into fuchsia devices.
///
/// Example output:
/// $ ./netls
/// > device liliac-shore-only-last (fe80::82e4:da4d:fe81:227d/3)
@visibleForTesting
List<FuchsiaDevice> parseFuchsiaDeviceOutput(String text) {
final List<FuchsiaDevice> devices = <FuchsiaDevice>[];
for (String rawLine in text.trim().split('\n')) {
final String line = rawLine.trim();
if (!line.startsWith('device'))
continue;
// ['device', 'device name', '(id)']
final List<String> words = line.split(' ');
final String name = words[1];
final String id = words[2].substring(1, words[2].length - 1);
devices.add(FuchsiaDevice(id, name: name));
}
return devices;
}
class FuchsiaDevice extends Device {
FuchsiaDevice(String id, { this.name }) : super(id);

View file

@ -0,0 +1,54 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../base/common.dart';
import '../base/context.dart';
import '../base/process.dart';
/// The [FuchsiaSdk] instance.
FuchsiaSdk get fuchsiaSdk => context[FuchsiaSdk];
/// The Fuchsia SDK shell commands.
///
/// This workflow assumes development within the fuchsia source tree,
/// including a working fx command-line tool in the user's PATH.
class FuchsiaSdk {
/// 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
/// > fe80::9aaa:fcff:fe60:d3af%eth1
Future<String> netaddr() async {
try {
final RunResult process = await runAsync(<String>['fx', 'netaddr', '--fuchsia', '--nowait']);
return process.stdout;
} on ArgumentError catch (exception) {
throwToolExit('$exception');
}
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
/// > device liliac-shore-only-last (fe80::82e4:da4d:fe81:227d/3)
Future<String> netls() async {
try {
final RunResult process = await runAsync(
<String>['fx', 'netls', '--nowait']);
return process.stdout;
} on ArgumentError catch (exception) {
throwToolExit('$exception');
}
return null;
}
}

View file

@ -0,0 +1,34 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../base/context.dart';
import '../base/os.dart';
import '../base/platform.dart';
import '../doctor.dart';
/// The [FuchsiaWorkflow] instance.
FuchsiaWorkflow get fuchsiaWorkflow => context[FuchsiaWorkflow];
/// The Fuchsia-specific implementation of a [Workflow].
///
/// This workflow assumes development within the fuchsia source tree,
/// including a working fx command-line tool in the user's PATH.
class FuchsiaWorkflow implements Workflow {
@override
bool get appliesToHostPlatform => platform.isLinux || platform.isMacOS;
@override
bool get canListDevices {
return os.which('fx') != null;
}
@override
bool get canLaunchDevices {
return os.which('fx') != null;
}
@override
bool get canListEmulators => false;
}

View file

@ -0,0 +1,29 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter_tools/src/fuchsia/fuchsia_device.dart';
import '../src/common.dart';
import '../src/context.dart';
void main() {
group('fuchsia device', () {
testUsingContext('stores the requested id and name', () {
const String deviceId = 'e80::0000:a00a:f00f:2002/3';
const String name = 'halfbaked';
final FuchsiaDevice device = FuchsiaDevice(deviceId, name: name);
expect(device.id, deviceId);
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<FuchsiaDevice> devices = parseFuchsiaDeviceOutput(example);
expect(devices.length, 1);
expect(devices.first.id, 'fe80::0000:a00a:f00f:2002/3');
expect(devices.first.name, 'lilia-shore-only-last');
});
});
}

View file

@ -0,0 +1,41 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/fuchsia/fuchsia_workflow.dart';
import 'package:mockito/mockito.dart';
import '../src/common.dart';
import '../src/context.dart';
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;
expect(fuchsiaWorkflow.canLaunchDevices, false);
expect(fuchsiaWorkflow.canListDevices, false);
expect(fuchsiaWorkflow.canListEmulators, false);
}, overrides: <Type, Generator>{
OperatingSystemUtils: () => utils,
});
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: <Type, Generator>{
OperatingSystemUtils: () => utils,
});
});
}