[flutter_tools] remove most mocks from Fuchsia device tests (#81789)
diff --git a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_dev_finder_test.dart b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_dev_finder_test.dart
index b2588b8..c69a7ea 100644
--- a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_dev_finder_test.dart
+++ b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_dev_finder_test.dart
@@ -10,30 +10,29 @@
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/fuchsia/fuchsia_dev_finder.dart';
import 'package:flutter_tools/src/fuchsia/fuchsia_sdk.dart';
-import 'package:mockito/mockito.dart';
+import 'package:test/fake.dart';
import '../../src/common.dart';
import '../../src/fake_process_manager.dart';
void main() {
- MockFuchsiaArtifacts mockFuchsiaArtifacts;
+ FakeFuchsiaArtifacts fuchsiaArtifacts;
BufferLogger logger;
MemoryFileSystem memoryFileSystem;
File deviceFinder;
setUp(() {
- mockFuchsiaArtifacts = MockFuchsiaArtifacts();
+ fuchsiaArtifacts = FakeFuchsiaArtifacts();
memoryFileSystem = MemoryFileSystem.test();
logger = BufferLogger.test();
deviceFinder = memoryFileSystem.file('device-finder');
-
- when(mockFuchsiaArtifacts.devFinder).thenReturn(deviceFinder);
+ fuchsiaArtifacts.devFinder = deviceFinder;
});
group('device-finder list', () {
testWithoutContext('device-finder not found', () {
final FuchsiaDevFinder fuchsiaDevFinder = FuchsiaDevFinder(
- fuchsiaArtifacts: mockFuchsiaArtifacts,
+ fuchsiaArtifacts: fuchsiaArtifacts,
logger: logger,
processManager: FakeProcessManager.any(),
);
@@ -54,7 +53,7 @@
]);
final FuchsiaDevFinder fuchsiaDevFinder = FuchsiaDevFinder(
- fuchsiaArtifacts: mockFuchsiaArtifacts,
+ fuchsiaArtifacts: fuchsiaArtifacts,
logger: logger,
processManager: processManager,
);
@@ -75,7 +74,7 @@
]);
final FuchsiaDevFinder fuchsiaDevFinder = FuchsiaDevFinder(
- fuchsiaArtifacts: mockFuchsiaArtifacts,
+ fuchsiaArtifacts: fuchsiaArtifacts,
logger: logger,
processManager: processManager,
);
@@ -96,7 +95,7 @@
]);
final FuchsiaDevFinder fuchsiaDevFinder = FuchsiaDevFinder(
- fuchsiaArtifacts: mockFuchsiaArtifacts,
+ fuchsiaArtifacts: fuchsiaArtifacts,
logger: logger,
processManager: processManager,
);
@@ -123,7 +122,7 @@
]);
final FuchsiaDevFinder fuchsiaDevFinder = FuchsiaDevFinder(
- fuchsiaArtifacts: mockFuchsiaArtifacts,
+ fuchsiaArtifacts: fuchsiaArtifacts,
logger: logger,
processManager: processManager,
);
@@ -133,4 +132,7 @@
});
}
-class MockFuchsiaArtifacts extends Mock implements FuchsiaArtifacts {}
+class FakeFuchsiaArtifacts extends Fake implements FuchsiaArtifacts {
+ @override
+ File devFinder;
+}
diff --git a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_start_test.dart b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_start_test.dart
new file mode 100644
index 0000000..124b049
--- /dev/null
+++ b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_start_test.dart
@@ -0,0 +1,678 @@
+// 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 'dart:async';
+import 'dart:convert';
+
+import 'package:file/memory.dart';
+import 'package:flutter_tools/src/artifacts.dart';
+import 'package:flutter_tools/src/base/common.dart';
+import 'package:flutter_tools/src/base/file_system.dart';
+import 'package:flutter_tools/src/base/io.dart';
+import 'package:flutter_tools/src/base/os.dart';
+import 'package:flutter_tools/src/build_info.dart';
+import 'package:flutter_tools/src/device.dart';
+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';
+import 'package:flutter_tools/src/fuchsia/tiles_ctl.dart';
+import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
+import 'package:flutter_tools/src/project.dart';
+import 'package:meta/meta.dart';
+import 'package:mockito/mockito.dart';
+
+import '../../src/common.dart';
+import '../../src/context.dart';
+import '../../src/fake_vm_services.dart';
+import '../../src/fakes.dart';
+
+void main() {
+ group('Fuchsia app start and stop: ', () {
+ MemoryFileSystem memoryFileSystem;
+ FakeOperatingSystemUtils osUtils;
+ FakeFuchsiaDeviceTools fuchsiaDeviceTools;
+ MockFuchsiaSdk fuchsiaSdk;
+ Artifacts artifacts;
+ FakeProcessManager fakeSuccessfulProcessManager;
+ FakeProcessManager fakeFailedProcessManager;
+ File sshConfig;
+
+ setUp(() {
+ memoryFileSystem = MemoryFileSystem.test();
+ osUtils = FakeOperatingSystemUtils();
+ fuchsiaDeviceTools = FakeFuchsiaDeviceTools();
+ fuchsiaSdk = MockFuchsiaSdk();
+ sshConfig = MemoryFileSystem.test().file('ssh_config')..writeAsStringSync('\n');
+ artifacts = Artifacts.test();
+ for (final BuildMode mode in <BuildMode>[BuildMode.debug, BuildMode.release]) {
+ memoryFileSystem.file(
+ artifacts.getArtifactPath(Artifact.fuchsiaKernelCompiler,
+ platform: TargetPlatform.fuchsia_arm64, mode: mode),
+ ).createSync();
+
+ memoryFileSystem.file(
+ artifacts.getArtifactPath(Artifact.platformKernelDill,
+ platform: TargetPlatform.fuchsia_arm64, mode: mode),
+ ).createSync();
+
+ memoryFileSystem.file(
+ artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath,
+ platform: TargetPlatform.fuchsia_arm64, mode: mode),
+ ).createSync();
+
+ memoryFileSystem.file(
+ artifacts.getArtifactPath(Artifact.fuchsiaFlutterRunner,
+ platform: TargetPlatform.fuchsia_arm64, mode: mode),
+ ).createSync();
+ }
+ fakeSuccessfulProcessManager = FakeProcessManager.list(<FakeCommand>[
+ FakeCommand(
+ command: <String>['ssh', '-F', sshConfig.absolute.path, '123', r'echo $SSH_CONNECTION'],
+ stdout: 'fe80::8c6c:2fff:fe3d:c5e1%ethp0003 50666 fe80::5054:ff:fe63:5e7a%ethp0003 22',
+ ),
+ ]);
+ fakeFailedProcessManager = FakeProcessManager.list(<FakeCommand>[
+ FakeCommand(
+ command: <String>['ssh', '-F', sshConfig.absolute.path, '123', r'echo $SSH_CONNECTION'],
+ stdout: '',
+ stderr: '',
+ exitCode: 1,
+ ),
+ ]);
+ });
+
+ Future<LaunchResult> setupAndStartApp({
+ @required bool prebuilt,
+ @required BuildMode mode,
+ }) async {
+ const String appName = 'app_name';
+ final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123');
+ globals.fs.directory('fuchsia').createSync(recursive: true);
+ final File pubspecFile = globals.fs.file('pubspec.yaml')..createSync();
+ pubspecFile.writeAsStringSync('name: $appName');
+
+ FuchsiaApp app;
+ if (prebuilt) {
+ final File far = globals.fs.file('app_name-0.far')..createSync();
+ app = FuchsiaApp.fromPrebuiltApp(far);
+ } else {
+ globals.fs.file(globals.fs.path.join('fuchsia', 'meta', '$appName.cmx'))
+ ..createSync(recursive: true)
+ ..writeAsStringSync('{}');
+ globals.fs.file('.packages').createSync();
+ globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
+ app = BuildableFuchsiaApp(project: FlutterProject.fromDirectoryTest(globals.fs.currentDirectory).fuchsia);
+ }
+
+ final DebuggingOptions debuggingOptions = DebuggingOptions.disabled(BuildInfo(mode, null, treeShakeIcons: false));
+ return 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>{
+ Artifacts: () => artifacts,
+ FileSystem: () => memoryFileSystem,
+ ProcessManager: () => fakeSuccessfulProcessManager,
+ FuchsiaDeviceTools: () => fuchsiaDeviceTools,
+ FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
+ FuchsiaSdk: () => fuchsiaSdk,
+ OperatingSystemUtils: () => osUtils,
+ });
+
+ testUsingContext('start and stop prebuilt in release mode', () async {
+ const String appName = 'app_name';
+ final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123');
+ globals.fs.directory('fuchsia').createSync(recursive: true);
+ final File pubspecFile = globals.fs.file('pubspec.yaml')..createSync();
+ pubspecFile.writeAsStringSync('name: $appName');
+ final File far = globals.fs.file('app_name-0.far')..createSync();
+
+ final FuchsiaApp app = FuchsiaApp.fromPrebuiltApp(far);
+ final DebuggingOptions debuggingOptions =
+ DebuggingOptions.disabled(const BuildInfo(BuildMode.release, null, treeShakeIcons: false));
+ 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);
+ }, overrides: <Type, Generator>{
+ Artifacts: () => artifacts,
+ FileSystem: () => memoryFileSystem,
+ ProcessManager: () => fakeSuccessfulProcessManager,
+ FuchsiaDeviceTools: () => fuchsiaDeviceTools,
+ FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
+ 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>{
+ Artifacts: () => artifacts,
+ FileSystem: () => memoryFileSystem,
+ ProcessManager: () => fakeSuccessfulProcessManager,
+ FuchsiaDeviceTools: () => fuchsiaDeviceTools,
+ FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
+ 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>{
+ Artifacts: () => artifacts,
+ FileSystem: () => memoryFileSystem,
+ ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
+ const FakeCommand(
+ command: <String>[
+ 'Artifact.genSnapshot.TargetPlatform.fuchsia_arm64.release',
+ '--deterministic',
+ '--snapshot_kind=app-aot-elf',
+ '--elf=build/fuchsia/elf.aotsnapshot',
+ 'build/fuchsia/app_name.dil'
+ ],
+ ),
+ FakeCommand(
+ command: <String>['ssh', '-F', sshConfig.absolute.path, '123', r'echo $SSH_CONNECTION'],
+ stdout: 'fe80::8c6c:2fff:fe3d:c5e1%ethp0003 50666 fe80::5054:ff:fe63:5e7a%ethp0003 22',
+ ),
+ ]),
+ FuchsiaDeviceTools: () => fuchsiaDeviceTools,
+ FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
+ 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>{
+ Artifacts: () => artifacts,
+ FileSystem: () => memoryFileSystem,
+ ProcessManager: () => fakeSuccessfulProcessManager,
+ FuchsiaDeviceTools: () => fuchsiaDeviceTools,
+ FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
+ FuchsiaSdk: () => fuchsiaSdk,
+ OperatingSystemUtils: () => osUtils,
+ });
+
+ testUsingContext('fail when cant get ssh config', () async {
+ expect(() async =>
+ setupAndStartApp(prebuilt: true, mode: BuildMode.release),
+ throwsToolExit(message: 'Cannot interact with device. No ssh config.\n'
+ 'Try setting FUCHSIA_SSH_CONFIG or FUCHSIA_BUILD_DIR.'));
+ }, overrides: <Type, Generator>{
+ Artifacts: () => artifacts,
+ FileSystem: () => memoryFileSystem,
+ ProcessManager: () => FakeProcessManager.any(),
+ FuchsiaDeviceTools: () => fuchsiaDeviceTools,
+ FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: null),
+ OperatingSystemUtils: () => osUtils,
+ });
+
+ testUsingContext('fail when cant get host address', () async {
+ expect(() async =>
+ setupAndStartApp(prebuilt: true, mode: BuildMode.release),
+ throwsToolExit(message: 'Failed to get local address, aborting.'));
+ }, overrides: <Type, Generator>{
+ Artifacts: () => artifacts,
+ FileSystem: () => memoryFileSystem,
+ ProcessManager: () => fakeFailedProcessManager,
+ FuchsiaDeviceTools: () => fuchsiaDeviceTools,
+ FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
+ 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>{
+ Artifacts: () => artifacts,
+ FileSystem: () => memoryFileSystem,
+ ProcessManager: () => fakeSuccessfulProcessManager,
+ FuchsiaDeviceTools: () => fuchsiaDeviceTools,
+ FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
+ 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>{
+ Artifacts: () => artifacts,
+ FileSystem: () => memoryFileSystem,
+ ProcessManager: () => fakeSuccessfulProcessManager,
+ FuchsiaDeviceTools: () => FakeFuchsiaDeviceTools(amber: FailingAmberCtl()),
+ FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
+ 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>{
+ Artifacts: () => artifacts,
+ FileSystem: () => memoryFileSystem,
+ ProcessManager: () => fakeSuccessfulProcessManager,
+ FuchsiaDeviceTools: () => FakeFuchsiaDeviceTools(tiles: FailingTilesCtl()),
+ FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
+ FuchsiaSdk: () => fuchsiaSdk,
+ OperatingSystemUtils: () => osUtils,
+ });
+
+ });
+}
+
+class MockProcessManager extends Mock implements ProcessManager {}
+
+class MockProcessResult extends Mock implements ProcessResult {}
+
+class MockProcess extends Mock implements Process {}
+
+Process _createMockProcess({
+ int exitCode = 0,
+ String stdout = '',
+ String stderr = '',
+ bool persistent = false,
+}) {
+ final Stream<List<int>> stdoutStream = Stream<List<int>>.fromIterable(<List<int>>[
+ utf8.encode(stdout),
+ ]);
+ final Stream<List<int>> stderrStream = Stream<List<int>>.fromIterable(<List<int>>[
+ utf8.encode(stderr),
+ ]);
+ final Process process = MockProcess();
+
+ when(process.stdout).thenAnswer((_) => stdoutStream);
+ when(process.stderr).thenAnswer((_) => stderrStream);
+
+ if (persistent) {
+ final Completer<int> exitCodeCompleter = Completer<int>();
+ when(process.kill()).thenAnswer((_) {
+ exitCodeCompleter.complete(-11);
+ return true;
+ });
+ when(process.exitCode).thenAnswer((_) => exitCodeCompleter.future);
+ } else {
+ when(process.exitCode).thenAnswer((_) => Future<int>.value(exitCode));
+ }
+ return process;
+}
+
+
+class FuchsiaDeviceWithFakeDiscovery extends FuchsiaDevice {
+ FuchsiaDeviceWithFakeDiscovery(String id, {String name}) : super(id, name: name);
+
+ @override
+ FuchsiaIsolateDiscoveryProtocol getIsolateDiscoveryProtocol(String isolateName) {
+ return FakeFuchsiaIsolateDiscoveryProtocol();
+ }
+
+ @override
+ Future<TargetPlatform> get targetPlatform async => TargetPlatform.fuchsia_arm64;
+}
+
+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;
+ }
+
+ @override
+ Future<bool> rmSrc(FuchsiaDevice device, FuchsiaPackageServer server) async {
+ return true;
+ }
+
+ @override
+ Future<bool> getUp(FuchsiaDevice device, String packageName) async {
+ return true;
+ }
+
+ @override
+ Future<bool> addRepoCfg(FuchsiaDevice device, FuchsiaPackageServer server) async {
+ return true;
+ }
+
+ @override
+ Future<bool> pkgCtlResolve(FuchsiaDevice device, FuchsiaPackageServer server, String packageName) async {
+ return true;
+ }
+
+ @override
+ Future<bool> pkgCtlRepoRemove(FuchsiaDevice device, FuchsiaPackageServer server) async {
+ return true;
+ }
+}
+
+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;
+ }
+
+ @override
+ Future<bool> addRepoCfg(FuchsiaDevice device, FuchsiaPackageServer server) async {
+ return false;
+ }
+
+ @override
+ Future<bool> pkgCtlResolve(FuchsiaDevice device, FuchsiaPackageServer server, String packageName) async {
+ return false;
+ }
+
+ @override
+ Future<bool> pkgCtlRepoRemove(FuchsiaDevice device, FuchsiaPackageServer server) async {
+ return false;
+ }
+}
+
+class FakeFuchsiaTilesCtl implements FuchsiaTilesCtl {
+ final Map<int, String> _runningApps = <int, String>{};
+ bool _started = false;
+ int _nextAppId = 1;
+
+ @override
+ Future<bool> start(FuchsiaDevice device) async {
+ _started = true;
+ return true;
+ }
+
+ @override
+ Future<Map<int, String>> list(FuchsiaDevice device) async {
+ if (!_started) {
+ return null;
+ }
+ return _runningApps;
+ }
+
+ @override
+ Future<bool> add(FuchsiaDevice device, String url, List<String> args) async {
+ if (!_started) {
+ return false;
+ }
+ _runningApps[_nextAppId] = url;
+ _nextAppId++;
+ return true;
+ }
+
+ @override
+ Future<bool> remove(FuchsiaDevice device, int key) async {
+ if (!_started) {
+ return false;
+ }
+ _runningApps.remove(key);
+ return true;
+ }
+
+ @override
+ Future<bool> quit(FuchsiaDevice device) async {
+ if (!_started) {
+ return false;
+ }
+ _started = false;
+ return true;
+ }
+}
+
+class FailingTilesCtl implements FuchsiaTilesCtl {
+ @override
+ Future<bool> start(FuchsiaDevice device) async {
+ return false;
+ }
+
+ @override
+ 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 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
+ Future<bool> init(String buildPath, String appName) async {
+ if (!globals.fs.directory(buildPath).existsSync()) {
+ return false;
+ }
+ globals.fs
+ .file(globals.fs.path.join(buildPath, 'meta', 'package'))
+ .createSync(recursive: true);
+ _appName = appName;
+ return true;
+ }
+
+ @override
+ Future<bool> build(String buildPath, String manifestPath) async {
+ if (!globals.fs.file(globals.fs.path.join(buildPath, 'meta', 'package')).existsSync() ||
+ !globals.fs.file(manifestPath).existsSync()) {
+ return false;
+ }
+ globals.fs.file(globals.fs.path.join(buildPath, 'meta.far')).createSync(recursive: true);
+ return true;
+ }
+
+ @override
+ Future<bool> archive(String buildPath, String manifestPath) async {
+ if (!globals.fs.file(globals.fs.path.join(buildPath, 'meta', 'package')).existsSync() ||
+ !globals.fs.file(manifestPath).existsSync()) {
+ return false;
+ }
+ if (_appName == null) {
+ return false;
+ }
+ globals.fs
+ .file(globals.fs.path.join(buildPath, '$_appName-0.far'))
+ .createSync(recursive: true);
+ return true;
+ }
+
+ @override
+ Future<bool> newrepo(String repoPath) async {
+ if (!globals.fs.directory(repoPath).existsSync()) {
+ return false;
+ }
+ return true;
+ }
+
+ @override
+ Future<Process> serve(String repoPath, String host, int port) async {
+ return _createMockProcess(persistent: true);
+ }
+
+ @override
+ Future<bool> publish(String repoPath, String packagePath) async {
+ if (!globals.fs.directory(repoPath).existsSync()) {
+ return false;
+ }
+ if (!globals.fs.file(packagePath).existsSync()) {
+ return false;
+ }
+ return true;
+ }
+}
+
+class FailingPM implements FuchsiaPM {
+ @override
+ Future<bool> init(String buildPath, String appName) async {
+ return false;
+ }
+
+
+ @override
+ Future<bool> build(String buildPath, String manifestPath) async {
+ return false;
+ }
+
+ @override
+ Future<bool> archive(String buildPath, 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,
+ @required String target, // E.g., lib/main.dart
+ BuildInfo buildInfo = BuildInfo.debug,
+ }) async {
+ final String outDir = getFuchsiaBuildDirectory();
+ final String appName = fuchsiaProject.project.manifest.appName;
+ final String manifestPath = globals.fs.path.join(outDir, '$appName.dilpmanifest');
+ globals.fs.file(manifestPath).createSync(recursive: true);
+ }
+}
+
+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({ Duration timeout }) async {
+ 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
+ Future<String> resolve(String deviceName) async {
+ return '192.168.42.10';
+ }
+}
+
+class MockFuchsiaSdk extends Mock implements FuchsiaSdk {
+ MockFuchsiaSdk({
+ FuchsiaPM pm,
+ FuchsiaKernelCompiler compiler,
+ FuchsiaDevFinder devFinder,
+ FuchsiaFfx ffx,
+ }) : fuchsiaPM = pm ?? FakeFuchsiaPM(),
+ fuchsiaKernelCompiler = compiler ?? FakeFuchsiaKernelCompiler(),
+ fuchsiaDevFinder = devFinder ?? FakeFuchsiaDevFinder(),
+ fuchsiaFfx = ffx ?? FakeFuchsiaFfx();
+
+ @override
+ final FuchsiaPM fuchsiaPM;
+
+ @override
+ final FuchsiaKernelCompiler fuchsiaKernelCompiler;
+
+ @override
+ final FuchsiaDevFinder fuchsiaDevFinder;
+
+ @override
+ final FuchsiaFfx fuchsiaFfx;
+}
diff --git a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart
index ff92544..2c55a59 100644
--- a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart
+++ b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart
@@ -5,25 +5,20 @@
// @dart = 2.8
import 'dart:async';
-import 'dart:convert';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/artifacts.dart';
-import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/dds.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
-import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/time.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/device_port_forwarder.dart';
-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';
@@ -31,18 +26,16 @@
import 'package:flutter_tools/src/fuchsia/fuchsia_pm.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/tiles_ctl.dart';
import 'package:flutter_tools/src/globals_null_migrated.dart' as globals;
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/vmservice.dart';
import 'package:meta/meta.dart';
-import 'package:mockito/mockito.dart';
+import 'package:test/fake.dart';
import 'package:vm_service/vm_service.dart' as vm_service;
import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/fake_vm_services.dart';
-import '../../src/fakes.dart';
final vm_service.Isolate fakeIsolate = vm_service.Isolate(
id: '1',
@@ -67,10 +60,12 @@
group('fuchsia device', () {
MemoryFileSystem memoryFileSystem;
File sshConfig;
+ FakeProcessManager processManager;
setUp(() {
memoryFileSystem = MemoryFileSystem.test();
sshConfig = memoryFileSystem.file('ssh_config')..writeAsStringSync('\n');
+ processManager = FakeProcessManager.empty();
});
testWithoutContext('stores the requested id and name', () {
@@ -94,33 +89,27 @@
});
testWithoutContext('lists nothing when workflow cannot list devices', () async {
- final MockFuchsiaWorkflow fuchsiaWorkflow = MockFuchsiaWorkflow();
+ final FakeFuchsiaWorkflow fuchsiaWorkflow = FakeFuchsiaWorkflow(canListDevices: false);
final FuchsiaDevices fuchsiaDevices = FuchsiaDevices(
platform: FakePlatform(operatingSystem: 'linux'),
fuchsiaSdk: null,
fuchsiaWorkflow: fuchsiaWorkflow,
logger: BufferLogger.test(),
);
- when(fuchsiaWorkflow.canListDevices).thenReturn(false);
expect(fuchsiaDevices.canListAnything, false);
expect(await fuchsiaDevices.pollingGetDevices(), isEmpty);
});
testWithoutContext('can parse ffx output for single device', () async {
- final MockFuchsiaWorkflow fuchsiaWorkflow = MockFuchsiaWorkflow();
- final MockFuchsiaSdk fuchsiaSdk = MockFuchsiaSdk();
+ final FakeFuchsiaWorkflow fuchsiaWorkflow = FakeFuchsiaWorkflow(shouldUseDeviceFinder: false, canListDevices: true);
+ final FakeFuchsiaSdk fuchsiaSdk = FakeFuchsiaSdk(devices: '2001:0db8:85a3:0000:0000:8a2e:0370:7334 paper-pulp-bush-angel');
final FuchsiaDevices fuchsiaDevices = FuchsiaDevices(
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(useDeviceFinder: false)).thenAnswer((Invocation invocation) async {
- return '2001:0db8:85a3:0000:0000:8a2e:0370:7334 paper-pulp-bush-angel';
- });
final Device device = (await fuchsiaDevices.pollingGetDevices()).single;
@@ -129,19 +118,14 @@
});
testWithoutContext('can parse device-finder output for single device', () async {
- final MockFuchsiaWorkflow fuchsiaWorkflow = MockFuchsiaWorkflow();
- final MockFuchsiaSdk fuchsiaSdk = MockFuchsiaSdk();
+ final FakeFuchsiaWorkflow fuchsiaWorkflow = FakeFuchsiaWorkflow(shouldUseDeviceFinder: true, canListDevices: true);
+ final FakeFuchsiaSdk fuchsiaSdk = FakeFuchsiaSdk(devFinderDevices: '2001:0db8:85a3:0000:0000:8a2e:0370:7334 paper-pulp-bush-angel');
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;
@@ -150,20 +134,17 @@
});
testWithoutContext('can parse ffx output for multiple devices', () async {
- final MockFuchsiaWorkflow fuchsiaWorkflow = MockFuchsiaWorkflow();
- final MockFuchsiaSdk fuchsiaSdk = MockFuchsiaSdk();
+ final FakeFuchsiaWorkflow fuchsiaWorkflow = FakeFuchsiaWorkflow(shouldUseDeviceFinder: false, canListDevices: true);
+ final FakeFuchsiaSdk fuchsiaSdk = FakeFuchsiaSdk(devices:
+ '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 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(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';
- });
final List<Device> devices = await fuchsiaDevices.pollingGetDevices();
@@ -174,20 +155,17 @@
});
testWithoutContext('can parse device-finder output for multiple devices', () async {
- final MockFuchsiaWorkflow fuchsiaWorkflow = MockFuchsiaWorkflow();
- final MockFuchsiaSdk fuchsiaSdk = MockFuchsiaSdk();
+ final FakeFuchsiaWorkflow fuchsiaWorkflow = FakeFuchsiaWorkflow(shouldUseDeviceFinder: true, canListDevices: true);
+ final FakeFuchsiaSdk fuchsiaSdk = FakeFuchsiaSdk(devFinderDevices:
+ '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 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 '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();
@@ -198,19 +176,14 @@
});
testWithoutContext('can parse junk output from ffx', () async {
- final MockFuchsiaWorkflow fuchsiaWorkflow = MockFuchsiaWorkflow();
- final MockFuchsiaSdk fuchsiaSdk = MockFuchsiaSdk();
+ final FakeFuchsiaWorkflow fuchsiaWorkflow = FakeFuchsiaWorkflow(shouldUseDeviceFinder: false, canListDevices: false);
+ final FakeFuchsiaSdk fuchsiaSdk = FakeFuchsiaSdk(devices: 'junk', devFinderDevices: 'junk');
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';
- });
final List<Device> devices = await fuchsiaDevices.pollingGetDevices();
@@ -218,19 +191,14 @@
});
testWithoutContext('can parse junk output from device-finder', () async {
- final MockFuchsiaWorkflow fuchsiaWorkflow = MockFuchsiaWorkflow();
- final MockFuchsiaSdk fuchsiaSdk = MockFuchsiaSdk();
+ final FakeFuchsiaWorkflow fuchsiaWorkflow = FakeFuchsiaWorkflow(shouldUseDeviceFinder: true, canListDevices: true);
+ final FakeFuchsiaSdk fuchsiaSdk = FakeFuchsiaSdk(devices: 'junk', devFinderDevices: 'junk');
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();
@@ -238,11 +206,12 @@
});
testUsingContext('disposing device disposes the portForwarder', () async {
- final MockPortForwarder mockPortForwarder = MockPortForwarder();
+ final FakePortForwarder portForwarder = FakePortForwarder();
final FuchsiaDevice device = FuchsiaDevice('123');
- device.portForwarder = mockPortForwarder;
+ device.portForwarder = portForwarder;
await device.dispose();
- verify(mockPortForwarder.dispose()).called(1);
+
+ expect(portForwarder.disposed, true);
});
testWithoutContext('default capabilities', () async {
@@ -286,130 +255,104 @@
expect(await device.targetPlatform, TargetPlatform.fuchsia_arm64);
}, overrides: <Type, Generator>{
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: null),
- FuchsiaSdk: () => MockFuchsiaSdk(),
- ProcessManager: () => MockProcessManager(),
+ FuchsiaSdk: () => FakeFuchsiaSdk(),
+ ProcessManager: () => processManager,
});
testUsingContext('targetPlatform arm64 works', () async {
- when(globals.processManager.run(any)).thenAnswer((Invocation _) async {
- return ProcessResult(1, 0, 'aarch64', '');
- });
+ processManager.addCommand(const FakeCommand(
+ command: <String>['ssh', '-F', '/ssh_config', '123', 'uname -m'],
+ stdout: 'aarch64',
+ ));
+
final FuchsiaDevice device = FuchsiaDevice('123');
expect(await device.targetPlatform, TargetPlatform.fuchsia_arm64);
}, overrides: <Type, Generator>{
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- FuchsiaSdk: () => MockFuchsiaSdk(),
- ProcessManager: () => MockProcessManager(),
+ FuchsiaSdk: () => FakeFuchsiaSdk(),
+ ProcessManager: () => processManager,
});
testUsingContext('targetPlatform x64 works', () async {
- when(globals.processManager.run(any)).thenAnswer((Invocation _) async {
- return ProcessResult(1, 0, 'x86_64', '');
- });
+ processManager.addCommand(const FakeCommand(
+ command: <String>['ssh', '-F', '/ssh_config', '123', 'uname -m'],
+ stdout: 'x86_64',
+ ));
+
final FuchsiaDevice device = FuchsiaDevice('123');
expect(await device.targetPlatform, TargetPlatform.fuchsia_x64);
}, overrides: <Type, Generator>{
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- FuchsiaSdk: () => MockFuchsiaSdk(),
- ProcessManager: () => MockProcessManager(),
+ FuchsiaSdk: () => FakeFuchsiaSdk(),
+ ProcessManager: () => processManager,
});
testUsingContext('hostAddress parsing works', () async {
- when(globals.processManager.run(any)).thenAnswer((Invocation _) async {
- return ProcessResult(
- 1,
- 0,
- 'fe80::8c6c:2fff:fe3d:c5e1%ethp0003 50666 fe80::5054:ff:fe63:5e7a%ethp0003 22',
- '',
- );
- });
+ processManager.addCommand(const FakeCommand(
+ command: <String>['ssh', '-F', '/ssh_config', 'id', r'echo $SSH_CONNECTION'],
+ stdout: 'fe80::8c6c:2fff:fe3d:c5e1%ethp0003 50666 fe80::5054:ff:fe63:5e7a%ethp0003 22',
+ ));
+
final FuchsiaDevice device = FuchsiaDevice('id');
expect(await device.hostAddress, 'fe80::8c6c:2fff:fe3d:c5e1%25ethp0003');
}, overrides: <Type, Generator>{
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- FuchsiaSdk: () => MockFuchsiaSdk(),
- ProcessManager: () => MockProcessManager(),
+ FuchsiaSdk: () => FakeFuchsiaSdk(),
+ ProcessManager: () => processManager,
});
testUsingContext('hostAddress parsing throws tool error on failure', () async {
- when(globals.processManager.run(any)).thenAnswer((Invocation _) async {
- return ProcessResult(1, 1, '', '');
- });
+ processManager.addCommand(const FakeCommand(
+ command: <String>['ssh', '-F', '/ssh_config', 'id', r'echo $SSH_CONNECTION'],
+ exitCode: 1,
+ ));
+
final FuchsiaDevice device = FuchsiaDevice('id');
- expect(() async => device.hostAddress, throwsToolExit());
+ await expectLater(() => device.hostAddress, throwsToolExit());
}, overrides: <Type, Generator>{
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- FuchsiaSdk: () => MockFuchsiaSdk(),
- ProcessManager: () => MockProcessManager(),
+ FuchsiaSdk: () => FakeFuchsiaSdk(),
+ ProcessManager: () => processManager,
});
testUsingContext('hostAddress parsing throws tool error on empty response', () async {
- when(globals.processManager.run(any)).thenAnswer((Invocation _) async {
- return ProcessResult(1, 0, '', '');
- });
+ processManager.addCommand(const FakeCommand(
+ command: <String>['ssh', '-F', '/ssh_config', 'id', r'echo $SSH_CONNECTION'],
+ ));
+
final FuchsiaDevice device = FuchsiaDevice('id');
expect(() async => device.hostAddress, throwsToolExit());
}, overrides: <Type, Generator>{
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- FuchsiaSdk: () => MockFuchsiaSdk(),
- ProcessManager: () => MockProcessManager(),
+ FuchsiaSdk: () => FakeFuchsiaSdk(),
+ ProcessManager: () => processManager,
});
});
group('displays friendly error when', () {
- MockProcessManager mockProcessManager;
- MockProcessResult mockProcessResult;
File artifactFile;
- MockProcessManager emptyStdoutProcessManager;
- MockProcessResult emptyStdoutProcessResult;
+ FakeProcessManager processManager;
setUp(() {
- mockProcessManager = MockProcessManager();
- mockProcessResult = MockProcessResult();
+ processManager = FakeProcessManager.empty();
artifactFile = MemoryFileSystem.test().file('artifact');
- when(mockProcessManager.run(
- any,
- environment: anyNamed('environment'),
- workingDirectory: anyNamed('workingDirectory'),
- )).thenAnswer((Invocation invocation) =>
- Future<ProcessResult>.value(mockProcessResult));
- when(mockProcessResult.exitCode).thenReturn(1);
- when<String>(mockProcessResult.stdout as String).thenReturn('');
- when<String>(mockProcessResult.stderr as String).thenReturn('');
-
- emptyStdoutProcessManager = MockProcessManager();
- emptyStdoutProcessResult = MockProcessResult();
- when(emptyStdoutProcessManager.run(
- any,
- environment: anyNamed('environment'),
- workingDirectory: anyNamed('workingDirectory'),
- )).thenAnswer((Invocation invocation) =>
- Future<ProcessResult>.value(emptyStdoutProcessResult));
- when(emptyStdoutProcessResult.exitCode).thenReturn(0);
- when<String>(emptyStdoutProcessResult.stdout as String).thenReturn('');
- when<String>(emptyStdoutProcessResult.stderr as String).thenReturn('');
});
testUsingContext('No vmservices found', () async {
+ processManager.addCommand(const FakeCommand(
+ command: <String>['ssh', '-F', '/artifact', 'id', 'find /hub -name vmservice-port'],
+ ));
final FuchsiaDevice device = FuchsiaDevice('id');
- ToolExit toolExit;
- try {
- await device.servicePorts();
- } on ToolExit catch (err) {
- toolExit = err;
- }
- expect(
- toolExit.message,
- contains(
- 'No Dart Observatories found. Are you running a debug build?'));
+
+ await expectLater(device.servicePorts, throwsToolExit(message: 'No Dart Observatories found. Are you running a debug build?'));
}, overrides: <Type, Generator>{
- ProcessManager: () => emptyStdoutProcessManager,
+ ProcessManager: () => processManager,
FuchsiaArtifacts: () => FuchsiaArtifacts(
- sshConfig: artifactFile,
- devFinder: artifactFile,
- ffx: artifactFile,
- ),
- FuchsiaSdk: () => MockFuchsiaSdk(),
+ sshConfig: artifactFile,
+ devFinder: artifactFile,
+ ffx: artifactFile,
+ ),
+ FuchsiaSdk: () => FakeFuchsiaSdk(),
});
group('device logs', () {
@@ -422,42 +365,29 @@
[2018-11-09 01:30:12][52580][52983][log] INFO: example_app.cmx(flutter): Did thing this time
''';
- MockProcessManager mockProcessManager;
- MockProcess mockProcess;
- Completer<int> exitCode;
- StreamController<List<int>> stdout;
- StreamController<List<int>> stderr;
+ FakeProcessManager processManager;
File devFinder;
File ffx;
File sshConfig;
setUp(() {
- mockProcessManager = MockProcessManager();
- mockProcess = MockProcess();
- stdout = StreamController<List<int>>(sync: true);
- stderr = StreamController<List<int>>(sync: true);
- exitCode = Completer<int>();
- when(mockProcessManager.start(any))
- .thenAnswer((Invocation _) => Future<Process>.value(mockProcess));
- when(mockProcess.exitCode).thenAnswer((Invocation _) => exitCode.future);
- when(mockProcess.stdout).thenAnswer((Invocation _) => stdout.stream);
- when(mockProcess.stderr).thenAnswer((Invocation _) => stderr.stream);
+ processManager = FakeProcessManager.empty();
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');
});
- tearDown(() {
- exitCode.complete(0);
- });
-
testUsingContext('can be parsed for an app', () async {
- final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
- final DeviceLogReader reader = device.getLogReader(
- app: FuchsiaModulePackage(name: 'example_app'));
- final List<String> logLines = <String>[];
final Completer<void> lock = Completer<void>();
+ processManager.addCommand(FakeCommand(
+ command: const <String>['ssh', '-F', '/ssh_config', 'id', 'log_listener --clock Local'],
+ stdout: exampleUtcLogs,
+ completer: lock,
+ ));
+ final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
+ final DeviceLogReader reader = device.getLogReader(app: FuchsiaModulePackage(name: 'example_app'));
+ final List<String> logLines = <String>[];
reader.logLines.listen((String line) {
logLines.add(line);
if (logLines.length == 2) {
@@ -466,52 +396,55 @@
});
expect(logLines, isEmpty);
- stdout.add(utf8.encode(exampleUtcLogs));
- await stdout.close();
- await lock.future.timeout(const Duration(seconds: 1));
-
+ await lock.future;
expect(logLines, <String>[
'[2018-11-09 01:27:45.000] Flutter: Error doing thing',
'[2018-11-09 01:30:12.000] Flutter: Did thing this time',
]);
}, overrides: <Type, Generator>{
- ProcessManager: () => mockProcessManager,
+ ProcessManager: () => processManager,
SystemClock: () => SystemClock.fixed(DateTime(2018, 11, 9, 1, 25, 45)),
FuchsiaArtifacts: () =>
FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig, ffx: ffx),
});
testUsingContext('cuts off prior logs', () async {
- final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
- final DeviceLogReader reader = device.getLogReader(
- app: FuchsiaModulePackage(name: 'example_app'));
- final List<String> logLines = <String>[];
final Completer<void> lock = Completer<void>();
+ processManager.addCommand(FakeCommand(
+ command: const <String>['ssh', '-F', '/ssh_config', 'id', 'log_listener --clock Local'],
+ stdout: exampleUtcLogs,
+ completer: lock,
+ ));
+ final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
+ final DeviceLogReader reader = device.getLogReader(app: FuchsiaModulePackage(name: 'example_app'));
+ final List<String> logLines = <String>[];
reader.logLines.listen((String line) {
logLines.add(line);
lock.complete();
});
expect(logLines, isEmpty);
- stdout.add(utf8.encode(exampleUtcLogs));
- await stdout.close();
await lock.future.timeout(const Duration(seconds: 1));
expect(logLines, <String>[
'[2018-11-09 01:30:12.000] Flutter: Did thing this time',
]);
}, overrides: <Type, Generator>{
- ProcessManager: () => mockProcessManager,
+ ProcessManager: () => processManager,
SystemClock: () => SystemClock.fixed(DateTime(2018, 11, 9, 1, 29, 45)),
- FuchsiaArtifacts: () =>
- FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig, ffx: ffx),
+ FuchsiaArtifacts: () => FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig, ffx: ffx),
});
testUsingContext('can be parsed for all apps', () async {
+ final Completer<void> lock = Completer<void>();
+ processManager.addCommand(FakeCommand(
+ command: const <String>['ssh', '-F', '/ssh_config', 'id', 'log_listener --clock Local'],
+ stdout: exampleUtcLogs,
+ completer: lock,
+ ));
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
final DeviceLogReader reader = device.getLogReader();
final List<String> logLines = <String>[];
- final Completer<void> lock = Completer<void>();
reader.logLines.listen((String line) {
logLines.add(line);
if (logLines.length == 3) {
@@ -520,8 +453,6 @@
});
expect(logLines, isEmpty);
- stdout.add(utf8.encode(exampleUtcLogs));
- await stdout.close();
await lock.future.timeout(const Duration(seconds: 1));
expect(logLines, <String>[
@@ -530,15 +461,20 @@
'[2018-11-09 01:30:12.000] Flutter: Did thing this time',
]);
}, overrides: <Type, Generator>{
- ProcessManager: () => mockProcessManager,
+ ProcessManager: () => processManager,
SystemClock: () => SystemClock.fixed(DateTime(2018, 11, 9, 1, 25, 45)),
- FuchsiaArtifacts: () =>
- FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig, ffx: ffx),
+ FuchsiaArtifacts: () => FuchsiaArtifacts(devFinder: devFinder, sshConfig: sshConfig, ffx: ffx),
});
});
});
group('screenshot', () {
+ FakeProcessManager processManager;
+
+ setUp(() {
+ processManager = FakeProcessManager.empty();
+ });
+
testUsingContext('is supported on posix platforms', () {
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
expect(device.supportsScreenshot, true);
@@ -567,26 +503,25 @@
});
testUsingContext('takeScreenshot throws if screencap failed', () async {
- final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester');
-
- when(globals.processManager.run(
- const <String>[
+ processManager.addCommand(const FakeCommand(
+ command: <String>[
'ssh',
'-F',
'/fuchsia/out/default/.ssh',
'0.0.0.0',
'screencap > /tmp/screenshot.ppm',
],
- workingDirectory: anyNamed('workingDirectory'),
- environment: anyNamed('environment'),
- )).thenAnswer((_) async => ProcessResult(0, 1, '', '<error-message>'));
+ exitCode: 1,
+ stderr: '<error-message>'
+ ));
+ final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester');
await expectLater(
() => device.takeScreenshot(globals.fs.file('file.ppm')),
throwsA(equals('Could not take a screenshot on device tester:\n<error-message>')),
);
}, overrides: <Type, Generator>{
- ProcessManager: () => MockProcessManager(),
+ ProcessManager: () => processManager,
FileSystem: () => MemoryFileSystem.test(),
Platform: () => FakePlatform(
environment: <String, String>{
@@ -598,49 +533,42 @@
testUsingContext('takeScreenshot throws if scp failed', () async {
final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester');
-
- when(globals.processManager.run(
- const <String>[
+ processManager.addCommand(const FakeCommand(
+ command: <String>[
'ssh',
'-F',
'/fuchsia/out/default/.ssh',
'0.0.0.0',
'screencap > /tmp/screenshot.ppm',
],
- workingDirectory: anyNamed('workingDirectory'),
- environment: anyNamed('environment'),
- )).thenAnswer((_) async => ProcessResult(0, 0, '', ''));
-
- when(globals.processManager.run(
- const <String>[
+ ));
+ processManager.addCommand(const FakeCommand(
+ command: <String>[
'scp',
'-F',
'/fuchsia/out/default/.ssh',
'0.0.0.0:/tmp/screenshot.ppm',
'file.ppm',
],
- workingDirectory: anyNamed('workingDirectory'),
- environment: anyNamed('environment'),
- )).thenAnswer((_) async => ProcessResult(0, 1, '', '<error-message>'));
-
- when(globals.processManager.run(
- const <String>[
+ exitCode: 1,
+ stderr: '<error-message>',
+ ));
+ processManager.addCommand(const FakeCommand(
+ command: <String>[
'ssh',
'-F',
'/fuchsia/out/default/.ssh',
'0.0.0.0',
'rm /tmp/screenshot.ppm',
],
- workingDirectory: anyNamed('workingDirectory'),
- environment: anyNamed('environment'),
- )).thenAnswer((_) async => ProcessResult(0, 0, '', ''));
+ ));
await expectLater(
() => device.takeScreenshot(globals.fs.file('file.ppm')),
throwsA(equals('Failed to copy screenshot from device:\n<error-message>')),
);
}, overrides: <Type, Generator>{
- ProcessManager: () => MockProcessManager(),
+ ProcessManager: () => processManager,
FileSystem: () => MemoryFileSystem.test(),
Platform: () => FakePlatform(
environment: <String, String>{
@@ -652,54 +580,43 @@
testUsingContext("takeScreenshot prints error if can't delete file from device", () async {
final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester');
-
- when(globals.processManager.run(
- const <String>[
+ processManager.addCommand(const FakeCommand(
+ command: <String>[
'ssh',
'-F',
'/fuchsia/out/default/.ssh',
'0.0.0.0',
'screencap > /tmp/screenshot.ppm',
],
- workingDirectory: anyNamed('workingDirectory'),
- environment: anyNamed('environment'),
- )).thenAnswer((_) async => ProcessResult(0, 0, '', ''));
-
- when(globals.processManager.run(
- const <String>[
+ ));
+ processManager.addCommand(const FakeCommand(
+ command: <String>[
'scp',
'-F',
'/fuchsia/out/default/.ssh',
'0.0.0.0:/tmp/screenshot.ppm',
'file.ppm',
],
- workingDirectory: anyNamed('workingDirectory'),
- environment: anyNamed('environment'),
- )).thenAnswer((_) async => ProcessResult(0, 0, '', ''));
-
- when(globals.processManager.run(
- const <String>[
+ ));
+ processManager.addCommand(const FakeCommand(
+ command: <String>[
'ssh',
'-F',
'/fuchsia/out/default/.ssh',
'0.0.0.0',
'rm /tmp/screenshot.ppm',
],
- workingDirectory: anyNamed('workingDirectory'),
- environment: anyNamed('environment'),
- )).thenAnswer((_) async => ProcessResult(0, 1, '', '<error-message>'));
+ exitCode: 1,
+ stderr: '<error-message>',
+ ));
- try {
- await device.takeScreenshot(globals.fs.file('file.ppm'));
- } on Exception {
- assert(false);
- }
+ await device.takeScreenshot(globals.fs.file('file.ppm'));
expect(
testLogger.errorText,
contains('Failed to delete screenshot.ppm from the device:\n<error-message>'),
);
}, overrides: <Type, Generator>{
- ProcessManager: () => MockProcessManager(),
+ ProcessManager: () => processManager,
FileSystem: () => MemoryFileSystem.test(),
Platform: () => FakePlatform(
environment: <String, String>{
@@ -711,47 +628,37 @@
testUsingContext('takeScreenshot returns', () async {
final FuchsiaDevice device = FuchsiaDevice('0.0.0.0', name: 'tester');
-
- when(globals.processManager.run(
- const <String>[
+ processManager.addCommand(const FakeCommand(
+ command: <String>[
'ssh',
'-F',
'/fuchsia/out/default/.ssh',
'0.0.0.0',
'screencap > /tmp/screenshot.ppm',
],
- workingDirectory: anyNamed('workingDirectory'),
- environment: anyNamed('environment'),
- )).thenAnswer((_) async => ProcessResult(0, 0, '', ''));
-
- when(globals.processManager.run(
- const <String>[
+ ));
+ processManager.addCommand(const FakeCommand(
+ command: <String>[
'scp',
'-F',
'/fuchsia/out/default/.ssh',
'0.0.0.0:/tmp/screenshot.ppm',
'file.ppm',
],
- workingDirectory: anyNamed('workingDirectory'),
- environment: anyNamed('environment'),
- )).thenAnswer((_) async => ProcessResult(0, 0, '', ''));
-
- when(globals.processManager.run(
- const <String>[
+ ));
+ processManager.addCommand(const FakeCommand(
+ command: <String>[
'ssh',
'-F',
'/fuchsia/out/default/.ssh',
'0.0.0.0',
'rm /tmp/screenshot.ppm',
],
- workingDirectory: anyNamed('workingDirectory'),
- environment: anyNamed('environment'),
- )).thenAnswer((_) async => ProcessResult(0, 0, '', ''));
+ ));
- expect(() async => device.takeScreenshot(globals.fs.file('file.ppm')),
- returnsNormally);
+ expect(() => device.takeScreenshot(globals.fs.file('file.ppm')), returnsNormally);
}, overrides: <Type, Generator>{
- ProcessManager: () => MockProcessManager(),
+ ProcessManager: () => processManager,
FileSystem: () => MemoryFileSystem.test(),
Platform: () => FakePlatform(
environment: <String, String>{
@@ -763,52 +670,35 @@
});
group('portForwarder', () {
- MockProcessManager mockProcessManager;
+ FakeProcessManager processManager;
File sshConfig;
setUp(() {
- mockProcessManager = MockProcessManager();
+ processManager = FakeProcessManager.empty();
sshConfig = MemoryFileSystem.test().file('irrelevant')..writeAsStringSync('\n');
});
testUsingContext('`unforward` prints stdout and stderr if ssh command failed', () async {
final FuchsiaDevice device = FuchsiaDevice('id', name: 'tester');
+ processManager.addCommand(const FakeCommand(
+ command: <String>['ssh', '-F', '/irrelevant', '-O', 'cancel', '-vvv', '-L', '0:127.0.0.1:1', 'id'],
+ exitCode: 1,
+ stdout: '<stdout>',
+ stderr: '<stderr>',
+ ));
- final MockProcessResult mockFailureProcessResult = MockProcessResult();
- when(mockFailureProcessResult.exitCode).thenReturn(1);
- when<String>(mockFailureProcessResult.stdout as String).thenReturn('<stdout>');
- when<String>(mockFailureProcessResult.stderr as String).thenReturn('<stderr>');
- when(mockProcessManager.run(<String>[
- 'ssh',
- '-F',
- sshConfig.absolute.path,
- '-O',
- 'cancel',
- '-vvv',
- '-L',
- '0:127.0.0.1:1',
- 'id',
- ])).thenAnswer((Invocation invocation) {
- return Future<ProcessResult>.value(mockFailureProcessResult);
- });
await expectLater(
() => device.portForwarder.unforward(ForwardedPort(/*hostPort=*/ 0, /*devicePort=*/ 1)),
throwsToolExit(message: 'Unforward command failed:\nstdout: <stdout>\nstderr: <stderr>'),
);
}, overrides: <Type, Generator>{
- ProcessManager: () => mockProcessManager,
+ ProcessManager: () => processManager,
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
});
});
group('FuchsiaIsolateDiscoveryProtocol', () {
- MockPortForwarder portForwarder;
-
- setUp(() {
- portForwarder = MockPortForwarder();
- });
-
Future<Uri> findUri(List<FlutterView> views, String expectedIsolateName) async {
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
requests: <VmServiceExpectation>[
@@ -824,8 +714,7 @@
],
httpAddress: Uri.parse('example'),
);
- final MockFuchsiaDevice fuchsiaDevice =
- MockFuchsiaDevice('123', portForwarder, false);
+ final MockFuchsiaDevice fuchsiaDevice = MockFuchsiaDevice('123', const NoOpDevicePortForwarder(), false);
final FuchsiaIsolateDiscoveryProtocol discoveryProtocol =
FuchsiaIsolateDiscoveryProtocol(
fuchsiaDevice,
@@ -834,15 +723,7 @@
(Device device, Uri uri, bool enableServiceAuthCodes) => null,
true, // only poll once.
);
- final MockDartDevelopmentService mockDds = MockDartDevelopmentService();
- when(fuchsiaDevice.dds).thenReturn(mockDds);
- when(mockDds.startDartDevelopmentService(any, any, any, any, logger: anyNamed('logger'))).thenReturn(null);
- when(mockDds.uri).thenReturn(Uri.parse('example'));
- when(fuchsiaDevice.servicePorts())
- .thenAnswer((Invocation invocation) async => <int>[1]);
- when(portForwarder.forward(1))
- .thenAnswer((Invocation invocation) async => 2);
- return await discoveryProtocol.uri;
+ return discoveryProtocol.uri;
}
testUsingContext('can find flutter view with matching isolate name', () async {
@@ -868,8 +749,7 @@
),
], expectedIsolateName);
- expect(
- uri.toString(), 'http://${InternetAddress.loopbackIPv4.address}:0/');
+ expect(uri.toString(), 'http://${InternetAddress.loopbackIPv4.address}:0/');
});
testUsingContext('can handle flutter view without matching isolate name', () async {
@@ -938,337 +818,64 @@
);
});
- group('Fuchsia app start and stop: ', () {
- MemoryFileSystem memoryFileSystem;
- FakeOperatingSystemUtils osUtils;
- FakeFuchsiaDeviceTools fuchsiaDeviceTools;
- MockFuchsiaSdk fuchsiaSdk;
- Artifacts artifacts;
- FakeProcessManager fakeSuccessfulProcessManager;
- FakeProcessManager fakeFailedProcessManager;
- File sshConfig;
-
- setUp(() {
- memoryFileSystem = MemoryFileSystem.test();
- osUtils = FakeOperatingSystemUtils();
- fuchsiaDeviceTools = FakeFuchsiaDeviceTools();
- fuchsiaSdk = MockFuchsiaSdk();
- sshConfig = MemoryFileSystem.test().file('ssh_config')..writeAsStringSync('\n');
- artifacts = Artifacts.test();
- for (final BuildMode mode in <BuildMode>[BuildMode.debug, BuildMode.release]) {
- memoryFileSystem.file(
- artifacts.getArtifactPath(Artifact.fuchsiaKernelCompiler,
- platform: TargetPlatform.fuchsia_arm64, mode: mode),
- ).createSync();
-
- memoryFileSystem.file(
- artifacts.getArtifactPath(Artifact.platformKernelDill,
- platform: TargetPlatform.fuchsia_arm64, mode: mode),
- ).createSync();
-
- memoryFileSystem.file(
- artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath,
- platform: TargetPlatform.fuchsia_arm64, mode: mode),
- ).createSync();
-
- memoryFileSystem.file(
- artifacts.getArtifactPath(Artifact.fuchsiaFlutterRunner,
- platform: TargetPlatform.fuchsia_arm64, mode: mode),
- ).createSync();
- }
- fakeSuccessfulProcessManager = FakeProcessManager.list(<FakeCommand>[
- FakeCommand(
- command: <String>['ssh', '-F', sshConfig.absolute.path, '123', r'echo $SSH_CONNECTION'],
- stdout: 'fe80::8c6c:2fff:fe3d:c5e1%ethp0003 50666 fe80::5054:ff:fe63:5e7a%ethp0003 22',
- ),
- ]);
- fakeFailedProcessManager = FakeProcessManager.list(<FakeCommand>[
- FakeCommand(
- command: <String>['ssh', '-F', sshConfig.absolute.path, '123', r'echo $SSH_CONNECTION'],
- stdout: '',
- stderr: '',
- exitCode: 1,
- ),
- ]);
- });
-
- Future<LaunchResult> setupAndStartApp({
- @required bool prebuilt,
- @required BuildMode mode,
- }) async {
- const String appName = 'app_name';
- final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123');
- globals.fs.directory('fuchsia').createSync(recursive: true);
- final File pubspecFile = globals.fs.file('pubspec.yaml')..createSync();
- pubspecFile.writeAsStringSync('name: $appName');
-
- FuchsiaApp app;
- if (prebuilt) {
- final File far = globals.fs.file('app_name-0.far')..createSync();
- app = FuchsiaApp.fromPrebuiltApp(far);
- } else {
- globals.fs.file(globals.fs.path.join('fuchsia', 'meta', '$appName.cmx'))
- ..createSync(recursive: true)
- ..writeAsStringSync('{}');
- globals.fs.file('.packages').createSync();
- globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
- app = BuildableFuchsiaApp(project: FlutterProject.fromDirectoryTest(globals.fs.currentDirectory).fuchsia);
- }
-
- final DebuggingOptions debuggingOptions = DebuggingOptions.disabled(BuildInfo(mode, null, treeShakeIcons: false));
- return 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>{
- Artifacts: () => artifacts,
- FileSystem: () => memoryFileSystem,
- ProcessManager: () => fakeSuccessfulProcessManager,
- FuchsiaDeviceTools: () => fuchsiaDeviceTools,
- FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- FuchsiaSdk: () => fuchsiaSdk,
- OperatingSystemUtils: () => osUtils,
- });
-
- testUsingContext('start and stop prebuilt in release mode', () async {
- const String appName = 'app_name';
- final FuchsiaDevice device = FuchsiaDeviceWithFakeDiscovery('123');
- globals.fs.directory('fuchsia').createSync(recursive: true);
- final File pubspecFile = globals.fs.file('pubspec.yaml')..createSync();
- pubspecFile.writeAsStringSync('name: $appName');
- final File far = globals.fs.file('app_name-0.far')..createSync();
-
- final FuchsiaApp app = FuchsiaApp.fromPrebuiltApp(far);
- final DebuggingOptions debuggingOptions =
- DebuggingOptions.disabled(const BuildInfo(BuildMode.release, null, treeShakeIcons: false));
- 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);
- }, overrides: <Type, Generator>{
- Artifacts: () => artifacts,
- FileSystem: () => memoryFileSystem,
- ProcessManager: () => fakeSuccessfulProcessManager,
- FuchsiaDeviceTools: () => fuchsiaDeviceTools,
- FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- 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>{
- Artifacts: () => artifacts,
- FileSystem: () => memoryFileSystem,
- ProcessManager: () => fakeSuccessfulProcessManager,
- FuchsiaDeviceTools: () => fuchsiaDeviceTools,
- FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- 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>{
- Artifacts: () => artifacts,
- FileSystem: () => memoryFileSystem,
- ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
- const FakeCommand(
- command: <String>[
- 'Artifact.genSnapshot.TargetPlatform.fuchsia_arm64.release',
- '--deterministic',
- '--snapshot_kind=app-aot-elf',
- '--elf=build/fuchsia/elf.aotsnapshot',
- 'build/fuchsia/app_name.dil'
- ],
- ),
- FakeCommand(
- command: <String>['ssh', '-F', sshConfig.absolute.path, '123', r'echo $SSH_CONNECTION'],
- stdout: 'fe80::8c6c:2fff:fe3d:c5e1%ethp0003 50666 fe80::5054:ff:fe63:5e7a%ethp0003 22',
- ),
- ]),
- FuchsiaDeviceTools: () => fuchsiaDeviceTools,
- FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- 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>{
- Artifacts: () => artifacts,
- FileSystem: () => memoryFileSystem,
- ProcessManager: () => fakeSuccessfulProcessManager,
- FuchsiaDeviceTools: () => fuchsiaDeviceTools,
- FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- FuchsiaSdk: () => fuchsiaSdk,
- OperatingSystemUtils: () => osUtils,
- });
-
- testUsingContext('fail when cant get ssh config', () async {
- expect(() async =>
- setupAndStartApp(prebuilt: true, mode: BuildMode.release),
- throwsToolExit(message: 'Cannot interact with device. No ssh config.\n'
- 'Try setting FUCHSIA_SSH_CONFIG or FUCHSIA_BUILD_DIR.'));
- }, overrides: <Type, Generator>{
- Artifacts: () => artifacts,
- FileSystem: () => memoryFileSystem,
- ProcessManager: () => FakeProcessManager.any(),
- FuchsiaDeviceTools: () => fuchsiaDeviceTools,
- FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: null),
- OperatingSystemUtils: () => osUtils,
- });
-
- testUsingContext('fail when cant get host address', () async {
- expect(() async =>
- setupAndStartApp(prebuilt: true, mode: BuildMode.release),
- throwsToolExit(message: 'Failed to get local address, aborting.'));
- }, overrides: <Type, Generator>{
- Artifacts: () => artifacts,
- FileSystem: () => memoryFileSystem,
- ProcessManager: () => fakeFailedProcessManager,
- FuchsiaDeviceTools: () => fuchsiaDeviceTools,
- FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- 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>{
- Artifacts: () => artifacts,
- FileSystem: () => memoryFileSystem,
- ProcessManager: () => fakeSuccessfulProcessManager,
- FuchsiaDeviceTools: () => fuchsiaDeviceTools,
- FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- 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>{
- Artifacts: () => artifacts,
- FileSystem: () => memoryFileSystem,
- ProcessManager: () => fakeSuccessfulProcessManager,
- FuchsiaDeviceTools: () => FakeFuchsiaDeviceTools(amber: FailingAmberCtl()),
- FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- 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>{
- Artifacts: () => artifacts,
- FileSystem: () => memoryFileSystem,
- ProcessManager: () => fakeSuccessfulProcessManager,
- FuchsiaDeviceTools: () => FakeFuchsiaDeviceTools(tiles: FailingTilesCtl()),
- FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- FuchsiaSdk: () => fuchsiaSdk,
- OperatingSystemUtils: () => osUtils,
- });
-
- });
-
group('sdkNameAndVersion: ', () {
File sshConfig;
- MockProcessManager mockSuccessProcessManager;
- MockProcessResult mockSuccessProcessResult;
- MockProcessManager mockFailureProcessManager;
- MockProcessResult mockFailureProcessResult;
- MockProcessManager emptyStdoutProcessManager;
- MockProcessResult emptyStdoutProcessResult;
+ FakeProcessManager processManager;
setUp(() {
sshConfig = MemoryFileSystem.test().file('ssh_config')..writeAsStringSync('\n');
-
- mockSuccessProcessManager = MockProcessManager();
- mockSuccessProcessResult = MockProcessResult();
- when(mockSuccessProcessManager.run(any)).thenAnswer(
- (Invocation invocation) => Future<ProcessResult>.value(mockSuccessProcessResult));
- when(mockSuccessProcessResult.exitCode).thenReturn(0);
- when<String>(mockSuccessProcessResult.stdout as String).thenReturn('version');
- when<String>(mockSuccessProcessResult.stderr as String).thenReturn('');
-
- mockFailureProcessManager = MockProcessManager();
- mockFailureProcessResult = MockProcessResult();
- when(mockFailureProcessManager.run(any)).thenAnswer(
- (Invocation invocation) => Future<ProcessResult>.value(mockFailureProcessResult));
- when(mockFailureProcessResult.exitCode).thenReturn(1);
- when<String>(mockFailureProcessResult.stdout as String).thenReturn('');
- when<String>(mockFailureProcessResult.stderr as String).thenReturn('');
-
- emptyStdoutProcessManager = MockProcessManager();
- emptyStdoutProcessResult = MockProcessResult();
- when(emptyStdoutProcessManager.run(any)).thenAnswer((Invocation invocation) =>
- Future<ProcessResult>.value(emptyStdoutProcessResult));
- when(emptyStdoutProcessResult.exitCode).thenReturn(0);
- when<String>(emptyStdoutProcessResult.stdout as String).thenReturn('');
- when<String>(emptyStdoutProcessResult.stderr as String).thenReturn('');
+ processManager = FakeProcessManager.empty();
});
testUsingContext('does not throw on non-existent ssh config', () async {
final FuchsiaDevice device = FuchsiaDevice('123');
+
expect(await device.sdkNameAndVersion, equals('Fuchsia'));
}, overrides: <Type, Generator>{
- ProcessManager: () => mockSuccessProcessManager,
+ ProcessManager: () => processManager,
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: null),
- FuchsiaSdk: () => MockFuchsiaSdk(),
+ FuchsiaSdk: () => FakeFuchsiaSdk(),
});
testUsingContext('returns what we get from the device on success', () async {
+ processManager.addCommand(const FakeCommand(
+ command: <String>['ssh', '-F', '/ssh_config', '123', 'cat /pkgfs/packages/build-info/0/data/version'],
+ stdout: 'version'
+ ));
final FuchsiaDevice device = FuchsiaDevice('123');
+
expect(await device.sdkNameAndVersion, equals('Fuchsia version'));
}, overrides: <Type, Generator>{
- ProcessManager: () => mockSuccessProcessManager,
+ ProcessManager: () => processManager,
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- FuchsiaSdk: () => MockFuchsiaSdk(),
+ FuchsiaSdk: () => FakeFuchsiaSdk(),
});
testUsingContext('returns "Fuchsia" when device command fails', () async {
+ processManager.addCommand(const FakeCommand(
+ command: <String>['ssh', '-F', '/ssh_config', '123', 'cat /pkgfs/packages/build-info/0/data/version'],
+ exitCode: 1,
+ ));
final FuchsiaDevice device = FuchsiaDevice('123');
+
expect(await device.sdkNameAndVersion, equals('Fuchsia'));
}, overrides: <Type, Generator>{
- ProcessManager: () => mockFailureProcessManager,
+ ProcessManager: () => processManager,
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- FuchsiaSdk: () => MockFuchsiaSdk(),
+ FuchsiaSdk: () => FakeFuchsiaSdk(),
});
testUsingContext('returns "Fuchsia" when device gives an empty result', () async {
+ processManager.addCommand(const FakeCommand(
+ command: <String>['ssh', '-F', '/ssh_config', '123', 'cat /pkgfs/packages/build-info/0/data/version'],
+ ));
final FuchsiaDevice device = FuchsiaDevice('123');
+
expect(await device.sdkNameAndVersion, equals('Fuchsia'));
}, overrides: <Type, Generator>{
- ProcessManager: () => emptyStdoutProcessManager,
+ ProcessManager: () => processManager,
FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
- FuchsiaSdk: () => MockFuchsiaSdk(),
+ FuchsiaSdk: () => FakeFuchsiaSdk(),
});
});
}
@@ -1280,43 +887,7 @@
final String name;
}
-class MockProcessManager extends Mock implements ProcessManager {}
-
-class MockProcessResult extends Mock implements ProcessResult {}
-
-class MockProcess extends Mock implements Process {}
-
-Process _createMockProcess({
- int exitCode = 0,
- String stdout = '',
- String stderr = '',
- bool persistent = false,
-}) {
- final Stream<List<int>> stdoutStream = Stream<List<int>>.fromIterable(<List<int>>[
- utf8.encode(stdout),
- ]);
- final Stream<List<int>> stderrStream = Stream<List<int>>.fromIterable(<List<int>>[
- utf8.encode(stderr),
- ]);
- final Process process = MockProcess();
-
- when(process.stdout).thenAnswer((_) => stdoutStream);
- when(process.stderr).thenAnswer((_) => stderrStream);
-
- if (persistent) {
- final Completer<int> exitCodeCompleter = Completer<int>();
- when(process.kill()).thenAnswer((_) {
- exitCodeCompleter.complete(-11);
- return true;
- });
- when(process.exitCode).thenAnswer((_) => exitCodeCompleter.future);
- } else {
- when(process.exitCode).thenAnswer((_) => Future<int>.value(exitCode));
- }
- return process;
-}
-
-class MockFuchsiaDevice extends Mock implements FuchsiaDevice {
+class MockFuchsiaDevice extends Fake implements FuchsiaDevice {
MockFuchsiaDevice(this.id, this.portForwarder, this._ipv6);
final bool _ipv6;
@@ -1332,9 +903,25 @@
@override
Future<TargetPlatform> get targetPlatform async => TargetPlatform.fuchsia_arm64;
+
+ @override
+ String get name => 'fuchsia';
+
+ @override
+ Future<List<int>> servicePorts() async => <int>[1];
+
+ @override
+ DartDevelopmentService get dds => FakeDartDevelopmentService();
}
-class MockPortForwarder extends Mock implements DevicePortForwarder {}
+class FakePortForwarder extends Fake implements DevicePortForwarder {
+ bool disposed = false;
+
+ @override
+ Future<void> dispose() async {
+ disposed = true;
+ }
+}
class FuchsiaDeviceWithFakeDiscovery extends FuchsiaDevice {
FuchsiaDeviceWithFakeDiscovery(String id, {String name}) : super(id, name: name);
@@ -1356,282 +943,6 @@
void dispose() {}
}
-class FakeFuchsiaAmberCtl implements FuchsiaAmberCtl {
- @override
- Future<bool> addSrc(FuchsiaDevice device, FuchsiaPackageServer server) async {
- return true;
- }
-
- @override
- Future<bool> rmSrc(FuchsiaDevice device, FuchsiaPackageServer server) async {
- return true;
- }
-
- @override
- Future<bool> getUp(FuchsiaDevice device, String packageName) async {
- return true;
- }
-
- @override
- Future<bool> addRepoCfg(FuchsiaDevice device, FuchsiaPackageServer server) async {
- return true;
- }
-
- @override
- Future<bool> pkgCtlResolve(FuchsiaDevice device, FuchsiaPackageServer server, String packageName) async {
- return true;
- }
-
- @override
- Future<bool> pkgCtlRepoRemove(FuchsiaDevice device, FuchsiaPackageServer server) async {
- return true;
- }
-}
-
-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;
- }
-
- @override
- Future<bool> addRepoCfg(FuchsiaDevice device, FuchsiaPackageServer server) async {
- return false;
- }
-
- @override
- Future<bool> pkgCtlResolve(FuchsiaDevice device, FuchsiaPackageServer server, String packageName) async {
- return false;
- }
-
- @override
- Future<bool> pkgCtlRepoRemove(FuchsiaDevice device, FuchsiaPackageServer server) async {
- return false;
- }
-}
-
-class FakeFuchsiaTilesCtl implements FuchsiaTilesCtl {
- final Map<int, String> _runningApps = <int, String>{};
- bool _started = false;
- int _nextAppId = 1;
-
- @override
- Future<bool> start(FuchsiaDevice device) async {
- _started = true;
- return true;
- }
-
- @override
- Future<Map<int, String>> list(FuchsiaDevice device) async {
- if (!_started) {
- return null;
- }
- return _runningApps;
- }
-
- @override
- Future<bool> add(FuchsiaDevice device, String url, List<String> args) async {
- if (!_started) {
- return false;
- }
- _runningApps[_nextAppId] = url;
- _nextAppId++;
- return true;
- }
-
- @override
- Future<bool> remove(FuchsiaDevice device, int key) async {
- if (!_started) {
- return false;
- }
- _runningApps.remove(key);
- return true;
- }
-
- @override
- Future<bool> quit(FuchsiaDevice device) async {
- if (!_started) {
- return false;
- }
- _started = false;
- return true;
- }
-}
-
-class FailingTilesCtl implements FuchsiaTilesCtl {
- @override
- Future<bool> start(FuchsiaDevice device) async {
- return false;
- }
-
- @override
- 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 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
- Future<bool> init(String buildPath, String appName) async {
- if (!globals.fs.directory(buildPath).existsSync()) {
- return false;
- }
- globals.fs
- .file(globals.fs.path.join(buildPath, 'meta', 'package'))
- .createSync(recursive: true);
- _appName = appName;
- return true;
- }
-
- @override
- Future<bool> build(String buildPath, String manifestPath) async {
- if (!globals.fs.file(globals.fs.path.join(buildPath, 'meta', 'package')).existsSync() ||
- !globals.fs.file(manifestPath).existsSync()) {
- return false;
- }
- globals.fs.file(globals.fs.path.join(buildPath, 'meta.far')).createSync(recursive: true);
- return true;
- }
-
- @override
- Future<bool> archive(String buildPath, String manifestPath) async {
- if (!globals.fs.file(globals.fs.path.join(buildPath, 'meta', 'package')).existsSync() ||
- !globals.fs.file(manifestPath).existsSync()) {
- return false;
- }
- if (_appName == null) {
- return false;
- }
- globals.fs
- .file(globals.fs.path.join(buildPath, '$_appName-0.far'))
- .createSync(recursive: true);
- return true;
- }
-
- @override
- Future<bool> newrepo(String repoPath) async {
- if (!globals.fs.directory(repoPath).existsSync()) {
- return false;
- }
- return true;
- }
-
- @override
- Future<Process> serve(String repoPath, String host, int port) async {
- return _createMockProcess(persistent: true);
- }
-
- @override
- Future<bool> publish(String repoPath, String packagePath) async {
- if (!globals.fs.directory(repoPath).existsSync()) {
- return false;
- }
- if (!globals.fs.file(packagePath).existsSync()) {
- return false;
- }
- return true;
- }
-}
-
-class FailingPM implements FuchsiaPM {
- @override
- Future<bool> init(String buildPath, String appName) async {
- return false;
- }
-
-
- @override
- Future<bool> build(String buildPath, String manifestPath) async {
- return false;
- }
-
- @override
- Future<bool> archive(String buildPath, 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,
- @required String target, // E.g., lib/main.dart
- BuildInfo buildInfo = BuildInfo.debug,
- }) async {
- final String outDir = getFuchsiaBuildDirectory();
- final String appName = fuchsiaProject.project.manifest.appName;
- final String manifestPath = globals.fs.path.join(outDir, '$appName.dilpmanifest');
- globals.fs.file(manifestPath).createSync(recursive: true);
- }
-}
-
-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({ Duration timeout }) async {
@@ -1656,16 +967,20 @@
}
}
-class MockFuchsiaSdk extends Mock implements FuchsiaSdk {
- MockFuchsiaSdk({
+class FakeFuchsiaSdk extends Fake implements FuchsiaSdk {
+ FakeFuchsiaSdk({
FuchsiaPM pm,
FuchsiaKernelCompiler compiler,
FuchsiaDevFinder devFinder,
FuchsiaFfx ffx,
- }) : fuchsiaPM = pm ?? FakeFuchsiaPM(),
- fuchsiaKernelCompiler = compiler ?? FakeFuchsiaKernelCompiler(),
+ String devices,
+ String devFinderDevices,
+ }) : fuchsiaPM = pm,
+ fuchsiaKernelCompiler = compiler,
fuchsiaDevFinder = devFinder ?? FakeFuchsiaDevFinder(),
- fuchsiaFfx = ffx ?? FakeFuchsiaFfx();
+ fuchsiaFfx = ffx ?? FakeFuchsiaFfx(),
+ _devices = devices,
+ _devFinderDevices = devFinderDevices;
@override
final FuchsiaPM fuchsiaPM;
@@ -1678,7 +993,48 @@
@override
final FuchsiaFfx fuchsiaFfx;
+
+ final String _devices;
+ final String _devFinderDevices;
+
+ @override
+ Future<String> listDevices({Duration timeout, bool useDeviceFinder = false}) async {
+ if (useDeviceFinder) {
+ return _devFinderDevices;
+ }
+ return _devices;
+ }
}
-class MockDartDevelopmentService extends Mock implements DartDevelopmentService {}
-class MockFuchsiaWorkflow extends Mock implements FuchsiaWorkflow {}
+class FakeDartDevelopmentService extends Fake implements DartDevelopmentService {
+ @override
+ Future<void> startDartDevelopmentService(Uri observatoryUri, int hostPort, bool ipv6, bool disableServiceAuthCodes, {Logger logger}) async { }
+
+ @override
+ Uri get uri => Uri.parse('example');
+}
+
+class FakeFuchsiaWorkflow implements FuchsiaWorkflow {
+ FakeFuchsiaWorkflow({
+ this.appliesToHostPlatform = true,
+ this.canLaunchDevices = true,
+ this.canListDevices = true,
+ this.canListEmulators = true,
+ this.shouldUseDeviceFinder = true,
+ });
+
+ @override
+ bool appliesToHostPlatform;
+
+ @override
+ bool canLaunchDevices;
+
+ @override
+ bool canListDevices;
+
+ @override
+ bool canListEmulators;
+
+ @override
+ bool shouldUseDeviceFinder;
+}