| // 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: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/version.dart'; |
| import 'package:flutter_tools/src/build_info.dart'; |
| import 'package:flutter_tools/src/ios/xcode_build_settings.dart'; |
| import 'package:flutter_tools/src/ios/xcodeproj.dart'; |
| import 'package:flutter_tools/src/project.dart'; |
| import 'package:flutter_tools/src/reporting/reporting.dart'; |
| |
| import '../../src/common.dart'; |
| import '../../src/context.dart'; |
| import '../../src/fake_process_manager.dart'; |
| |
| const String xcodebuild = '/usr/bin/xcodebuild'; |
| |
| void main() { |
| group('MockProcessManager', () { |
| setUp(() { |
| final FileSystem fileSystem = MemoryFileSystem.test(); |
| fileSystem.file(xcodebuild).createSync(recursive: true); |
| }); |
| }); |
| |
| const FakeCommand kWhichSysctlCommand = FakeCommand( |
| command: <String>[ |
| 'which', |
| 'sysctl', |
| ], |
| ); |
| |
| // x64 host. |
| const FakeCommand kx64CheckCommand = FakeCommand( |
| command: <String>[ |
| 'sysctl', |
| 'hw.optional.arm64', |
| ], |
| exitCode: 1, |
| ); |
| |
| // ARM host. |
| const FakeCommand kARMCheckCommand = FakeCommand( |
| command: <String>[ |
| 'sysctl', |
| 'hw.optional.arm64', |
| ], |
| stdout: 'hw.optional.arm64: 1', |
| ); |
| |
| late FakeProcessManager fakeProcessManager; |
| late XcodeProjectInterpreter xcodeProjectInterpreter; |
| late FakePlatform platform; |
| late FileSystem fileSystem; |
| late BufferLogger logger; |
| |
| setUp(() { |
| fakeProcessManager = FakeProcessManager.empty(); |
| platform = FakePlatform(operatingSystem: 'macos'); |
| fileSystem = MemoryFileSystem.test(); |
| fileSystem.file(xcodebuild).createSync(recursive: true); |
| logger = BufferLogger.test(); |
| xcodeProjectInterpreter = XcodeProjectInterpreter( |
| logger: logger, |
| fileSystem: fileSystem, |
| platform: platform, |
| processManager: fakeProcessManager, |
| usage: TestUsage(), |
| ); |
| }); |
| |
| testWithoutContext('xcodebuild versionText returns null when xcodebuild is not fully installed', () { |
| fakeProcessManager.addCommands(const <FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>['xcrun', 'xcodebuild', '-version'], |
| stdout: "xcode-select: error: tool 'xcodebuild' requires Xcode, " |
| "but active developer directory '/Library/Developer/CommandLineTools' " |
| 'is a command line tools instance', |
| exitCode: 1, |
| ), |
| ]); |
| |
| expect(xcodeProjectInterpreter.versionText, isNull); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }); |
| |
| testWithoutContext('xcodebuild versionText returns null when xcodebuild is not installed', () { |
| fakeProcessManager.addCommands(const <FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>['xcrun', 'xcodebuild', '-version'], |
| exception: ProcessException(xcodebuild, <String>['-version']), |
| ), |
| ]); |
| |
| expect(xcodeProjectInterpreter.versionText, isNull); |
| }); |
| |
| testWithoutContext('xcodebuild versionText returns formatted version text', () { |
| fakeProcessManager.addCommands(const <FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>['xcrun', 'xcodebuild', '-version'], |
| stdout: 'Xcode 8.3.3\nBuild version 8E3004b', |
| ), |
| ]); |
| |
| expect(xcodeProjectInterpreter.versionText, 'Xcode 8.3.3, Build version 8E3004b'); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }); |
| |
| testWithoutContext('xcodebuild versionText handles Xcode version string with unexpected format', () { |
| fakeProcessManager.addCommands(const <FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>['xcrun', 'xcodebuild', '-version'], |
| stdout: 'Xcode Ultra5000\nBuild version 8E3004b', |
| ), |
| ]); |
| |
| expect(xcodeProjectInterpreter.versionText, 'Xcode Ultra5000, Build version 8E3004b'); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }); |
| |
| testWithoutContext('xcodebuild version parts can be parsed', () { |
| fakeProcessManager.addCommands(const <FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>['xcrun', 'xcodebuild', '-version'], |
| stdout: 'Xcode 11.4.1\nBuild version 11N111s', |
| ), |
| ]); |
| |
| expect(xcodeProjectInterpreter.version, Version(11, 4, 1)); |
| expect(xcodeProjectInterpreter.build, '11N111s'); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }); |
| |
| testWithoutContext('xcodebuild minor and patch version default to 0', () { |
| fakeProcessManager.addCommands(const <FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>['xcrun', 'xcodebuild', '-version'], |
| stdout: 'Xcode 11\nBuild version 11N111s', |
| ), |
| ]); |
| |
| expect(xcodeProjectInterpreter.version, Version(11, 0, 0)); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }); |
| |
| testWithoutContext('xcodebuild version parts is null when version has unexpected format', () { |
| fakeProcessManager.addCommands(const <FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>['xcrun', 'xcodebuild', '-version'], |
| stdout: 'Xcode Ultra5000\nBuild version 8E3004b', |
| ), |
| ]); |
| expect(xcodeProjectInterpreter.version, isNull); |
| expect(xcodeProjectInterpreter.build, isNull); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }); |
| |
| testWithoutContext('xcodebuild isInstalled is false when not on MacOS', () { |
| final Platform platform = FakePlatform(operatingSystem: 'notMacOS'); |
| xcodeProjectInterpreter = XcodeProjectInterpreter( |
| logger: logger, |
| fileSystem: fileSystem, |
| platform: platform, |
| processManager: fakeProcessManager, |
| usage: TestUsage(), |
| ); |
| fileSystem.file(xcodebuild).deleteSync(); |
| |
| expect(xcodeProjectInterpreter.isInstalled, isFalse); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }); |
| |
| testWithoutContext('xcodebuild isInstalled is false when xcodebuild does not exist', () { |
| fileSystem.file(xcodebuild).deleteSync(); |
| |
| expect(xcodeProjectInterpreter.isInstalled, isFalse); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }); |
| |
| testWithoutContext( |
| 'xcodebuild isInstalled is false when Xcode is not fully installed', () { |
| fakeProcessManager.addCommands(const <FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>['xcrun', 'xcodebuild', '-version'], |
| stdout: "xcode-select: error: tool 'xcodebuild' requires Xcode, " |
| "but active developer directory '/Library/Developer/CommandLineTools' " |
| 'is a command line tools instance', |
| exitCode: 1, |
| ), |
| ]); |
| |
| expect(xcodeProjectInterpreter.isInstalled, isFalse); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }); |
| |
| testWithoutContext('xcodebuild isInstalled is false when version has unexpected format', () { |
| fakeProcessManager.addCommands(const <FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>['xcrun', 'xcodebuild', '-version'], |
| stdout: 'Xcode Ultra5000\nBuild version 8E3004b', |
| ), |
| ]); |
| |
| expect(xcodeProjectInterpreter.isInstalled, isFalse); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }); |
| |
| testWithoutContext('xcodebuild isInstalled is true when version has expected format', () { |
| fakeProcessManager.addCommands(const <FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>['xcrun', 'xcodebuild', '-version'], |
| stdout: 'Xcode 8.3.3\nBuild version 8E3004b', |
| ), |
| ]); |
| |
| expect(xcodeProjectInterpreter.isInstalled, isTrue); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }); |
| |
| testWithoutContext('xcrun runs natively on arm64', () { |
| fakeProcessManager.addCommands(const <FakeCommand>[ |
| kWhichSysctlCommand, |
| kARMCheckCommand, |
| ]); |
| |
| expect(xcodeProjectInterpreter.xcrunCommand(), <String>[ |
| '/usr/bin/arch', |
| '-arm64e', |
| 'xcrun', |
| ]); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }); |
| |
| testUsingContext('xcodebuild build settings is empty when xcodebuild failed to get the build settings', () async { |
| platform.environment = const <String, String>{}; |
| |
| fakeProcessManager.addCommands(<FakeCommand>[ |
| kWhichSysctlCommand, |
| const FakeCommand( |
| command: <String>[ |
| 'sysctl', |
| 'hw.optional.arm64', |
| ], |
| exitCode: 1, |
| ), |
| FakeCommand( |
| command: <String>[ |
| 'xcrun', |
| 'xcodebuild', |
| '-project', |
| '/', |
| '-scheme', |
| 'Free', |
| '-destination', |
| 'id=123', |
| '-showBuildSettings', |
| 'BUILD_DIR=${fileSystem.path.absolute('build', 'ios')}', |
| ], |
| exitCode: 1, |
| ), |
| ]); |
| |
| expect( |
| await xcodeProjectInterpreter.getBuildSettings('', buildContext: const XcodeProjectBuildContext(deviceId: '123', scheme: 'Free')), |
| const <String, String>{}); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('build settings passes in the simulator SDK', () async { |
| platform.environment = const <String, String>{}; |
| |
| fakeProcessManager.addCommands(<FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>[ |
| 'xcrun', |
| 'xcodebuild', |
| '-project', |
| '/', |
| '-sdk', |
| 'iphonesimulator', |
| '-destination', |
| 'generic/platform=iOS Simulator', |
| '-showBuildSettings', |
| 'BUILD_DIR=${fileSystem.path.absolute('build', 'ios')}', |
| ], |
| exitCode: 1, |
| ), |
| ]); |
| |
| expect( |
| await xcodeProjectInterpreter.getBuildSettings( |
| '', |
| buildContext: const XcodeProjectBuildContext(environmentType: EnvironmentType.simulator), |
| ), |
| const <String, String>{}, |
| ); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('build settings accepts an empty scheme', () async { |
| platform.environment = const <String, String>{}; |
| |
| fakeProcessManager.addCommands(<FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>[ |
| 'xcrun', |
| 'xcodebuild', |
| '-project', |
| '/', |
| '-destination', |
| 'generic/platform=iOS', |
| '-showBuildSettings', |
| 'BUILD_DIR=${fileSystem.path.absolute('build', 'ios')}', |
| ], |
| exitCode: 1, |
| ), |
| ]); |
| |
| expect(await xcodeProjectInterpreter.getBuildSettings('', buildContext: const XcodeProjectBuildContext()), |
| const <String, String>{}); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('xcodebuild build settings contains Flutter Xcode environment variables', () async { |
| platform.environment = const <String, String>{ |
| 'FLUTTER_XCODE_CODE_SIGN_STYLE': 'Manual', |
| 'FLUTTER_XCODE_ARCHS': 'arm64', |
| }; |
| fakeProcessManager.addCommands(<FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>[ |
| 'xcrun', |
| 'xcodebuild', |
| '-project', |
| fileSystem.path.separator, |
| '-scheme', |
| 'Free', |
| '-destination', |
| 'generic/platform=iOS', |
| '-showBuildSettings', |
| 'BUILD_DIR=${fileSystem.path.absolute('build', 'ios')}', |
| 'CODE_SIGN_STYLE=Manual', |
| 'ARCHS=arm64', |
| ], |
| ), |
| ]); |
| expect( |
| await xcodeProjectInterpreter.getBuildSettings('', buildContext: const XcodeProjectBuildContext(scheme: 'Free')), |
| const <String, String>{}); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('build settings uses watch destination if isWatch is true', () async { |
| platform.environment = const <String, String>{}; |
| |
| fakeProcessManager.addCommands(<FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>[ |
| 'xcrun', |
| 'xcodebuild', |
| '-project', |
| '/', |
| '-destination', |
| 'generic/platform=watchOS', |
| '-showBuildSettings', |
| 'BUILD_DIR=${fileSystem.path.absolute('build', 'ios')}', |
| ], |
| exitCode: 1, |
| ), |
| ]); |
| |
| expect( |
| await xcodeProjectInterpreter.getBuildSettings( |
| '', |
| buildContext: const XcodeProjectBuildContext(isWatch: true), |
| ), |
| const <String, String>{}, |
| ); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('build settings uses watch simulator destination if isWatch is true and environment type is simulator', () async { |
| platform.environment = const <String, String>{}; |
| |
| fakeProcessManager.addCommands(<FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>[ |
| 'xcrun', |
| 'xcodebuild', |
| '-project', |
| '/', |
| '-sdk', |
| 'iphonesimulator', |
| '-destination', |
| 'generic/platform=watchOS Simulator', |
| '-showBuildSettings', |
| 'BUILD_DIR=${fileSystem.path.absolute('build', 'ios')}', |
| ], |
| exitCode: 1, |
| ), |
| ]); |
| |
| expect( |
| await xcodeProjectInterpreter.getBuildSettings( |
| '', |
| buildContext: const XcodeProjectBuildContext(environmentType: EnvironmentType.simulator, isWatch: true), |
| ), |
| const <String, String>{}, |
| ); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }, overrides: <Type, Generator>{ |
| FileSystem: () => fileSystem, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testWithoutContext('xcodebuild clean contains Flutter Xcode environment variables', () async { |
| platform.environment = const <String, String>{ |
| 'FLUTTER_XCODE_CODE_SIGN_STYLE': 'Manual', |
| 'FLUTTER_XCODE_ARCHS': 'arm64', |
| }; |
| |
| fakeProcessManager.addCommands(const <FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>[ |
| 'xcrun', |
| 'xcodebuild', |
| '-workspace', |
| 'workspace_path', |
| '-scheme', |
| 'Free', |
| '-quiet', |
| 'clean', |
| 'CODE_SIGN_STYLE=Manual', |
| 'ARCHS=arm64', |
| ], |
| ), |
| ]); |
| |
| await xcodeProjectInterpreter.cleanWorkspace('workspace_path', 'Free'); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }); |
| |
| testWithoutContext('xcodebuild -list getInfo returns something when xcodebuild -list succeeds', () async { |
| const String workingDirectory = '/'; |
| fakeProcessManager.addCommands(const <FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>['xcrun', 'xcodebuild', '-list'], |
| ), |
| ]); |
| |
| final XcodeProjectInterpreter xcodeProjectInterpreter = XcodeProjectInterpreter( |
| logger: logger, |
| fileSystem: fileSystem, |
| platform: platform, |
| processManager: fakeProcessManager, |
| usage: TestUsage(), |
| ); |
| |
| expect(await xcodeProjectInterpreter.getInfo(workingDirectory), isNotNull); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }); |
| |
| testWithoutContext('xcodebuild -list getInfo throws a tool exit when it is unable to find a project', () async { |
| const String workingDirectory = '/'; |
| const String stderr = 'Useful Xcode failure message about missing project.'; |
| |
| fakeProcessManager.addCommands(const <FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>['xcrun', 'xcodebuild', '-list'], |
| exitCode: 66, |
| stderr: stderr, |
| ), |
| ]); |
| |
| final XcodeProjectInterpreter xcodeProjectInterpreter = XcodeProjectInterpreter( |
| logger: logger, |
| fileSystem: fileSystem, |
| platform: platform, |
| processManager: fakeProcessManager, |
| usage: TestUsage(), |
| ); |
| |
| expect(() => xcodeProjectInterpreter.getInfo(workingDirectory), throwsToolExit(message: stderr)); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }); |
| |
| testWithoutContext('xcodebuild -list getInfo throws a tool exit when project is corrupted', () async { |
| const String workingDirectory = '/'; |
| const String stderr = 'Useful Xcode failure message about corrupted project.'; |
| |
| fakeProcessManager.addCommands(const <FakeCommand>[ |
| kWhichSysctlCommand, |
| kx64CheckCommand, |
| FakeCommand( |
| command: <String>['xcrun', 'xcodebuild', '-list'], |
| exitCode: 74, |
| stderr: stderr, |
| ), |
| ]); |
| |
| final XcodeProjectInterpreter xcodeProjectInterpreter = XcodeProjectInterpreter( |
| logger: logger, |
| fileSystem: fileSystem, |
| platform: platform, |
| processManager: fakeProcessManager, |
| usage: TestUsage(), |
| ); |
| |
| expect(() => xcodeProjectInterpreter.getInfo(workingDirectory), throwsToolExit(message: stderr)); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }); |
| |
| testWithoutContext('Xcode project properties from default project can be parsed', () { |
| const String output = ''' |
| Information about project "Runner": |
| Targets: |
| Runner |
| |
| Build Configurations: |
| Debug |
| Release |
| |
| If no build configuration is specified and -scheme is not passed then "Release" is used. |
| |
| Schemes: |
| Runner |
| |
| '''; |
| final XcodeProjectInfo info = XcodeProjectInfo.fromXcodeBuildOutput(output, logger); |
| expect(info.targets, <String>['Runner']); |
| expect(info.schemes, <String>['Runner']); |
| expect(info.buildConfigurations, <String>['Debug', 'Release']); |
| }); |
| |
| testWithoutContext('Xcode project properties from project with custom schemes can be parsed', () { |
| const String output = ''' |
| Information about project "Runner": |
| Targets: |
| Runner |
| |
| Build Configurations: |
| Debug (Free) |
| Debug (Paid) |
| Release (Free) |
| Release (Paid) |
| |
| If no build configuration is specified and -scheme is not passed then "Release (Free)" is used. |
| |
| Schemes: |
| Free |
| Paid |
| |
| '''; |
| final XcodeProjectInfo info = XcodeProjectInfo.fromXcodeBuildOutput(output, logger); |
| expect(info.targets, <String>['Runner']); |
| expect(info.schemes, <String>['Free', 'Paid']); |
| expect(info.buildConfigurations, <String>['Debug (Free)', 'Debug (Paid)', 'Release (Free)', 'Release (Paid)']); |
| }); |
| |
| testWithoutContext('expected scheme for non-flavored build is Runner', () { |
| expect(XcodeProjectInfo.expectedSchemeFor(BuildInfo.debug), 'Runner'); |
| expect(XcodeProjectInfo.expectedSchemeFor(BuildInfo.profile), 'Runner'); |
| expect(XcodeProjectInfo.expectedSchemeFor(BuildInfo.release), 'Runner'); |
| }); |
| |
| testWithoutContext('expected build configuration for non-flavored build is derived from BuildMode', () { |
| expect(XcodeProjectInfo.expectedBuildConfigurationFor(BuildInfo.debug, 'Runner'), 'Debug'); |
| expect(XcodeProjectInfo.expectedBuildConfigurationFor(BuildInfo.profile, 'Runner'), 'Profile'); |
| expect(XcodeProjectInfo.expectedBuildConfigurationFor(BuildInfo.release, 'Runner'), 'Release'); |
| }); |
| |
| testWithoutContext('expected scheme for flavored build is the title-cased flavor', () { |
| expect(XcodeProjectInfo.expectedSchemeFor(const BuildInfo(BuildMode.debug, 'hello', treeShakeIcons: false)), 'Hello'); |
| expect(XcodeProjectInfo.expectedSchemeFor(const BuildInfo(BuildMode.profile, 'HELLO', treeShakeIcons: false)), 'HELLO'); |
| expect(XcodeProjectInfo.expectedSchemeFor(const BuildInfo(BuildMode.release, 'Hello', treeShakeIcons: false)), 'Hello'); |
| }); |
| testWithoutContext('expected build configuration for flavored build is Mode-Flavor', () { |
| expect(XcodeProjectInfo.expectedBuildConfigurationFor(const BuildInfo(BuildMode.debug, 'hello', treeShakeIcons: false), 'Hello'), 'Debug-Hello'); |
| expect(XcodeProjectInfo.expectedBuildConfigurationFor(const BuildInfo(BuildMode.profile, 'HELLO', treeShakeIcons: false), 'Hello'), 'Profile-Hello'); |
| expect(XcodeProjectInfo.expectedBuildConfigurationFor(const BuildInfo(BuildMode.release, 'Hello', treeShakeIcons: false), 'Hello'), 'Release-Hello'); |
| }); |
| |
| testWithoutContext('scheme for default project is Runner', () { |
| final XcodeProjectInfo info = XcodeProjectInfo(<String>['Runner'], <String>['Debug', 'Release'], <String>['Runner'], logger); |
| |
| expect(info.schemeFor(BuildInfo.debug), 'Runner'); |
| expect(info.schemeFor(BuildInfo.profile), 'Runner'); |
| expect(info.schemeFor(BuildInfo.release), 'Runner'); |
| expect(info.schemeFor(const BuildInfo(BuildMode.debug, 'unknown', treeShakeIcons: false)), isNull); |
| }); |
| |
| testWithoutContext('build configuration for default project is matched against BuildMode', () { |
| final XcodeProjectInfo info = XcodeProjectInfo(<String>['Runner'], <String>['Debug', 'Profile', 'Release'], <String>['Runner'], logger); |
| |
| expect(info.buildConfigurationFor(BuildInfo.debug, 'Runner'), 'Debug'); |
| expect(info.buildConfigurationFor(BuildInfo.profile, 'Runner'), 'Profile'); |
| expect(info.buildConfigurationFor(BuildInfo.release, 'Runner'), 'Release'); |
| }); |
| |
| testWithoutContext('scheme for project with custom schemes is matched against flavor', () { |
| final XcodeProjectInfo info = XcodeProjectInfo( |
| <String>['Runner'], |
| <String>['Debug (Free)', 'Debug (Paid)', 'Release (Free)', 'Release (Paid)'], |
| <String>['Free', 'Paid'], |
| logger, |
| ); |
| |
| expect(info.schemeFor(const BuildInfo(BuildMode.debug, 'free', treeShakeIcons: false)), 'Free'); |
| expect(info.schemeFor(const BuildInfo(BuildMode.profile, 'Free', treeShakeIcons: false)), 'Free'); |
| expect(info.schemeFor(const BuildInfo(BuildMode.release, 'paid', treeShakeIcons: false)), 'Paid'); |
| expect(info.schemeFor(BuildInfo.debug), isNull); |
| expect(info.schemeFor(const BuildInfo(BuildMode.debug, 'unknown', treeShakeIcons: false)), isNull); |
| }); |
| |
| testWithoutContext('reports default scheme error and exit', () { |
| final XcodeProjectInfo defaultInfo = XcodeProjectInfo( |
| <String>[], |
| <String>[], |
| <String>['Runner'], |
| logger, |
| ); |
| |
| expect( |
| defaultInfo.reportFlavorNotFoundAndExit, |
| throwsToolExit( |
| message: 'The Xcode project does not define custom schemes. You cannot use the --flavor option.' |
| ), |
| ); |
| }); |
| |
| testWithoutContext('reports custom scheme error and exit', () { |
| final XcodeProjectInfo info = XcodeProjectInfo( |
| <String>[], |
| <String>[], |
| <String>['Free', 'Paid'], |
| logger, |
| ); |
| |
| expect( |
| info.reportFlavorNotFoundAndExit, |
| throwsToolExit( |
| message: 'You must specify a --flavor option to select one of the available schemes.' |
| ), |
| ); |
| }); |
| |
| testWithoutContext('build configuration for project with custom schemes is matched against BuildMode and flavor', () { |
| final XcodeProjectInfo info = XcodeProjectInfo( |
| <String>['Runner'], |
| <String>['debug (free)', 'Debug paid', 'profile - Free', 'Profile-Paid', 'release - Free', 'Release-Paid'], |
| <String>['Free', 'Paid'], |
| logger, |
| ); |
| |
| expect(info.buildConfigurationFor(const BuildInfo(BuildMode.debug, 'free', treeShakeIcons: false), 'Free'), 'debug (free)'); |
| expect(info.buildConfigurationFor(const BuildInfo(BuildMode.debug, 'Paid', treeShakeIcons: false), 'Paid'), 'Debug paid'); |
| expect(info.buildConfigurationFor(const BuildInfo(BuildMode.profile, 'FREE', treeShakeIcons: false), 'Free'), 'profile - Free'); |
| expect(info.buildConfigurationFor(const BuildInfo(BuildMode.release, 'paid', treeShakeIcons: false), 'Paid'), 'Release-Paid'); |
| }); |
| |
| testWithoutContext('build configuration for project with inconsistent naming is null', () { |
| final XcodeProjectInfo info = XcodeProjectInfo( |
| <String>['Runner'], |
| <String>['Debug-F', 'Dbg Paid', 'Rel Free', 'Release Full'], |
| <String>['Free', 'Paid'], |
| logger, |
| ); |
| expect(info.buildConfigurationFor(const BuildInfo(BuildMode.debug, 'Free', treeShakeIcons: false), 'Free'), null); |
| expect(info.buildConfigurationFor(const BuildInfo(BuildMode.profile, 'Free', treeShakeIcons: false), 'Free'), null); |
| expect(info.buildConfigurationFor(const BuildInfo(BuildMode.release, 'Paid', treeShakeIcons: false), 'Paid'), null); |
| }); |
| group('environmentVariablesAsXcodeBuildSettings', () { |
| late FakePlatform platform; |
| |
| setUp(() { |
| platform = FakePlatform(); |
| }); |
| |
| testWithoutContext('environment variables as Xcode build settings', () { |
| platform.environment = const <String, String>{ |
| 'Ignored': 'Bogus', |
| 'FLUTTER_NOT_XCODE': 'Bogus', |
| 'FLUTTER_XCODE_CODE_SIGN_STYLE': 'Manual', |
| 'FLUTTER_XCODE_ARCHS': 'arm64', |
| }; |
| final List<String> environmentVariablesAsBuildSettings = environmentVariablesAsXcodeBuildSettings(platform); |
| expect(environmentVariablesAsBuildSettings, <String>['CODE_SIGN_STYLE=Manual', 'ARCHS=arm64']); |
| }); |
| }); |
| |
| group('updateGeneratedXcodeProperties', () { |
| late Artifacts localIosArtifacts; |
| late FakePlatform macOS; |
| late FileSystem fs; |
| |
| setUp(() { |
| fs = MemoryFileSystem.test(); |
| localIosArtifacts = Artifacts.test(localEngine: 'out/ios_profile_arm64'); |
| macOS = FakePlatform(operatingSystem: 'macos'); |
| fs.file(xcodebuild).createSync(recursive: true); |
| }); |
| |
| group('arm simulator', () { |
| late FakeProcessManager fakeProcessManager; |
| late XcodeProjectInterpreter xcodeProjectInterpreter; |
| |
| setUp(() { |
| fakeProcessManager = FakeProcessManager.empty(); |
| xcodeProjectInterpreter = XcodeProjectInterpreter.test(processManager: fakeProcessManager); |
| }); |
| |
| testUsingContext('does not exclude arm64 simulator when supported by all plugins', () async { |
| const BuildInfo buildInfo = BuildInfo.debug; |
| final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project')); |
| final Directory podXcodeProject = project.ios.hostAppRoot.childDirectory('Pods').childDirectory('Pods.xcodeproj') |
| ..createSync(recursive: true); |
| |
| final String buildDirectory = fileSystem.path.absolute('build', 'ios'); |
| fakeProcessManager.addCommands(<FakeCommand>[ |
| kWhichSysctlCommand, |
| kARMCheckCommand, |
| FakeCommand( |
| command: <String>[ |
| '/usr/bin/arch', |
| '-arm64e', |
| 'xcrun', |
| 'xcodebuild', |
| '-alltargets', |
| '-sdk', |
| 'iphonesimulator', |
| '-project', |
| podXcodeProject.path, |
| '-showBuildSettings', |
| 'BUILD_DIR=$buildDirectory', |
| 'OBJROOT=$buildDirectory', |
| ], |
| stdout: ''' |
| Build settings for action build and target plugin1: |
| ENABLE_BITCODE = NO; |
| EXCLUDED_ARCHS = i386; |
| INFOPLIST_FILE = Runner/Info.plist; |
| UNRELATED_BUILD_SETTING = arm64; |
| |
| Build settings for action build and target plugin2: |
| ENABLE_BITCODE = NO; |
| EXCLUDED_ARCHS = i386; |
| INFOPLIST_FILE = Runner/Info.plist; |
| UNRELATED_BUILD_SETTING = arm64; |
| ''' |
| ), |
| ]); |
| await updateGeneratedXcodeProperties( |
| project: project, |
| buildInfo: buildInfo, |
| ); |
| |
| final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig'); |
| expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386\n')); |
| expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphoneos*]=armv7\n')); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }, overrides: <Type, Generator>{ |
| Artifacts: () => localIosArtifacts, |
| Platform: () => macOS, |
| FileSystem: () => fs, |
| ProcessManager: () => fakeProcessManager, |
| XcodeProjectInterpreter: () => xcodeProjectInterpreter, |
| }); |
| |
| testUsingContext('excludes arm64 simulator when build setting fetch fails', () async { |
| const BuildInfo buildInfo = BuildInfo.debug; |
| final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project')); |
| final Directory podXcodeProject = project.ios.hostAppRoot.childDirectory('Pods').childDirectory('Pods.xcodeproj') |
| ..createSync(recursive: true); |
| |
| final String buildDirectory = fileSystem.path.absolute('build', 'ios'); |
| fakeProcessManager.addCommands(<FakeCommand>[ |
| kWhichSysctlCommand, |
| kARMCheckCommand, |
| FakeCommand( |
| command: <String>[ |
| '/usr/bin/arch', |
| '-arm64e', |
| 'xcrun', |
| 'xcodebuild', |
| '-alltargets', |
| '-sdk', |
| 'iphonesimulator', |
| '-project', |
| podXcodeProject.path, |
| '-showBuildSettings', |
| 'BUILD_DIR=$buildDirectory', |
| 'OBJROOT=$buildDirectory', |
| ], |
| exitCode: 1, |
| ), |
| ]); |
| await updateGeneratedXcodeProperties( |
| project: project, |
| buildInfo: buildInfo, |
| ); |
| |
| final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig'); |
| expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386 arm64\n')); |
| expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphoneos*]=armv7\n')); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }, overrides: <Type, Generator>{ |
| Artifacts: () => localIosArtifacts, |
| Platform: () => macOS, |
| FileSystem: () => fs, |
| ProcessManager: () => fakeProcessManager, |
| XcodeProjectInterpreter: () => xcodeProjectInterpreter, |
| }); |
| |
| testUsingContext('excludes arm64 simulator when unsupported by plugins', () async { |
| const BuildInfo buildInfo = BuildInfo.debug; |
| final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project')); |
| final Directory podXcodeProject = project.ios.hostAppRoot.childDirectory('Pods').childDirectory('Pods.xcodeproj') |
| ..createSync(recursive: true); |
| |
| final String buildDirectory = fileSystem.path.absolute('build', 'ios'); |
| fakeProcessManager.addCommands(<FakeCommand>[ |
| kWhichSysctlCommand, |
| kARMCheckCommand, |
| FakeCommand( |
| command: <String>[ |
| '/usr/bin/arch', |
| '-arm64e', |
| 'xcrun', |
| 'xcodebuild', |
| '-alltargets', |
| '-sdk', |
| 'iphonesimulator', |
| '-project', |
| podXcodeProject.path, |
| '-showBuildSettings', |
| 'BUILD_DIR=$buildDirectory', |
| 'OBJROOT=$buildDirectory', |
| ], |
| stdout: ''' |
| Build settings for action build and target plugin1: |
| ENABLE_BITCODE = NO; |
| EXCLUDED_ARCHS = i386; |
| INFOPLIST_FILE = Runner/Info.plist; |
| UNRELATED_BUILD_SETTING = arm64; |
| |
| Build settings for action build and target plugin2: |
| ENABLE_BITCODE = NO; |
| EXCLUDED_ARCHS = i386 arm64; |
| INFOPLIST_FILE = Runner/Info.plist; |
| UNRELATED_BUILD_SETTING = arm64; |
| ''' |
| ), |
| ]); |
| await updateGeneratedXcodeProperties( |
| project: project, |
| buildInfo: buildInfo, |
| ); |
| |
| final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig'); |
| expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386 arm64\n')); |
| expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphoneos*]=armv7\n')); |
| expect(fakeProcessManager, hasNoRemainingExpectations); |
| }, overrides: <Type, Generator>{ |
| Artifacts: () => localIosArtifacts, |
| Platform: () => macOS, |
| FileSystem: () => fs, |
| ProcessManager: () => fakeProcessManager, |
| XcodeProjectInterpreter: () => xcodeProjectInterpreter, |
| }); |
| }); |
| |
| void testUsingOsxContext(String description, dynamic Function() testMethod) { |
| testUsingContext(description, testMethod, overrides: <Type, Generator>{ |
| Artifacts: () => localIosArtifacts, |
| Platform: () => macOS, |
| FileSystem: () => fs, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| } |
| |
| testUsingOsxContext('exits when armv7 local engine is set', () async { |
| localIosArtifacts = Artifacts.test(localEngine: 'out/ios_profile_arm'); |
| const BuildInfo buildInfo = BuildInfo.debug; |
| final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project')); |
| await expectLater(() => |
| updateGeneratedXcodeProperties( |
| project: project, |
| buildInfo: buildInfo, |
| ), |
| throwsToolExit(message: '32-bit iOS local engine binaries are not supported.'), |
| ); |
| }); |
| |
| testUsingContext('sets ARCHS=arm64 when arm64 local host engine is set', () async { |
| const BuildInfo buildInfo = BuildInfo.debug; |
| final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project')); |
| await updateGeneratedXcodeProperties( |
| project: project, |
| buildInfo: buildInfo, |
| useMacOSConfig: true, |
| ); |
| |
| final File config = fs.file('path/to/project/macos/Flutter/ephemeral/Flutter-Generated.xcconfig'); |
| expect(config.existsSync(), isTrue); |
| |
| final String contents = config.readAsStringSync(); |
| expect(contents.contains('ARCHS=arm64\n'), isTrue); |
| |
| final File buildPhaseScript = fs.file('path/to/project/macos/Flutter/ephemeral/flutter_export_environment.sh'); |
| expect(buildPhaseScript.existsSync(), isTrue); |
| |
| final String buildPhaseScriptContents = buildPhaseScript.readAsStringSync(); |
| expect(buildPhaseScriptContents.contains('export "ARCHS=arm64"'), isTrue); |
| }, overrides: <Type, Generator>{ |
| Artifacts: () => Artifacts.test(localEngine: 'out/host_profile_arm64'), |
| Platform: () => macOS, |
| FileSystem: () => fs, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('sets ARCHS=x86_64 when x64 local host engine is set', () async { |
| const BuildInfo buildInfo = BuildInfo.debug; |
| final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project')); |
| await updateGeneratedXcodeProperties( |
| project: project, |
| buildInfo: buildInfo, |
| useMacOSConfig: true, |
| ); |
| |
| final File config = fs.file('path/to/project/macos/Flutter/ephemeral/Flutter-Generated.xcconfig'); |
| expect(config.existsSync(), isTrue); |
| |
| final String contents = config.readAsStringSync(); |
| expect(contents.contains('ARCHS=x86_64\n'), isTrue); |
| |
| final File buildPhaseScript = fs.file('path/to/project/macos/Flutter/ephemeral/flutter_export_environment.sh'); |
| expect(buildPhaseScript.existsSync(), isTrue); |
| |
| final String buildPhaseScriptContents = buildPhaseScript.readAsStringSync(); |
| expect(buildPhaseScriptContents.contains('export "ARCHS=x86_64"'), isTrue); |
| }, overrides: <Type, Generator>{ |
| Artifacts: () => Artifacts.test(localEngine: 'out/host_profile'), |
| Platform: () => macOS, |
| FileSystem: () => fs, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingOsxContext('does not exclude arm64 simulator when there are no plugins', () async { |
| const BuildInfo buildInfo = BuildInfo.debug; |
| final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project')); |
| await updateGeneratedXcodeProperties( |
| project: project, |
| buildInfo: buildInfo, |
| ); |
| |
| final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig'); |
| expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386\n')); |
| expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphoneos*]=armv7\n')); |
| |
| final File buildPhaseScript = fs.file('path/to/project/ios/Flutter/flutter_export_environment.sh'); |
| expect(buildPhaseScript.readAsStringSync(), isNot(contains('EXCLUDED_ARCHS'))); |
| }); |
| |
| testUsingOsxContext('sets TRACK_WIDGET_CREATION=true when trackWidgetCreation is true', () async { |
| const BuildInfo buildInfo = BuildInfo.debug; |
| final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project')); |
| await updateGeneratedXcodeProperties( |
| project: project, |
| buildInfo: buildInfo, |
| ); |
| |
| final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig'); |
| expect(config.existsSync(), isTrue); |
| |
| final String contents = config.readAsStringSync(); |
| expect(contents.contains('TRACK_WIDGET_CREATION=true'), isTrue); |
| |
| final File buildPhaseScript = fs.file('path/to/project/ios/Flutter/flutter_export_environment.sh'); |
| expect(buildPhaseScript.existsSync(), isTrue); |
| |
| final String buildPhaseScriptContents = buildPhaseScript.readAsStringSync(); |
| expect(buildPhaseScriptContents.contains('TRACK_WIDGET_CREATION=true'), isTrue); |
| }); |
| |
| testUsingOsxContext('does not set TRACK_WIDGET_CREATION when trackWidgetCreation is false', () async { |
| const BuildInfo buildInfo = BuildInfo(BuildMode.debug, null, treeShakeIcons: false); |
| final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project')); |
| await updateGeneratedXcodeProperties( |
| project: project, |
| buildInfo: buildInfo, |
| ); |
| |
| final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig'); |
| expect(config.existsSync(), isTrue); |
| |
| final String contents = config.readAsStringSync(); |
| expect(contents.contains('TRACK_WIDGET_CREATION=true'), isFalse); |
| |
| final File buildPhaseScript = fs.file('path/to/project/ios/Flutter/flutter_export_environment.sh'); |
| expect(buildPhaseScript.existsSync(), isTrue); |
| |
| final String buildPhaseScriptContents = buildPhaseScript.readAsStringSync(); |
| expect(buildPhaseScriptContents.contains('TRACK_WIDGET_CREATION=true'), isFalse); |
| }); |
| |
| group('sim local engine', () { |
| testUsingContext('sets ARCHS=x86_64 when x86 sim local engine is set', () async { |
| const BuildInfo buildInfo = BuildInfo.debug; |
| final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project')); |
| await updateGeneratedXcodeProperties( |
| project: project, |
| buildInfo: buildInfo, |
| ); |
| |
| final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig'); |
| expect(config.existsSync(), isTrue); |
| |
| final String contents = config.readAsStringSync(); |
| expect(contents.contains('ARCHS=x86_64'), isTrue); |
| |
| final File buildPhaseScript = fs.file('path/to/project/ios/Flutter/flutter_export_environment.sh'); |
| expect(buildPhaseScript.existsSync(), isTrue); |
| |
| final String buildPhaseScriptContents = buildPhaseScript.readAsStringSync(); |
| expect(buildPhaseScriptContents.contains('ARCHS=x86_64'), isTrue); |
| }, overrides: <Type, Generator>{ |
| Artifacts: () => Artifacts.test(localEngine: 'out/ios_debug_sim_unopt'), |
| Platform: () => macOS, |
| FileSystem: () => fs, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| |
| testUsingContext('sets ARCHS=arm64 when arm64 sim local engine is set', () async { |
| const BuildInfo buildInfo = BuildInfo.debug; |
| final FlutterProject project = FlutterProject.fromDirectoryTest(fs.directory('path/to/project')); |
| await updateGeneratedXcodeProperties( |
| project: project, |
| buildInfo: buildInfo, |
| ); |
| |
| final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig'); |
| expect(config.existsSync(), isTrue); |
| |
| final String contents = config.readAsStringSync(); |
| expect(contents.contains('ARCHS=arm64'), isTrue); |
| |
| final File buildPhaseScript = fs.file('path/to/project/ios/Flutter/flutter_export_environment.sh'); |
| expect(buildPhaseScript.existsSync(), isTrue); |
| |
| final String buildPhaseScriptContents = buildPhaseScript.readAsStringSync(); |
| expect(buildPhaseScriptContents.contains('ARCHS=arm64'), isTrue); |
| }, overrides: <Type, Generator>{ |
| Artifacts: () => Artifacts.test(localEngine: 'out/ios_debug_sim_arm64'), |
| Platform: () => macOS, |
| FileSystem: () => fs, |
| ProcessManager: () => FakeProcessManager.any(), |
| }); |
| }); |
| |
| String? propertyFor(String key, File file) { |
| final List<String> properties = file |
| .readAsLinesSync() |
| .where((String line) => line.startsWith('$key=')) |
| .map((String line) => line.split('=')[1]) |
| .toList(); |
| return properties.isEmpty ? null : properties.first; |
| } |
| |
| Future<void> checkBuildVersion({ |
| required String manifestString, |
| required BuildInfo buildInfo, |
| String? expectedBuildName, |
| String? expectedBuildNumber, |
| }) async { |
| final File manifestFile = fs.file('path/to/project/pubspec.yaml'); |
| manifestFile.createSync(recursive: true); |
| manifestFile.writeAsStringSync(manifestString); |
| |
| await updateGeneratedXcodeProperties( |
| project: FlutterProject.fromDirectoryTest(fs.directory('path/to/project')), |
| buildInfo: buildInfo, |
| ); |
| |
| final File localPropertiesFile = fs.file('path/to/project/ios/Flutter/Generated.xcconfig'); |
| expect(propertyFor('FLUTTER_BUILD_NAME', localPropertiesFile), expectedBuildName); |
| expect(propertyFor('FLUTTER_BUILD_NUMBER', localPropertiesFile), expectedBuildNumber); |
| expect(propertyFor('FLUTTER_BUILD_NUMBER', localPropertiesFile), isNotNull); |
| } |
| |
| testUsingOsxContext('extract build name and number from pubspec.yaml', () async { |
| const String manifest = ''' |
| name: test |
| version: 1.0.0+1 |
| dependencies: |
| flutter: |
| sdk: flutter |
| flutter: |
| '''; |
| |
| const BuildInfo buildInfo = BuildInfo(BuildMode.release, null, treeShakeIcons: false); |
| await checkBuildVersion( |
| manifestString: manifest, |
| buildInfo: buildInfo, |
| expectedBuildName: '1.0.0', |
| expectedBuildNumber: '1', |
| ); |
| }); |
| |
| testUsingOsxContext('extract build name from pubspec.yaml', () async { |
| const String manifest = ''' |
| name: test |
| version: 1.0.0 |
| dependencies: |
| flutter: |
| sdk: flutter |
| flutter: |
| '''; |
| const BuildInfo buildInfo = BuildInfo(BuildMode.release, null, treeShakeIcons: false); |
| await checkBuildVersion( |
| manifestString: manifest, |
| buildInfo: buildInfo, |
| expectedBuildName: '1.0.0', |
| expectedBuildNumber: '1.0.0', |
| ); |
| }); |
| |
| testUsingOsxContext('allow build info to override build name', () async { |
| const String manifest = ''' |
| name: test |
| version: 1.0.0+1 |
| dependencies: |
| flutter: |
| sdk: flutter |
| flutter: |
| '''; |
| const BuildInfo buildInfo = BuildInfo(BuildMode.release, null, buildName: '1.0.2', treeShakeIcons: false); |
| await checkBuildVersion( |
| manifestString: manifest, |
| buildInfo: buildInfo, |
| expectedBuildName: '1.0.2', |
| expectedBuildNumber: '1', |
| ); |
| }); |
| |
| testUsingOsxContext('allow build info to override build name with build number fallback', () async { |
| const String manifest = ''' |
| name: test |
| version: 1.0.0 |
| dependencies: |
| flutter: |
| sdk: flutter |
| flutter: |
| '''; |
| const BuildInfo buildInfo = BuildInfo(BuildMode.release, null, buildName: '1.0.2', treeShakeIcons: false); |
| await checkBuildVersion( |
| manifestString: manifest, |
| buildInfo: buildInfo, |
| expectedBuildName: '1.0.2', |
| expectedBuildNumber: '1.0.2', |
| ); |
| }); |
| |
| testUsingOsxContext('allow build info to override build number', () async { |
| const String manifest = ''' |
| name: test |
| version: 1.0.0+1 |
| dependencies: |
| flutter: |
| sdk: flutter |
| flutter: |
| '''; |
| const BuildInfo buildInfo = BuildInfo(BuildMode.release, null, buildNumber: '3', treeShakeIcons: false); |
| await checkBuildVersion( |
| manifestString: manifest, |
| buildInfo: buildInfo, |
| expectedBuildName: '1.0.0', |
| expectedBuildNumber: '3', |
| ); |
| }); |
| |
| testUsingOsxContext('allow build info to override build name and number', () async { |
| const String manifest = ''' |
| name: test |
| version: 1.0.0+1 |
| dependencies: |
| flutter: |
| sdk: flutter |
| flutter: |
| '''; |
| const BuildInfo buildInfo = BuildInfo(BuildMode.release, null, buildName: '1.0.2', buildNumber: '3', treeShakeIcons: false); |
| await checkBuildVersion( |
| manifestString: manifest, |
| buildInfo: buildInfo, |
| expectedBuildName: '1.0.2', |
| expectedBuildNumber: '3', |
| ); |
| }); |
| |
| testUsingOsxContext('allow build info to override build name and set number', () async { |
| const String manifest = ''' |
| name: test |
| version: 1.0.0 |
| dependencies: |
| flutter: |
| sdk: flutter |
| flutter: |
| '''; |
| const BuildInfo buildInfo = BuildInfo(BuildMode.release, null, buildName: '1.0.2', buildNumber: '3', treeShakeIcons: false); |
| await checkBuildVersion( |
| manifestString: manifest, |
| buildInfo: buildInfo, |
| expectedBuildName: '1.0.2', |
| expectedBuildNumber: '3', |
| ); |
| }); |
| |
| testUsingOsxContext('allow build info to set build name and number', () async { |
| const String manifest = ''' |
| name: test |
| dependencies: |
| flutter: |
| sdk: flutter |
| flutter: |
| '''; |
| const BuildInfo buildInfo = BuildInfo(BuildMode.release, null, buildName: '1.0.2', buildNumber: '3', treeShakeIcons: false); |
| await checkBuildVersion( |
| manifestString: manifest, |
| buildInfo: buildInfo, |
| expectedBuildName: '1.0.2', |
| expectedBuildNumber: '3', |
| ); |
| }); |
| |
| testUsingOsxContext('default build name and number when version is missing', () async { |
| const String manifest = ''' |
| name: test |
| dependencies: |
| flutter: |
| sdk: flutter |
| flutter: |
| '''; |
| const BuildInfo buildInfo = BuildInfo(BuildMode.release, null, treeShakeIcons: false); |
| await checkBuildVersion( |
| manifestString: manifest, |
| buildInfo: buildInfo, |
| expectedBuildName: '1.0.0', |
| expectedBuildNumber: '1', |
| ); |
| }); |
| }); |
| } |