diff --git a/dev/integration_tests/flutter_gallery/windows/flutter/CMakeLists.txt b/dev/integration_tests/flutter_gallery/windows/flutter/CMakeLists.txt index 903f4899d6fce..b2e4bd8d658b2 100644 --- a/dev/integration_tests/flutter_gallery/windows/flutter/CMakeLists.txt +++ b/dev/integration_tests/flutter_gallery/windows/flutter/CMakeLists.txt @@ -1,4 +1,3 @@ -# This file controls Flutter-level build steps. It should not be edited. cmake_minimum_required(VERSION 3.14) set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") @@ -10,11 +9,6 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # https://github.com/flutter/flutter/issues/57146. set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") -# Set fallback configurations for older versions of the flutter tool. -if (NOT DEFINED FLUTTER_TARGET_PLATFORM) - set(FLUTTER_TARGET_PLATFORM "windows-x64") -endif() - # === Flutter Library === set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") @@ -97,7 +91,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - ${FLUTTER_TARGET_PLATFORM} $ + windows-x64 $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS diff --git a/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.cc b/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000000000..4f7884874da74 --- /dev/null +++ b/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,14 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); +} diff --git a/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.h b/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000000000..dc139d85a9310 --- /dev/null +++ b/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugins.cmake b/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugins.cmake new file mode 100644 index 0000000000000..88b22e5c775e5 --- /dev/null +++ b/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/examples/hello_world/linux/flutter/generated_plugin_registrant.cc b/examples/hello_world/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000000000..e71a16d23d058 --- /dev/null +++ b/examples/hello_world/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void fl_register_plugins(FlPluginRegistry* registry) { +} diff --git a/examples/hello_world/linux/flutter/generated_plugin_registrant.h b/examples/hello_world/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000000000..e0f0a47bc08f3 --- /dev/null +++ b/examples/hello_world/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/examples/hello_world/linux/flutter/generated_plugins.cmake b/examples/hello_world/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000000000..2e1de87a7eb61 --- /dev/null +++ b/examples/hello_world/linux/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/packages/flutter_tools/lib/executable.dart b/packages/flutter_tools/lib/executable.dart index 9bd3ea190d1f7..6831d6f8f8cf1 100644 --- a/packages/flutter_tools/lib/executable.dart +++ b/packages/flutter_tools/lib/executable.dart @@ -173,9 +173,11 @@ List generateCommands({ fileSystem: globals.fs, ), BuildCommand( + artifacts: globals.artifacts!, fileSystem: globals.fs, buildSystem: globals.buildSystem, osUtils: globals.os, + processUtils: globals.processUtils, verboseHelp: verboseHelp, androidSdk: globals.androidSdk, logger: globals.logger, diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart index 161e8b6ae7daa..fd23e85f94a60 100644 --- a/packages/flutter_tools/lib/src/artifacts.dart +++ b/packages/flutter_tools/lib/src/artifacts.dart @@ -69,6 +69,9 @@ enum Artifact { /// The location of file generators. flutterToolsFileGenerators, + + /// Pre-built desktop debug app. + flutterPreviewDevice, } /// A subset of [Artifact]s that are platform and build mode independent @@ -213,6 +216,8 @@ String? _artifactToFileName(Artifact artifact, Platform hostPlatform, [ BuildMod return 'const_finder.dart.snapshot'; case Artifact.flutterToolsFileGenerators: return ''; + case Artifact.flutterPreviewDevice: + return 'flutter_preview$exe'; } } @@ -573,6 +578,7 @@ class CachedArtifacts implements Artifacts { case Artifact.windowsCppClientWrapper: case Artifact.windowsDesktopPath: case Artifact.flutterToolsFileGenerators: + case Artifact.flutterPreviewDevice: return _getHostArtifactPath(artifact, platform, mode); } } @@ -612,6 +618,7 @@ class CachedArtifacts implements Artifacts { case Artifact.windowsCppClientWrapper: case Artifact.windowsDesktopPath: case Artifact.flutterToolsFileGenerators: + case Artifact.flutterPreviewDevice: return _getHostArtifactPath(artifact, platform, mode); } } @@ -663,6 +670,7 @@ class CachedArtifacts implements Artifacts { case Artifact.windowsCppClientWrapper: case Artifact.windowsDesktopPath: case Artifact.flutterToolsFileGenerators: + case Artifact.flutterPreviewDevice: return _getHostArtifactPath(artifact, platform, mode); } } @@ -745,6 +753,9 @@ class CachedArtifacts implements Artifacts { throw StateError('Artifact $artifact not available for platform $platform.'); case Artifact.flutterToolsFileGenerators: return _getFileGeneratorsPath(); + case Artifact.flutterPreviewDevice: + assert(platform == TargetPlatform.windows_x64); + return _cache.getArtifactDirectory('flutter_preview').childFile('flutter_preview.exe').path; } } @@ -1016,6 +1027,8 @@ class CachedLocalEngineArtifacts implements Artifacts { return _fileSystem.path.join(_getDartSdkPath(), 'bin', 'utils', artifactFileName); case Artifact.flutterToolsFileGenerators: return _getFileGeneratorsPath(); + case Artifact.flutterPreviewDevice: + throw UnimplementedError('TODO!'); // TODO } } @@ -1118,7 +1131,6 @@ class CachedLocalWebSdkArtifacts implements Artifacts { _platform = platform, _operatingSystemUtils = operatingSystemUtils; - final Artifacts _parent; final String _webSdkPath; final FileSystem _fileSystem; @@ -1169,6 +1181,7 @@ class CachedLocalWebSdkArtifacts implements Artifacts { case Artifact.fontSubset: case Artifact.constFinder: case Artifact.flutterToolsFileGenerators: + case Artifact.flutterPreviewDevice: break; } } diff --git a/packages/flutter_tools/lib/src/commands/build.dart b/packages/flutter_tools/lib/src/commands/build.dart index cad3d81453ebb..5bca720f71783 100644 --- a/packages/flutter_tools/lib/src/commands/build.dart +++ b/packages/flutter_tools/lib/src/commands/build.dart @@ -5,11 +5,14 @@ import 'package:meta/meta.dart'; import '../android/android_sdk.dart'; +import '../artifacts.dart'; import '../base/file_system.dart'; import '../base/logger.dart'; import '../base/os.dart'; +import '../base/process.dart'; import '../build_info.dart'; import '../build_system/build_system.dart'; +import '../cache.dart'; import '../commands/build_linux.dart'; import '../commands/build_macos.dart'; import '../commands/build_windows.dart'; @@ -21,15 +24,18 @@ import 'build_bundle.dart'; import 'build_ios.dart'; import 'build_ios_framework.dart'; import 'build_macos_framework.dart'; +import 'build_preview.dart'; import 'build_web.dart'; class BuildCommand extends FlutterCommand { BuildCommand({ + required Artifacts artifacts, required FileSystem fileSystem, required BuildSystem buildSystem, required OperatingSystemUtils osUtils, required Logger logger, required AndroidSdk? androidSdk, + required ProcessUtils processUtils, bool verboseHelp = false, }){ _addSubcommand( @@ -67,6 +73,14 @@ class BuildCommand extends FlutterCommand { verboseHelp: verboseHelp )); _addSubcommand(BuildWindowsCommand(logger: logger, verboseHelp: verboseHelp)); + _addSubcommand(BuildPreviewCommand( + artifacts: artifacts, + flutterRoot: Cache.flutterRoot!, + fs: fileSystem, + logger: logger, + processUtils: processUtils, + verboseHelp: verboseHelp, + )); } void _addSubcommand(BuildSubCommand command) { @@ -90,14 +104,15 @@ class BuildCommand extends FlutterCommand { abstract class BuildSubCommand extends FlutterCommand { BuildSubCommand({ - required Logger logger, + required this.logger, required bool verboseHelp - }): _logger = logger { + }) { requiresPubspecYaml(); usesFatalWarningsOption(verboseHelp: verboseHelp); } - final Logger _logger; + @protected + final Logger logger; @override bool get reportNullSafety => true; @@ -111,15 +126,15 @@ abstract class BuildSubCommand extends FlutterCommand { @protected void displayNullSafetyMode(BuildInfo buildInfo) { if (buildInfo.nullSafetyMode != NullSafetyMode.sound) { - _logger.printStatus(''); - _logger.printStatus( + logger.printStatus(''); + logger.printStatus( 'Building without sound null safety ⚠️', emphasis: true, ); - _logger.printStatus( + logger.printStatus( 'Dart 3 will only support sound null safety, see https://dart.dev/null-safety', ); } - _logger.printStatus(''); + logger.printStatus(''); } } diff --git a/packages/flutter_tools/lib/src/commands/build_preview.dart b/packages/flutter_tools/lib/src/commands/build_preview.dart new file mode 100644 index 0000000000000..05a81da19cecf --- /dev/null +++ b/packages/flutter_tools/lib/src/commands/build_preview.dart @@ -0,0 +1,105 @@ +import 'package:file/file.dart'; + +import '../artifacts.dart'; +import '../base/common.dart'; +import '../base/io.dart'; +import '../base/process.dart'; +import '../build_info.dart'; +import '../cache.dart'; +import '../globals.dart' as globals; +import '../project.dart'; +import '../runner/flutter_command.dart' show FlutterCommandResult; +import '../windows/build_windows.dart'; +import 'build.dart'; + +class BuildPreviewCommand extends BuildSubCommand { + BuildPreviewCommand({ + required super.logger, + required bool verboseHelp, + required this.fs, + required this.flutterRoot, + required this.processUtils, + required this.artifacts, + }) : super(verboseHelp: verboseHelp) { + addCommonDesktopBuildOptions(verboseHelp: verboseHelp); + } + + @override + final String name = '_preview'; + + @override + final bool hidden = true; + + @override + Future> get requiredArtifacts async => { + DevelopmentArtifact.windows, + }; + + @override + final String description = 'Build Flutter preview (desktop) app.'; + + final FileSystem fs; + final String flutterRoot; + final ProcessUtils processUtils; + final Artifacts artifacts; + + static const BuildInfo buildInfo = BuildInfo( + BuildMode.debug, + null, // no flavor + // users may add icons later + treeShakeIcons: false, + ); + + @override + void requiresPubspecYaml() {} + + static const String appName = 'flutter_preview'; + + @override + Future runCommand() async { + final Directory targetDir = fs.systemTempDirectory.createTempSync('flutter-build-preview'); + final FlutterProject flutterProject = await _createProject(targetDir); + if (!globals.platform.isWindows) { + throwToolExit('"build _preview" is currently only supported on Windows hosts.'); + } + await buildWindows( + flutterProject.windows, + buildInfo, + ); + + final File previewDevice = targetDir + .childDirectory(getWindowsBuildDirectory(TargetPlatform.windows_x64)) + .childDirectory('runner') + .childDirectory('Debug') + .childFile('$appName.exe'); + if (!previewDevice.existsSync()) { + throw StateError('Preview device not found at ${previewDevice.absolute.path}'); + } + final String newPath = artifacts.getArtifactPath(Artifact.flutterPreviewDevice); + fs.file(newPath).parent.createSync(recursive: true); + previewDevice.copySync(newPath); + return FlutterCommandResult.success(); + } + + Future _createProject(Directory targetDir) async { + final List args = [ + fs.path.join(flutterRoot, 'bin', 'flutter.bat'), + 'create', + '--empty', + '--project-name', + 'flutter_preview', + targetDir.path, + ]; + final RunResult result = await processUtils.run( + args, + allowReentrantFlutter: true, + ); + if (result.exitCode != 0) { + final StringBuffer buffer = StringBuffer('${args.join(' ')} exited with code ${result.exitCode}'); + buffer.writeln('stdout:\n${result.stdout}\n'); + buffer.writeln('stderr:\n${result.stderr}'); + throw ProcessException(args.first, args.sublist(1), buffer.toString(), result.exitCode); + } + return FlutterProject.fromDirectory(targetDir); + } +} diff --git a/packages/flutter_tools/lib/src/features.dart b/packages/flutter_tools/lib/src/features.dart index 284416992133b..ec3657ef6b880 100644 --- a/packages/flutter_tools/lib/src/features.dart +++ b/packages/flutter_tools/lib/src/features.dart @@ -53,6 +53,9 @@ abstract class FeatureFlags { /// Whether native assets compilation and bundling is enabled. bool get isNativeAssetsEnabled => false; + /// Whether native assets compilation and bundling is enabled. + bool get isPreviewDeviceEnabled => true; + /// Whether a particular feature is enabled for the current channel. /// /// Prefer using one of the specific getters above instead of this API. @@ -72,6 +75,7 @@ const List allFeatures = [ flutterWebWasm, cliAnimation, nativeAssets, + previewDevice, ]; /// All current Flutter feature flags that can be configured. @@ -172,6 +176,19 @@ const Feature nativeAssets = Feature( ), ); +/// Enable Flutter preview prebuilt device. +const Feature previewDevice = Feature( + name: 'Flutter preview prebuilt device', + configSetting: 'enable-flutter-preview', + environmentOverride: 'FLUTTER_PREVIEW_DEVICE', + master: FeatureChannelSetting( + available: true, + ), + beta: FeatureChannelSetting( + available: true, + ), +); + /// A [Feature] is a process for conditionally enabling tool features. /// /// All settings are optional, and if not provided will generally default to diff --git a/packages/flutter_tools/lib/src/flutter_device_manager.dart b/packages/flutter_tools/lib/src/flutter_device_manager.dart index dc98b4a7d0dcb..3b9558e53d0f5 100644 --- a/packages/flutter_tools/lib/src/flutter_device_manager.dart +++ b/packages/flutter_tools/lib/src/flutter_device_manager.dart @@ -27,6 +27,7 @@ import 'macos/macos_device.dart'; import 'macos/macos_ipad_device.dart'; import 'macos/macos_workflow.dart'; import 'macos/xcdevice.dart'; +import 'preview_device.dart'; import 'tester/flutter_tester.dart'; import 'version.dart'; import 'web/web_device.dart'; @@ -104,6 +105,14 @@ class FlutterDeviceManager extends DeviceManager { fileSystem: fileSystem, operatingSystemUtils: operatingSystemUtils, ), + PreviewDeviceDiscovery( + platform: platform, + artifacts: artifacts, + fileSystem: fileSystem, + logger: logger, + processManager: processManager, + featureFlags: featureFlags, + ), LinuxDevices( platform: platform, featureFlags: featureFlags, diff --git a/packages/flutter_tools/lib/src/flutter_features.dart b/packages/flutter_tools/lib/src/flutter_features.dart index 1418e90009631..ebb3403b154f5 100644 --- a/packages/flutter_tools/lib/src/flutter_features.dart +++ b/packages/flutter_tools/lib/src/flutter_features.dart @@ -58,6 +58,9 @@ class FlutterFeatureFlags implements FeatureFlags { @override bool get isNativeAssetsEnabled => isEnabled(nativeAssets); + @override + bool get isPreviewDeviceEnabled => isEnabled(previewDevice); + @override bool isEnabled(Feature feature) { final String currentChannel = _flutterVersion.channel; diff --git a/packages/flutter_tools/lib/src/preview_device.dart b/packages/flutter_tools/lib/src/preview_device.dart index aff36eebc30ae..a4fbd7104c93f 100644 --- a/packages/flutter_tools/lib/src/preview_device.dart +++ b/packages/flutter_tools/lib/src/preview_device.dart @@ -8,17 +8,18 @@ import 'package:meta/meta.dart'; import 'package:process/process.dart'; import 'application_package.dart'; +import 'artifacts.dart'; import 'base/file_system.dart'; import 'base/io.dart'; import 'base/logger.dart'; import 'base/platform.dart'; import 'build_info.dart'; import 'bundle_builder.dart'; -import 'cache.dart'; import 'desktop_device.dart'; import 'devfs.dart'; import 'device.dart'; import 'device_port_forwarder.dart'; +import 'features.dart'; import 'project.dart'; import 'protocol_discovery.dart'; @@ -28,6 +29,75 @@ BundleBuilder _defaultBundleBuilder() { return BundleBuilder(); } +class PreviewDeviceDiscovery extends DeviceDiscovery { + PreviewDeviceDiscovery({ + required Platform platform, + required Artifacts artifacts, + required FileSystem fileSystem, + required Logger logger, + required ProcessManager processManager, + required FeatureFlags featureFlags, + }) : _artifacts = artifacts, + _logger = logger, + _processManager = processManager, + _fileSystem = fileSystem, + _platform = platform, + _features = featureFlags; + + final Platform _platform; + final Artifacts _artifacts; + final Logger _logger; + final ProcessManager _processManager; + final FileSystem _fileSystem; + final FeatureFlags _features; + + @override + bool get canListAnything => _platform.isWindows; + + @override + Future> devices({ + Duration? timeout, + DeviceDiscoveryFilter? filter, + }) async { + final PreviewDevice device = PreviewDevice( + artifacts: _artifacts, + fileSystem: _fileSystem, + logger: _logger, + processManager: _processManager, + previewBinary: _fileSystem.file(_artifacts.getArtifactPath(Artifact.flutterPreviewDevice)), + ); + + final bool matchesRequirements; + if (!_platform.isWindows) { + matchesRequirements = false; + } else if (_features.isPreviewDeviceEnabled) { + matchesRequirements = false; + } else if (filter == null) { + matchesRequirements = true; + } else { + matchesRequirements = await filter.matchesRequirements(device); + } + return [ + if (matchesRequirements) + device, + ]; + } + + @override + Future> discoverDevices({ + Duration? timeout, + DeviceDiscoveryFilter? filter, + }) { + return devices(); + } + + @override + bool get supportsPlatform => true; + + @override + List get wellKnownIds => ['preview']; +} + /// A device type that runs a prebuilt desktop binary alongside a locally compiled kernel file. /// /// This could be used to support debug local development without plugins on machines that @@ -35,23 +105,26 @@ BundleBuilder _defaultBundleBuilder() { /// device is not currently discoverable. class PreviewDevice extends Device { PreviewDevice({ - required Platform platform, required ProcessManager processManager, required Logger logger, required FileSystem fileSystem, + required Artifacts artifacts, + required File previewBinary, @visibleForTesting BundleBuilderFactory builderFactory = _defaultBundleBuilder, - }) : _platform = platform, + }) : _previewBinary = previewBinary, _processManager = processManager, _logger = logger, _fileSystem = fileSystem, _bundleBuilderFactory = builderFactory, + _artifacts = artifacts, super('preview', ephemeral: false, category: Category.desktop, platformType: PlatformType.custom); - final Platform _platform; final ProcessManager _processManager; final Logger _logger; final FileSystem _fileSystem; final BundleBuilderFactory _bundleBuilderFactory; + final Artifacts _artifacts; + final File _previewBinary; @override void clearLogs() { } @@ -116,7 +189,7 @@ class PreviewDevice extends Device { await _bundleBuilderFactory().build( buildInfo: debuggingOptions.buildInfo, mainPath: mainPath, - platform: TargetPlatform.tester, + platform: TargetPlatform.windows_x64, assetDirPath: getAssetBuildDirectory(), ); copyDirectory(_fileSystem.directory( @@ -128,13 +201,18 @@ class PreviewDevice extends Device { } // Merge with precompiled executable. - final Directory precompiledDirectory = _fileSystem.directory(_fileSystem.path.join(Cache.flutterRoot!, 'artifacts_temp', 'Debug')); - copyDirectory(precompiledDirectory, assetDirectory); + final String copiedPreviewBinaryPath = assetDirectory.childFile(_previewBinary.basename).path; + _previewBinary.copySync(copiedPreviewBinaryPath); + + final String windowsPath = _artifacts + .getArtifactPath(Artifact.windowsDesktopPath, platform: TargetPlatform.windows_x64, mode: BuildMode.debug); + final File windowsDll = _fileSystem.file(_fileSystem.path.join(windowsPath, 'flutter_windows.dll')); + final File icu = _fileSystem.file(_fileSystem.path.join(windowsPath, 'icudtl.dat')); + windowsDll.copySync(assetDirectory.childFile('flutter_windows.dll').path); + icu.copySync(assetDirectory.childDirectory('data').childFile('icudtl.dat').path); final Process process = await _processManager.start( - [ - assetDirectory.childFile('splash').path, - ], + [copiedPreviewBinaryPath], ); _process = process; _logReader.initializeProcess(process); @@ -169,10 +247,7 @@ class PreviewDevice extends Device { @override Future get targetPlatform async { - if (_platform.isWindows) { - return TargetPlatform.windows_x64; - } - return TargetPlatform.tester; + return TargetPlatform.windows_x64; } @override diff --git a/packages/flutter_tools/lib/src/windows/build_windows.dart b/packages/flutter_tools/lib/src/windows/build_windows.dart index dddc0d424d2bf..2a4af0408a81e 100644 --- a/packages/flutter_tools/lib/src/windows/build_windows.dart +++ b/packages/flutter_tools/lib/src/windows/build_windows.dart @@ -56,9 +56,10 @@ Future buildWindows(WindowsProject windowsProject, BuildInfo buildInfo, { // TODO(pbo-linaro): Add support for windows-arm64 platform, https://github.com/flutter/flutter/issues/129807 const TargetPlatform targetPlatform = TargetPlatform.windows_x64; - final Directory buildDirectory = globals.fs.directory( - getWindowsBuildDirectory(targetPlatform) - ); + final Directory buildDirectory = globals.fs.directory(globals.fs.path.join( + projectPath, + getWindowsBuildDirectory(targetPlatform), + )); final List migrators = [ CmakeCustomCommandMigration(windowsProject, globals.logger), diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_ios_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_ios_test.dart index 8f0ae0d5b3257..9cdbbdd3751ea 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_ios_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_ios_test.dart @@ -5,11 +5,13 @@ import 'package:args/command_runner.dart'; import 'package:file/memory.dart'; import 'package:flutter_tools/src/android/android_sdk.dart'; +import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/platform.dart'; +import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; @@ -30,7 +32,6 @@ import '../../src/test_build_system.dart'; import '../../src/test_flutter_command_runner.dart'; class FakeXcodeProjectInterpreterWithBuildSettings extends FakeXcodeProjectInterpreter { - FakeXcodeProjectInterpreterWithBuildSettings({this.productBundleIdentifier, this.developmentTeam = 'abc'}); @override @@ -69,6 +70,10 @@ final Platform notMacosPlatform = FakePlatform( void main() { late FileSystem fileSystem; late TestUsage usage; + late BufferLogger logger; + late FakeProcessManager processManager; + late ProcessUtils processUtils; + late Artifacts artifacts; setUpAll(() { Cache.disableLocking(); @@ -76,7 +81,14 @@ void main() { setUp(() { fileSystem = MemoryFileSystem.test(); + artifacts = Artifacts.test(fileSystem: fileSystem); usage = TestUsage(); + logger = BufferLogger.test(); + processManager = FakeProcessManager.empty(); + processUtils = ProcessUtils( + logger: logger, + processManager: processManager, + ); }); // Sets up the minimal mock project files necessary to look like a Flutter project. @@ -192,10 +204,12 @@ void main() { testUsingContext('ios build fails when there is no ios project', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createCoreMockProjectFiles(); @@ -206,16 +220,18 @@ void main() { }, overrides: { Platform: () => macosPlatform, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ios build fails in debug with code analysis', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createCoreMockProjectFiles(); @@ -226,16 +242,18 @@ void main() { }, overrides: { Platform: () => macosPlatform, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ios build fails on non-macOS platform', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fileSystem.file('pubspec.yaml').createSync(); @@ -250,169 +268,175 @@ void main() { }, overrides: { Platform: () => notMacosPlatform, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ios build invokes xcode build', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(onRun: () { + fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); + }), + setUpRsyncCommand(), + ]); + await createTestCommandRunner(command).run( const ['build', 'ios', '--no-pub'] ); expect(testLogger.statusText, contains('build/ios/iphoneos/Runner.app')); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(onRun: () { - fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); - }), - setUpRsyncCommand(), - ]), + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ios build invokes xcode build with renamed xcodeproj and xcworkspace', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), osUtils: FakeOperatingSystemUtils(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(customNaming: true, onRun: () { + fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); + }), + setUpRsyncCommand(), + ]); + fileSystem.directory(fileSystem.path.join('ios', 'RenamedProj.xcodeproj')).createSync(recursive: true); fileSystem.directory(fileSystem.path.join('ios', 'RenamedWorkspace.xcworkspace')).createSync(recursive: true); fileSystem.file(fileSystem.path.join('ios', 'RenamedProj.xcodeproj', 'project.pbxproj')).createSync(); createCoreMockProjectFiles(); await createTestCommandRunner(command).run( - const ['build', 'ios', '--no-pub'] + const ['build', 'ios', '--no-pub'] ); expect(testLogger.statusText, contains('build/ios/iphoneos/Runner.app')); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(customNaming: true, onRun: () { - fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); - }), - setUpRsyncCommand(), - ]), + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ios build invokes xcode build with device ID', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(deviceId: '1234', onRun: () { + fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); + }), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); await createTestCommandRunner(command).run( - const ['build', 'ios', '--no-pub', '--device-id', '1234'] + const ['build', 'ios', '--no-pub', '--device-id', '1234'], ); expect(testLogger.statusText, contains('build/ios/iphoneos/Runner.app')); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(deviceId: '1234', onRun: () { - fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); - }), - setUpRsyncCommand(), - ]), + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ios simulator build invokes xcode build', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(simulator: true, onRun: () { + fileSystem.directory('build/ios/Debug-iphonesimulator/Runner.app').createSync(recursive: true); + }), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); await createTestCommandRunner(command).run( - const ['build', 'ios', '--simulator', '--no-pub'] + const ['build', 'ios', '--simulator', '--no-pub'], ); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(simulator: true, onRun: () { - fileSystem.directory('build/ios/Debug-iphonesimulator/Runner.app').createSync(recursive: true); - }), - setUpRsyncCommand(), - ]), + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ios build invokes xcode build with verbosity', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); - - await createTestCommandRunner(command).run( - const ['build', 'ios', '--no-pub', '-v'] - ); - }, overrides: { - FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ + processManager.addCommands([ xattrCommand, setUpFakeXcodeBuildHandler(verbose: true, onRun: () { fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); }), setUpRsyncCommand(), - ]), + ]); + + await createTestCommandRunner(command).run( + const ['build', 'ios', '--no-pub', '-v'], + ); + }, overrides: { + FileSystem: () => fileSystem, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Performs code size analysis and sends analytics', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); - createMinimalMockProjectFiles(); - - await createTestCommandRunner(command).run( - const ['build', 'ios', '--no-pub', '--analyze-size'] - ); - - expect(testLogger.statusText, contains('A summary of your iOS bundle analysis can be found at')); - expect(testLogger.statusText, contains('dart devtools --appSizeBase=')); - expect(usage.events, contains( - const TestUsageEvent('code-size-analysis', 'ios'), - )); - }, overrides: { - FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ + processManager.addCommands([ xattrCommand, setUpFakeXcodeBuildHandler(onRun: () { fileSystem.directory('build/ios/Release-iphoneos/Runner.app').createSync(recursive: true); @@ -434,7 +458,22 @@ void main() { setUpRsyncCommand(onRun: () => fileSystem.file('build/ios/iphoneos/Runner.app/Frameworks/App.framework/App') ..createSync(recursive: true) ..writeAsBytesSync(List.generate(10000, (int index) => 0))), - ]), + ]); + createMinimalMockProjectFiles(); + + await createTestCommandRunner(command).run( + const ['build', 'ios', '--no-pub', '--analyze-size'] + ); + + expect(logger.statusText, contains('A summary of your iOS bundle analysis can be found at')); + expect(logger.statusText, contains('dart devtools --appSizeBase=')); + expect(usage.events, contains( + const TestUsageEvent('code-size-analysis', 'ios'), + )); + }, overrides: { + FileSystem: () => fileSystem, + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, FileSystemUtils: () => FileSystemUtils(fileSystem: fileSystem, platform: macosPlatform), Usage: () => usage, @@ -461,11 +500,13 @@ void main() { testUsingContext('Sends an analytics event when Impeller is enabled', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: MemoryFileSystem.test(), logger: BufferLogger.test(), osUtils: FakeOperatingSystemUtils(), + processUtils: processUtils, ); createMinimalMockProjectFiles(); @@ -504,11 +545,13 @@ void main() { testUsingContext('Sends an analytics event when Impeller is disabled', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: fileSystem, logger: BufferLogger.test(), osUtils: FakeOperatingSystemUtils(), + processUtils: processUtils, ); createMinimalMockProjectFiles(); @@ -570,12 +613,22 @@ void main() { group('xcresults device', () { testUsingContext('Trace error if xcresult is empty.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + }), + setUpXCResultCommand(), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -584,29 +637,34 @@ void main() { throwsToolExit(), ); - expect(testLogger.traceText, contains('xcresult parser: Unrecognized top level json format.')); + expect(logger.traceText, contains('xcresult parser: Unrecognized top level json format.')); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - }), - setUpXCResultCommand(), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Display xcresult issues on console if parsed, suppress Xcode output', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + }, stdout: 'Lots of spew from Xcode', + ), + setUpXCResultCommand(stdout: kSampleResultJsonWithIssues), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -615,33 +673,36 @@ void main() { throwsToolExit(), ); - expect(testLogger.errorText, contains("Use of undeclared identifier 'asdas'")); - expect(testLogger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); - expect(testLogger.statusText, isNot(contains("Xcode's output"))); - expect(testLogger.statusText, isNot(contains('Lots of spew from Xcode'))); + expect(logger.errorText, contains("Use of undeclared identifier 'asdas'")); + expect(logger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); + expect(logger.statusText, isNot(contains("Xcode's output"))); + expect(logger.statusText, isNot(contains('Lots of spew from Xcode'))); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - }, stdout: 'Lots of spew from Xcode', - ), - setUpXCResultCommand(stdout: kSampleResultJsonWithIssues), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Do not display xcresult issues that needs to be discarded.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + }), + setUpXCResultCommand(stdout: kSampleResultJsonWithIssuesToBeDiscarded), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -650,32 +711,34 @@ void main() { throwsToolExit(), ); - expect(testLogger.errorText, contains("Use of undeclared identifier 'asdas'")); - expect(testLogger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); - expect(testLogger.errorText, isNot(contains('Command PhaseScriptExecution failed with a nonzero exit code'))); - expect(testLogger.warningText, isNot(contains("The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 14.0.99."))); + expect(logger.errorText, contains("Use of undeclared identifier 'asdas'")); + expect(logger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); + expect(logger.errorText, isNot(contains('Command PhaseScriptExecution failed with a nonzero exit code'))); + expect(logger.warningText, isNot(contains("The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 14.0.99."))); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - }), - setUpXCResultCommand(stdout: kSampleResultJsonWithIssuesToBeDiscarded), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Trace if xcresult bundle does not exist.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(exitCode: 1), + setUpXCResultCommand(stdout: kSampleResultJsonWithIssues), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -687,24 +750,29 @@ void main() { expect(testLogger.traceText, contains('The xcresult bundle are not generated. Displaying xcresult is disabled.')); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(exitCode: 1), - setUpXCResultCommand(stdout: kSampleResultJsonWithIssues), - setUpRsyncCommand(), - ]), + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Extra error message for provision profile issue in xcresult bundle.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + }), + setUpXCResultCommand(stdout: kSampleResultJsonWithProvisionIssue), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -713,33 +781,40 @@ void main() { throwsToolExit(), ); - expect(testLogger.errorText, contains('Some Provisioning profile issue.')); - expect(testLogger.errorText, contains('It appears that there was a problem signing your application prior to installation on the device.')); - expect(testLogger.errorText, contains('Verify that the Bundle Identifier in your project is your signing id in Xcode')); - expect(testLogger.errorText, contains('open ios/Runner.xcworkspace')); - expect(testLogger.errorText, contains("Also try selecting 'Product > Build' to fix the problem.")); + expect(logger.errorText, contains('Some Provisioning profile issue.')); + expect(logger.errorText, contains('It appears that there was a problem signing your application prior to installation on the device.')); + expect(logger.errorText, contains('Verify that the Bundle Identifier in your project is your signing id in Xcode')); + expect(logger.errorText, contains('open ios/Runner.xcworkspace')); + expect(logger.errorText, contains("Also try selecting 'Product > Build' to fix the problem.")); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - }), - setUpXCResultCommand(stdout: kSampleResultJsonWithProvisionIssue), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Display xcresult issues with no provisioning profile.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler( + exitCode: 1, + onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + } + ), + setUpXCResultCommand(stdout: kSampleResultJsonWithNoProvisioningProfileIssue), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -748,33 +823,34 @@ void main() { throwsToolExit(), ); - expect(testLogger.errorText, contains('Runner requires a provisioning profile. Select a provisioning profile in the Signing & Capabilities editor')); - expect(testLogger.errorText, contains(noProvisioningProfileInstruction)); + expect(logger.errorText, contains('Runner requires a provisioning profile. Select a provisioning profile in the Signing & Capabilities editor')); + expect(logger.errorText, contains(noProvisioningProfileInstruction)); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler( - exitCode: 1, - onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - } - ), - setUpXCResultCommand(stdout: kSampleResultJsonWithNoProvisioningProfileIssue), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Extra error message for missing simulator platform in xcresult bundle.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + }), + setUpXCResultCommand(stdout: kSampleResultJsonWithActionIssues), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -783,38 +859,26 @@ void main() { throwsToolExit(), ); - expect(testLogger.errorText, contains(missingPlatformInstructions('iOS 17.0'))); + expect(logger.errorText, contains(missingPlatformInstructions('iOS 17.0'))); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler(exitCode: 1, onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - }), - setUpXCResultCommand(stdout: kSampleResultJsonWithActionIssues), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Delete xcresult bundle before each xcodebuild command.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); - - createMinimalMockProjectFiles(); - - await createTestCommandRunner(command).run(const ['build', 'ios', '--no-pub']); - - expect(testLogger.statusText, contains('Xcode build done.')); - }, overrides: { - FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ + processManager.addCommands([ xattrCommand, // Intentionally fail the first xcodebuild command with concurrent run failure message. setUpFakeXcodeBuildHandler( @@ -836,32 +900,32 @@ void main() { ), setUpXCResultCommand(stdout: kSampleResultJsonNoIssues), setUpRsyncCommand(), - ], - ), + ]); + + createMinimalMockProjectFiles(); + + await createTestCommandRunner(command).run(const ['build', 'ios', '--no-pub']); + + expect(logger.statusText, contains('Xcode build done.')); + }, overrides: { + FileSystem: () => fileSystem, + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Failed to parse xcresult but display missing provisioning profile issue from stdout.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); - - createMinimalMockProjectFiles(); - - await expectLater( - createTestCommandRunner(command).run(const ['build', 'ios', '--no-pub']), - throwsToolExit(), - ); - - expect(testLogger.errorText, contains(noProvisioningProfileInstruction)); - }, overrides: { - FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ + processManager.addCommands([ xattrCommand, setUpFakeXcodeBuildHandler( exitCode: 1, @@ -874,19 +938,45 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig ), setUpXCResultCommand(stdout: kSampleResultJsonInvalidIssuesMap), setUpRsyncCommand(), - ]), + ]); + + createMinimalMockProjectFiles(); + + await expectLater( + createTestCommandRunner(command).run(const ['build', 'ios', '--no-pub']), + throwsToolExit(), + ); + + expect(logger.errorText, contains(noProvisioningProfileInstruction)); + }, overrides: { + FileSystem: () => fileSystem, + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Failed to parse xcresult but detected no development team issue.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler( + exitCode: 1, + onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + } + ), + setUpXCResultCommand(stdout: kSampleResultJsonInvalidIssuesMap), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -895,30 +985,23 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig throwsToolExit(), ); - expect(testLogger.errorText, contains(noDevelopmentTeamInstruction)); + expect(logger.errorText, contains(noDevelopmentTeamInstruction)); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler( - exitCode: 1, - onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - } - ), - setUpXCResultCommand(stdout: kSampleResultJsonInvalidIssuesMap), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(developmentTeam: null), }); testUsingContext('xcresult did not detect issue but detected by stdout.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); @@ -953,12 +1036,25 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig testUsingContext('xcresult did not detect issue, no development team is detected from build setting.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler( + exitCode: 1, + onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + } + ), + setUpXCResultCommand(stdout: kSampleResultJsonInvalidIssuesMap), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -970,29 +1066,32 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig expect(testLogger.errorText, contains(noDevelopmentTeamInstruction)); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler( - exitCode: 1, - onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - } - ), - setUpXCResultCommand(stdout: kSampleResultJsonInvalidIssuesMap), - setUpRsyncCommand(), - ]), + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(developmentTeam: null), }); testUsingContext('No development team issue error message is not displayed if no provisioning profile issue is detected from xcresult first.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler( + exitCode: 1, + onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + } + ), + setUpXCResultCommand(stdout: kSampleResultJsonWithNoProvisioningProfileIssue), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -1001,33 +1100,37 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig throwsToolExit(), ); - expect(testLogger.errorText, contains(noProvisioningProfileInstruction)); - expect(testLogger.errorText, isNot(contains(noDevelopmentTeamInstruction))); + expect(logger.errorText, contains(noProvisioningProfileInstruction)); + expect(logger.errorText, isNot(contains(noDevelopmentTeamInstruction))); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler( - exitCode: 1, - onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - } - ), - setUpXCResultCommand(stdout: kSampleResultJsonWithNoProvisioningProfileIssue), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(developmentTeam: null), }); testUsingContext('General provisioning profile issue error message is not displayed if no development team issue is detected first.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler( + exitCode: 1, + onRun: () { + fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); + } + ), + setUpXCResultCommand(stdout: kSampleResultJsonWithProvisionIssue), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -1036,21 +1139,12 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig throwsToolExit(), ); - expect(testLogger.errorText, contains(noDevelopmentTeamInstruction)); - expect(testLogger.errorText, isNot(contains('It appears that there was a problem signing your application prior to installation on the device.'))); + expect(logger.errorText, contains(noDevelopmentTeamInstruction)); + expect(logger.errorText, isNot(contains('It appears that there was a problem signing your application prior to installation on the device.'))); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler( - exitCode: 1, - onRun: () { - fileSystem.systemTempDirectory.childDirectory(_xcBundleDirectoryPath).createSync(); - } - ), - setUpXCResultCommand(stdout: kSampleResultJsonWithProvisionIssue), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(developmentTeam: null), }); @@ -1059,24 +1153,15 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig group('xcresults simulator', () { testUsingContext('Trace error if xcresult is empty.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); - - createMinimalMockProjectFiles(); - - await expectLater( - createTestCommandRunner(command).run(const ['build', 'ios', '--simulator', '--no-pub']), - throwsToolExit(), - ); - - expect(testLogger.traceText, contains('xcresult parser: Unrecognized top level json format.')); - }, overrides: { - FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ + processManager.addCommands([ xattrCommand, setUpFakeXcodeBuildHandler( simulator: true, @@ -1087,32 +1172,35 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig ), setUpXCResultCommand(), setUpRsyncCommand(), - ]), + ]); + + createMinimalMockProjectFiles(); + + await expectLater( + createTestCommandRunner(command).run(const ['build', 'ios', '--simulator', '--no-pub']), + throwsToolExit(), + ); + + expect(logger.traceText, contains('xcresult parser: Unrecognized top level json format.')); + }, overrides: { + FileSystem: () => fileSystem, + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Display xcresult issues on console if parsed.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); - - createMinimalMockProjectFiles(); - - await expectLater( - createTestCommandRunner(command).run(const ['build', 'ios', '--simulator', '--no-pub']), - throwsToolExit(), - ); - - expect(testLogger.errorText, contains("Use of undeclared identifier 'asdas'")); - expect(testLogger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); - }, overrides: { - FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ + processManager.addCommands([ xattrCommand, setUpFakeXcodeBuildHandler( simulator: true, @@ -1123,34 +1211,37 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig ), setUpXCResultCommand(stdout: kSampleResultJsonWithIssues), setUpRsyncCommand(), - ]), + ]); + + createMinimalMockProjectFiles(); + + await expectLater( + createTestCommandRunner(command).run(const ['build', 'ios', '--simulator', '--no-pub']), + throwsToolExit(), + ); + + expect(logger.errorText, contains("Use of undeclared identifier 'asdas'")); + expect(logger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); + }, overrides: { + FileSystem: () => fileSystem, + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Do not display xcresult issues that needs to be discarded.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); - createMinimalMockProjectFiles(); - - await expectLater( - createTestCommandRunner(command).run(const ['build', 'ios', '--simulator', '--no-pub']), - throwsToolExit(), - ); - - expect(testLogger.errorText, contains("Use of undeclared identifier 'asdas'")); - expect(testLogger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); - expect(testLogger.errorText, isNot(contains('Command PhaseScriptExecution failed with a nonzero exit code'))); - expect(testLogger.warningText, isNot(contains("The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 14.0.99."))); - }, overrides: { - FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ + processManager.addCommands([ xattrCommand, setUpFakeXcodeBuildHandler( simulator: true, @@ -1161,19 +1252,46 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig ), setUpXCResultCommand(stdout: kSampleResultJsonWithIssuesToBeDiscarded), setUpRsyncCommand(), - ]), + ]); + + createMinimalMockProjectFiles(); + + await expectLater( + createTestCommandRunner(command).run(const ['build', 'ios', '--simulator', '--no-pub']), + throwsToolExit(), + ); + + expect(logger.errorText, contains("Use of undeclared identifier 'asdas'")); + expect(logger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); + expect(logger.errorText, isNot(contains('Command PhaseScriptExecution failed with a nonzero exit code'))); + expect(logger.warningText, isNot(contains("The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 14.0.99."))); + }, overrides: { + FileSystem: () => fileSystem, + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Trace if xcresult bundle does not exist.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); + processManager.addCommands([ + xattrCommand, + setUpFakeXcodeBuildHandler( + simulator: true, + exitCode: 1, + ), + setUpXCResultCommand(stdout: kSampleResultJsonWithIssues), + setUpRsyncCommand(), + ]); createMinimalMockProjectFiles(); @@ -1182,18 +1300,11 @@ Runner requires a provisioning profile. Select a provisioning profile in the Sig throwsToolExit(), ); - expect(testLogger.traceText, contains('The xcresult bundle are not generated. Displaying xcresult is disabled.')); + expect(logger.traceText, contains('The xcresult bundle are not generated. Displaying xcresult is disabled.')); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.list([ - xattrCommand, - setUpFakeXcodeBuildHandler( - simulator: true, - exitCode: 1, - ), - setUpXCResultCommand(stdout: kSampleResultJsonWithIssues), - setUpRsyncCommand(), - ]), + Logger: () => logger, + ProcessManager: () => processManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart index e925821917847..6e2c083e1a3ac 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart @@ -6,9 +6,11 @@ import 'dart:typed_data'; import 'package:args/command_runner.dart'; import 'package:file/memory.dart'; +import 'package:flutter_tools/src/artifacts.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/base/process.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/commands/build.dart'; @@ -33,10 +35,10 @@ class FakeXcodeProjectInterpreterWithBuildSettings extends FakeXcodeProjectInter @override Future> getBuildSettings( - String projectPath, { - XcodeProjectBuildContext? buildContext, - Duration timeout = const Duration(minutes: 1), - }) async { + String projectPath, { + XcodeProjectBuildContext? buildContext, + Duration timeout = const Duration(minutes: 1), + }) async { return { ...overrides, 'PRODUCT_BUNDLE_IDENTIFIER': 'io.flutter.someProject', @@ -72,7 +74,10 @@ void main() { late FileSystem fileSystem; late TestUsage usage; late FakeProcessManager fakeProcessManager; + late ProcessUtils processUtils; late FakePlistUtils plistUtils; + late BufferLogger logger; + late Artifacts artifacts; setUpAll(() { Cache.disableLocking(); @@ -80,8 +85,14 @@ void main() { setUp(() { fileSystem = MemoryFileSystem.test(); + artifacts = Artifacts.test(fileSystem: fileSystem); usage = TestUsage(); fakeProcessManager = FakeProcessManager.empty(); + logger = BufferLogger.test(); + processUtils = ProcessUtils( + logger: logger, + processManager: fakeProcessManager, + ); plistUtils = FakePlistUtils(); }); @@ -196,10 +207,12 @@ void main() { testUsingContext('ipa build fails when there is no ios project', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createCoreMockProjectFiles(); @@ -210,16 +223,18 @@ void main() { }, overrides: { Platform: () => macosPlatform, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => fakeProcessManager, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ipa build fails in debug with code analysis', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createCoreMockProjectFiles(); @@ -230,16 +245,18 @@ void main() { }, overrides: { Platform: () => macosPlatform, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => fakeProcessManager, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ipa build fails on non-macOS platform', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fileSystem.file('pubspec.yaml').createSync(); @@ -253,18 +270,21 @@ void main() { ), supported ? throwsToolExit() : throwsA(isA())); }, overrides: { Platform: () => notMacosPlatform, + Logger: () => logger, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => fakeProcessManager, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ipa build fails when export plist does not exist', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -281,7 +301,8 @@ void main() { ); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + Logger: () => logger, + ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -290,10 +311,12 @@ void main() { testUsingContext('ipa build fails when export plist is not a file', () async { final Directory bogus = fileSystem.directory('bogus')..createSync(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -310,17 +333,19 @@ void main() { ); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ipa build fails when --export-options-plist and --export-method are used together', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -339,17 +364,19 @@ void main() { ); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('ipa build reports when IPA fails', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -379,13 +406,14 @@ void main() { const ['build', 'ipa', '--no-pub'] ); - expect(testLogger.statusText, contains('build/ios/archive/Runner.xcarchive')); - expect(testLogger.statusText, contains('Building App Store IPA')); - expect(testLogger.errorText, contains('Encountered error while creating the IPA:')); - expect(testLogger.errorText, contains('error: exportArchive: "Runner.app" requires a provisioning profile.')); + expect(logger.statusText, contains('build/ios/archive/Runner.xcarchive')); + expect(logger.statusText, contains('Building App Store IPA')); + expect(logger.errorText, contains('Encountered error while creating the IPA:')); + expect(logger.errorText, contains('error: exportArchive: "Runner.app" requires a provisioning profile.')); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -394,10 +422,12 @@ void main() { testUsingContext('ipa build invokes xcodebuild and archives for app store', () async { final File cachedExportOptionsPlist = fileSystem.file('/CachedExportOptions.plist'); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -427,14 +457,15 @@ void main() { final String actualIpaPlistContents = fileSystem.file(cachedExportOptionsPlist).readAsStringSync(); expect(actualIpaPlistContents, expectedIpaPlistContents); - expect(testLogger.statusText, contains('build/ios/archive/Runner.xcarchive')); - expect(testLogger.statusText, contains('Building App Store IPA')); - expect(testLogger.statusText, contains('Built IPA to /build/ios/ipa')); - expect(testLogger.statusText, contains('To upload to the App Store')); - expect(testLogger.statusText, contains('Apple Transporter macOS app')); + expect(logger.statusText, contains('build/ios/archive/Runner.xcarchive')); + expect(logger.statusText, contains('Building App Store IPA')); + expect(logger.statusText, contains('Built IPA to /build/ios/ipa')); + expect(logger.statusText, contains('To upload to the App Store')); + expect(logger.statusText, contains('Apple Transporter macOS app')); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -443,10 +474,12 @@ void main() { testUsingContext('ipa build invokes xcodebuild and archives for ad-hoc distribution', () async { final File cachedExportOptionsPlist = fileSystem.file('/CachedExportOptions.plist'); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -476,14 +509,15 @@ void main() { final String actualIpaPlistContents = fileSystem.file(cachedExportOptionsPlist).readAsStringSync(); expect(actualIpaPlistContents, expectedIpaPlistContents); - expect(testLogger.statusText, contains('build/ios/archive/Runner.xcarchive')); - expect(testLogger.statusText, contains('Building ad-hoc IPA')); - expect(testLogger.statusText, contains('Built IPA to /build/ios/ipa')); - // Don't instruct how to upload to the App Store. - expect(testLogger.statusText, isNot(contains('To upload'))); + expect(logger.statusText, contains('build/ios/archive/Runner.xcarchive')); + expect(logger.statusText, contains('Building ad-hoc IPA')); + expect(logger.statusText, contains('Built IPA to /build/ios/ipa')); + // Don'ltruct how to upload to the App Store. + expect(logger.statusText, isNot(contains('To upload'))); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -492,10 +526,12 @@ void main() { testUsingContext('ipa build invokes xcodebuild and archives for enterprise distribution', () async { final File cachedExportOptionsPlist = fileSystem.file('/CachedExportOptions.plist'); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -525,14 +561,15 @@ void main() { final String actualIpaPlistContents = fileSystem.file(cachedExportOptionsPlist).readAsStringSync(); expect(actualIpaPlistContents, expectedIpaPlistContents); - expect(testLogger.statusText, contains('build/ios/archive/Runner.xcarchive')); - expect(testLogger.statusText, contains('Building enterprise IPA')); - expect(testLogger.statusText, contains('Built IPA to /build/ios/ipa')); - // Don't instruct how to upload to the App Store. - expect(testLogger.statusText, isNot(contains('To upload'))); + expect(logger.statusText, contains('build/ios/archive/Runner.xcarchive')); + expect(logger.statusText, contains('Building enterprise IPA')); + expect(logger.statusText, contains('Built IPA to /build/ios/ipa')); + // Don'ltruct how to upload to the App Store. + expect(logger.statusText, isNot(contains('To upload'))); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -540,10 +577,12 @@ void main() { testUsingContext('ipa build invokes xcode build with verbosity', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -559,6 +598,7 @@ void main() { expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -566,10 +606,12 @@ void main() { testUsingContext('ipa build --no-codesign skips codesigning and IPA creation', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -605,9 +647,10 @@ void main() { const ['build', 'ipa', '--no-pub', '--no-codesign'] ); expect(fakeProcessManager, hasNoRemainingExpectations); - expect(testLogger.statusText, contains('Codesigning disabled with --no-codesign, skipping IPA')); + expect(logger.statusText, contains('Codesigning disabled with --no-codesign, skipping IPA')); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -615,14 +658,17 @@ void main() { testUsingContext('code size analysis fails when app not found', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); + fakeProcessManager.addCommand(setUpFakeXcodeBuildHandler()); await expectToolExitLater( createTestCommandRunner(command).run( const ['build', 'ipa', '--no-pub', '--analyze-size'] @@ -631,17 +677,19 @@ void main() { ); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), }); testUsingContext('Performs code size analysis and sends analytics', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -674,14 +722,15 @@ void main() { const ['build', 'ipa', '--no-pub', '--analyze-size'] ); - expect(testLogger.statusText, contains('A summary of your iOS bundle analysis can be found at')); - expect(testLogger.statusText, contains('dart devtools --appSizeBase=')); + expect(logger.statusText, contains('A summary of your iOS bundle analysis can be found at')); + expect(logger.statusText, contains('dart devtools --appSizeBase=')); expect(usage.events, contains( const TestUsageEvent('code-size-analysis', 'ios'), )); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, FileSystemUtils: () => FileSystemUtils(fileSystem: fileSystem, platform: macosPlatform), @@ -695,10 +744,12 @@ void main() { final File exportOptions = fileSystem.file('ExportOptions.plist') ..createSync(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -718,10 +769,11 @@ void main() { ], ); - expect(testLogger.statusText, contains('Built IPA to $outputPath.')); + expect(logger.statusText, contains('Built IPA to $outputPath.')); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -729,10 +781,12 @@ void main() { testUsingContext('Trace error if xcresult is empty.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -749,10 +803,11 @@ void main() { throwsToolExit(), ); - expect(testLogger.traceText, contains('xcresult parser: Unrecognized top level json format.')); + expect(logger.traceText, contains('xcresult parser: Unrecognized top level json format.')); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -760,10 +815,12 @@ void main() { testUsingContext('Display xcresult issues on console if parsed.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -780,11 +837,12 @@ void main() { throwsToolExit(), ); - expect(testLogger.errorText, contains("Use of undeclared identifier 'asdas'")); - expect(testLogger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); + expect(logger.errorText, contains("Use of undeclared identifier 'asdas'")); + expect(logger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -792,10 +850,12 @@ void main() { testUsingContext('Do not display xcresult issues that needs to be discarded.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -812,13 +872,14 @@ void main() { throwsToolExit(), ); - expect(testLogger.errorText, contains("Use of undeclared identifier 'asdas'")); - expect(testLogger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); - expect(testLogger.errorText, isNot(contains('Command PhaseScriptExecution failed with a nonzero exit code'))); - expect(testLogger.warningText, isNot(contains("The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 14.0.99."))); + expect(logger.errorText, contains("Use of undeclared identifier 'asdas'")); + expect(logger.errorText, contains('/Users/m/Projects/test_create/ios/Runner/AppDelegate.m:7:56')); + expect(logger.errorText, isNot(contains('Command PhaseScriptExecution failed with a nonzero exit code'))); + expect(logger.warningText, isNot(contains("The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 14.0.99."))); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -826,10 +887,12 @@ void main() { testUsingContext('Trace if xcresult bundle does not exist.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -843,10 +906,11 @@ void main() { throwsToolExit(), ); - expect(testLogger.traceText, contains('The xcresult bundle are not generated. Displaying xcresult is disabled.')); + expect(logger.traceText, contains('The xcresult bundle are not generated. Displaying xcresult is disabled.')); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -855,10 +919,12 @@ void main() { testUsingContext('Extra error message for provision profile issue in xcresulb bundle.', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fakeProcessManager.addCommands([ @@ -875,14 +941,15 @@ void main() { throwsToolExit(), ); - expect(testLogger.errorText, contains('Some Provisioning profile issue.')); - expect(testLogger.errorText, contains('It appears that there was a problem signing your application prior to installation on the device.')); - expect(testLogger.errorText, contains('Verify that the Bundle Identifier in your project is your signing id in Xcode')); - expect(testLogger.errorText, contains('open ios/Runner.xcworkspace')); - expect(testLogger.errorText, contains("Also try selecting 'Product > Build' to fix the problem.")); + expect(logger.errorText, contains('Some Provisioning profile issue.')); + expect(logger.errorText, contains('It appears that there was a problem signing your application prior to installation on the device.')); + expect(logger.errorText, contains('Verify that the Bundle Identifier in your project is your signing id in Xcode')); + expect(logger.errorText, contains('open ios/Runner.xcworkspace')); + expect(logger.errorText, contains("Also try selecting 'Product > Build' to fix the problem.")); expect(fakeProcessManager, hasNoRemainingExpectations); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -907,17 +974,19 @@ void main() { }; final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, + logger.statusText, contains( '[!] App Settings Validation\n' ' ! Version Number: Missing\n' @@ -928,11 +997,12 @@ void main() { ' ! You must set up the missing app settings.\n' )); expect( - testLogger.statusText, + logger.statusText, contains('To update the settings, please refer to https://docs.flutter.dev/deployment/ios') ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -963,17 +1033,19 @@ void main() { }; final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, + logger.statusText, contains( '[✓] App Settings Validation\n' ' • Version Number: 12.34.56\n' @@ -984,11 +1056,12 @@ void main() { ) ); expect( - testLogger.statusText, + logger.statusText, contains('To update the settings, please refer to https://docs.flutter.dev/deployment/ios') ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1018,32 +1091,35 @@ void main() { }; final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, - contains( - '[✓] App Settings Validation\n' - ' • Version Number: 12.34.56\n' - ' • Build Number: 666\n' - ' • Display Name: Awesome Gallery\n' - ' • Deployment Target: 11.0\n' - ' • Bundle Identifier: io.flutter.someProject\n' - ) + logger.statusText, + contains( + '[✓] App Settings Validation\n' + ' • Version Number: 12.34.56\n' + ' • Build Number: 666\n' + ' • Display Name: Awesome Gallery\n' + ' • Deployment Target: 11.0\n' + ' • Bundle Identifier: io.flutter.someProject\n' + ), ); expect( - testLogger.statusText, - contains('To update the settings, please refer to https://docs.flutter.dev/deployment/ios') + logger.statusText, + contains('To update the settings, please refer to https://docs.flutter.dev/deployment/ios'), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1069,21 +1145,25 @@ void main() { }; final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( - ['build', 'ipa', '--no-pub']); + ['build', 'ipa', '--no-pub'], + ); expect( - testLogger.statusText, - contains(' ! Your application still contains the default "com.example" bundle identifier.') + logger.statusText, + contains(' ! Your application still contains the default "com.example" bundle identifier.'), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1108,21 +1188,24 @@ void main() { }; final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, + logger.statusText, isNot(contains(' ! Your application still contains the default "com.example" bundle identifier.')) ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1189,21 +1272,24 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, + logger.statusText, contains(' ! App icon is set to the default placeholder icon. Replace with unique icons.'), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1268,21 +1354,24 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, - isNot(contains(' ! App icon is set to the default placeholder icon. Replace with unique icons.')) + logger.statusText, + isNot(contains('! App icon is set to the default placeholder icon. Replace with unique icons.')), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1327,21 +1416,24 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, + logger.statusText, contains(' ! App icon is using the incorrect size (e.g. Icon-App-20x20@2x.png).') ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1386,21 +1478,25 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( - ['build', 'ipa', '--no-pub']); + ['build', 'ipa', '--no-pub'], + ); expect( - testLogger.statusText, - contains(' ! App icon is using the incorrect size (e.g. Icon-App-20x20@2x.png).') + logger.statusText, + contains(' ! App icon is using the incorrect size (e.g. Icon-App-20x20@2x.png).'), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1445,21 +1541,24 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, - isNot(contains(' ! App icon is using the incorrect size (e.g. Icon-App-20x20@2x.png).')) + logger.statusText, + isNot(contains(' ! App icon is using the incorrect size (e.g. Icon-App-20x20@2x.png).')), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1505,22 +1604,26 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( - ['build', 'ipa', '--no-pub']); + ['build', 'ipa', '--no-pub'], + ); // The validation should be skipped, even when the icon size is incorrect. expect( - testLogger.statusText, + logger.statusText, isNot(contains(' ! App icon is using the incorrect size (e.g. Icon-App-20x20@2x.png).')), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1609,24 +1712,28 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( - ['build', 'ipa', '--no-pub']); + ['build', 'ipa', '--no-pub'], + ); // The validation should be skipped, even when the image size is incorrect. for (final String imageFileName in imageFileNames) { expect( - testLogger.statusText, - isNot(contains(' ! App icon is using the incorrect size (e.g. $imageFileName).')) + logger.statusText, + isNot(contains(' ! App icon is using the incorrect size (e.g. $imageFileName).')), ); } }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1689,21 +1796,24 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, + logger.statusText, contains(' ! Launch image is set to the default placeholder icon. Replace with unique launch image.'), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), @@ -1767,21 +1877,24 @@ void main() { createMinimalMockProjectFiles(); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + fileSystem: fileSystem, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); await createTestCommandRunner(command).run( ['build', 'ipa', '--no-pub']); expect( - testLogger.statusText, + logger.statusText, isNot(contains(' ! Launch image is set to the default placeholder icon. Replace with unique launch image.')), ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => fakeProcessManager, Platform: () => macosPlatform, XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(), diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_linux_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_linux_test.dart index d5f533465e6db..ec3bc880ddeb7 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_linux_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_linux_test.dart @@ -5,10 +5,12 @@ import 'package:args/command_runner.dart'; import 'package:file/memory.dart'; import 'package:file_testing/file_testing.dart'; +import 'package:flutter_tools/src/artifacts.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/base/process.dart'; import 'package:flutter_tools/src/base/utils.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; @@ -47,13 +49,23 @@ void main() { }); late FileSystem fileSystem; - late ProcessManager processManager; + late FakeProcessManager processManager; + late ProcessUtils processUtils; + late Logger logger; late TestUsage usage; + late Artifacts artifacts; setUp(() { fileSystem = MemoryFileSystem.test(); + artifacts = Artifacts.test(fileSystem: fileSystem); Cache.flutterRoot = _kTestFlutterRoot; usage = TestUsage(); + logger = BufferLogger.test(); + processManager = FakeProcessManager.empty(); + processUtils = ProcessUtils( + logger: logger, + processManager: processManager, + ); }); // Creates the mock files necessary to look like a Flutter project. @@ -110,10 +122,12 @@ void main() { testUsingContext('Linux build fails when there is no linux project', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockCoreProjectFiles(); @@ -126,16 +140,18 @@ void main() { }, overrides: { Platform: () => linuxPlatform, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true), }); testUsingContext('Linux build fails on non-linux platform', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); @@ -146,16 +162,18 @@ void main() { }, overrides: { Platform: () => notLinuxPlatform, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true), }); testUsingContext('Linux build fails when feature is disabled', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); @@ -166,19 +184,21 @@ void main() { }, overrides: { Platform: () => linuxPlatform, FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, FeatureFlags: () => TestFeatureFlags(), }); testUsingContext('Linux build invokes CMake and ninja, and writes temporary files', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('release'), ninjaCommand('release'), ]); @@ -199,10 +219,12 @@ void main() { testUsingContext('Handles missing cmake', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); @@ -222,14 +244,16 @@ void main() { testUsingContext('Handles argument error from missing ninja', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('release'), ninjaCommand('release', onRun: () { throw ArgumentError(); @@ -249,14 +273,16 @@ void main() { testUsingContext('Linux build does not spew stdout to status logger', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('debug'), ninjaCommand('debug', stdout: 'STDOUT STUFF', @@ -280,10 +306,12 @@ void main() { testUsingContext('Linux build extracts errors from stdout', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); @@ -309,7 +337,7 @@ ninja: build stopped: subcommand failed. ERROR: No file or variants found for asset: images/a_dot_burr.jpeg '''; - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('release'), ninjaCommand('release', stdout: stdout, @@ -340,14 +368,16 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg testUsingContext('Linux verbose build sets VERBOSE_SCRIPT_LOGGING', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('debug'), ninjaCommand('debug', environment: const { @@ -366,6 +396,7 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg expect(testLogger.errorText, isNot(contains('STDOUT STUFF'))); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => processManager, Platform: () => linuxPlatform, FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true), @@ -374,14 +405,16 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg testUsingContext('Linux on x64 build --debug passes debug mode to cmake and ninja', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('debug'), ninjaCommand('debug'), ]); @@ -391,6 +424,7 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg ); }, overrides: { FileSystem: () => fileSystem, + Logger: () => logger, ProcessManager: () => processManager, Platform: () => linuxPlatform, FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true), @@ -399,14 +433,16 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg testUsingContext('Linux on ARM64 build --debug passes debug mode to cmake and ninja', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: CustomFakeOperatingSystemUtils(hostPlatform: HostPlatform.linux_arm64), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('debug', target: 'arm64'), ninjaCommand('debug', target: 'arm64'), ]); @@ -423,14 +459,16 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg testUsingContext('Linux on x64 build --profile passes profile mode to make', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('profile'), ninjaCommand('profile'), ]); @@ -448,14 +486,16 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg testUsingContext('Linux on ARM64 build --profile passes profile mode to make', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: CustomFakeOperatingSystemUtils(hostPlatform: HostPlatform.linux_arm64), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('profile', target: 'arm64'), ninjaCommand('profile', target: 'arm64'), ]); @@ -472,10 +512,12 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg testUsingContext('Not support Linux cross-build for x64 on arm64', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: CustomFakeOperatingSystemUtils(hostPlatform: HostPlatform.linux_arm64), ); @@ -489,14 +531,16 @@ ERROR: No file or variants found for asset: images/a_dot_burr.jpeg testUsingContext('Linux build configures CMake exports', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('release'), ninjaCommand('release'), ]); @@ -576,21 +620,25 @@ set(BINARY_NAME "fizz_bar") expect(getCmakeExecutableName(flutterProject.linux), 'fizz_bar'); }, overrides: { FileSystem: () => fileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: true), }); testUsingContext('Refuses to build for Linux when feature is disabled', () { final CommandRunner runner = createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), )); - expect(() => runner.run(['build', 'linux', '--no-pub']), - throwsToolExit()); + expect( + () => runner.run(['build', 'linux', '--no-pub']), + throwsToolExit(), + ); }, overrides: { FeatureFlags: () => TestFeatureFlags(), }); @@ -611,14 +659,16 @@ set(BINARY_NAME "fizz_bar") testUsingContext('Performs code size analysis and sends analytics', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('release'), ninjaCommand('release', onRun: () { fileSystem.file('build/flutter_size_01/snapshot.linux-x64.json') @@ -662,14 +712,16 @@ set(BINARY_NAME "fizz_bar") testUsingContext('Linux on ARM64 build --release passes, and check if the LinuxBuildDirectory for arm64 can be referenced correctly by using analytics', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: CustomFakeOperatingSystemUtils(hostPlatform: HostPlatform.linux_arm64), ); setUpMockProjectFilesForBuild(); - processManager = FakeProcessManager.list([ + processManager.addCommands([ cmakeCommand('release', target: 'arm64'), ninjaCommand('release', target: 'arm64', onRun: () { fileSystem.file('build/flutter_size_01/snapshot.linux-arm64.json') diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart index 014ae63b6e07a..1d643369053b3 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart @@ -10,6 +10,7 @@ import 'package:flutter_tools/src/artifacts.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/base/process.dart'; import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; @@ -65,7 +66,10 @@ void main() { late FileSystem fileSystem; late TestUsage usage; late FakeProcessManager fakeProcessManager; + late ProcessUtils processUtils; + late BufferLogger logger; late XcodeProjectInterpreter xcodeProjectInterpreter; + late Artifacts artifacts; setUpAll(() { Cache.disableLocking(); @@ -73,8 +77,14 @@ void main() { setUp(() { fileSystem = MemoryFileSystem.test(); + artifacts = Artifacts.test(fileSystem: fileSystem); + logger = BufferLogger.test(); usage = TestUsage(); fakeProcessManager = FakeProcessManager.empty(); + processUtils = ProcessUtils( + logger: logger, + processManager: fakeProcessManager, + ); xcodeProjectInterpreter = FakeXcodeProjectInterpreter(); }); @@ -139,10 +149,12 @@ STDERR STUFF testUsingContext('macOS build fails when there is no macos project', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createCoreMockProjectFiles(); @@ -161,10 +173,12 @@ STDERR STUFF testUsingContext('macOS build successfully with renamed .xcodeproj/.xcworkspace files', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); @@ -184,10 +198,12 @@ STDERR STUFF testUsingContext('macOS build fails on non-macOS platform', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fileSystem.file('pubspec.yaml').createSync(); @@ -206,10 +222,12 @@ STDERR STUFF testUsingContext('macOS build fails when feature is disabled', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); fileSystem.file('pubspec.yaml').createSync(); @@ -228,10 +246,12 @@ STDERR STUFF testUsingContext('macOS build forwards error stdout to status logger error', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -258,10 +278,12 @@ STDERR STUFF testUsingContext('macOS build invokes xcode build (debug)', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -280,10 +302,12 @@ STDERR STUFF testUsingContext('macOS build invokes xcode build (debug) with verbosity', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -303,10 +327,12 @@ STDERR STUFF testUsingContext('macOS build invokes xcode build (profile)', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -326,10 +352,12 @@ STDERR STUFF testUsingContext('macOS build invokes xcode build (release)', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -348,10 +376,12 @@ STDERR STUFF testUsingContext('macOS build supports standard desktop build options', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -439,10 +469,12 @@ STDERR STUFF ]); final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: fileSystem, - logger: BufferLogger.test(), + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); @@ -461,10 +493,12 @@ STDERR STUFF testUsingContext('macOS build supports build-name and build-number', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); @@ -496,10 +530,12 @@ STDERR STUFF testUsingContext('Refuses to build for macOS when feature is disabled', () { final CommandRunner runner = createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), )); @@ -526,10 +562,12 @@ STDERR STUFF testUsingContext('Performs code size analysis and sends analytics', () async { final BuildCommand command = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); createMinimalMockProjectFiles(); diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_test.dart index 435c5d583400f..3422c2eb99b29 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_test.dart @@ -4,8 +4,10 @@ import 'package:args/command_runner.dart'; import 'package:file/memory.dart'; +import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; +import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/commands/build.dart'; @@ -28,23 +30,37 @@ void main() { ]), throwsToolExit(message: '"--${FlutterOptions.kDartObfuscationOption}" can only be used in ' 'combination with "--${FlutterOptions.kSplitDebugInfoOption}"')); }); + group('Fatal Logs', () { late FakeBuildCommand command; late MemoryFileSystem fs; + late BufferLogger logger; + late ProcessManager processManager; + late ProcessUtils processUtils; + late Artifacts artifacts; setUp(() { fs = MemoryFileSystem.test(); + artifacts = Artifacts.test(fileSystem: fs); fs.file('/package/pubspec.yaml').createSync(recursive: true); fs.currentDirectory = '/package'; Cache.disableLocking(); + logger = BufferLogger.test(); + processManager = FakeProcessManager.empty(); + processUtils = ProcessUtils( + logger: logger, + processManager: processManager, + ); }); testUsingContext("doesn't fail if --fatal-warnings specified and no warnings occur", () async { command = FakeBuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fs, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); try { @@ -58,15 +74,17 @@ void main() { } }, overrides: { FileSystem: () => fs, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); testUsingContext("doesn't fail if --fatal-warnings not specified", () async { command = FakeBuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fs, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); testLogger.printWarning('Warning: Mild annoyance Will Robinson!'); @@ -80,15 +98,17 @@ void main() { } }, overrides: { FileSystem: () => fs, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); testUsingContext('fails if --fatal-warnings specified and warnings emitted', () async { command = FakeBuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fs, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); testLogger.printWarning('Warning: Mild annoyance Will Robinson!'); @@ -99,15 +119,17 @@ void main() { ]), throwsToolExit(message: 'Logger received warning output during the run, and "--${FlutterOptions.kFatalWarnings}" is enabled.')); }, overrides: { FileSystem: () => fs, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); testUsingContext('fails if --fatal-warnings specified and errors emitted', () async { command = FakeBuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fs, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); testLogger.printError('Error: Danger Will Robinson!'); @@ -118,7 +140,7 @@ void main() { ]), throwsToolExit(message: 'Logger received error output during the run, and "--${FlutterOptions.kFatalWarnings}" is enabled.')); }, overrides: { FileSystem: () => fs, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); }); } @@ -149,8 +171,10 @@ class FakeBuildCommand extends BuildCommand { required super.osUtils, required Logger logger, required super.androidSdk, + required super.processUtils, + required super.artifacts, bool verboseHelp = false, - }) : super(logger: logger, verboseHelp: verboseHelp,) { + }) : super(logger: logger) { addSubcommand(FakeBuildSubcommand(logger: logger, verboseHelp: verboseHelp)); } diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart index c9a5547239e52..a9a1bc1839c7c 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart @@ -4,9 +4,11 @@ import 'package:args/command_runner.dart'; import 'package:file/memory.dart'; +import 'package:flutter_tools/src/artifacts.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/base/process.dart'; import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; @@ -28,6 +30,10 @@ void main() { 'FLUTTER_ROOT': '/', }, ); + late ProcessUtils processUtils; + late BufferLogger logger; + late ProcessManager processManager; + late Artifacts artifacts; setUpAll(() { Cache.flutterRoot = ''; @@ -42,15 +48,24 @@ void main() { fileSystem.file('.packages').createSync(); fileSystem.file(fileSystem.path.join('web', 'index.html')).createSync(recursive: true); fileSystem.file(fileSystem.path.join('lib', 'main.dart')).createSync(recursive: true); + artifacts = Artifacts.test(fileSystem: fileSystem); + logger = BufferLogger.test(); + processManager = FakeProcessManager.empty(); + processUtils = ProcessUtils( + logger: logger, + processManager: processManager, + ); }); testUsingContext('Refuses to build for web when missing index.html', () async { fileSystem.file(fileSystem.path.join('web', 'index.html')).deleteSync(); final CommandRunner runner = createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), )); @@ -62,15 +77,17 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); testUsingContext('Refuses to build a debug build for web', () async { final CommandRunner runner = createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: fileSystem, - logger: BufferLogger.test(), + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), )); @@ -79,15 +96,17 @@ void main() { }, overrides: { Platform: () => fakePlatform, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); testUsingContext('Refuses to build for web when feature is disabled', () async { final CommandRunner runner = createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), )); @@ -99,15 +118,17 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); testUsingContext('Setup for a web build with default output directory', () async { final BuildCommand buildCommand = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: fileSystem, - logger: BufferLogger.test(), + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); final CommandRunner runner = createTestCommandRunner(buildCommand); @@ -121,7 +142,7 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, BuildSystem: () => TestBuildSystem.all(BuildResult(success: true), (Target target, Environment environment) { expect(environment.defines, { 'TargetFile': 'lib/main.dart', @@ -144,11 +165,13 @@ void main() { testUsingContext('Does not allow -O0 optimization level', () async { final BuildCommand buildCommand = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: fileSystem, logger: BufferLogger.test(), osUtils: FakeOperatingSystemUtils(), + processUtils: processUtils, ); final CommandRunner runner = createTestCommandRunner(buildCommand); setupFileSystemForEndToEndTest(fileSystem); @@ -191,10 +214,12 @@ void main() { testUsingContext('Setup for a web build with a user specified output directory', () async { final BuildCommand buildCommand = BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), fileSystem: fileSystem, - logger: BufferLogger.test(), + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); final CommandRunner runner = createTestCommandRunner(buildCommand); @@ -219,7 +244,7 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, BuildSystem: () => TestBuildSystem.all(BuildResult(success: true), (Target target, Environment environment) { expect(environment.defines, { 'TargetFile': 'lib/main.dart', @@ -246,7 +271,7 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); testUsingContext('not hidden if feature flag is enabled', () async { @@ -255,7 +280,7 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, }); testUsingContext('Defaults to web renderer auto mode when no option is specified', () async { @@ -270,7 +295,7 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)), }); @@ -295,7 +320,7 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)), }); @@ -311,7 +336,7 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)), }); @@ -327,7 +352,7 @@ void main() { Platform: () => fakePlatform, FileSystem: () => fileSystem, FeatureFlags: () => TestFeatureFlags(isWebEnabled: true), - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)), }); } diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_windows_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_windows_test.dart index f77e830ebdb23..ec80512529886 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/build_windows_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/build_windows_test.dart @@ -82,7 +82,7 @@ void main() { '-S', fileSystem.path.absolute(fileSystem.path.dirname(buildFilePath)), '-B', - r'build\windows\x64', + r'C:\build\windows\x64', '-G', generator, '-A', @@ -103,7 +103,7 @@ void main() { command: [ _cmakePath, '--build', - r'build\windows\x64', + r'C:\build\windows\x64', '--config', buildMode, ...['--target', 'INSTALL'], diff --git a/packages/flutter_tools/test/commands.shard/permeable/build_preview_test.dart b/packages/flutter_tools/test/commands.shard/permeable/build_preview_test.dart new file mode 100644 index 0000000000000..e78d653416710 --- /dev/null +++ b/packages/flutter_tools/test/commands.shard/permeable/build_preview_test.dart @@ -0,0 +1,53 @@ +// 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 'package:args/command_runner.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/cache.dart'; +import 'package:flutter_tools/src/commands/build_preview.dart'; +import 'package:flutter_tools/src/globals.dart' as globals; + +import '../../src/common.dart'; +import '../../src/context.dart'; +import '../../src/test_flutter_command_runner.dart'; + +void main() { + Cache.disableLocking(); + + late Directory tempDir; + late BufferLogger logger; + final FileSystem fs = LocalFileSystemBlockingSetCurrentDirectory(); + + setUp(() { + tempDir = fs.systemTempDirectory.createTempSync('flutter_tools_packages_test.'); + logger = BufferLogger.test(); + }); + + tearDown(() { + tryToDelete(tempDir); + }); + + testUsingContext('foo bar', () async { + final String projectPath = await createProject( + tempDir, + arguments: ['--no-pub', '--template=app'], + ); + final BuildPreviewCommand command = BuildPreviewCommand( + logger: logger, + verboseHelp: true, + fs: fs, + processUtils: globals.processUtils, + flutterRoot: Cache.flutterRoot!, + artifacts: globals.artifacts!, + ); + final CommandRunner runner = createTestCommandRunner(command); + await runner.run([ + '_preview', + '--no-pub', + fs.path.join(projectPath, 'lib', 'main.dart'), + ]); + }, skip: !const LocalPlatform().isWindows); +} diff --git a/packages/flutter_tools/test/general.shard/analytics_test.dart b/packages/flutter_tools/test/general.shard/analytics_test.dart index c6cdf97745b98..a3d23bf6d4169 100644 --- a/packages/flutter_tools/test/general.shard/analytics_test.dart +++ b/packages/flutter_tools/test/general.shard/analytics_test.dart @@ -6,11 +6,13 @@ import 'package:args/command_runner.dart'; import 'package:file/memory.dart'; import 'package:flutter_tools/src/android/android_studio.dart'; import 'package:flutter_tools/src/android/android_workflow.dart'; +import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/config.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/base/process.dart'; import 'package:flutter_tools/src/base/time.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; @@ -42,6 +44,7 @@ void main() { late Directory tempDir; late Config testConfig; late FileSystem fs; + const String flutterRoot = '/path/to/flutter'; setUp(() { @@ -161,6 +164,9 @@ void main() { late FakeClock fakeClock; late FakeDoctor doctor; late FakeAndroidStudio androidStudio; + late ProcessManager processManager; + late BufferLogger logger; + late ProcessUtils processUtils; setUp(() { memoryFileSystem = MemoryFileSystem.test(); @@ -169,6 +175,9 @@ void main() { fakeClock = FakeClock(); doctor = FakeDoctor(); androidStudio = FakeAndroidStudio(); + processManager = FakeProcessManager.empty(); + logger = BufferLogger.test(); + processUtils = ProcessUtils(logger: logger, processManager: processManager); }); testUsingContext('flutter commands send timing events', () async { @@ -220,17 +229,17 @@ void main() { testUsingContext('compound command usage path', () async { final BuildCommand buildCommand = BuildCommand( + artifacts: Artifacts.test(fileSystem: memoryFileSystem), androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: memoryFileSystem, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); final FlutterCommand buildApkCommand = buildCommand.subcommands['apk']! as FlutterCommand; expect(await buildApkCommand.usagePath, 'build/apk'); - }, overrides: { - Usage: () => testUsage, }); testUsingContext('command sends localtime', () async { @@ -253,7 +262,7 @@ void main() { expect(log.contains(formatDateTime(dateTime)), isTrue); }, overrides: { FileSystem: () => memoryFileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, SystemClock: () => fakeClock, Platform: () => FakePlatform( environment: { @@ -283,7 +292,7 @@ void main() { expect(log.contains(formatDateTime(dateTime)), isTrue); }, overrides: { FileSystem: () => memoryFileSystem, - ProcessManager: () => FakeProcessManager.any(), + ProcessManager: () => processManager, SystemClock: () => fakeClock, Platform: () => FakePlatform( environment: { diff --git a/packages/flutter_tools/test/general.shard/base/os_utils_test.dart b/packages/flutter_tools/test/general.shard/base/os_utils_test.dart index 0ec8408a65872..6a8685df3c445 100644 --- a/packages/flutter_tools/test/general.shard/base/os_utils_test.dart +++ b/packages/flutter_tools/test/general.shard/base/os_utils_test.dart @@ -6,10 +6,10 @@ 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/base/signals.dart'; import 'package:process/process.dart'; import '../../src/common.dart'; +import '../../src/context.dart'; void main() { group('OperatingSystemUtils', () { @@ -17,7 +17,7 @@ void main() { late FileSystem fileSystem; setUp(() { - fileSystem = LocalFileSystem.test(signals: Signals.test()); + fileSystem = LocalFileSystem.test(signals: FakeSignals()); tempDir = fileSystem.systemTempDirectory.createTempSync('flutter_tools_os_utils_test.'); }); diff --git a/packages/flutter_tools/test/general.shard/commands/build_test.dart b/packages/flutter_tools/test/general.shard/commands/build_test.dart index 9663a387cb848..090924bed9335 100644 --- a/packages/flutter_tools/test/general.shard/commands/build_test.dart +++ b/packages/flutter_tools/test/general.shard/commands/build_test.dart @@ -5,10 +5,12 @@ import 'package:args/args.dart'; import 'package:args/command_runner.dart'; import 'package:file/memory.dart'; +import 'package:flutter_tools/src/artifacts.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/base/process.dart'; import 'package:flutter_tools/src/base/signals.dart'; import 'package:flutter_tools/src/base/terminal.dart'; import 'package:flutter_tools/src/build_info.dart'; @@ -111,11 +113,19 @@ void main() { }); testUsingContext('Include only supported sub commands', () { + final BufferLogger logger = BufferLogger.test(); + final ProcessUtils processUtils = ProcessUtils( + logger: logger, + processManager: FakeProcessManager.empty(), + ); + final MemoryFileSystem fs = MemoryFileSystem.test(); final BuildCommand command = BuildCommand( + artifacts: Artifacts.test(fileSystem: fs), androidSdk: FakeAndroidSdk(), buildSystem: TestBuildSystem.all(BuildResult(success: true)), - fileSystem: MemoryFileSystem.test(), - logger: BufferLogger.test(), + fileSystem: fs, + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), ); for (final Command x in command.subcommands.values) { diff --git a/packages/flutter_tools/test/general.shard/preview_device_test.dart b/packages/flutter_tools/test/general.shard/preview_device_test.dart index 876dbc64950ad..928631aa5c628 100644 --- a/packages/flutter_tools/test/general.shard/preview_device_test.dart +++ b/packages/flutter_tools/test/general.shard/preview_device_test.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'package:file/memory.dart'; import 'package:flutter_tools/src/application_package.dart'; +import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/platform.dart'; @@ -22,20 +23,38 @@ import 'package:test/fake.dart'; import '../src/common.dart'; import '../src/context.dart'; +import '../src/fakes.dart'; void main() { + String? flutterRootBackup; + late MemoryFileSystem fs; + late File previewBinary; + + setUp(() { + fs = MemoryFileSystem.test(style: FileSystemStyle.windows); + Cache.flutterRoot = r'C:\path\to\flutter'; + previewBinary = fs.file('${Cache.flutterRoot}\\bin\\cache\\artifacts\\flutter_preview\\flutter_preview.exe'); + previewBinary.createSync(recursive: true); + flutterRootBackup = Cache.flutterRoot; + }); + + tearDown(() { + Cache.flutterRoot = flutterRootBackup; + }); + testWithoutContext('PreviewDevice defaults', () async { final PreviewDevice device = PreviewDevice( - fileSystem: MemoryFileSystem.test(), + artifacts: Artifacts.test(), + fileSystem: fs, processManager: FakeProcessManager.any(), + previewBinary: previewBinary, logger: BufferLogger.test(), - platform: FakePlatform(), ); expect(await device.isLocalEmulator, false); expect(device.name, 'preview'); expect(await device.sdkNameAndVersion, 'preview'); - expect(await device.targetPlatform, TargetPlatform.tester); + expect(await device.targetPlatform, TargetPlatform.windows_x64); expect(device.category, Category.desktop); expect(device.ephemeral, false); expect(device.id, 'preview'); @@ -48,29 +67,33 @@ void main() { }); testUsingContext('Can build a simulator app', () async { - Cache.flutterRoot = ''; final Completer completer = Completer(); - final FileSystem fileSystem = MemoryFileSystem.test(); final BufferLogger logger = BufferLogger.test(); final PreviewDevice device = PreviewDevice( - fileSystem: fileSystem, + artifacts: Artifacts.test(), + fileSystem: fs, + previewBinary: previewBinary, processManager: FakeProcessManager.list([ FakeCommand( command: const [ - '/.tmp_rand0/flutter_preview.rand0/splash', + r'C:\.tmp_rand0\flutter_preview.rand0\flutter_preview.exe', ], stdout: 'The Dart VM service is listening on http://127.0.0.1:64494/fZ_B2N6JRwY=/\n', completer: completer, ), ]), logger: logger, - platform: FakePlatform(), - builderFactory: () => FakeBundleBuilder(fileSystem), + builderFactory: () => FakeBundleBuilder(fs), ); - fileSystem + fs .directory('artifacts_temp') .childDirectory('Debug') .createSync(recursive: true); + final Directory previewDeviceCacheDir = fs + .directory('Artifact.windowsDesktopPath.TargetPlatform.windows_x64.debug') + ..createSync(recursive: true); + previewDeviceCacheDir.childFile('flutter_windows.dll').writeAsStringSync('1010101'); + previewDeviceCacheDir.childFile('icudtl.dat').writeAsStringSync('1010101'); final LaunchResult result = await device.startApp( FakeApplicationPackage(), @@ -80,6 +103,67 @@ void main() { expect(result.started, true); expect(result.vmServiceUri, Uri.parse('http://127.0.0.1:64494/fZ_B2N6JRwY=/')); }); + + group('PreviewDeviceDiscovery', () { + late Artifacts artifacts; + late ProcessManager processManager; + final FakePlatform windowsPlatform = FakePlatform(operatingSystem: 'windows'); + final FakePlatform macPlatform = FakePlatform(operatingSystem: 'macos'); + final FakePlatform linuxPlatform = FakePlatform(); + final TestFeatureFlags featureFlags = TestFeatureFlags(isPreviewDeviceEnabled: true); + + setUp(() { + artifacts = Artifacts.test(fileSystem: fs); + processManager = FakeProcessManager.empty(); + }); + + testWithoutContext('PreviewDeviceDiscovery on linux', () async { + final PreviewDeviceDiscovery discovery = PreviewDeviceDiscovery( + artifacts: artifacts, + fileSystem: fs, + logger: BufferLogger.test(), + processManager: processManager, + platform: linuxPlatform, + featureFlags: featureFlags, + ); + + final List devices = await discovery.devices(); + + expect(devices, isEmpty); + }); + + testWithoutContext('PreviewDeviceDiscovery on macOS', () async { + final PreviewDeviceDiscovery discovery = PreviewDeviceDiscovery( + artifacts: artifacts, + fileSystem: fs, + logger: BufferLogger.test(), + processManager: processManager, + platform: macPlatform, + featureFlags: featureFlags, + ); + + final List devices = await discovery.devices(); + + expect(devices, isEmpty); + }); + + testWithoutContext('PreviewDeviceDiscovery on Windows', () async { + final PreviewDeviceDiscovery discovery = PreviewDeviceDiscovery( + artifacts: artifacts, + fileSystem: fs, + logger: BufferLogger.test(), + processManager: processManager, + platform: windowsPlatform, + featureFlags: featureFlags, + ); + + final List devices = await discovery.devices(); + + expect(devices, hasLength(1)); + final Device previewDevice = devices.first; + expect(previewDevice, isA()); + }); + }); } class FakeFlutterProject extends Fake implements FlutterProject { } diff --git a/packages/flutter_tools/test/general.shard/web/migrations/scrub_generated_plugin_registrant_test.dart b/packages/flutter_tools/test/general.shard/web/migrations/scrub_generated_plugin_registrant_test.dart index 4261dd88a7ffa..1b7ac91b06330 100644 --- a/packages/flutter_tools/test/general.shard/web/migrations/scrub_generated_plugin_registrant_test.dart +++ b/packages/flutter_tools/test/general.shard/web/migrations/scrub_generated_plugin_registrant_test.dart @@ -3,8 +3,10 @@ // found in the LICENSE file. import 'package:file/memory.dart'; +import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; +import 'package:flutter_tools/src/base/process.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/commands/build.dart'; @@ -26,14 +28,24 @@ void main() { late File registrant; // Environment overrides + late Artifacts artifacts; late FileSystem fileSystem; late ProcessManager processManager; late BuildSystem buildSystem; + late ProcessUtils processUtils; + late BufferLogger logger; setUp(() { // Prepare environment overrides fileSystem = MemoryFileSystem.test(); + artifacts = Artifacts.test(fileSystem: fileSystem); processManager = FakeProcessManager.any(); + logger = BufferLogger.test(); + processUtils = ProcessUtils( + processManager: processManager, + logger: logger, + ); + buildSystem = TestBuildSystem.all(BuildResult(success: true)); // Write some initial state into our testing filesystem setupFileSystemForEndToEndTest(fileSystem); @@ -47,11 +59,13 @@ void main() { expect(registrant.existsSync(), isFalse); await createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: buildSystem, fileSystem: fileSystem, logger: BufferLogger.test(), osUtils: FakeOperatingSystemUtils(), + processUtils: processUtils, )) .run(['build', 'web', '--no-pub']); @@ -70,11 +84,13 @@ void main() { expect(contentsBeforeBuild, isNot(contains('lib/generated_plugin_registrant.dart'))); await createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: buildSystem, fileSystem: fileSystem, - logger: BufferLogger.test(), + logger: logger, osUtils: FakeOperatingSystemUtils(), + processUtils: processUtils, )) .run(['build', 'web', '--no-pub']); @@ -92,10 +108,12 @@ void main() { expect(gitignore.readAsStringSync(), contains('lib/generated_plugin_registrant.dart')); await createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: buildSystem, fileSystem: fileSystem, - logger: BufferLogger.test(), + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), )) .run(['build', 'web', '--no-pub']); @@ -113,10 +131,12 @@ void main() { expect(registrant.existsSync(), isTrue); await createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: buildSystem, fileSystem: fileSystem, - logger: BufferLogger.test(), + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), )) .run(['build', 'web', '--no-pub']); @@ -136,10 +156,12 @@ void main() { expect(gitignore.readAsStringSync(), contains('lib/generated_plugin_registrant.dart')); await createTestCommandRunner(BuildCommand( + artifacts: artifacts, androidSdk: FakeAndroidSdk(), buildSystem: buildSystem, fileSystem: fileSystem, - logger: BufferLogger.test(), + logger: logger, + processUtils: processUtils, osUtils: FakeOperatingSystemUtils(), )) .run(['build', 'web', '--no-pub']); diff --git a/packages/flutter_tools/test/src/context.dart b/packages/flutter_tools/test/src/context.dart index 4fc36d2ce0831..5b0861ac4d49e 100644 --- a/packages/flutter_tools/test/src/context.dart +++ b/packages/flutter_tools/test/src/context.dart @@ -382,7 +382,8 @@ class NoopCrashReporter implements CrashReporter { } class LocalFileSystemBlockingSetCurrentDirectory extends LocalFileSystem { - // Use [FakeSignals] so developers running the test suite can kill the test runner. + // Use [FakeSignals] so developers running the test suite can kill the test + // runner. LocalFileSystemBlockingSetCurrentDirectory() : super.test(signals: FakeSignals()); @override diff --git a/packages/flutter_tools/test/src/fakes.dart b/packages/flutter_tools/test/src/fakes.dart index bca86131dc4e8..33dfdb554ab63 100644 --- a/packages/flutter_tools/test/src/fakes.dart +++ b/packages/flutter_tools/test/src/fakes.dart @@ -462,6 +462,7 @@ class TestFeatureFlags implements FeatureFlags { this.isFlutterWebWasmEnabled = false, this.isCliAnimationEnabled = true, this.isNativeAssetsEnabled = false, + this.isPreviewDeviceEnabled = false, }); @override @@ -497,31 +498,24 @@ class TestFeatureFlags implements FeatureFlags { @override final bool isNativeAssetsEnabled; + @override + final bool isPreviewDeviceEnabled; + @override bool isEnabled(Feature feature) { - switch (feature) { - case flutterWebFeature: - return isWebEnabled; - case flutterLinuxDesktopFeature: - return isLinuxEnabled; - case flutterMacOSDesktopFeature: - return isMacOSEnabled; - case flutterWindowsDesktopFeature: - return isWindowsEnabled; - case flutterAndroidFeature: - return isAndroidEnabled; - case flutterIOSFeature: - return isIOSEnabled; - case flutterFuchsiaFeature: - return isFuchsiaEnabled; - case flutterCustomDevicesFeature: - return areCustomDevicesEnabled; - case cliAnimation: - return isCliAnimationEnabled; - case nativeAssets: - return isNativeAssetsEnabled; - } - return false; + return switch (feature) { + flutterWebFeature => isWebEnabled, + flutterLinuxDesktopFeature => isLinuxEnabled, + flutterMacOSDesktopFeature => isMacOSEnabled, + flutterWindowsDesktopFeature => isWindowsEnabled, + flutterAndroidFeature => isAndroidEnabled, + flutterIOSFeature => isIOSEnabled, + flutterFuchsiaFeature => isFuchsiaEnabled, + flutterCustomDevicesFeature => areCustomDevicesEnabled, + cliAnimation => isCliAnimationEnabled, + nativeAssets => isNativeAssetsEnabled, + _ => false, + }; } }