[flutter_tool] Improve Fuchsia 'run' tests (#33263)
diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_dev_finder.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_dev_finder.dart
index a110ac8..b3a9b77 100644
--- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_dev_finder.dart
+++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_dev_finder.dart
@@ -4,6 +4,7 @@
import '../base/common.dart';
import '../base/process.dart';
+import '../globals.dart';
import 'fuchsia_sdk.dart';
// Usage: dev_finder <flags> <subcommand> <subcommand args>
@@ -31,7 +32,11 @@
'-full'
];
final RunResult result = await runAsync(command);
- return (result.exitCode == 0) ? result.stdout.split('\n') : null;
+ if (result.exitCode != 0) {
+ printError('dev_finder failed: ${result.stderr}');
+ return null;
+ }
+ return result.stdout.split('\n');
}
/// Returns the host address by which the device [deviceName] should use for
@@ -51,6 +56,10 @@
deviceName
];
final RunResult result = await runAsync(command);
- return (result.exitCode == 0) ? result.stdout.trim() : null;
+ if (result.exitCode != 0) {
+ printError('dev_finder failed: ${result.stderr}');
+ return null;
+ }
+ return result.stdout.trim();
}
}
diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
index b48aac8..3a82092 100644
--- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
+++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
@@ -44,9 +44,6 @@
FuchsiaTilesCtl get tilesCtl => _tilesCtl ??= FuchsiaTilesCtl();
}
-final FuchsiaAmberCtl _amberCtl = fuchsiaDeviceTools.amberCtl;
-final FuchsiaTilesCtl _tilesCtl = fuchsiaDeviceTools.tilesCtl;
-
final String _ipv4Loopback = InternetAddress.loopbackIPv4.address;
final String _ipv6Loopback = InternetAddress.loopbackIPv6.address;
@@ -233,6 +230,10 @@
await stopApp(package);
// Find out who the device thinks we are.
final String host = await fuchsiaSdk.fuchsiaDevFinder.resolve(name);
+ if (host == null) {
+ printError('Failed to resolve host for Fuchsia device');
+ return LaunchResult.failed();
+ }
final int port = await os.findFreePort();
if (port == 0) {
printError('Failed to find a free port');
@@ -265,14 +266,14 @@
}
// Teach amber about the package server.
- if (!await _amberCtl.addSrc(this, fuchsiaPackageServer)) {
+ if (!await fuchsiaDeviceTools.amberCtl.addSrc(this, fuchsiaPackageServer)) {
printError('Failed to teach amber about the package server');
return LaunchResult.failed();
}
serverRegistered = true;
// Tell amber to prefetch the app.
- if (!await _amberCtl.getUp(this, appName)) {
+ if (!await fuchsiaDeviceTools.amberCtl.getUp(this, appName)) {
printError('Failed to get amber to prefetch the package');
return LaunchResult.failed();
}
@@ -286,14 +287,14 @@
// Instruct tiles_ctl to start the app.
final String fuchsiaUrl =
'fuchsia-pkg://fuchsia.com/$appName#meta/$appName.cmx';
- if (!await _tilesCtl.add(this, fuchsiaUrl, <String>[])) {
+ if (!await fuchsiaDeviceTools.tilesCtl.add(this, fuchsiaUrl, <String>[])) {
printError('Failed to add the app to tiles');
return LaunchResult.failed();
}
} finally {
// Try to un-teach amber about the package server if needed.
if (serverRegistered) {
- await _amberCtl.rmSrc(this, fuchsiaPackageServer);
+ await fuchsiaDeviceTools.amberCtl.rmSrc(this, fuchsiaPackageServer);
}
// Shutdown the package server and delete the package repo;
fuchsiaPackageServer.stop();
@@ -308,7 +309,7 @@
// In a debug or profile build, try to find the observatory uri.
final FuchsiaIsolateDiscoveryProtocol discovery =
- FuchsiaIsolateDiscoveryProtocol(this, appName);
+ getIsolateDiscoveryProtocol(appName);
try {
final Uri observatoryUri = await discovery.uri;
return LaunchResult.succeeded(observatoryUri: observatoryUri);
@@ -321,7 +322,7 @@
Future<bool> stopApp(covariant FuchsiaApp app) async {
final int appKey = await FuchsiaTilesCtl.findAppKey(this, app.id);
if (appKey != -1) {
- if (!await _tilesCtl.remove(this, appKey)) {
+ if (!await fuchsiaDeviceTools.tilesCtl.remove(this, appKey)) {
printError('tiles_ctl remove on ${app.id} failed.');
return false;
}
diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart
index c2af066..0cda7a7 100644
--- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart
+++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_sdk.dart
@@ -50,6 +50,9 @@
return null;
}
final List<String> devices = await fuchsiaDevFinder.list();
+ if (devices == null) {
+ return null;
+ }
return devices.isNotEmpty ? devices[0] : null;
}
diff --git a/packages/flutter_tools/test/fuchsia/fuchsa_device_test.dart b/packages/flutter_tools/test/fuchsia/fuchsa_device_test.dart
index 735df55..7e10b66 100644
--- a/packages/flutter_tools/test/fuchsia/fuchsa_device_test.dart
+++ b/packages/flutter_tools/test/fuchsia/fuchsa_device_test.dart
@@ -407,32 +407,49 @@
group('fuchsia app start and stop: ', () {
MemoryFileSystem memoryFileSystem;
MockOperatingSystemUtils osUtils;
- MockFuchsiaDeviceTools fuchsiaDeviceTools;
+ FakeFuchsiaDeviceTools fuchsiaDeviceTools;
MockFuchsiaSdk fuchsiaSdk;
setUp(() {
memoryFileSystem = MemoryFileSystem();
osUtils = MockOperatingSystemUtils();
- fuchsiaDeviceTools = MockFuchsiaDeviceTools();
+ fuchsiaDeviceTools = FakeFuchsiaDeviceTools();
fuchsiaSdk = MockFuchsiaSdk();
when(osUtils.findFreePort()).thenAnswer((_) => Future<int>.value(12345));
});
- testUsingContext('start prebuilt app in release mode', () async {
+ Future<LaunchResult> setupAndStartApp({
+ @required bool prebuilt,
+ @required BuildMode mode,
+ }) async {
const String appName = 'app_name';
- final FuchsiaDevice device = FuchsiaDevice('123');
+ final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123');
fs.directory('fuchsia').createSync(recursive: true);
final File pubspecFile = fs.file('pubspec.yaml')..createSync();
pubspecFile.writeAsStringSync('name: $appName');
- final File far = fs.file('app_name-0.far')..createSync();
- final FuchsiaApp app = FuchsiaApp.fromPrebuiltApp(far);
+ FuchsiaApp app;
+ if (prebuilt) {
+ final File far = fs.file('app_name-0.far')..createSync();
+ app = FuchsiaApp.fromPrebuiltApp(far);
+ } else {
+ fs.file(fs.path.join('fuchsia', 'meta', '$appName.cmx'))
+ .createSync(recursive: true);
+ fs.file('.packages').createSync();
+ fs.file(fs.path.join('lib', 'main.dart')).createSync(recursive: true);
+ app = BuildableFuchsiaApp(project: FlutterProject.current().fuchsia);
+ }
+
final DebuggingOptions debuggingOptions =
- DebuggingOptions.disabled(const BuildInfo(BuildMode.release, null));
- final LaunchResult launchResult = await device.startApp(app,
- prebuiltApplication: true,
+ DebuggingOptions.disabled(BuildInfo(mode, null));
+ return await device.startApp(app,
+ prebuiltApplication: prebuilt,
debuggingOptions: debuggingOptions);
+ }
+ testUsingContext('start prebuilt in release mode', () async {
+ final LaunchResult launchResult =
+ await setupAndStartApp(prebuilt: true, mode: BuildMode.release);
expect(launchResult.started, isTrue);
expect(launchResult.hasObservatory, isFalse);
}, overrides: <Type, Generator>{
@@ -442,9 +459,9 @@
OperatingSystemUtils: () => osUtils,
});
- testUsingContext('start and stop prebuilt app in release mode', () async {
+ testUsingContext('start and stop prebuilt in release mode', () async {
const String appName = 'app_name';
- final FuchsiaDevice device = FuchsiaDevice('123');
+ final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123');
fs.directory('fuchsia').createSync(recursive: true);
final File pubspecFile = fs.file('pubspec.yaml')..createSync();
pubspecFile.writeAsStringSync('name: $appName');
@@ -456,7 +473,6 @@
final LaunchResult launchResult = await device.startApp(app,
prebuiltApplication: true,
debuggingOptions: debuggingOptions);
-
expect(launchResult.started, isTrue);
expect(launchResult.hasObservatory, isFalse);
expect(await device.stopApp(app), isTrue);
@@ -466,6 +482,91 @@
FuchsiaSdk: () => fuchsiaSdk,
OperatingSystemUtils: () => osUtils,
});
+
+ testUsingContext('start prebuilt in debug mode', () async {
+ final LaunchResult launchResult =
+ await setupAndStartApp(prebuilt: true, mode: BuildMode.debug);
+ expect(launchResult.started, isTrue);
+ expect(launchResult.hasObservatory, isTrue);
+ }, overrides: <Type, Generator>{
+ FileSystem: () => memoryFileSystem,
+ FuchsiaDeviceTools: () => fuchsiaDeviceTools,
+ FuchsiaSdk: () => fuchsiaSdk,
+ OperatingSystemUtils: () => osUtils,
+ });
+
+ testUsingContext('start buildable in release mode', () async {
+ final LaunchResult launchResult =
+ await setupAndStartApp(prebuilt: false, mode: BuildMode.release);
+ expect(launchResult.started, isTrue);
+ expect(launchResult.hasObservatory, isFalse);
+ }, overrides: <Type, Generator>{
+ FileSystem: () => memoryFileSystem,
+ FuchsiaDeviceTools: () => fuchsiaDeviceTools,
+ FuchsiaSdk: () => fuchsiaSdk,
+ OperatingSystemUtils: () => osUtils,
+ });
+
+ testUsingContext('start buildable in debug mode', () async {
+ final LaunchResult launchResult =
+ await setupAndStartApp(prebuilt: false, mode: BuildMode.debug);
+ expect(launchResult.started, isTrue);
+ expect(launchResult.hasObservatory, isTrue);
+ }, overrides: <Type, Generator>{
+ FileSystem: () => memoryFileSystem,
+ FuchsiaDeviceTools: () => fuchsiaDeviceTools,
+ FuchsiaSdk: () => fuchsiaSdk,
+ OperatingSystemUtils: () => osUtils,
+ });
+
+ testUsingContext('fail with correct LaunchResult when dev_finder fails', () async {
+ final LaunchResult launchResult =
+ await setupAndStartApp(prebuilt: true, mode: BuildMode.release);
+ expect(launchResult.started, isFalse);
+ expect(launchResult.hasObservatory, isFalse);
+ }, overrides: <Type, Generator>{
+ FileSystem: () => memoryFileSystem,
+ FuchsiaDeviceTools: () => fuchsiaDeviceTools,
+ FuchsiaSdk: () => MockFuchsiaSdk(devFinder: FailingDevFinder()),
+ OperatingSystemUtils: () => osUtils,
+ });
+
+ testUsingContext('fail with correct LaunchResult when pm fails', () async {
+ final LaunchResult launchResult =
+ await setupAndStartApp(prebuilt: true, mode: BuildMode.release);
+ expect(launchResult.started, isFalse);
+ expect(launchResult.hasObservatory, isFalse);
+ }, overrides: <Type, Generator>{
+ FileSystem: () => memoryFileSystem,
+ FuchsiaDeviceTools: () => fuchsiaDeviceTools,
+ FuchsiaSdk: () => MockFuchsiaSdk(pm: FailingPM()),
+ OperatingSystemUtils: () => osUtils,
+ });
+
+ testUsingContext('fail with correct LaunchResult when amber fails', () async {
+ final LaunchResult launchResult =
+ await setupAndStartApp(prebuilt: true, mode: BuildMode.release);
+ expect(launchResult.started, isFalse);
+ expect(launchResult.hasObservatory, isFalse);
+ }, overrides: <Type, Generator>{
+ FileSystem: () => memoryFileSystem,
+ FuchsiaDeviceTools: () => FakeFuchsiaDeviceTools(amber: FailingAmberCtl()),
+ FuchsiaSdk: () => fuchsiaSdk,
+ OperatingSystemUtils: () => osUtils,
+ });
+
+ testUsingContext('fail with correct LaunchResult when tiles fails', () async {
+ final LaunchResult launchResult =
+ await setupAndStartApp(prebuilt: true, mode: BuildMode.release);
+ expect(launchResult.started, isFalse);
+ expect(launchResult.hasObservatory, isFalse);
+ }, overrides: <Type, Generator>{
+ FileSystem: () => memoryFileSystem,
+ FuchsiaDeviceTools: () => FakeFuchsiaDeviceTools(tiles: FailingTilesCtl()),
+ FuchsiaSdk: () => fuchsiaSdk,
+ OperatingSystemUtils: () => osUtils,
+ });
+
});
}
@@ -559,7 +660,24 @@
final String name;
}
-class MockFuchsiaAmberCtl extends Mock implements FuchsiaAmberCtl {
+class FuchsiaDeviceWithFakeDiscovery extends FuchsiaDevice {
+ FuchsiaDeviceWithFakeDiscovery(String id, {String name}) : super(id, name: name);
+
+ @override
+ FuchsiaIsolateDiscoveryProtocol getIsolateDiscoveryProtocol(
+ String isolateName) =>
+ FakeFuchsiaIsolateDiscoveryProtocol();
+}
+
+class FakeFuchsiaIsolateDiscoveryProtocol implements FuchsiaIsolateDiscoveryProtocol {
+ @override
+ FutureOr<Uri> get uri => Uri.parse('http://[::1]:37');
+
+ @override
+ void dispose() {}
+}
+
+class FakeFuchsiaAmberCtl implements FuchsiaAmberCtl {
@override
Future<bool> addSrc(FuchsiaDevice device, FuchsiaPackageServer server) async {
return true;
@@ -576,7 +694,24 @@
}
}
-class MockFuchsiaTilesCtl extends Mock implements FuchsiaTilesCtl {
+class FailingAmberCtl implements FuchsiaAmberCtl {
+ @override
+ Future<bool> addSrc(FuchsiaDevice device, FuchsiaPackageServer server) async {
+ return false;
+ }
+
+ @override
+ Future<bool> rmSrc(FuchsiaDevice device, FuchsiaPackageServer server) async {
+ return false;
+ }
+
+ @override
+ Future<bool> getUp(FuchsiaDevice device, String packageName) async {
+ return false;
+ }
+}
+
+class FakeFuchsiaTilesCtl implements FuchsiaTilesCtl {
final Map<int, String> _runningApps = <int, String>{};
bool _started = false;
int _nextAppId = 1;
@@ -624,15 +759,48 @@
}
}
-class MockFuchsiaDeviceTools extends Mock implements FuchsiaDeviceTools {
+class FailingTilesCtl implements FuchsiaTilesCtl {
@override
- final FuchsiaAmberCtl amberCtl = MockFuchsiaAmberCtl();
+ Future<bool> start(FuchsiaDevice device) async {
+ return false;
+ }
@override
- final FuchsiaTilesCtl tilesCtl = MockFuchsiaTilesCtl();
+ Future<Map<int, String>> list(FuchsiaDevice device) async {
+ return null;
+ }
+
+ @override
+ Future<bool> add(FuchsiaDevice device, String url, List<String> args) async {
+ return false;
+ }
+
+ @override
+ Future<bool> remove(FuchsiaDevice device, int key) async {
+ return false;
+ }
+
+ @override
+ Future<bool> quit(FuchsiaDevice device) async {
+ return false;
+ }
}
-class MockFuchsiaPM extends Mock implements FuchsiaPM {
+class FakeFuchsiaDeviceTools implements FuchsiaDeviceTools {
+ FakeFuchsiaDeviceTools({
+ FuchsiaAmberCtl amber,
+ FuchsiaTilesCtl tiles,
+ }) : amberCtl = amber ?? FakeFuchsiaAmberCtl(),
+ tilesCtl = tiles ?? FakeFuchsiaTilesCtl();
+
+ @override
+ final FuchsiaAmberCtl amberCtl;
+
+ @override
+ final FuchsiaTilesCtl tilesCtl;
+}
+
+class FakeFuchsiaPM implements FuchsiaPM {
String _appName;
@override
@@ -710,7 +878,46 @@
}
}
-class MockFuchsiaKernelCompiler extends Mock implements FuchsiaKernelCompiler {
+class FailingPM implements FuchsiaPM {
+ @override
+ Future<bool> init(String buildPath, String appName) async {
+ return false;
+ }
+
+ @override
+ Future<bool> genkey(String buildPath, String outKeyPath) async {
+ return false;
+ }
+
+ @override
+ Future<bool> build(
+ String buildPath, String keyPath, String manifestPath) async {
+ return false;
+ }
+
+ @override
+ Future<bool> archive(
+ String buildPath, String keyPath, String manifestPath) async {
+ return false;
+ }
+
+ @override
+ Future<bool> newrepo(String repoPath) async {
+ return false;
+ }
+
+ @override
+ Future<Process> serve(String repoPath, String host, int port) async {
+ return _createMockProcess(exitCode: 6);
+ }
+
+ @override
+ Future<bool> publish(String repoPath, String packagePath) async {
+ return false;
+ }
+}
+
+class FakeFuchsiaKernelCompiler implements FuchsiaKernelCompiler {
@override
Future<void> build({
@required FuchsiaProject fuchsiaProject,
@@ -724,7 +931,18 @@
}
}
-class MockFuchsiaDevFinder extends Mock implements FuchsiaDevFinder {
+class FailingKernelCompiler implements FuchsiaKernelCompiler {
+ @override
+ Future<void> build({
+ @required FuchsiaProject fuchsiaProject,
+ @required String target, // E.g., lib/main.dart
+ BuildInfo buildInfo = BuildInfo.debug,
+ }) async {
+ throwToolExit('Build process failed');
+ }
+}
+
+class FakeFuchsiaDevFinder implements FuchsiaDevFinder {
@override
Future<List<String>> list() async {
return <String>['192.168.42.172 scare-cable-skip-joy'];
@@ -736,14 +954,33 @@
}
}
+class FailingDevFinder implements FuchsiaDevFinder {
+ @override
+ Future<List<String>> list() async {
+ return null;
+ }
+
+ @override
+ Future<String> resolve(String deviceName) async {
+ return null;
+ }
+}
+
class MockFuchsiaSdk extends Mock implements FuchsiaSdk {
- @override
- final FuchsiaPM fuchsiaPM = MockFuchsiaPM();
+ MockFuchsiaSdk({
+ FuchsiaPM pm,
+ FuchsiaKernelCompiler compiler,
+ FuchsiaDevFinder devFinder,
+ }) : fuchsiaPM = pm ?? FakeFuchsiaPM(),
+ fuchsiaKernelCompiler = compiler ?? FakeFuchsiaKernelCompiler(),
+ fuchsiaDevFinder = devFinder ?? FakeFuchsiaDevFinder();
@override
- final FuchsiaKernelCompiler fuchsiaKernelCompiler =
- MockFuchsiaKernelCompiler();
+ final FuchsiaPM fuchsiaPM;
@override
- final FuchsiaDevFinder fuchsiaDevFinder = MockFuchsiaDevFinder();
+ final FuchsiaKernelCompiler fuchsiaKernelCompiler;
+
+ @override
+ final FuchsiaDevFinder fuchsiaDevFinder;
}