Unverified Commit ddb81770 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] remove globals from desktop configuration (#67146)

Refactors the desktop devices and workflow to remove unnecessary usage of global variables. This should make it easier to test and continue enhancing the desktop functionality of the tooling

#47161
parent ddb01a0c
...@@ -615,14 +615,13 @@ class AndroidDevice extends Device { ...@@ -615,14 +615,13 @@ class AndroidDevice extends Device {
ProtocolDiscovery observatoryDiscovery; ProtocolDiscovery observatoryDiscovery;
if (debuggingOptions.debuggingEnabled) { if (debuggingOptions.debuggingEnabled) {
// TODO(devoncarew): Remember the forwarding information (so we can later remove the
// port forwarding or set it up again when adb fails on us).
observatoryDiscovery = ProtocolDiscovery.observatory( observatoryDiscovery = ProtocolDiscovery.observatory(
await getLogReader(), await getLogReader(),
portForwarder: portForwarder, portForwarder: portForwarder,
hostPort: debuggingOptions.hostVmServicePort, hostPort: debuggingOptions.hostVmServicePort,
devicePort: debuggingOptions.deviceVmServicePort, devicePort: debuggingOptions.deviceVmServicePort,
ipv6: ipv6, ipv6: ipv6,
logger: _logger,
); );
} }
......
...@@ -144,10 +144,12 @@ Future<T> runInContext<T>( ...@@ -144,10 +144,12 @@ Future<T> runInContext<T>(
config: globals.config, config: globals.config,
fuchsiaWorkflow: fuchsiaWorkflow, fuchsiaWorkflow: fuchsiaWorkflow,
xcDevice: globals.xcdevice, xcDevice: globals.xcdevice,
windowsWorkflow: windowsWorkflow,
macOSWorkflow: MacOSWorkflow( macOSWorkflow: MacOSWorkflow(
platform: globals.platform, platform: globals.platform,
featureFlags: featureFlags, featureFlags: featureFlags,
), ),
operatingSystemUtils: globals.os,
), ),
Doctor: () => Doctor(logger: globals.logger), Doctor: () => Doctor(logger: globals.logger),
DoctorValidatorsProvider: () => DoctorValidatorsProvider.defaultInstance, DoctorValidatorsProvider: () => DoctorValidatorsProvider.defaultInstance,
...@@ -249,7 +251,10 @@ Future<T> runInContext<T>( ...@@ -249,7 +251,10 @@ Future<T> runInContext<T>(
featureFlags: featureFlags, featureFlags: featureFlags,
platform: globals.platform, platform: globals.platform,
), ),
WindowsWorkflow: () => const WindowsWorkflow(), WindowsWorkflow: () => WindowsWorkflow(
featureFlags: featureFlags,
platform: globals.platform,
),
Xcode: () => Xcode( Xcode: () => Xcode(
logger: globals.logger, logger: globals.logger,
processManager: globals.processManager, processManager: globals.processManager,
......
...@@ -12,11 +12,11 @@ import 'base/common.dart'; ...@@ -12,11 +12,11 @@ import 'base/common.dart';
import 'base/file_system.dart'; import 'base/file_system.dart';
import 'base/io.dart'; import 'base/io.dart';
import 'base/logger.dart'; import 'base/logger.dart';
import 'base/os.dart';
import 'build_info.dart'; import 'build_info.dart';
import 'convert.dart'; import 'convert.dart';
import 'devfs.dart'; import 'devfs.dart';
import 'device.dart'; import 'device.dart';
import 'globals.dart' as globals;
import 'protocol_discovery.dart'; import 'protocol_discovery.dart';
/// A partial implementation of Device for desktop-class devices to inherit /// A partial implementation of Device for desktop-class devices to inherit
...@@ -25,12 +25,14 @@ abstract class DesktopDevice extends Device { ...@@ -25,12 +25,14 @@ abstract class DesktopDevice extends Device {
DesktopDevice(String identifier, { DesktopDevice(String identifier, {
@required PlatformType platformType, @required PlatformType platformType,
@required bool ephemeral, @required bool ephemeral,
Logger logger, @required Logger logger,
ProcessManager processManager, @required ProcessManager processManager,
FileSystem fileSystem, @required FileSystem fileSystem,
}) : _logger = logger ?? globals.logger, // TODO(jonahwilliams): remove after updating google3 @required OperatingSystemUtils operatingSystemUtils,
_processManager = processManager ?? globals.processManager, }) : _logger = logger,
_fileSystem = fileSystem ?? globals.fs, _processManager = processManager,
_fileSystem = fileSystem,
_operatingSystemUtils = operatingSystemUtils,
super( super(
identifier, identifier,
category: Category.desktop, category: Category.desktop,
...@@ -41,6 +43,7 @@ abstract class DesktopDevice extends Device { ...@@ -41,6 +43,7 @@ abstract class DesktopDevice extends Device {
final Logger _logger; final Logger _logger;
final ProcessManager _processManager; final ProcessManager _processManager;
final FileSystem _fileSystem; final FileSystem _fileSystem;
final OperatingSystemUtils _operatingSystemUtils;
final Set<Process> _runningProcesses = <Process>{}; final Set<Process> _runningProcesses = <Process>{};
final DesktopLogReader _deviceLogReader = DesktopLogReader(); final DesktopLogReader _deviceLogReader = DesktopLogReader();
...@@ -86,7 +89,7 @@ abstract class DesktopDevice extends Device { ...@@ -86,7 +89,7 @@ abstract class DesktopDevice extends Device {
DevicePortForwarder get portForwarder => const NoOpDevicePortForwarder(); DevicePortForwarder get portForwarder => const NoOpDevicePortForwarder();
@override @override
Future<String> get sdkNameAndVersion async => globals.os.name; Future<String> get sdkNameAndVersion async => _operatingSystemUtils.name;
@override @override
bool supportsRuntimeMode(BuildMode buildMode) => buildMode != BuildMode.jitRelease; bool supportsRuntimeMode(BuildMode buildMode) => buildMode != BuildMode.jitRelease;
...@@ -130,9 +133,11 @@ abstract class DesktopDevice extends Device { ...@@ -130,9 +133,11 @@ abstract class DesktopDevice extends Device {
return LaunchResult.failed(); return LaunchResult.failed();
} }
final Process process = await _processManager.start(<String>[ final Process process = await _processManager.start(
<String>[
executable, executable,
]); ],
);
_runningProcesses.add(process); _runningProcesses.add(process);
unawaited(process.exitCode.then((_) => _runningProcesses.remove(process))); unawaited(process.exitCode.then((_) => _runningProcesses.remove(process)));
...@@ -144,6 +149,7 @@ abstract class DesktopDevice extends Device { ...@@ -144,6 +149,7 @@ abstract class DesktopDevice extends Device {
devicePort: debuggingOptions?.deviceVmServicePort, devicePort: debuggingOptions?.deviceVmServicePort,
hostPort: debuggingOptions?.hostVmServicePort, hostPort: debuggingOptions?.hostVmServicePort,
ipv6: ipv6, ipv6: ipv6,
logger: _logger,
); );
try { try {
final Uri observatoryUri = await observatoryDiscovery.uri; final Uri observatoryUri = await observatoryDiscovery.uri;
...@@ -172,7 +178,7 @@ abstract class DesktopDevice extends Device { ...@@ -172,7 +178,7 @@ abstract class DesktopDevice extends Device {
// Walk a copy of _runningProcesses, since the exit handler removes from the // Walk a copy of _runningProcesses, since the exit handler removes from the
// set. // set.
for (final Process process in Set<Process>.of(_runningProcesses)) { for (final Process process in Set<Process>.of(_runningProcesses)) {
succeeded &= process.kill(); succeeded &= _processManager.killPid(process.pid);
} }
return succeeded; return succeeded;
} }
...@@ -198,9 +204,12 @@ abstract class DesktopDevice extends Device { ...@@ -198,9 +204,12 @@ abstract class DesktopDevice extends Device {
void onAttached(ApplicationPackage package, BuildMode buildMode, Process process) {} void onAttached(ApplicationPackage package, BuildMode buildMode, Process process) {}
} }
/// A log reader for desktop applications that delegates to a [Process] stdout
/// and stderr streams.
class DesktopLogReader extends DeviceLogReader { class DesktopLogReader extends DeviceLogReader {
final StreamController<List<int>> _inputController = StreamController<List<int>>.broadcast(); final StreamController<List<int>> _inputController = StreamController<List<int>>.broadcast();
/// Begin listening to the stdout and stderr streams of the provided [process].
void initializeProcess(Process process) { void initializeProcess(Process process) {
process.stdout.listen(_inputController.add); process.stdout.listen(_inputController.add);
process.stderr.listen(_inputController.add); process.stderr.listen(_inputController.add);
......
...@@ -21,6 +21,7 @@ import 'base/dds.dart'; ...@@ -21,6 +21,7 @@ import 'base/dds.dart';
import 'base/file_system.dart'; import 'base/file_system.dart';
import 'base/io.dart'; import 'base/io.dart';
import 'base/logger.dart'; import 'base/logger.dart';
import 'base/os.dart';
import 'base/platform.dart'; import 'base/platform.dart';
import 'base/user_messages.dart'; import 'base/user_messages.dart';
import 'base/utils.dart'; import 'base/utils.dart';
...@@ -42,6 +43,7 @@ import 'tester/flutter_tester.dart'; ...@@ -42,6 +43,7 @@ import 'tester/flutter_tester.dart';
import 'version.dart'; import 'version.dart';
import 'web/web_device.dart'; import 'web/web_device.dart';
import 'windows/windows_device.dart'; import 'windows/windows_device.dart';
import 'windows/windows_workflow.dart';
DeviceManager get deviceManager => context.get<DeviceManager>(); DeviceManager get deviceManager => context.get<DeviceManager>();
...@@ -340,6 +342,8 @@ class FlutterDeviceManager extends DeviceManager { ...@@ -340,6 +342,8 @@ class FlutterDeviceManager extends DeviceManager {
@required Config config, @required Config config,
@required Artifacts artifacts, @required Artifacts artifacts,
@required MacOSWorkflow macOSWorkflow, @required MacOSWorkflow macOSWorkflow,
@required OperatingSystemUtils operatingSystemUtils,
@required WindowsWorkflow windowsWorkflow,
}) : deviceDiscoverers = <DeviceDiscovery>[ }) : deviceDiscoverers = <DeviceDiscovery>[
AndroidDevices( AndroidDevices(
logger: logger, logger: logger,
...@@ -376,6 +380,7 @@ class FlutterDeviceManager extends DeviceManager { ...@@ -376,6 +380,7 @@ class FlutterDeviceManager extends DeviceManager {
logger: logger, logger: logger,
platform: platform, platform: platform,
fileSystem: fileSystem, fileSystem: fileSystem,
operatingSystemUtils: operatingSystemUtils,
), ),
LinuxDevices( LinuxDevices(
platform: platform, platform: platform,
...@@ -383,8 +388,15 @@ class FlutterDeviceManager extends DeviceManager { ...@@ -383,8 +388,15 @@ class FlutterDeviceManager extends DeviceManager {
processManager: processManager, processManager: processManager,
logger: logger, logger: logger,
fileSystem: fileSystem, fileSystem: fileSystem,
operatingSystemUtils: operatingSystemUtils,
),
WindowsDevices(
processManager: processManager,
operatingSystemUtils: operatingSystemUtils,
logger: logger,
fileSystem: fileSystem,
windowsWorkflow: windowsWorkflow,
), ),
WindowsDevices(),
WebDevices( WebDevices(
featureFlags: featureFlags, featureFlags: featureFlags,
fileSystem: fileSystem, fileSystem: fileSystem,
......
...@@ -7,12 +7,12 @@ import 'package:process/process.dart'; ...@@ -7,12 +7,12 @@ import 'package:process/process.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/logger.dart'; import '../base/logger.dart';
import '../base/os.dart';
import '../base/platform.dart'; import '../base/platform.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../desktop_device.dart'; import '../desktop_device.dart';
import '../device.dart'; import '../device.dart';
import '../features.dart'; import '../features.dart';
import '../globals.dart' as globals;
import '../project.dart'; import '../project.dart';
import 'application_package.dart'; import 'application_package.dart';
import 'build_linux.dart'; import 'build_linux.dart';
...@@ -24,6 +24,7 @@ class LinuxDevice extends DesktopDevice { ...@@ -24,6 +24,7 @@ class LinuxDevice extends DesktopDevice {
@required ProcessManager processManager, @required ProcessManager processManager,
@required Logger logger, @required Logger logger,
@required FileSystem fileSystem, @required FileSystem fileSystem,
@required OperatingSystemUtils operatingSystemUtils,
}) : super( }) : super(
'linux', 'linux',
platformType: PlatformType.linux, platformType: PlatformType.linux,
...@@ -31,6 +32,7 @@ class LinuxDevice extends DesktopDevice { ...@@ -31,6 +32,7 @@ class LinuxDevice extends DesktopDevice {
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
operatingSystemUtils: operatingSystemUtils,
); );
@override @override
...@@ -70,17 +72,19 @@ class LinuxDevices extends PollingDeviceDiscovery { ...@@ -70,17 +72,19 @@ class LinuxDevices extends PollingDeviceDiscovery {
LinuxDevices({ LinuxDevices({
@required Platform platform, @required Platform platform,
@required FeatureFlags featureFlags, @required FeatureFlags featureFlags,
FileSystem fileSystem, @required OperatingSystemUtils operatingSystemUtils,
ProcessManager processManager, @required FileSystem fileSystem,
Logger logger, @required ProcessManager processManager,
}) : _platform = platform ?? globals.platform, // TODO(jonahwilliams): remove after google3 roll @required Logger logger,
}) : _platform = platform,
_linuxWorkflow = LinuxWorkflow( _linuxWorkflow = LinuxWorkflow(
platform: platform, platform: platform,
featureFlags: featureFlags, featureFlags: featureFlags,
), ),
_fileSystem = fileSystem ?? globals.fs, _fileSystem = fileSystem,
_logger = logger, _logger = logger,
_processManager = processManager ?? globals.processManager, _processManager = processManager,
_operatingSystemUtils = operatingSystemUtils,
super('linux devices'); super('linux devices');
final Platform _platform; final Platform _platform;
...@@ -88,6 +92,7 @@ class LinuxDevices extends PollingDeviceDiscovery { ...@@ -88,6 +92,7 @@ class LinuxDevices extends PollingDeviceDiscovery {
final ProcessManager _processManager; final ProcessManager _processManager;
final Logger _logger; final Logger _logger;
final FileSystem _fileSystem; final FileSystem _fileSystem;
final OperatingSystemUtils _operatingSystemUtils;
@override @override
bool get supportsPlatform => _platform.isLinux; bool get supportsPlatform => _platform.isLinux;
...@@ -105,6 +110,7 @@ class LinuxDevices extends PollingDeviceDiscovery { ...@@ -105,6 +110,7 @@ class LinuxDevices extends PollingDeviceDiscovery {
logger: _logger, logger: _logger,
processManager: _processManager, processManager: _processManager,
fileSystem: _fileSystem, fileSystem: _fileSystem,
operatingSystemUtils: _operatingSystemUtils,
), ),
]; ];
} }
......
...@@ -8,11 +8,11 @@ import 'package:process/process.dart'; ...@@ -8,11 +8,11 @@ import 'package:process/process.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/io.dart'; import '../base/io.dart';
import '../base/logger.dart'; import '../base/logger.dart';
import '../base/os.dart';
import '../base/platform.dart'; import '../base/platform.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../desktop_device.dart'; import '../desktop_device.dart';
import '../device.dart'; import '../device.dart';
import '../globals.dart' as globals;
import '../macos/application_package.dart'; import '../macos/application_package.dart';
import '../project.dart'; import '../project.dart';
import 'build_macos.dart'; import 'build_macos.dart';
...@@ -23,7 +23,8 @@ class MacOSDevice extends DesktopDevice { ...@@ -23,7 +23,8 @@ class MacOSDevice extends DesktopDevice {
MacOSDevice({ MacOSDevice({
@required ProcessManager processManager, @required ProcessManager processManager,
@required Logger logger, @required Logger logger,
FileSystem fileSystem, @required FileSystem fileSystem,
@required OperatingSystemUtils operatingSystemUtils,
}) : _processManager = processManager, }) : _processManager = processManager,
_logger = logger, _logger = logger,
super( super(
...@@ -32,7 +33,8 @@ class MacOSDevice extends DesktopDevice { ...@@ -32,7 +33,8 @@ class MacOSDevice extends DesktopDevice {
ephemeral: false, ephemeral: false,
processManager: processManager, processManager: processManager,
logger: logger, logger: logger,
fileSystem: fileSystem ?? globals.fs, fileSystem: fileSystem,
operatingSystemUtils: operatingSystemUtils,
); );
final ProcessManager _processManager; final ProcessManager _processManager;
...@@ -93,12 +95,14 @@ class MacOSDevices extends PollingDeviceDiscovery { ...@@ -93,12 +95,14 @@ class MacOSDevices extends PollingDeviceDiscovery {
@required MacOSWorkflow macOSWorkflow, @required MacOSWorkflow macOSWorkflow,
@required ProcessManager processManager, @required ProcessManager processManager,
@required Logger logger, @required Logger logger,
FileSystem fileSystem, @required FileSystem fileSystem,
@required OperatingSystemUtils operatingSystemUtils,
}) : _logger = logger, }) : _logger = logger,
_platform = platform, _platform = platform,
_macOSWorkflow = macOSWorkflow, _macOSWorkflow = macOSWorkflow,
_processManager = processManager, _processManager = processManager,
_fileSystem = fileSystem ?? globals.fs, _fileSystem = fileSystem,
_operatingSystemUtils = operatingSystemUtils,
super('macOS devices'); super('macOS devices');
final MacOSWorkflow _macOSWorkflow; final MacOSWorkflow _macOSWorkflow;
...@@ -106,6 +110,7 @@ class MacOSDevices extends PollingDeviceDiscovery { ...@@ -106,6 +110,7 @@ class MacOSDevices extends PollingDeviceDiscovery {
final ProcessManager _processManager; final ProcessManager _processManager;
final Logger _logger; final Logger _logger;
final FileSystem _fileSystem; final FileSystem _fileSystem;
final OperatingSystemUtils _operatingSystemUtils;
@override @override
bool get supportsPlatform => _platform.isMacOS; bool get supportsPlatform => _platform.isMacOS;
...@@ -123,6 +128,7 @@ class MacOSDevices extends PollingDeviceDiscovery { ...@@ -123,6 +128,7 @@ class MacOSDevices extends PollingDeviceDiscovery {
processManager: _processManager, processManager: _processManager,
logger: _logger, logger: _logger,
fileSystem: _fileSystem, fileSystem: _fileSystem,
operatingSystemUtils: _operatingSystemUtils,
), ),
]; ];
} }
......
...@@ -7,6 +7,7 @@ import 'dart:async'; ...@@ -7,6 +7,7 @@ import 'dart:async';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'base/io.dart'; import 'base/io.dart';
import 'base/logger.dart';
import 'device.dart'; import 'device.dart';
import 'globals.dart' as globals; import 'globals.dart' as globals;
...@@ -22,8 +23,9 @@ class ProtocolDiscovery { ...@@ -22,8 +23,9 @@ class ProtocolDiscovery {
this.hostPort, this.hostPort,
this.devicePort, this.devicePort,
this.ipv6, this.ipv6,
}) : assert(logReader != null) Logger logger,
{ }) : _logger = logger,
assert(logReader != null) {
_deviceLogSubscription = logReader.logLines.listen( _deviceLogSubscription = logReader.logLines.listen(
_handleLine, _handleLine,
onDone: _stopScrapingLogs, onDone: _stopScrapingLogs,
...@@ -39,6 +41,7 @@ class ProtocolDiscovery { ...@@ -39,6 +41,7 @@ class ProtocolDiscovery {
@required int hostPort, @required int hostPort,
@required int devicePort, @required int devicePort,
@required bool ipv6, @required bool ipv6,
Logger logger, // TODO(jonahwilliams): make required.
}) { }) {
const String kObservatoryService = 'Observatory'; const String kObservatoryService = 'Observatory';
return ProtocolDiscovery._( return ProtocolDiscovery._(
...@@ -50,6 +53,7 @@ class ProtocolDiscovery { ...@@ -50,6 +53,7 @@ class ProtocolDiscovery {
hostPort: hostPort, hostPort: hostPort,
devicePort: devicePort, devicePort: devicePort,
ipv6: ipv6, ipv6: ipv6,
logger: logger ?? globals.logger,
); );
} }
...@@ -59,6 +63,7 @@ class ProtocolDiscovery { ...@@ -59,6 +63,7 @@ class ProtocolDiscovery {
final int hostPort; final int hostPort;
final int devicePort; final int devicePort;
final bool ipv6; final bool ipv6;
final Logger _logger;
/// The time to wait before forwarding a new observatory URIs from [logReader]. /// The time to wait before forwarding a new observatory URIs from [logReader].
final Duration throttleDuration; final Duration throttleDuration;
...@@ -138,20 +143,20 @@ class ProtocolDiscovery { ...@@ -138,20 +143,20 @@ class ProtocolDiscovery {
return; return;
} }
if (devicePort != null && uri.port != devicePort) { if (devicePort != null && uri.port != devicePort) {
globals.printTrace('skipping potential observatory $uri due to device port mismatch'); _logger.printTrace('skipping potential observatory $uri due to device port mismatch');
return; return;
} }
_uriStreamController.add(uri); _uriStreamController.add(uri);
} }
Future<Uri> _forwardPort(Uri deviceUri) async { Future<Uri> _forwardPort(Uri deviceUri) async {
globals.printTrace('$serviceName URL on device: $deviceUri'); _logger.printTrace('$serviceName URL on device: $deviceUri');
Uri hostUri = deviceUri; Uri hostUri = deviceUri;
if (portForwarder != null) { if (portForwarder != null) {
final int actualDevicePort = deviceUri.port; final int actualDevicePort = deviceUri.port;
final int actualHostPort = await portForwarder.forward(actualDevicePort, hostPort: hostPort); final int actualHostPort = await portForwarder.forward(actualDevicePort, hostPort: hostPort);
globals.printTrace('Forwarded host port $actualHostPort to device port $actualDevicePort for $serviceName'); _logger.printTrace('Forwarded host port $actualHostPort to device port $actualDevicePort for $serviceName');
hostUri = deviceUri.replace(port: actualHostPort); hostUri = deviceUri.replace(port: actualHostPort);
} }
......
...@@ -3,13 +3,16 @@ ...@@ -3,13 +3,16 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:process/process.dart';
import '../base/file_system.dart';
import '../base/io.dart'; import '../base/io.dart';
import '../base/logger.dart';
import '../base/os.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../desktop_device.dart'; import '../desktop_device.dart';
import '../device.dart'; import '../device.dart';
import '../globals.dart' as globals;
import '../project.dart'; import '../project.dart';
import 'application_package.dart'; import 'application_package.dart';
import 'build_windows.dart'; import 'build_windows.dart';
...@@ -17,10 +20,19 @@ import 'windows_workflow.dart'; ...@@ -17,10 +20,19 @@ import 'windows_workflow.dart';
/// A device that represents a desktop Windows target. /// A device that represents a desktop Windows target.
class WindowsDevice extends DesktopDevice { class WindowsDevice extends DesktopDevice {
WindowsDevice() : super( WindowsDevice({
@required ProcessManager processManager,
@required Logger logger,
@required FileSystem fileSystem,
@required OperatingSystemUtils operatingSystemUtils,
}) : super(
'windows', 'windows',
platformType: PlatformType.windows, platformType: PlatformType.windows,
ephemeral: false, ephemeral: false,
processManager: processManager,
logger: logger,
fileSystem: fileSystem,
operatingSystemUtils: operatingSystemUtils,
); );
@override @override
...@@ -57,13 +69,30 @@ class WindowsDevice extends DesktopDevice { ...@@ -57,13 +69,30 @@ class WindowsDevice extends DesktopDevice {
} }
class WindowsDevices extends PollingDeviceDiscovery { class WindowsDevices extends PollingDeviceDiscovery {
WindowsDevices() : super('windows devices'); WindowsDevices({
@required ProcessManager processManager,
@required Logger logger,
@required FileSystem fileSystem,
@required OperatingSystemUtils operatingSystemUtils,
@required WindowsWorkflow windowsWorkflow,
}) : _fileSystem = fileSystem,
_logger = logger,
_processManager = processManager,
_operatingSystemUtils = operatingSystemUtils,
_windowsWorkflow = windowsWorkflow,
super('windows devices');
final FileSystem _fileSystem;
final Logger _logger;
final ProcessManager _processManager;
final OperatingSystemUtils _operatingSystemUtils;
final WindowsWorkflow _windowsWorkflow;
@override @override
bool get supportsPlatform => globals.platform.isWindows; bool get supportsPlatform => _windowsWorkflow.appliesToHostPlatform;
@override @override
bool get canListAnything => windowsWorkflow.canListDevices; bool get canListAnything => _windowsWorkflow.canListDevices;
@override @override
Future<List<Device>> pollingGetDevices({ Duration timeout }) async { Future<List<Device>> pollingGetDevices({ Duration timeout }) async {
...@@ -71,7 +100,12 @@ class WindowsDevices extends PollingDeviceDiscovery { ...@@ -71,7 +100,12 @@ class WindowsDevices extends PollingDeviceDiscovery {
return const <Device>[]; return const <Device>[];
} }
return <Device>[ return <Device>[
WindowsDevice(), WindowsDevice(
fileSystem: _fileSystem,
logger: _logger,
processManager: _processManager,
operatingSystemUtils: _operatingSystemUtils,
),
]; ];
} }
......
...@@ -2,29 +2,38 @@ ...@@ -2,29 +2,38 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:meta/meta.dart';
import '../base/context.dart'; import '../base/context.dart';
import '../base/platform.dart';
import '../doctor.dart'; import '../doctor.dart';
import '../features.dart'; import '../features.dart';
import '../globals.dart' as globals;
/// The [WindowsWorkflow] instance. /// The [WindowsWorkflow] instance.
WindowsWorkflow get windowsWorkflow => context.get<WindowsWorkflow>(); WindowsWorkflow get windowsWorkflow => context.get<WindowsWorkflow>();
/// The windows-specific implementation of a [Workflow]. /// The Windows-specific implementation of a [Workflow].
/// ///
/// This workflow requires the flutter-desktop-embedding as a sibling /// This workflow requires the host machine to be Windows, and the Windows
/// repository to the flutter repo. /// desktop configuration setting to be enabled.
class WindowsWorkflow implements Workflow { class WindowsWorkflow implements Workflow {
const WindowsWorkflow(); const WindowsWorkflow({
@required Platform platform,
@required FeatureFlags featureFlags,
}) : _platform = platform,
_featureFlags = featureFlags;
final Platform _platform;
final FeatureFlags _featureFlags;
@override @override
bool get appliesToHostPlatform => globals.platform.isWindows && featureFlags.isWindowsEnabled; bool get appliesToHostPlatform => _platform.isWindows && _featureFlags.isWindowsEnabled;
@override @override
bool get canLaunchDevices => globals.platform.isWindows && featureFlags.isWindowsEnabled; bool get canLaunchDevices => _platform.isWindows && _featureFlags.isWindowsEnabled;
@override @override
bool get canListDevices => globals.platform.isWindows && featureFlags.isWindowsEnabled; bool get canListDevices => _platform.isWindows && _featureFlags.isWindowsEnabled;
@override @override
bool get canListEmulators => false; bool get canListEmulators => false;
......
...@@ -5,10 +5,10 @@ ...@@ -5,10 +5,10 @@
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.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/platform.dart';
import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/linux/application_package.dart'; import 'package:flutter_tools/src/linux/application_package.dart';
import 'package:flutter_tools/src/linux/linux_device.dart'; import 'package:flutter_tools/src/linux/linux_device.dart';
import 'package:flutter_tools/src/project.dart'; import 'package:flutter_tools/src/project.dart';
...@@ -32,6 +32,7 @@ void main() { ...@@ -32,6 +32,7 @@ void main() {
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
logger: BufferLogger.test(), logger: BufferLogger.test(),
fileSystem: MemoryFileSystem.test(), fileSystem: MemoryFileSystem.test(),
operatingSystemUtils: FakeOperatingSystemUtils(),
); );
final PrebuiltLinuxApp linuxApp = PrebuiltLinuxApp(executable: 'foo'); final PrebuiltLinuxApp linuxApp = PrebuiltLinuxApp(executable: 'foo');
...@@ -57,6 +58,7 @@ void main() { ...@@ -57,6 +58,7 @@ void main() {
featureFlags: TestFeatureFlags(isLinuxEnabled: true), featureFlags: TestFeatureFlags(isLinuxEnabled: true),
logger: BufferLogger.test(), logger: BufferLogger.test(),
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
operatingSystemUtils: FakeOperatingSystemUtils(),
).devices, <Device>[]); ).devices, <Device>[]);
}); });
...@@ -67,6 +69,7 @@ void main() { ...@@ -67,6 +69,7 @@ void main() {
featureFlags: TestFeatureFlags(isLinuxEnabled: false), featureFlags: TestFeatureFlags(isLinuxEnabled: false),
logger: BufferLogger.test(), logger: BufferLogger.test(),
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
operatingSystemUtils: FakeOperatingSystemUtils(),
).devices, <Device>[]); ).devices, <Device>[]);
}); });
...@@ -77,6 +80,7 @@ void main() { ...@@ -77,6 +80,7 @@ void main() {
featureFlags: TestFeatureFlags(isLinuxEnabled: true), featureFlags: TestFeatureFlags(isLinuxEnabled: true),
logger: BufferLogger.test(), logger: BufferLogger.test(),
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
operatingSystemUtils: FakeOperatingSystemUtils(),
).devices, hasLength(1)); ).devices, hasLength(1));
}); });
...@@ -88,47 +92,47 @@ void main() { ...@@ -88,47 +92,47 @@ void main() {
featureFlags: TestFeatureFlags(isLinuxEnabled: true), featureFlags: TestFeatureFlags(isLinuxEnabled: true),
logger: BufferLogger.test(), logger: BufferLogger.test(),
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
operatingSystemUtils: FakeOperatingSystemUtils(),
).discoverDevices(timeout: const Duration(seconds: 10)); ).discoverDevices(timeout: const Duration(seconds: 10));
expect(devices, hasLength(1)); expect(devices, hasLength(1));
}); });
testUsingContext('LinuxDevice.isSupportedForProject is true with editable host app', () async { testWithoutContext('LinuxDevice.isSupportedForProject is true with editable host app', () async {
globals.fs.file('pubspec.yaml').createSync(); final FileSystem fileSystem = MemoryFileSystem.test();
globals.fs.file('.packages').createSync(); fileSystem.file('pubspec.yaml').createSync();
globals.fs.directory('linux').createSync(); fileSystem.file('.packages').createSync();
final FlutterProject flutterProject = FlutterProject.current(); fileSystem.directory('linux').createSync();
final FlutterProject flutterProject = setUpFlutterProject(fileSystem.currentDirectory);
expect(LinuxDevice( expect(LinuxDevice(
logger: BufferLogger.test(), logger: BufferLogger.test(),
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
fileSystem: MemoryFileSystem.test(), fileSystem: fileSystem,
operatingSystemUtils: FakeOperatingSystemUtils(),
).isSupportedForProject(flutterProject), true); ).isSupportedForProject(flutterProject), true);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('LinuxDevice.isSupportedForProject is false with no host app', () async { testWithoutContext('LinuxDevice.isSupportedForProject is false with no host app', () async {
globals.fs.file('pubspec.yaml').createSync(); final FileSystem fileSystem = MemoryFileSystem.test();
globals.fs.file('.packages').createSync(); fileSystem.file('pubspec.yaml').createSync();
final FlutterProject flutterProject = FlutterProject.current(); fileSystem.file('.packages').createSync();
final FlutterProject flutterProject = setUpFlutterProject(fileSystem.currentDirectory);
expect(LinuxDevice( expect(LinuxDevice(
logger: BufferLogger.test(), logger: BufferLogger.test(),
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
fileSystem: MemoryFileSystem.test(), fileSystem: fileSystem,
operatingSystemUtils: FakeOperatingSystemUtils(),
).isSupportedForProject(flutterProject), false); ).isSupportedForProject(flutterProject), false);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('LinuxDevice.executablePathForDevice uses the correct package executable', () async { testWithoutContext('LinuxDevice.executablePathForDevice uses the correct package executable', () async {
final MockLinuxApp mockApp = MockLinuxApp(); final MockLinuxApp mockApp = MockLinuxApp();
final LinuxDevice device = LinuxDevice( final LinuxDevice device = LinuxDevice(
logger: BufferLogger.test(), logger: BufferLogger.test(),
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
fileSystem: MemoryFileSystem.test(), fileSystem: MemoryFileSystem.test(),
operatingSystemUtils: FakeOperatingSystemUtils(),
); );
const String debugPath = 'debug/executable'; const String debugPath = 'debug/executable';
const String profilePath = 'profile/executable'; const String profilePath = 'profile/executable';
...@@ -140,10 +144,19 @@ void main() { ...@@ -140,10 +144,19 @@ void main() {
expect(device.executablePathForDevice(mockApp, BuildMode.debug), debugPath); expect(device.executablePathForDevice(mockApp, BuildMode.debug), debugPath);
expect(device.executablePathForDevice(mockApp, BuildMode.profile), profilePath); expect(device.executablePathForDevice(mockApp, BuildMode.profile), profilePath);
expect(device.executablePathForDevice(mockApp, BuildMode.release), releasePath); expect(device.executablePathForDevice(mockApp, BuildMode.release), releasePath);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
}); });
} }
FlutterProject setUpFlutterProject(Directory directory) {
final FlutterProjectFactory flutterProjectFactory = FlutterProjectFactory(
fileSystem: directory.fileSystem,
logger: BufferLogger.test(),
);
return flutterProjectFactory.fromDirectory(directory);
}
class MockLinuxApp extends Mock implements LinuxApp {} class MockLinuxApp extends Mock implements LinuxApp {}
class FakeOperatingSystemUtils extends Fake implements OperatingSystemUtils {
@override
String get name => 'Linux';
}
...@@ -5,19 +5,16 @@ ...@@ -5,19 +5,16 @@
import 'dart:async'; import 'dart:async';
import 'package:file/memory.dart'; 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/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/device.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/application_package.dart';
import 'package:flutter_tools/src/macos/macos_device.dart'; import 'package:flutter_tools/src/macos/macos_device.dart';
import 'package:flutter_tools/src/macos/macos_workflow.dart'; import 'package:flutter_tools/src/macos/macos_workflow.dart';
import 'package:flutter_tools/src/project.dart'; import 'package:flutter_tools/src/project.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/context.dart'; import '../../src/context.dart';
...@@ -37,6 +34,7 @@ void main() { ...@@ -37,6 +34,7 @@ void main() {
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
logger: BufferLogger.test(), logger: BufferLogger.test(),
fileSystem: MemoryFileSystem.test(), fileSystem: MemoryFileSystem.test(),
operatingSystemUtils: FakeOperatingSystemUtils(),
); );
final MockMacOSApp mockMacOSApp = MockMacOSApp(); final MockMacOSApp mockMacOSApp = MockMacOSApp();
...@@ -54,7 +52,7 @@ void main() { ...@@ -54,7 +52,7 @@ void main() {
expect(device.supportsRuntimeMode(BuildMode.jitRelease), false); expect(device.supportsRuntimeMode(BuildMode.jitRelease), false);
}); });
testUsingContext('Attaches to log reader when running in release mode', () async { testWithoutContext('Attaches to log reader when running in release mode', () async {
final Completer<void> completer = Completer<void>(); final Completer<void> completer = Completer<void>();
final MacOSDevice device = MacOSDevice( final MacOSDevice device = MacOSDevice(
fileSystem: MemoryFileSystem.test(), fileSystem: MemoryFileSystem.test(),
...@@ -67,6 +65,7 @@ void main() { ...@@ -67,6 +65,7 @@ void main() {
) )
]), ]),
logger: BufferLogger.test(), logger: BufferLogger.test(),
operatingSystemUtils: FakeOperatingSystemUtils(),
); );
final MockMacOSApp mockMacOSApp = MockMacOSApp(); final MockMacOSApp mockMacOSApp = MockMacOSApp();
when(mockMacOSApp.executable(BuildMode.release)).thenReturn('Example.app'); when(mockMacOSApp.executable(BuildMode.release)).thenReturn('Example.app');
...@@ -83,9 +82,6 @@ void main() { ...@@ -83,9 +82,6 @@ void main() {
expect(logReader.logLines, emits('Hello WorldGoodnight, Moon')); expect(logReader.logLines, emits('Hello WorldGoodnight, Moon'));
completer.complete(); completer.complete();
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
}); });
testWithoutContext('No devices listed if platform is unsupported', () async { testWithoutContext('No devices listed if platform is unsupported', () async {
...@@ -94,6 +90,7 @@ void main() { ...@@ -94,6 +90,7 @@ void main() {
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
logger: BufferLogger.test(), logger: BufferLogger.test(),
platform: linux, platform: linux,
operatingSystemUtils: FakeOperatingSystemUtils(),
macOSWorkflow: MacOSWorkflow( macOSWorkflow: MacOSWorkflow(
featureFlags: TestFeatureFlags(isMacOSEnabled: true), featureFlags: TestFeatureFlags(isMacOSEnabled: true),
platform: linux, platform: linux,
...@@ -107,6 +104,7 @@ void main() { ...@@ -107,6 +104,7 @@ void main() {
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
logger: BufferLogger.test(), logger: BufferLogger.test(),
platform: macOS, platform: macOS,
operatingSystemUtils: FakeOperatingSystemUtils(),
macOSWorkflow: MacOSWorkflow( macOSWorkflow: MacOSWorkflow(
featureFlags: TestFeatureFlags(isMacOSEnabled: false), featureFlags: TestFeatureFlags(isMacOSEnabled: false),
platform: macOS, platform: macOS,
...@@ -122,6 +120,7 @@ void main() { ...@@ -122,6 +120,7 @@ void main() {
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
logger: BufferLogger.test(), logger: BufferLogger.test(),
platform: macOS, platform: macOS,
operatingSystemUtils: FakeOperatingSystemUtils(),
macOSWorkflow: MacOSWorkflow( macOSWorkflow: MacOSWorkflow(
featureFlags: TestFeatureFlags(isMacOSEnabled: true), featureFlags: TestFeatureFlags(isMacOSEnabled: true),
platform: macOS, platform: macOS,
...@@ -137,6 +136,7 @@ void main() { ...@@ -137,6 +136,7 @@ void main() {
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
logger: BufferLogger.test(), logger: BufferLogger.test(),
platform: macOS, platform: macOS,
operatingSystemUtils: FakeOperatingSystemUtils(),
macOSWorkflow: MacOSWorkflow( macOSWorkflow: MacOSWorkflow(
featureFlags: TestFeatureFlags(isMacOSEnabled: true), featureFlags: TestFeatureFlags(isMacOSEnabled: true),
platform: macOS, platform: macOS,
...@@ -149,38 +149,36 @@ void main() { ...@@ -149,38 +149,36 @@ void main() {
expect(devices, hasLength(1)); expect(devices, hasLength(1));
}); });
testUsingContext('isSupportedForProject is true with editable host app', () async { testWithoutContext('isSupportedForProject is true with editable host app', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final MacOSDevice device = MacOSDevice( final MacOSDevice device = MacOSDevice(
fileSystem: MemoryFileSystem.test(), fileSystem: MemoryFileSystem.test(),
logger: BufferLogger.test(), logger: BufferLogger.test(),
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
operatingSystemUtils: FakeOperatingSystemUtils(),
); );
globals.fs.file('pubspec.yaml').createSync(); fileSystem.file('pubspec.yaml').createSync();
globals.fs.file('.packages').createSync(); fileSystem.file('.packages').createSync();
globals.fs.directory('macos').createSync(); fileSystem.directory('macos').createSync();
final FlutterProject flutterProject = FlutterProject.current(); final FlutterProject flutterProject = setUpFlutterProject(fileSystem.currentDirectory);
expect(device.isSupportedForProject(flutterProject), true); expect(device.isSupportedForProject(flutterProject), true);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('isSupportedForProject is false with no host app', () async { testUsingContext('isSupportedForProject is false with no host app', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final MacOSDevice device = MacOSDevice( final MacOSDevice device = MacOSDevice(
fileSystem: MemoryFileSystem.test(), fileSystem: fileSystem,
logger: BufferLogger.test(), logger: BufferLogger.test(),
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
operatingSystemUtils: FakeOperatingSystemUtils(),
); );
globals.fs.file('pubspec.yaml').createSync(); fileSystem.file('pubspec.yaml').createSync();
globals.fs.file('.packages').createSync(); fileSystem.file('.packages').createSync();
final FlutterProject flutterProject = FlutterProject.current(); final FlutterProject flutterProject = setUpFlutterProject(fileSystem.currentDirectory);
expect(device.isSupportedForProject(flutterProject), false); expect(device.isSupportedForProject(flutterProject), false);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('executablePathForDevice uses the correct package executable', () async { testUsingContext('executablePathForDevice uses the correct package executable', () async {
...@@ -189,6 +187,7 @@ void main() { ...@@ -189,6 +187,7 @@ void main() {
fileSystem: MemoryFileSystem.test(), fileSystem: MemoryFileSystem.test(),
logger: BufferLogger.test(), logger: BufferLogger.test(),
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
operatingSystemUtils: FakeOperatingSystemUtils(),
); );
const String debugPath = 'debug/executable'; const String debugPath = 'debug/executable';
const String profilePath = 'profile/executable'; const String profilePath = 'profile/executable';
...@@ -200,10 +199,15 @@ void main() { ...@@ -200,10 +199,15 @@ void main() {
expect(device.executablePathForDevice(mockApp, BuildMode.debug), debugPath); expect(device.executablePathForDevice(mockApp, BuildMode.debug), debugPath);
expect(device.executablePathForDevice(mockApp, BuildMode.profile), profilePath); expect(device.executablePathForDevice(mockApp, BuildMode.profile), profilePath);
expect(device.executablePathForDevice(mockApp, BuildMode.release), releasePath); expect(device.executablePathForDevice(mockApp, BuildMode.release), releasePath);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
}); });
} }
FlutterProject setUpFlutterProject(Directory directory) {
final FlutterProjectFactory flutterProjectFactory = FlutterProjectFactory(
fileSystem: directory.fileSystem,
logger: BufferLogger.test(),
);
return flutterProjectFactory.fromDirectory(directory);
}
class MockMacOSApp extends Mock implements MacOSApp {} class MockMacOSApp extends Mock implements MacOSApp {}
...@@ -3,51 +3,60 @@ ...@@ -3,51 +3,60 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/features.dart';
import 'package:flutter_tools/src/windows/windows_workflow.dart'; import 'package:flutter_tools/src/windows/windows_workflow.dart';
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/testbed.dart'; import '../../src/testbed.dart';
void main() { void main() {
Testbed testbed; final FakePlatform windows = FakePlatform(operatingSystem: 'windows');
FakePlatform windows; final FakePlatform notWindows = FakePlatform(operatingSystem: 'linux');
FakePlatform notWindows;
testWithoutContext('Windows workflow configuration when feature is enabled on Windows host machine', () {
setUp(() { final WindowsWorkflow windowsWorkflow = WindowsWorkflow(
windows = FakePlatform(operatingSystem: 'windows'); platform: windows,
notWindows = FakePlatform(operatingSystem: 'linux'); featureFlags: TestFeatureFlags(isWindowsEnabled: true),
testbed = Testbed(
overrides: <Type, Generator>{
Platform: () => windows,
FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true),
},
); );
});
test('Windows default workflow values', () => testbed.run(() {
expect(windowsWorkflow.appliesToHostPlatform, true); expect(windowsWorkflow.appliesToHostPlatform, true);
expect(windowsWorkflow.canListDevices, true); expect(windowsWorkflow.canListDevices, true);
expect(windowsWorkflow.canLaunchDevices, true); expect(windowsWorkflow.canLaunchDevices, true);
expect(windowsWorkflow.canListEmulators, false); expect(windowsWorkflow.canListEmulators, false);
})); });
testWithoutContext('Windows workflow configuration when feature is disabled on Windows host machine', () {
final WindowsWorkflow windowsWorkflow = WindowsWorkflow(
platform: windows,
featureFlags: TestFeatureFlags(isWindowsEnabled: false),
);
test('Windows defaults on non-windows platform', () => testbed.run(() {
expect(windowsWorkflow.appliesToHostPlatform, false); expect(windowsWorkflow.appliesToHostPlatform, false);
expect(windowsWorkflow.canListDevices, false); expect(windowsWorkflow.canListDevices, false);
expect(windowsWorkflow.canLaunchDevices, false); expect(windowsWorkflow.canLaunchDevices, false);
expect(windowsWorkflow.canListEmulators, false); expect(windowsWorkflow.canListEmulators, false);
}, overrides: <Type, Generator>{ });
Platform: () => notWindows,
})); testWithoutContext('Windows workflow configuration when feature is enabled on non-Windows host machine', () {
final WindowsWorkflow windowsWorkflow = WindowsWorkflow(
platform: notWindows,
featureFlags: TestFeatureFlags(isWindowsEnabled: true),
);
test('Windows defaults on non-windows platform', () => testbed.run(() {
expect(windowsWorkflow.appliesToHostPlatform, false); expect(windowsWorkflow.appliesToHostPlatform, false);
expect(windowsWorkflow.canListDevices, false); expect(windowsWorkflow.canListDevices, false);
expect(windowsWorkflow.canLaunchDevices, false); expect(windowsWorkflow.canLaunchDevices, false);
expect(windowsWorkflow.canListEmulators, false); expect(windowsWorkflow.canListEmulators, false);
}, overrides: <Type, Generator>{ });
FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: false),
})); testWithoutContext('Windows workflow configuration when feature is disabled on non-Windows host machine', () {
final WindowsWorkflow windowsWorkflow = WindowsWorkflow(
platform: notWindows,
featureFlags: TestFeatureFlags(isWindowsEnabled: false),
);
expect(windowsWorkflow.appliesToHostPlatform, false);
expect(windowsWorkflow.canListDevices, false);
expect(windowsWorkflow.canLaunchDevices, false);
expect(windowsWorkflow.canListEmulators, false);
});
} }
...@@ -123,13 +123,13 @@ class _FakeProcess implements Process { ...@@ -123,13 +123,13 @@ class _FakeProcess implements Process {
this._stderr, this._stderr,
this.stdin, this.stdin,
this._stdout, this._stdout,
Completer<void> completer, this._completer,
) : exitCode = Future<void>.delayed(duration).then((void value) { ) : exitCode = Future<void>.delayed(duration).then((void value) {
if (onRun != null) { if (onRun != null) {
onRun(); onRun();
} }
if (completer != null) { if (_completer != null) {
return completer.future.then((void _) => _exitCode); return _completer.future.then((void _) => _exitCode);
} }
return _exitCode; return _exitCode;
}), }),
...@@ -141,6 +141,7 @@ class _FakeProcess implements Process { ...@@ -141,6 +141,7 @@ class _FakeProcess implements Process {
: Stream<List<int>>.value(utf8.encode(_stdout)); : Stream<List<int>>.value(utf8.encode(_stdout));
final int _exitCode; final int _exitCode;
final Completer<void> _completer;
@override @override
final Future<int> exitCode; final Future<int> exitCode;
...@@ -205,6 +206,8 @@ abstract class FakeProcessManager implements ProcessManager { ...@@ -205,6 +206,8 @@ abstract class FakeProcessManager implements ProcessManager {
commands.forEach(addCommand); commands.forEach(addCommand);
} }
final Map<int, _FakeProcess> _fakeRunningProcesses = <int, _FakeProcess>{};
/// Whether this fake has more [FakeCommand]s that are expected to run. /// Whether this fake has more [FakeCommand]s that are expected to run.
/// ///
/// This is always `true` for [FakeProcessManager.any]. /// This is always `true` for [FakeProcessManager.any].
...@@ -248,7 +251,16 @@ abstract class FakeProcessManager implements ProcessManager { ...@@ -248,7 +251,16 @@ abstract class FakeProcessManager implements ProcessManager {
bool includeParentEnvironment = true, // ignored bool includeParentEnvironment = true, // ignored
bool runInShell = false, // ignored bool runInShell = false, // ignored
ProcessStartMode mode = ProcessStartMode.normal, // ignored ProcessStartMode mode = ProcessStartMode.normal, // ignored
}) async => _runCommand(command.cast<String>(), workingDirectory, environment, systemEncoding); }) {
final _FakeProcess process = _runCommand(command.cast<String>(), workingDirectory, environment, systemEncoding);
if (process._completer != null) {
_fakeRunningProcesses[process.pid] = process;
process.exitCode.whenComplete(() {
_fakeRunningProcesses.remove(process.pid);
});
}
return Future<Process>.value(process);
}
@override @override
Future<ProcessResult> run( Future<ProcessResult> run(
...@@ -294,9 +306,14 @@ abstract class FakeProcessManager implements ProcessManager { ...@@ -294,9 +306,14 @@ abstract class FakeProcessManager implements ProcessManager {
@override @override
bool killPid(int pid, [io.ProcessSignal signal = io.ProcessSignal.sigterm]) { bool killPid(int pid, [io.ProcessSignal signal = io.ProcessSignal.sigterm]) {
// Killing a fake process has no effect. // Killing a fake process has no effect unless it has an attached completer.
final _FakeProcess fakeProcess = _fakeRunningProcesses[pid];
if (fakeProcess == null) {
return false; return false;
} }
fakeProcess._completer.complete();
return true;
}
} }
class _FakeAnyProcessManager extends FakeProcessManager { class _FakeAnyProcessManager extends FakeProcessManager {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment