mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

* Reland: [macos] add flavor options to tool commands Adds --flavor option to flutter run and flutter build. Running against preexisting devicelab flavor tests for feature parity between macOS, iOS, and Android. This relands #118421 by alex-wallen which was reverted in #118858 due to the following test failures: The bail-out with "Host and target are the same. Nothing to install." added in `packages/flutter_tools/lib/src/commands/install.dart` triggered failures in the following tests, which unconditionally attempt to install the built app, which is unsupported on desktop since the host and target are the same: * https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8791495589540422465/+/u/run_flutter_view_macos__start_up/test_stdout * https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8791496218824259121/+/u/run_complex_layout_win_desktop__start_up/test_stdout * https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8791496218165602641/+/u/run_flutter_gallery_win_desktop__start_up/test_stdout Fixes #64088 * Partial revert: eliminate install check on desktop The original flavour support patch included a check that triggered a failure when flutter install is run on desktop OSes. This was intentional, since the host and target devices are the same and installation is unnecessary to launch the app on currently-supported desktop OSes. Note that Windows UWP apps *do* require installation to run, and we used to have an install command for those apps, though UWP is no longer supported. Since that part of the change was orthogonal to flavour support itself, I'm reverting that component of the change and we can deal with it separately if so desired.
267 lines
9.5 KiB
Dart
267 lines
9.5 KiB
Dart
// 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.
|
|
|
|
import 'dart:async';
|
|
|
|
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/os.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/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:test/fake.dart';
|
|
|
|
import '../../src/common.dart';
|
|
import '../../src/fake_process_manager.dart';
|
|
import '../../src/fakes.dart';
|
|
|
|
final FakePlatform macOS = FakePlatform(
|
|
operatingSystem: 'macos',
|
|
);
|
|
|
|
final FakePlatform linux = FakePlatform();
|
|
|
|
void main() {
|
|
testWithoutContext('default configuration', () async {
|
|
final MacOSDevice device = MacOSDevice(
|
|
processManager: FakeProcessManager.any(),
|
|
logger: BufferLogger.test(),
|
|
fileSystem: MemoryFileSystem.test(),
|
|
operatingSystemUtils: FakeOperatingSystemUtils(),
|
|
);
|
|
final FakeMacOSApp package = FakeMacOSApp();
|
|
|
|
expect(await device.targetPlatform, TargetPlatform.darwin);
|
|
expect(device.name, 'macOS');
|
|
expect(await device.installApp(package), true);
|
|
expect(await device.uninstallApp(package), true);
|
|
expect(await device.isLatestBuildInstalled(package), true);
|
|
expect(await device.isAppInstalled(package), true);
|
|
expect(device.category, Category.desktop);
|
|
|
|
expect(device.supportsRuntimeMode(BuildMode.debug), true);
|
|
expect(device.supportsRuntimeMode(BuildMode.profile), true);
|
|
expect(device.supportsRuntimeMode(BuildMode.release), true);
|
|
expect(device.supportsRuntimeMode(BuildMode.jitRelease), false);
|
|
});
|
|
|
|
testWithoutContext('Attaches to log reader when running in release mode', () async {
|
|
final Completer<void> completer = Completer<void>();
|
|
final MacOSDevice device = MacOSDevice(
|
|
fileSystem: MemoryFileSystem.test(),
|
|
processManager: FakeProcessManager.list(<FakeCommand>[
|
|
FakeCommand(
|
|
command: const <String>['release/executable'],
|
|
stdout: 'Hello World\n',
|
|
stderr: 'Goodnight, Moon\n',
|
|
completer: completer,
|
|
),
|
|
]),
|
|
logger: BufferLogger.test(),
|
|
operatingSystemUtils: FakeOperatingSystemUtils(),
|
|
);
|
|
final FakeMacOSApp package = FakeMacOSApp();
|
|
|
|
final LaunchResult result = await device.startApp(
|
|
package,
|
|
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
|
|
prebuiltApplication: true,
|
|
);
|
|
|
|
expect(result.started, true);
|
|
|
|
final DeviceLogReader logReader = device.getLogReader(app: package);
|
|
|
|
expect(logReader.logLines, emitsInAnyOrder(<String>['Hello World', 'Goodnight, Moon']));
|
|
completer.complete();
|
|
});
|
|
|
|
testWithoutContext('No devices listed if platform is unsupported', () async {
|
|
expect(await MacOSDevices(
|
|
fileSystem: MemoryFileSystem.test(),
|
|
processManager: FakeProcessManager.any(),
|
|
logger: BufferLogger.test(),
|
|
platform: linux,
|
|
operatingSystemUtils: FakeOperatingSystemUtils(),
|
|
macOSWorkflow: MacOSWorkflow(
|
|
featureFlags: TestFeatureFlags(isMacOSEnabled: true),
|
|
platform: linux,
|
|
),
|
|
).devices, isEmpty);
|
|
});
|
|
|
|
testWithoutContext('No devices listed if platform is supported and feature is disabled', () async {
|
|
final MacOSDevices macOSDevices = MacOSDevices(
|
|
fileSystem: MemoryFileSystem.test(),
|
|
processManager: FakeProcessManager.any(),
|
|
logger: BufferLogger.test(),
|
|
platform: macOS,
|
|
operatingSystemUtils: FakeOperatingSystemUtils(),
|
|
macOSWorkflow: MacOSWorkflow(
|
|
featureFlags: TestFeatureFlags(),
|
|
platform: macOS,
|
|
),
|
|
);
|
|
|
|
expect(await macOSDevices.devices, isEmpty);
|
|
});
|
|
|
|
testWithoutContext('devices listed if platform is supported and feature is enabled', () async {
|
|
final MacOSDevices macOSDevices = MacOSDevices(
|
|
fileSystem: MemoryFileSystem.test(),
|
|
processManager: FakeProcessManager.any(),
|
|
logger: BufferLogger.test(),
|
|
platform: macOS,
|
|
operatingSystemUtils: FakeOperatingSystemUtils(),
|
|
macOSWorkflow: MacOSWorkflow(
|
|
featureFlags: TestFeatureFlags(isMacOSEnabled: true),
|
|
platform: macOS,
|
|
),
|
|
);
|
|
|
|
expect(await macOSDevices.devices, hasLength(1));
|
|
});
|
|
|
|
testWithoutContext('has a well known device id macos', () async {
|
|
final MacOSDevices macOSDevices = MacOSDevices(
|
|
fileSystem: MemoryFileSystem.test(),
|
|
processManager: FakeProcessManager.any(),
|
|
logger: BufferLogger.test(),
|
|
platform: macOS,
|
|
operatingSystemUtils: FakeOperatingSystemUtils(),
|
|
macOSWorkflow: MacOSWorkflow(
|
|
featureFlags: TestFeatureFlags(isMacOSEnabled: true),
|
|
platform: macOS,
|
|
),
|
|
);
|
|
|
|
expect(macOSDevices.wellKnownIds, <String>['macos']);
|
|
});
|
|
|
|
testWithoutContext('can discover devices with a provided timeout', () async {
|
|
final MacOSDevices macOSDevices = MacOSDevices(
|
|
fileSystem: MemoryFileSystem.test(),
|
|
processManager: FakeProcessManager.any(),
|
|
logger: BufferLogger.test(),
|
|
platform: macOS,
|
|
operatingSystemUtils: FakeOperatingSystemUtils(),
|
|
macOSWorkflow: MacOSWorkflow(
|
|
featureFlags: TestFeatureFlags(isMacOSEnabled: true),
|
|
platform: macOS,
|
|
),
|
|
);
|
|
|
|
// Timeout ignored.
|
|
final List<Device> devices = await macOSDevices.discoverDevices(timeout: const Duration(seconds: 10));
|
|
|
|
expect(devices, hasLength(1));
|
|
});
|
|
|
|
testWithoutContext('isSupportedForProject is true with editable host app', () async {
|
|
final FileSystem fileSystem = MemoryFileSystem.test();
|
|
final MacOSDevice device = MacOSDevice(
|
|
fileSystem: MemoryFileSystem.test(),
|
|
logger: BufferLogger.test(),
|
|
processManager: FakeProcessManager.any(),
|
|
operatingSystemUtils: FakeOperatingSystemUtils(),
|
|
);
|
|
|
|
fileSystem.file('pubspec.yaml').createSync();
|
|
fileSystem.file('.packages').createSync();
|
|
fileSystem.directory('macos').createSync();
|
|
final FlutterProject flutterProject = setUpFlutterProject(fileSystem.currentDirectory);
|
|
|
|
expect(device.isSupportedForProject(flutterProject), true);
|
|
});
|
|
|
|
testWithoutContext('target platform display name on x86_64', () async {
|
|
final FakeOperatingSystemUtils fakeOperatingSystemUtils =
|
|
FakeOperatingSystemUtils();
|
|
fakeOperatingSystemUtils.hostPlatform = HostPlatform.darwin_x64;
|
|
final MacOSDevice device = MacOSDevice(
|
|
fileSystem: MemoryFileSystem.test(),
|
|
logger: BufferLogger.test(),
|
|
processManager: FakeProcessManager.any(),
|
|
operatingSystemUtils: fakeOperatingSystemUtils,
|
|
);
|
|
|
|
expect(await device.targetPlatformDisplayName, 'darwin-x64');
|
|
});
|
|
|
|
testWithoutContext('target platform display name on ARM', () async {
|
|
final FakeOperatingSystemUtils fakeOperatingSystemUtils =
|
|
FakeOperatingSystemUtils();
|
|
fakeOperatingSystemUtils.hostPlatform = HostPlatform.darwin_arm64;
|
|
final MacOSDevice device = MacOSDevice(
|
|
fileSystem: MemoryFileSystem.test(),
|
|
logger: BufferLogger.test(),
|
|
processManager: FakeProcessManager.any(),
|
|
operatingSystemUtils: fakeOperatingSystemUtils,
|
|
);
|
|
|
|
expect(await device.targetPlatformDisplayName, 'darwin-arm64');
|
|
});
|
|
|
|
testWithoutContext('isSupportedForProject is false with no host app', () async {
|
|
final FileSystem fileSystem = MemoryFileSystem.test();
|
|
final MacOSDevice device = MacOSDevice(
|
|
fileSystem: fileSystem,
|
|
logger: BufferLogger.test(),
|
|
processManager: FakeProcessManager.any(),
|
|
operatingSystemUtils: FakeOperatingSystemUtils(),
|
|
);
|
|
fileSystem.file('pubspec.yaml').createSync();
|
|
fileSystem.file('.packages').createSync();
|
|
final FlutterProject flutterProject = setUpFlutterProject(fileSystem.currentDirectory);
|
|
|
|
expect(device.isSupportedForProject(flutterProject), false);
|
|
});
|
|
|
|
testWithoutContext('executablePathForDevice uses the correct package executable', () async {
|
|
final FakeMacOSApp package = FakeMacOSApp();
|
|
final MacOSDevice device = MacOSDevice(
|
|
fileSystem: MemoryFileSystem.test(),
|
|
logger: BufferLogger.test(),
|
|
processManager: FakeProcessManager.any(),
|
|
operatingSystemUtils: FakeOperatingSystemUtils(),
|
|
);
|
|
const String debugPath = 'debug/executable';
|
|
const String profilePath = 'profile/executable';
|
|
const String releasePath = 'release/executable';
|
|
|
|
expect(device.executablePathForDevice(package, BuildInfo.debug), debugPath);
|
|
expect(device.executablePathForDevice(package, BuildInfo.profile), profilePath);
|
|
expect(device.executablePathForDevice(package, BuildInfo.release), releasePath);
|
|
});
|
|
}
|
|
|
|
FlutterProject setUpFlutterProject(Directory directory) {
|
|
final FlutterProjectFactory flutterProjectFactory = FlutterProjectFactory(
|
|
fileSystem: directory.fileSystem,
|
|
logger: BufferLogger.test(),
|
|
);
|
|
return flutterProjectFactory.fromDirectory(directory);
|
|
}
|
|
|
|
class FakeMacOSApp extends Fake implements MacOSApp {
|
|
@override
|
|
String executable(BuildInfo buildInfo) {
|
|
switch (buildInfo) {
|
|
case BuildInfo.debug:
|
|
return 'debug/executable';
|
|
case BuildInfo.profile:
|
|
return 'profile/executable';
|
|
case BuildInfo.release:
|
|
return 'release/executable';
|
|
default:
|
|
throw StateError('');
|
|
}
|
|
}
|
|
}
|