[flutter_tools] macOS cleanups, attach to log reader in release mode (#61913)
diff --git a/packages/flutter_tools/lib/src/context_runner.dart b/packages/flutter_tools/lib/src/context_runner.dart
index 2c6499c..1cb415c 100644
--- a/packages/flutter_tools/lib/src/context_runner.dart
+++ b/packages/flutter_tools/lib/src/context_runner.dart
@@ -142,6 +142,10 @@
config: globals.config,
fuchsiaWorkflow: fuchsiaWorkflow,
xcDevice: globals.xcdevice,
+ macOSWorkflow: MacOSWorkflow(
+ platform: globals.platform,
+ featureFlags: featureFlags,
+ ),
),
Doctor: () => Doctor(logger: globals.logger),
DoctorValidatorsProvider: () => DoctorValidatorsProvider.defaultInstance,
@@ -193,7 +197,10 @@
outputPreferences: globals.outputPreferences,
timeoutConfiguration: timeoutConfiguration,
),
- MacOSWorkflow: () => const MacOSWorkflow(),
+ MacOSWorkflow: () => MacOSWorkflow(
+ featureFlags: featureFlags,
+ platform: globals.platform,
+ ),
MDnsObservatoryDiscovery: () => MDnsObservatoryDiscovery(),
OperatingSystemUtils: () => OperatingSystemUtils(
fileSystem: globals.fs,
diff --git a/packages/flutter_tools/lib/src/desktop_device.dart b/packages/flutter_tools/lib/src/desktop_device.dart
index 937bfcd..26561e5 100644
--- a/packages/flutter_tools/lib/src/desktop_device.dart
+++ b/packages/flutter_tools/lib/src/desktop_device.dart
@@ -5,10 +5,12 @@
import 'dart:async';
import 'package:meta/meta.dart';
+import 'package:process/process.dart';
import 'application_package.dart';
import 'base/common.dart';
import 'base/io.dart';
+import 'base/logger.dart';
import 'build_info.dart';
import 'convert.dart';
import 'device.dart';
@@ -18,15 +20,23 @@
/// A partial implementation of Device for desktop-class devices to inherit
/// from, containing implementations that are common to all desktop devices.
abstract class DesktopDevice extends Device {
- DesktopDevice(String identifier, {@required PlatformType platformType, @required bool ephemeral}) : super(
- identifier,
- category: Category.desktop,
- platformType: platformType,
- ephemeral: ephemeral,
- );
+ DesktopDevice(String identifier, {
+ @required PlatformType platformType,
+ @required bool ephemeral,
+ Logger logger,
+ ProcessManager processManager,
+ }) : _logger = logger ?? globals.logger, // TODO(jonahwilliams): remove after updating google3
+ _processManager = processManager ?? globals.processManager,
+ super(
+ identifier,
+ category: Category.desktop,
+ platformType: platformType,
+ ephemeral: ephemeral,
+ );
+ final Logger _logger;
+ final ProcessManager _processManager;
final Set<Process> _runningProcesses = <Process>{};
-
final DesktopLogReader _deviceLogReader = DesktopLogReader();
// Since the host and target devices are the same, no work needs to be done
@@ -108,20 +118,20 @@
final BuildMode buildMode = debuggingOptions?.buildInfo?.mode;
final String executable = executablePathForDevice(package, buildMode);
if (executable == null) {
- globals.printError('Unable to find executable to run');
+ _logger.printError('Unable to find executable to run');
return LaunchResult.failed();
}
- final Process process = await globals.processManager.start(<String>[
+ final Process process = await _processManager.start(<String>[
executable,
]);
_runningProcesses.add(process);
unawaited(process.exitCode.then((_) => _runningProcesses.remove(process)));
+ _deviceLogReader.initializeProcess(process);
if (debuggingOptions?.buildInfo?.isRelease == true) {
return LaunchResult.succeeded();
}
- _deviceLogReader.initializeProcess(process);
final ProtocolDiscovery observatoryDiscovery = ProtocolDiscovery.observatory(_deviceLogReader,
devicePort: debuggingOptions?.deviceVmServicePort,
hostPort: debuggingOptions?.hostVmServicePort,
@@ -133,12 +143,12 @@
onAttached(package, buildMode, process);
return LaunchResult.succeeded(observatoryUri: observatoryUri);
}
- globals.printError(
+ _logger.printError(
'Error waiting for a debug connection: '
'The log reader stopped unexpectedly.',
);
} on Exception catch (error) {
- globals.printError('Error waiting for a debug connection: $error');
+ _logger.printError('Error waiting for a debug connection: $error');
} finally {
await observatoryDiscovery.cancel();
}
@@ -186,9 +196,7 @@
void initializeProcess(Process process) {
process.stdout.listen(_inputController.add);
process.stderr.listen(_inputController.add);
- process.exitCode.then((int result) {
- _inputController.close();
- });
+ process.exitCode.whenComplete(_inputController.close);
}
@override
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart
index 2c72599..1130db6 100644
--- a/packages/flutter_tools/lib/src/device.dart
+++ b/packages/flutter_tools/lib/src/device.dart
@@ -33,6 +33,7 @@
import 'ios/simulators.dart';
import 'linux/linux_device.dart';
import 'macos/macos_device.dart';
+import 'macos/macos_workflow.dart';
import 'macos/xcode.dart';
import 'project.dart';
import 'tester/flutter_tester.dart';
@@ -292,6 +293,7 @@
@required FlutterVersion flutterVersion,
@required Config config,
@required Artifacts artifacts,
+ @required MacOSWorkflow macOSWorkflow,
}) : deviceDiscoverers = <DeviceDiscovery>[
AndroidDevices(
logger: logger,
@@ -322,10 +324,17 @@
logger: logger,
artifacts: artifacts,
),
- MacOSDevices(),
+ MacOSDevices(
+ processManager: processManager,
+ macOSWorkflow: macOSWorkflow,
+ logger: logger,
+ platform: platform,
+ ),
LinuxDevices(
platform: platform,
featureFlags: featureFlags,
+ processManager: processManager,
+ logger: logger,
),
WindowsDevices(),
WebDevices(
diff --git a/packages/flutter_tools/lib/src/doctor.dart b/packages/flutter_tools/lib/src/doctor.dart
index 389068e..8c40420 100644
--- a/packages/flutter_tools/lib/src/doctor.dart
+++ b/packages/flutter_tools/lib/src/doctor.dart
@@ -65,6 +65,11 @@
featureFlags: featureFlags,
);
+ final MacOSWorkflow macOSWorkflow = MacOSWorkflow(
+ platform: globals.platform,
+ featureFlags: featureFlags,
+ );
+
@override
List<DoctorValidator> get validators {
if (_validators != null) {
diff --git a/packages/flutter_tools/lib/src/linux/linux_device.dart b/packages/flutter_tools/lib/src/linux/linux_device.dart
index 2cc4295..8916f46 100644
--- a/packages/flutter_tools/lib/src/linux/linux_device.dart
+++ b/packages/flutter_tools/lib/src/linux/linux_device.dart
@@ -3,12 +3,15 @@
// found in the LICENSE file.
import 'package:meta/meta.dart';
+import 'package:process/process.dart';
+import '../base/logger.dart';
import '../base/platform.dart';
import '../build_info.dart';
import '../desktop_device.dart';
import '../device.dart';
import '../features.dart';
+import '../globals.dart' as globals;
import '../project.dart';
import 'application_package.dart';
import 'build_linux.dart';
@@ -16,10 +19,15 @@
/// A device that represents a desktop Linux target.
class LinuxDevice extends DesktopDevice {
- LinuxDevice() : super(
+ LinuxDevice({
+ @required ProcessManager processManager,
+ @required Logger logger,
+ }) : super(
'linux',
platformType: PlatformType.linux,
ephemeral: false,
+ logger: logger,
+ processManager: processManager,
);
@override
@@ -59,15 +67,21 @@
LinuxDevices({
@required Platform platform,
@required FeatureFlags featureFlags,
- }) : _platform = platform,
+ ProcessManager processManager,
+ Logger logger,
+ }) : _platform = platform ?? globals.platform, // TODO(jonahwilliams): remove after google3 roll
_linuxWorkflow = LinuxWorkflow(
platform: platform,
featureFlags: featureFlags,
),
+ _logger = logger,
+ _processManager = processManager ?? globals.processManager,
super('linux devices');
final Platform _platform;
final LinuxWorkflow _linuxWorkflow;
+ final ProcessManager _processManager;
+ final Logger _logger;
@override
bool get supportsPlatform => _platform.isLinux;
@@ -81,7 +95,10 @@
return const <Device>[];
}
return <Device>[
- LinuxDevice(),
+ LinuxDevice(
+ logger: _logger,
+ processManager: _processManager,
+ ),
];
}
diff --git a/packages/flutter_tools/lib/src/macos/macos_device.dart b/packages/flutter_tools/lib/src/macos/macos_device.dart
index 1d7ef01..f92b7f3 100644
--- a/packages/flutter_tools/lib/src/macos/macos_device.dart
+++ b/packages/flutter_tools/lib/src/macos/macos_device.dart
@@ -2,11 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import 'package:meta/meta.dart';
+import 'package:process/process.dart';
+
import '../base/io.dart';
+import '../base/logger.dart';
+import '../base/platform.dart';
import '../build_info.dart';
import '../desktop_device.dart';
import '../device.dart';
-import '../globals.dart' as globals;
import '../macos/application_package.dart';
import '../project.dart';
import 'build_macos.dart';
@@ -14,11 +18,21 @@
/// A device that represents a desktop MacOS target.
class MacOSDevice extends DesktopDevice {
- MacOSDevice() : super(
- 'macos',
- platformType: PlatformType.macos,
- ephemeral: false,
- );
+ MacOSDevice({
+ @required ProcessManager processManager,
+ @required Logger logger,
+ }) : _processManager = processManager,
+ _logger = logger,
+ super(
+ 'macos',
+ platformType: PlatformType.macos,
+ ephemeral: false,
+ processManager: processManager,
+ logger: logger,
+ );
+
+ final ProcessManager _processManager;
+ final Logger _logger;
@override
bool isSupported() => true;
@@ -44,7 +58,7 @@
flutterProject: FlutterProject.current(),
buildInfo: buildInfo,
targetOverride: mainPath,
- verboseLogging: globals.logger.isVerbose,
+ verboseLogging: _logger.isVerbose,
);
}
@@ -59,7 +73,7 @@
// than post-attach, since this won't run for release builds, but there's
// no general-purpose way of knowing when a process is far enoug along in
// the launch process for 'open' to foreground it.
- globals.processManager.run(<String>[
+ _processManager.run(<String>[
'open', package.applicationBundle(buildMode),
]).then((ProcessResult result) {
if (result.exitCode != 0) {
@@ -70,13 +84,27 @@
}
class MacOSDevices extends PollingDeviceDiscovery {
- MacOSDevices() : super('macOS devices');
+ MacOSDevices({
+ @required Platform platform,
+ @required MacOSWorkflow macOSWorkflow,
+ @required ProcessManager processManager,
+ @required Logger logger,
+ }) : _logger = logger,
+ _platform = platform,
+ _macOSWorkflow = macOSWorkflow,
+ _processManager = processManager,
+ super('macOS devices');
+
+ final MacOSWorkflow _macOSWorkflow;
+ final Platform _platform;
+ final ProcessManager _processManager;
+ final Logger _logger;
@override
- bool get supportsPlatform => globals.platform.isMacOS;
+ bool get supportsPlatform => _platform.isMacOS;
@override
- bool get canListAnything => macOSWorkflow.canListDevices;
+ bool get canListAnything => _macOSWorkflow.canListDevices;
@override
Future<List<Device>> pollingGetDevices({ Duration timeout }) async {
@@ -84,7 +112,7 @@
return const <Device>[];
}
return <Device>[
- MacOSDevice(),
+ MacOSDevice(processManager: _processManager, logger: _logger),
];
}
diff --git a/packages/flutter_tools/lib/src/macos/macos_workflow.dart b/packages/flutter_tools/lib/src/macos/macos_workflow.dart
index 0ae1ae4..b91c68c 100644
--- a/packages/flutter_tools/lib/src/macos/macos_workflow.dart
+++ b/packages/flutter_tools/lib/src/macos/macos_workflow.dart
@@ -2,29 +2,35 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import '../base/context.dart';
+import 'package:meta/meta.dart';
+
+import '../base/platform.dart';
import '../doctor.dart';
import '../features.dart';
-import '../globals.dart' as globals;
-/// The [MacOSWorkflow] instance.
-MacOSWorkflow get macOSWorkflow => context.get<MacOSWorkflow>();
/// The macOS-specific implementation of a [Workflow].
///
/// This workflow requires the flutter-desktop-embedding as a sibling
/// repository to the flutter repo.
class MacOSWorkflow implements Workflow {
- const MacOSWorkflow();
+ const MacOSWorkflow({
+ @required Platform platform,
+ @required FeatureFlags featureFlags,
+ }) : _platform = platform,
+ _featureFlags = featureFlags;
+
+ final Platform _platform;
+ final FeatureFlags _featureFlags;
@override
- bool get appliesToHostPlatform => globals.platform.isMacOS && featureFlags.isMacOSEnabled;
+ bool get appliesToHostPlatform => _platform.isMacOS && _featureFlags.isMacOSEnabled;
@override
- bool get canLaunchDevices => globals.platform.isMacOS && featureFlags.isMacOSEnabled;
+ bool get canLaunchDevices => _platform.isMacOS && _featureFlags.isMacOSEnabled;
@override
- bool get canListDevices => globals.platform.isMacOS && featureFlags.isMacOSEnabled;
+ bool get canListDevices => _platform.isMacOS && _featureFlags.isMacOSEnabled;
@override
bool get canListEmulators => false;
diff --git a/packages/flutter_tools/test/general.shard/linux/linux_device_test.dart b/packages/flutter_tools/test/general.shard/linux/linux_device_test.dart
index 72ec9f7..5a8e458 100644
--- a/packages/flutter_tools/test/general.shard/linux/linux_device_test.dart
+++ b/packages/flutter_tools/test/general.shard/linux/linux_device_test.dart
@@ -4,6 +4,7 @@
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart';
+import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/device.dart';
@@ -17,15 +18,21 @@
import '../../src/context.dart';
import '../../src/testbed.dart';
-void main() {
- final LinuxDevice device = LinuxDevice();
- final MockPlatform notLinux = MockPlatform();
- when(notLinux.isLinux).thenReturn(false);
+final FakePlatform linux = FakePlatform(
+ operatingSystem: 'linux',
+);
+final FakePlatform windows = FakePlatform(
+ operatingSystem: 'windows',
+);
- final MockPlatform mockLinuxPlatform = MockPlatform();
- when(mockLinuxPlatform.isLinux).thenReturn(true);
+void main() {
testWithoutContext('LinuxDevice defaults', () async {
+ final LinuxDevice device = LinuxDevice(
+ processManager: FakeProcessManager.any(),
+ logger: BufferLogger.test(),
+ );
+
final PrebuiltLinuxApp linuxApp = PrebuiltLinuxApp(executable: 'foo');
expect(await device.targetPlatform, TargetPlatform.linux_x64);
expect(device.name, 'Linux');
@@ -44,30 +51,38 @@
testWithoutContext('LinuxDevice: no devices listed if platform unsupported', () async {
expect(await LinuxDevices(
- platform: notLinux,
+ platform: windows,
featureFlags: TestFeatureFlags(isLinuxEnabled: true),
+ logger: BufferLogger.test(),
+ processManager: FakeProcessManager.any(),
).devices, <Device>[]);
});
testWithoutContext('LinuxDevice: no devices listed if Linux feature flag disabled', () async {
expect(await LinuxDevices(
- platform: mockLinuxPlatform,
+ platform: linux,
featureFlags: TestFeatureFlags(isLinuxEnabled: false),
+ logger: BufferLogger.test(),
+ processManager: FakeProcessManager.any(),
).devices, <Device>[]);
});
testWithoutContext('LinuxDevice: devices', () async {
expect(await LinuxDevices(
- platform: mockLinuxPlatform,
+ platform: linux,
featureFlags: TestFeatureFlags(isLinuxEnabled: true),
+ logger: BufferLogger.test(),
+ processManager: FakeProcessManager.any(),
).devices, hasLength(1));
});
testWithoutContext('LinuxDevice: discoverDevices', () async {
// Timeout ignored.
final List<Device> devices = await LinuxDevices(
- platform: mockLinuxPlatform,
+ platform: linux,
featureFlags: TestFeatureFlags(isLinuxEnabled: true),
+ logger: BufferLogger.test(),
+ processManager: FakeProcessManager.any(),
).discoverDevices(timeout: const Duration(seconds: 10));
expect(devices, hasLength(1));
});
@@ -78,7 +93,10 @@
globals.fs.directory('linux').createSync();
final FlutterProject flutterProject = FlutterProject.current();
- expect(LinuxDevice().isSupportedForProject(flutterProject), true);
+ expect(LinuxDevice(
+ logger: BufferLogger.test(),
+ processManager: FakeProcessManager.any(),
+ ).isSupportedForProject(flutterProject), true);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
ProcessManager: () => FakeProcessManager.any(),
@@ -89,7 +107,10 @@
globals.fs.file('.packages').createSync();
final FlutterProject flutterProject = FlutterProject.current();
- expect(LinuxDevice().isSupportedForProject(flutterProject), false);
+ expect(LinuxDevice(
+ logger: BufferLogger.test(),
+ processManager: FakeProcessManager.any(),
+ ).isSupportedForProject(flutterProject), false);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
ProcessManager: () => FakeProcessManager.any(),
@@ -97,6 +118,10 @@
testUsingContext('LinuxDevice.executablePathForDevice uses the correct package executable', () async {
final MockLinuxApp mockApp = MockLinuxApp();
+ final LinuxDevice device = LinuxDevice(
+ logger: BufferLogger.test(),
+ processManager: FakeProcessManager.any(),
+ );
const String debugPath = 'debug/executable';
const String profilePath = 'profile/executable';
const String releasePath = 'release/executable';
@@ -104,15 +129,13 @@
when(mockApp.executable(BuildMode.profile)).thenReturn(profilePath);
when(mockApp.executable(BuildMode.release)).thenReturn(releasePath);
- expect(LinuxDevice().executablePathForDevice(mockApp, BuildMode.debug), debugPath);
- expect(LinuxDevice().executablePathForDevice(mockApp, BuildMode.profile), profilePath);
- expect(LinuxDevice().executablePathForDevice(mockApp, BuildMode.release), releasePath);
+ expect(device.executablePathForDevice(mockApp, BuildMode.debug), debugPath);
+ expect(device.executablePathForDevice(mockApp, BuildMode.profile), profilePath);
+ expect(device.executablePathForDevice(mockApp, BuildMode.release), releasePath);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
ProcessManager: () => FakeProcessManager.any(),
});
}
-class MockPlatform extends Mock implements Platform {}
-
class MockLinuxApp extends Mock implements LinuxApp {}
diff --git a/packages/flutter_tools/test/general.shard/macos/macos_device_test.dart b/packages/flutter_tools/test/general.shard/macos/macos_device_test.dart
index 728a596..0b0b66e 100644
--- a/packages/flutter_tools/test/general.shard/macos/macos_device_test.dart
+++ b/packages/flutter_tools/test/general.shard/macos/macos_device_test.dart
@@ -2,17 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import 'dart:async';
+
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/context.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/platform.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/device.dart';
-import 'package:flutter_tools/src/features.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/macos/application_package.dart';
import 'package:flutter_tools/src/macos/macos_device.dart';
+import 'package:flutter_tools/src/macos/macos_workflow.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
@@ -21,104 +23,178 @@
import '../../src/context.dart';
import '../../src/testbed.dart';
+final FakePlatform macOS = FakePlatform(
+ operatingSystem: 'macos',
+);
+
+final FakePlatform linux = FakePlatform(
+ operatingSystem: 'linux',
+);
+
void main() {
- group(MacOSDevice, () {
- final MacOSDevice device = MacOSDevice();
- final MockProcessManager mockProcessManager = MockProcessManager();
+ testWithoutContext('default configuration', () async {
+ final MacOSDevice device = MacOSDevice(
+ processManager: FakeProcessManager.any(),
+ logger: BufferLogger.test(),
+ );
+ final MockMacOSApp mockMacOSApp = MockMacOSApp();
- final MockPlatform notMac = MockPlatform();
- when(notMac.isMacOS).thenReturn(false);
- when(notMac.environment).thenReturn(const <String, String>{});
+ expect(await device.targetPlatform, TargetPlatform.darwin_x64);
+ expect(device.name, 'macOS');
+ expect(await device.installApp(mockMacOSApp), true);
+ expect(await device.uninstallApp(mockMacOSApp), true);
+ expect(await device.isLatestBuildInstalled(mockMacOSApp), true);
+ expect(await device.isAppInstalled(mockMacOSApp), true);
+ expect(device.category, Category.desktop);
- final MockPlatform mockMacPlatform = MockPlatform();
- when(mockMacPlatform.isMacOS).thenReturn(true);
+ expect(device.supportsRuntimeMode(BuildMode.debug), true);
+ expect(device.supportsRuntimeMode(BuildMode.profile), true);
+ expect(device.supportsRuntimeMode(BuildMode.release), true);
+ expect(device.supportsRuntimeMode(BuildMode.jitRelease), false);
+ });
- when(mockProcessManager.run(any)).thenAnswer((Invocation invocation) async {
- return ProcessResult(0, 1, '', '');
- });
+ testUsingContext('Attaches to log reader when running in release mode', () async {
+ final Completer<void> completer = Completer<void>();
+ final MacOSDevice device = MacOSDevice(
+ processManager: FakeProcessManager.list(<FakeCommand>[
+ FakeCommand(
+ command: const <String>['Example.app'],
+ stdout: 'Hello World',
+ stderr: 'Goodnight, Moon',
+ completer: completer,
+ )
+ ]),
+ logger: BufferLogger.test(),
+ );
+ final MockMacOSApp mockMacOSApp = MockMacOSApp();
+ when(mockMacOSApp.executable(BuildMode.release)).thenReturn('Example.app');
- testUsingContext('defaults', () async {
- final MockMacOSApp mockMacOSApp = MockMacOSApp();
- expect(await device.targetPlatform, TargetPlatform.darwin_x64);
- expect(device.name, 'macOS');
- expect(await device.installApp(mockMacOSApp), true);
- expect(await device.uninstallApp(mockMacOSApp), true);
- expect(await device.isLatestBuildInstalled(mockMacOSApp), true);
- expect(await device.isAppInstalled(mockMacOSApp), true);
- expect(device.category, Category.desktop);
+ final LaunchResult result = await device.startApp(
+ mockMacOSApp,
+ debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
+ prebuiltApplication: true,
+ );
- expect(device.supportsRuntimeMode(BuildMode.debug), true);
- expect(device.supportsRuntimeMode(BuildMode.profile), true);
- expect(device.supportsRuntimeMode(BuildMode.release), true);
- expect(device.supportsRuntimeMode(BuildMode.jitRelease), false);
- });
+ expect(result.started, true);
- testUsingContext('No devices listed if platform unsupported', () async {
- expect(await MacOSDevices().devices, <Device>[]);
- }, overrides: <Type, Generator>{
- Platform: () => notMac,
- });
+ final DeviceLogReader logReader = device.getLogReader(app: mockMacOSApp);
- testUsingContext('devices', () async {
- expect(await MacOSDevices().devices, hasLength(1));
- }, overrides: <Type, Generator>{
- Platform: () => mockMacPlatform,
- FeatureFlags: () => TestFeatureFlags(isMacOSEnabled: true),
- });
+ expect(logReader.logLines, emits('Hello WorldGoodnight, Moon'));
+ completer.complete();
+ }, overrides: <Type, Generator>{
+ FileSystem: () => MemoryFileSystem.test(),
+ ProcessManager: () => FakeProcessManager.any(),
+ });
- testUsingContext('discoverDevices', () async {
- // Timeout ignored.
- final List<Device> devices = await MacOSDevices().discoverDevices(timeout: const Duration(seconds: 10));
- expect(devices, hasLength(1));
- }, overrides: <Type, Generator>{
- Platform: () => mockMacPlatform,
- FeatureFlags: () => TestFeatureFlags(isMacOSEnabled: true),
- });
+ testWithoutContext('No devices listed if platform is unsupported', () async {
+ expect(await MacOSDevices(
+ processManager: FakeProcessManager.any(),
+ logger: BufferLogger.test(),
+ platform: linux,
+ macOSWorkflow: MacOSWorkflow(
+ featureFlags: TestFeatureFlags(isMacOSEnabled: true),
+ platform: linux,
+ ),
+ ).devices, isEmpty);
+ });
- testUsingContext('isSupportedForProject is true with editable host app', () async {
- globals.fs.file('pubspec.yaml').createSync();
- globals.fs.file('.packages').createSync();
- globals.fs.directory('macos').createSync();
- final FlutterProject flutterProject = FlutterProject.current();
+ testWithoutContext('No devices listed if platform is supported and feature is disabled', () async {
+ final MacOSDevices macOSDevices = MacOSDevices(
+ processManager: FakeProcessManager.any(),
+ logger: BufferLogger.test(),
+ platform: macOS,
+ macOSWorkflow: MacOSWorkflow(
+ featureFlags: TestFeatureFlags(isMacOSEnabled: false),
+ platform: macOS,
+ ),
+ );
- expect(MacOSDevice().isSupportedForProject(flutterProject), true);
- }, overrides: <Type, Generator>{
- FileSystem: () => MemoryFileSystem(),
- ProcessManager: () => FakeProcessManager.any(),
- });
+ expect(await macOSDevices.devices, isEmpty);
+ });
- testUsingContext('isSupportedForProject is false with no host app', () async {
- globals.fs.file('pubspec.yaml').createSync();
- globals.fs.file('.packages').createSync();
- final FlutterProject flutterProject = FlutterProject.current();
+ testWithoutContext('devices listed if platform is supported and feature is enabled', () async {
+ final MacOSDevices macOSDevices = MacOSDevices(
+ processManager: FakeProcessManager.any(),
+ logger: BufferLogger.test(),
+ platform: macOS,
+ macOSWorkflow: MacOSWorkflow(
+ featureFlags: TestFeatureFlags(isMacOSEnabled: true),
+ platform: macOS,
+ ),
+ );
- expect(MacOSDevice().isSupportedForProject(flutterProject), false);
- }, overrides: <Type, Generator>{
- FileSystem: () => MemoryFileSystem(),
- ProcessManager: () => FakeProcessManager.any(),
- });
+ expect(await macOSDevices.devices, hasLength(1));
+ });
- testUsingContext('executablePathForDevice uses the correct package executable', () async {
- final MockMacOSApp mockApp = MockMacOSApp();
- const String debugPath = 'debug/executable';
- const String profilePath = 'profile/executable';
- const String releasePath = 'release/executable';
- when(mockApp.executable(BuildMode.debug)).thenReturn(debugPath);
- when(mockApp.executable(BuildMode.profile)).thenReturn(profilePath);
- when(mockApp.executable(BuildMode.release)).thenReturn(releasePath);
+ testWithoutContext('can discover devices with a provided timeout', () async {
+ final MacOSDevices macOSDevices = MacOSDevices(
+ processManager: FakeProcessManager.any(),
+ logger: BufferLogger.test(),
+ platform: macOS,
+ macOSWorkflow: MacOSWorkflow(
+ featureFlags: TestFeatureFlags(isMacOSEnabled: true),
+ platform: macOS,
+ ),
+ );
- expect(MacOSDevice().executablePathForDevice(mockApp, BuildMode.debug), debugPath);
- expect(MacOSDevice().executablePathForDevice(mockApp, BuildMode.profile), profilePath);
- expect(MacOSDevice().executablePathForDevice(mockApp, BuildMode.release), releasePath);
- }, overrides: <Type, Generator>{
- FileSystem: () => MemoryFileSystem(),
- ProcessManager: () => FakeProcessManager.any(),
- });
+ // Timeout ignored.
+ final List<Device> devices = await macOSDevices.discoverDevices(timeout: const Duration(seconds: 10));
+
+ expect(devices, hasLength(1));
+ });
+
+ testUsingContext('isSupportedForProject is true with editable host app', () async {
+ final MacOSDevice device = MacOSDevice(
+ logger: BufferLogger.test(),
+ processManager: FakeProcessManager.any(),
+ );
+
+ globals.fs.file('pubspec.yaml').createSync();
+ globals.fs.file('.packages').createSync();
+ globals.fs.directory('macos').createSync();
+ final FlutterProject flutterProject = FlutterProject.current();
+
+ expect(device.isSupportedForProject(flutterProject), true);
+ }, overrides: <Type, Generator>{
+ FileSystem: () => MemoryFileSystem.test(),
+ ProcessManager: () => FakeProcessManager.any(),
+ });
+
+ testUsingContext('isSupportedForProject is false with no host app', () async {
+ final MacOSDevice device = MacOSDevice(
+ logger: BufferLogger.test(),
+ processManager: FakeProcessManager.any(),
+ );
+ globals.fs.file('pubspec.yaml').createSync();
+ globals.fs.file('.packages').createSync();
+ final FlutterProject flutterProject = FlutterProject.current();
+
+ expect(device.isSupportedForProject(flutterProject), false);
+ }, overrides: <Type, Generator>{
+ FileSystem: () => MemoryFileSystem.test(),
+ ProcessManager: () => FakeProcessManager.any(),
+ });
+
+ testUsingContext('executablePathForDevice uses the correct package executable', () async {
+ final MockMacOSApp mockApp = MockMacOSApp();
+ final MacOSDevice device = MacOSDevice(
+ logger: BufferLogger.test(),
+ processManager: FakeProcessManager.any(),
+ );
+ const String debugPath = 'debug/executable';
+ const String profilePath = 'profile/executable';
+ const String releasePath = 'release/executable';
+ when(mockApp.executable(BuildMode.debug)).thenReturn(debugPath);
+ when(mockApp.executable(BuildMode.profile)).thenReturn(profilePath);
+ when(mockApp.executable(BuildMode.release)).thenReturn(releasePath);
+
+ expect(device.executablePathForDevice(mockApp, BuildMode.debug), debugPath);
+ expect(device.executablePathForDevice(mockApp, BuildMode.profile), profilePath);
+ expect(device.executablePathForDevice(mockApp, BuildMode.release), releasePath);
+ }, overrides: <Type, Generator>{
+ FileSystem: () => MemoryFileSystem.test(),
+ ProcessManager: () => FakeProcessManager.any(),
});
}
-class MockPlatform extends Mock implements Platform {}
-
class MockMacOSApp extends Mock implements MacOSApp {}
-
-class MockProcessManager extends Mock implements ProcessManager {}
diff --git a/packages/flutter_tools/test/general.shard/macos/macos_workflow_test.dart b/packages/flutter_tools/test/general.shard/macos/macos_workflow_test.dart
index 0c598de..37e4d30 100644
--- a/packages/flutter_tools/test/general.shard/macos/macos_workflow_test.dart
+++ b/packages/flutter_tools/test/general.shard/macos/macos_workflow_test.dart
@@ -3,60 +3,53 @@
// found in the LICENSE file.
import 'package:flutter_tools/src/base/platform.dart';
-import 'package:flutter_tools/src/features.dart';
import 'package:flutter_tools/src/macos/macos_workflow.dart';
-import 'package:mockito/mockito.dart';
-import 'package:process/process.dart';
import '../../src/common.dart';
-import '../../src/context.dart';
import '../../src/testbed.dart';
+final FakePlatform macOS = FakePlatform(
+ operatingSystem: 'macos',
+);
+
+final FakePlatform linux = FakePlatform(
+ operatingSystem: 'linux',
+);
+
void main() {
- MockPlatform mac;
- MockPlatform notMac;
- Testbed testbed;
+ testWithoutContext('Applies to macOS platform', () {
+ final MacOSWorkflow macOSWorkflow = MacOSWorkflow(
+ platform: macOS,
+ featureFlags: TestFeatureFlags(isMacOSEnabled: true),
+ );
- setUp(() {
- mac = MockPlatform();
- notMac = MockPlatform();
- when(mac.isMacOS).thenReturn(true);
- when(notMac.isMacOS).thenReturn(false);
- testbed = Testbed(overrides: <Type, Generator>{
- Platform: () => mac,
- FeatureFlags: () => TestFeatureFlags(isMacOSEnabled: true),
- });
- });
-
- test('Applies to macOS platform', () => testbed.run(() {
expect(macOSWorkflow.appliesToHostPlatform, true);
expect(macOSWorkflow.canListDevices, true);
expect(macOSWorkflow.canLaunchDevices, true);
expect(macOSWorkflow.canListEmulators, false);
- }));
+ });
- test('Does not apply to non-macOS platform', () => testbed.run(() {
+ testWithoutContext('Does not apply to non-macOS platform', () {
+ final MacOSWorkflow macOSWorkflow = MacOSWorkflow(
+ platform: linux,
+ featureFlags: TestFeatureFlags(isMacOSEnabled: true),
+ );
+
expect(macOSWorkflow.appliesToHostPlatform, false);
expect(macOSWorkflow.canListDevices, false);
expect(macOSWorkflow.canLaunchDevices, false);
expect(macOSWorkflow.canListEmulators, false);
- }, overrides: <Type, Generator>{
- Platform: () => notMac,
- }));
+ });
- test('Does not apply when feature is disabled', () => testbed.run(() {
+ testWithoutContext('Does not apply when feature is disabled', () {
+ final MacOSWorkflow macOSWorkflow = MacOSWorkflow(
+ platform: macOS,
+ featureFlags: TestFeatureFlags(isMacOSEnabled: false),
+ );
+
expect(macOSWorkflow.appliesToHostPlatform, false);
expect(macOSWorkflow.canListDevices, false);
expect(macOSWorkflow.canLaunchDevices, false);
expect(macOSWorkflow.canListEmulators, false);
- }, overrides: <Type, Generator>{
- FeatureFlags: () => TestFeatureFlags(isMacOSEnabled: false),
- }));
+ });
}
-
-class MockPlatform extends Mock implements Platform {
- @override
- Map<String, String> environment = <String, String>{};
-}
-
-class MockProcessManager extends Mock implements ProcessManager {}