Unverified Commit 125451bc authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Migrate mac.dart to null safety (#88846)

parent a1cd3f45
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
...@@ -36,10 +34,10 @@ import 'xcodeproj.dart'; ...@@ -36,10 +34,10 @@ import 'xcodeproj.dart';
class IMobileDevice { class IMobileDevice {
IMobileDevice({ IMobileDevice({
@required Artifacts artifacts, required Artifacts artifacts,
@required Cache cache, required Cache cache,
@required ProcessManager processManager, required ProcessManager processManager,
@required Logger logger, required Logger logger,
}) : _idevicesyslogPath = artifacts.getHostArtifact(HostArtifact.idevicesyslog).path, }) : _idevicesyslogPath = artifacts.getHostArtifact(HostArtifact.idevicesyslog).path,
_idevicescreenshotPath = artifacts.getHostArtifact(HostArtifact.idevicescreenshot).path, _idevicescreenshotPath = artifacts.getHostArtifact(HostArtifact.idevicescreenshot).path,
_dyLdLibEntry = cache.dyLdLibEntry, _dyLdLibEntry = cache.dyLdLibEntry,
...@@ -53,7 +51,7 @@ class IMobileDevice { ...@@ -53,7 +51,7 @@ class IMobileDevice {
final ProcessUtils _processUtils; final ProcessUtils _processUtils;
bool get isInstalled => _isInstalled ??= _processManager.canRun(_idevicescreenshotPath); bool get isInstalled => _isInstalled ??= _processManager.canRun(_idevicescreenshotPath);
bool _isInstalled; bool? _isInstalled;
/// Starts `idevicesyslog` and returns the running process. /// Starts `idevicesyslog` and returns the running process.
Future<Process> startLogger(String deviceID) { Future<Process> startLogger(String deviceID) {
...@@ -93,13 +91,13 @@ class IMobileDevice { ...@@ -93,13 +91,13 @@ class IMobileDevice {
} }
Future<XcodeBuildResult> buildXcodeProject({ Future<XcodeBuildResult> buildXcodeProject({
BuildableIOSApp app, required BuildableIOSApp app,
BuildInfo buildInfo, required BuildInfo buildInfo,
String targetOverride, required String targetOverride,
EnvironmentType environmentType = EnvironmentType.physical, EnvironmentType environmentType = EnvironmentType.physical,
DarwinArch activeArch, DarwinArch? activeArch,
bool codesign = true, bool codesign = true,
String deviceID, String? deviceID,
bool configOnly = false, bool configOnly = false,
XcodeBuildAction buildAction = XcodeBuildAction.build, XcodeBuildAction buildAction = XcodeBuildAction.build,
}) async { }) async {
...@@ -126,12 +124,16 @@ Future<XcodeBuildResult> buildXcodeProject({ ...@@ -126,12 +124,16 @@ Future<XcodeBuildResult> buildXcodeProject({
await removeFinderExtendedAttributes(app.project.parent.directory, globals.processUtils, globals.logger); await removeFinderExtendedAttributes(app.project.parent.directory, globals.processUtils, globals.logger);
final XcodeProjectInfo projectInfo = await app.project.projectInfo(); final XcodeProjectInfo? projectInfo = await app.project.projectInfo();
final String scheme = projectInfo.schemeFor(buildInfo); if (projectInfo == null) {
globals.printError('Xcode project not found.');
return XcodeBuildResult(success: false);
}
final String? scheme = projectInfo.schemeFor(buildInfo);
if (scheme == null) { if (scheme == null) {
projectInfo.reportFlavorNotFoundAndExit(); projectInfo.reportFlavorNotFoundAndExit();
} }
final String configuration = projectInfo.buildConfigurationFor(buildInfo, scheme); final String? configuration = projectInfo.buildConfigurationFor(buildInfo, scheme);
if (configuration == null) { if (configuration == null) {
globals.printError(''); globals.printError('');
globals.printError('The Xcode project defines build configurations: ${projectInfo.buildConfigurations.join(', ')}'); globals.printError('The Xcode project defines build configurations: ${projectInfo.buildConfigurations.join(', ')}');
...@@ -159,14 +161,14 @@ Future<XcodeBuildResult> buildXcodeProject({ ...@@ -159,14 +161,14 @@ Future<XcodeBuildResult> buildXcodeProject({
} }
final FlutterManifest manifest = app.project.parent.manifest; final FlutterManifest manifest = app.project.parent.manifest;
final String buildName = parsedBuildName(manifest: manifest, buildInfo: buildInfo); final String? buildName = parsedBuildName(manifest: manifest, buildInfo: buildInfo);
final bool buildNameIsMissing = buildName == null || buildName.isEmpty; final bool buildNameIsMissing = buildName == null || buildName.isEmpty;
if (buildNameIsMissing) { if (buildNameIsMissing) {
globals.printStatus('Warning: Missing build name (CFBundleShortVersionString).'); globals.printStatus('Warning: Missing build name (CFBundleShortVersionString).');
} }
final String buildNumber = parsedBuildNumber(manifest: manifest, buildInfo: buildInfo); final String? buildNumber = parsedBuildNumber(manifest: manifest, buildInfo: buildInfo);
final bool buildNumberIsMissing = buildNumber == null || buildNumber.isEmpty; final bool buildNumberIsMissing = buildNumber == null || buildNumber.isEmpty;
if (buildNumberIsMissing) { if (buildNumberIsMissing) {
...@@ -177,7 +179,7 @@ Future<XcodeBuildResult> buildXcodeProject({ ...@@ -177,7 +179,7 @@ Future<XcodeBuildResult> buildXcodeProject({
'file version field before submitting to the App Store.'); 'file version field before submitting to the App Store.');
} }
Map<String, String> autoSigningConfigs; Map<String, String>? autoSigningConfigs;
final Map<String, String> buildSettings = await app.project.buildSettingsForBuildInfo( final Map<String, String> buildSettings = await app.project.buildSettingsForBuildInfo(
buildInfo, buildInfo,
...@@ -206,7 +208,7 @@ Future<XcodeBuildResult> buildXcodeProject({ ...@@ -206,7 +208,7 @@ Future<XcodeBuildResult> buildXcodeProject({
} }
final List<String> buildCommands = <String>[ final List<String> buildCommands = <String>[
...globals.xcode.xcrunCommand(), ...globals.xcode!.xcrunCommand(),
'xcodebuild', 'xcodebuild',
'-configuration', '-configuration',
configuration, configuration,
...@@ -291,18 +293,18 @@ Future<XcodeBuildResult> buildXcodeProject({ ...@@ -291,18 +293,18 @@ Future<XcodeBuildResult> buildXcodeProject({
); );
} }
Status buildSubStatus; Status? buildSubStatus;
Status initialBuildStatus; Status? initialBuildStatus;
Directory tempDir; Directory? tempDir;
File scriptOutputPipeFile; File? scriptOutputPipeFile;
if (globals.logger.hasTerminal) { if (globals.logger.hasTerminal) {
tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_build_log_pipe.'); tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_build_log_pipe.');
scriptOutputPipeFile = tempDir.childFile('pipe_to_stdout'); scriptOutputPipeFile = tempDir.childFile('pipe_to_stdout');
globals.os.makePipe(scriptOutputPipeFile.path); globals.os.makePipe(scriptOutputPipeFile.path);
Future<void> listenToScriptOutputLine() async { Future<void> listenToScriptOutputLine() async {
final List<String> lines = await scriptOutputPipeFile.readAsLines(); final List<String> lines = await scriptOutputPipeFile!.readAsLines();
for (final String line in lines) { for (final String line in lines) {
if (line == 'done' || line == 'all done') { if (line == 'done' || line == 'all done') {
buildSubStatus?.stop(); buildSubStatus?.stop();
...@@ -347,7 +349,7 @@ Future<XcodeBuildResult> buildXcodeProject({ ...@@ -347,7 +349,7 @@ Future<XcodeBuildResult> buildXcodeProject({
final Stopwatch sw = Stopwatch()..start(); final Stopwatch sw = Stopwatch()..start();
initialBuildStatus = globals.logger.startProgress('Running Xcode build...'); initialBuildStatus = globals.logger.startProgress('Running Xcode build...');
final RunResult buildResult = await _runBuildWithRetries(buildCommands, app); final RunResult? buildResult = await _runBuildWithRetries(buildCommands, app);
// Notifies listener that no more output is coming. // Notifies listener that no more output is coming.
scriptOutputPipeFile?.writeAsStringSync('all done'); scriptOutputPipeFile?.writeAsStringSync('all done');
...@@ -361,7 +363,7 @@ Future<XcodeBuildResult> buildXcodeProject({ ...@@ -361,7 +363,7 @@ Future<XcodeBuildResult> buildXcodeProject({
); );
globals.flutterUsage.sendTiming(xcodeBuildActionToString(buildAction), 'xcode-ios', Duration(milliseconds: sw.elapsedMilliseconds)); globals.flutterUsage.sendTiming(xcodeBuildActionToString(buildAction), 'xcode-ios', Duration(milliseconds: sw.elapsedMilliseconds));
if (buildResult.exitCode != 0) { if (buildResult != null && buildResult.exitCode != 0) {
globals.printStatus('Failed to build iOS app'); globals.printStatus('Failed to build iOS app');
if (buildResult.stderr.isNotEmpty) { if (buildResult.stderr.isNotEmpty) {
globals.printStatus('Error output from Xcode build:\n↳'); globals.printStatus('Error output from Xcode build:\n↳');
...@@ -383,18 +385,22 @@ Future<XcodeBuildResult> buildXcodeProject({ ...@@ -383,18 +385,22 @@ Future<XcodeBuildResult> buildXcodeProject({
), ),
); );
} else { } else {
String outputDir; String? outputDir;
if (buildAction == XcodeBuildAction.build) { if (buildAction == XcodeBuildAction.build) {
// If the app contains a watch companion target, the sdk argument of xcodebuild has to be omitted. // If the app contains a watch companion target, the sdk argument of xcodebuild has to be omitted.
// For some reason this leads to TARGET_BUILD_DIR always ending in 'iphoneos' even though the // For some reason this leads to TARGET_BUILD_DIR always ending in 'iphoneos' even though the
// actual directory will end with 'iphonesimulator' for simulator builds. // actual directory will end with 'iphonesimulator' for simulator builds.
// The value of TARGET_BUILD_DIR is adjusted to accommodate for this effect. // The value of TARGET_BUILD_DIR is adjusted to accommodate for this effect.
String targetBuildDir = buildSettings['TARGET_BUILD_DIR']; String? targetBuildDir = buildSettings['TARGET_BUILD_DIR'];
if (targetBuildDir == null) {
globals.printError('Xcode build is missing expected TARGET_BUILD_DIR build setting.');
return XcodeBuildResult(success: false);
}
if (hasWatchCompanion && environmentType == EnvironmentType.simulator) { if (hasWatchCompanion && environmentType == EnvironmentType.simulator) {
globals.printTrace('Replacing iphoneos with iphonesimulator in TARGET_BUILD_DIR.'); globals.printTrace('Replacing iphoneos with iphonesimulator in TARGET_BUILD_DIR.');
targetBuildDir = targetBuildDir.replaceFirst('iphoneos', 'iphonesimulator'); targetBuildDir = targetBuildDir.replaceFirst('iphoneos', 'iphonesimulator');
} }
final String appBundle = buildSettings['WRAPPER_NAME']; final String? appBundle = buildSettings['WRAPPER_NAME'];
final String expectedOutputDirectory = globals.fs.path.join( final String expectedOutputDirectory = globals.fs.path.join(
targetBuildDir, targetBuildDir,
appBundle, appBundle,
...@@ -463,11 +469,11 @@ Future<void> removeFinderExtendedAttributes(Directory projectDirectory, ProcessU ...@@ -463,11 +469,11 @@ Future<void> removeFinderExtendedAttributes(Directory projectDirectory, ProcessU
} }
} }
Future<RunResult> _runBuildWithRetries(List<String> buildCommands, BuildableIOSApp app) async { Future<RunResult?> _runBuildWithRetries(List<String> buildCommands, BuildableIOSApp app) async {
int buildRetryDelaySeconds = 1; int buildRetryDelaySeconds = 1;
int remainingTries = 8; int remainingTries = 8;
RunResult buildResult; RunResult? buildResult;
while (remainingTries > 0) { while (remainingTries > 0) {
remainingTries--; remainingTries--;
buildRetryDelaySeconds *= 2; buildRetryDelaySeconds *= 2;
...@@ -507,13 +513,14 @@ return result.exitCode != 0 && ...@@ -507,13 +513,14 @@ return result.exitCode != 0 &&
} }
Future<void> diagnoseXcodeBuildFailure(XcodeBuildResult result, Usage flutterUsage, Logger logger) async { Future<void> diagnoseXcodeBuildFailure(XcodeBuildResult result, Usage flutterUsage, Logger logger) async {
if (result.xcodeBuildExecution != null && final XcodeBuildExecution? xcodeBuildExecution = result.xcodeBuildExecution;
result.xcodeBuildExecution.environmentType == EnvironmentType.physical && if (xcodeBuildExecution != null &&
result.stdout?.toUpperCase()?.contains('BITCODE') == true) { xcodeBuildExecution.environmentType == EnvironmentType.physical &&
result.stdout?.toUpperCase().contains('BITCODE') == true) {
BuildEvent('xcode-bitcode-failure', BuildEvent('xcode-bitcode-failure',
type: 'ios', type: 'ios',
command: result.xcodeBuildExecution.buildCommands.toString(), command: xcodeBuildExecution.buildCommands.toString(),
settings: result.xcodeBuildExecution.buildSettings.toString(), settings: xcodeBuildExecution.buildSettings.toString(),
flutterUsage: flutterUsage, flutterUsage: flutterUsage,
).send(); ).send();
} }
...@@ -531,9 +538,8 @@ Future<void> diagnoseXcodeBuildFailure(XcodeBuildResult result, Usage flutterUsa ...@@ -531,9 +538,8 @@ Future<void> diagnoseXcodeBuildFailure(XcodeBuildResult result, Usage flutterUsa
logger.printError(' flutter clean'); logger.printError(' flutter clean');
return; return;
} }
if (xcodeBuildExecution != null &&
if (result.xcodeBuildExecution != null && xcodeBuildExecution.environmentType == EnvironmentType.physical &&
result.xcodeBuildExecution.environmentType == EnvironmentType.physical &&
result.stdout?.contains('BCEROR') == true && result.stdout?.contains('BCEROR') == true &&
// May need updating if Xcode changes its outputs. // May need updating if Xcode changes its outputs.
result.stdout?.contains("Xcode couldn't find a provisioning profile matching") == true) { result.stdout?.contains("Xcode couldn't find a provisioning profile matching") == true) {
...@@ -543,16 +549,16 @@ Future<void> diagnoseXcodeBuildFailure(XcodeBuildResult result, Usage flutterUsa ...@@ -543,16 +549,16 @@ Future<void> diagnoseXcodeBuildFailure(XcodeBuildResult result, Usage flutterUsa
// Make sure the user has specified one of: // Make sure the user has specified one of:
// * DEVELOPMENT_TEAM (automatic signing) // * DEVELOPMENT_TEAM (automatic signing)
// * PROVISIONING_PROFILE (manual signing) // * PROVISIONING_PROFILE (manual signing)
if (result.xcodeBuildExecution != null && if (xcodeBuildExecution != null &&
result.xcodeBuildExecution.environmentType == EnvironmentType.physical && xcodeBuildExecution.environmentType == EnvironmentType.physical &&
!<String>['DEVELOPMENT_TEAM', 'PROVISIONING_PROFILE'].any( !<String>['DEVELOPMENT_TEAM', 'PROVISIONING_PROFILE'].any(
result.xcodeBuildExecution.buildSettings.containsKey)) { xcodeBuildExecution.buildSettings.containsKey)) {
logger.printError(noDevelopmentTeamInstruction, emphasis: true); logger.printError(noDevelopmentTeamInstruction, emphasis: true);
return; return;
} }
if (result.xcodeBuildExecution != null && if (xcodeBuildExecution != null &&
result.xcodeBuildExecution.environmentType == EnvironmentType.physical && xcodeBuildExecution.environmentType == EnvironmentType.physical &&
result.xcodeBuildExecution.buildSettings['PRODUCT_BUNDLE_IDENTIFIER']?.contains('com.example') == true) { xcodeBuildExecution.buildSettings['PRODUCT_BUNDLE_IDENTIFIER']?.contains('com.example') == true) {
logger.printError(''); logger.printError('');
logger.printError('It appears that your application still contains the default signing identifier.'); logger.printError('It appears that your application still contains the default signing identifier.');
logger.printError("Try replacing 'com.example' with your signing id in Xcode:"); logger.printError("Try replacing 'com.example' with your signing id in Xcode:");
...@@ -589,7 +595,7 @@ String xcodeBuildActionToString(XcodeBuildAction action) { ...@@ -589,7 +595,7 @@ String xcodeBuildActionToString(XcodeBuildAction action) {
class XcodeBuildResult { class XcodeBuildResult {
XcodeBuildResult({ XcodeBuildResult({
@required this.success, required this.success,
this.output, this.output,
this.stdout, this.stdout,
this.stderr, this.stderr,
...@@ -597,20 +603,20 @@ class XcodeBuildResult { ...@@ -597,20 +603,20 @@ class XcodeBuildResult {
}); });
final bool success; final bool success;
final String output; final String? output;
final String stdout; final String? stdout;
final String stderr; final String? stderr;
/// The invocation of the build that resulted in this result instance. /// The invocation of the build that resulted in this result instance.
final XcodeBuildExecution xcodeBuildExecution; final XcodeBuildExecution? xcodeBuildExecution;
} }
/// Describes an invocation of a Xcode build command. /// Describes an invocation of a Xcode build command.
class XcodeBuildExecution { class XcodeBuildExecution {
XcodeBuildExecution({ XcodeBuildExecution({
@required this.buildCommands, required this.buildCommands,
@required this.appDirectory, required this.appDirectory,
@required this.environmentType, required this.environmentType,
@required this.buildSettings, required this.buildSettings,
}); });
/// The original list of Xcode build commands used to produce this build result. /// The original list of Xcode build commands used to produce this build result.
...@@ -627,12 +633,13 @@ bool _checkXcodeVersion() { ...@@ -627,12 +633,13 @@ bool _checkXcodeVersion() {
if (!globals.platform.isMacOS) { if (!globals.platform.isMacOS) {
return false; return false;
} }
if (!globals.xcodeProjectInterpreter.isInstalled) { final XcodeProjectInterpreter? xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
if (xcodeProjectInterpreter?.isInstalled != true) {
globals.printError('Cannot find "xcodebuild". $_xcodeRequirement'); globals.printError('Cannot find "xcodebuild". $_xcodeRequirement');
return false; return false;
} }
if (!globals.xcode.isRequiredVersionSatisfactory) { if (globals.xcode?.isRequiredVersionSatisfactory != true) {
globals.printError('Found "${globals.xcodeProjectInterpreter.versionText}". $_xcodeRequirement'); globals.printError('Found "${xcodeProjectInterpreter?.versionText}". $_xcodeRequirement');
return false; return false;
} }
return true; return true;
...@@ -649,10 +656,10 @@ bool upgradePbxProjWithFlutterAssets(IosProject project, Logger logger) { ...@@ -649,10 +656,10 @@ bool upgradePbxProjWithFlutterAssets(IosProject project, Logger logger) {
final Set<String> printedStatuses = <String>{}; final Set<String> printedStatuses = <String>{};
for (final String line in lines) { for (final String line in lines) {
final Match match = oldAssets.firstMatch(line); final Match? match = oldAssets.firstMatch(line);
if (match != null) { if (match != null) {
if (printedStatuses.add(match.group(1))) { if (printedStatuses.add(match.group(1)!)) {
logger.printStatus('Removing obsolete reference to ${match.group(1)} from ${project.xcodeProject?.basename}'); logger.printStatus('Removing obsolete reference to ${match.group(1)} from ${project.xcodeProject.basename}');
} }
} else { } else {
buffer.writeln(line); buffer.writeln(line);
......
...@@ -373,7 +373,7 @@ class XcodeProjectBuildContext { ...@@ -373,7 +373,7 @@ class XcodeProjectBuildContext {
/// ///
/// Represents the output of `xcodebuild -list`. /// Represents the output of `xcodebuild -list`.
class XcodeProjectInfo { class XcodeProjectInfo {
XcodeProjectInfo( const XcodeProjectInfo(
this.targets, this.targets,
this.buildConfigurations, this.buildConfigurations,
this.schemes, this.schemes,
......
...@@ -86,18 +86,88 @@ void main() { ...@@ -86,18 +86,88 @@ void main() {
BufferLogger logger; BufferLogger logger;
Xcode xcode; Xcode xcode;
FakeXcodeProjectInterpreter fakeXcodeProjectInterpreter; FakeXcodeProjectInterpreter fakeXcodeProjectInterpreter;
XcodeProjectInfo projectInfo;
setUp(() { setUp(() {
logger = BufferLogger.test(); logger = BufferLogger.test();
fileSystem = MemoryFileSystem.test(); fileSystem = MemoryFileSystem.test();
processManager = FakeProcessManager.empty(); processManager = FakeProcessManager.empty();
fakeXcodeProjectInterpreter = FakeXcodeProjectInterpreter(); projectInfo = XcodeProjectInfo(
<String>['Runner'],
<String>['Debug', 'Release'],
<String>['Runner'],
logger,
);
fakeXcodeProjectInterpreter = FakeXcodeProjectInterpreter(projectInfo: projectInfo);
xcode = Xcode.test(processManager: FakeProcessManager.any(), xcodeProjectInterpreter: fakeXcodeProjectInterpreter); xcode = Xcode.test(processManager: FakeProcessManager.any(), xcodeProjectInterpreter: fakeXcodeProjectInterpreter);
fileSystem.file('foo/.packages') fileSystem.file('foo/.packages')
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsStringSync('\n'); ..writeAsStringSync('\n');
}); });
testUsingContext('missing TARGET_BUILD_DIR', () async {
final IOSDevice iosDevice = setUpIOSDevice(
fileSystem: fileSystem,
processManager: processManager,
logger: logger,
artifacts: artifacts,
);
setUpIOSProject(fileSystem);
final FlutterProject flutterProject = FlutterProject.fromDirectory(fileSystem.currentDirectory);
final BuildableIOSApp buildableIOSApp = BuildableIOSApp(flutterProject.ios, 'flutter', 'My Super Awesome App.app');
processManager.addCommand(FakeCommand(command: _xattrArgs(flutterProject)));
processManager.addCommand(const FakeCommand(command: kRunReleaseArgs));
final LaunchResult launchResult = await iosDevice.startApp(
buildableIOSApp,
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
platformArgs: <String, Object>{},
);
expect(launchResult.started, false);
expect(logger.errorText, contains('Xcode build is missing expected TARGET_BUILD_DIR build setting'));
expect(processManager, hasNoRemainingExpectations);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
FileSystem: () => fileSystem,
Logger: () => logger,
Platform: () => macPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(buildSettings: const <String, String>{
'WRAPPER_NAME': 'My Super Awesome App.app',
'DEVELOPMENT_TEAM': '3333CCCC33',
}, projectInfo: projectInfo),
Xcode: () => xcode,
});
testUsingContext('missing project info', () async {
final IOSDevice iosDevice = setUpIOSDevice(
fileSystem: fileSystem,
processManager: FakeProcessManager.any(),
logger: logger,
artifacts: artifacts,
);
setUpIOSProject(fileSystem);
final FlutterProject flutterProject = FlutterProject.fromDirectory(fileSystem.currentDirectory);
final BuildableIOSApp buildableIOSApp = BuildableIOSApp(flutterProject.ios, 'flutter', 'My Super Awesome App.app');
final LaunchResult launchResult = await iosDevice.startApp(
buildableIOSApp,
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
platformArgs: <String, Object>{},
);
expect(launchResult.started, false);
expect(logger.errorText, contains('Xcode project not found'));
}, overrides: <Type, Generator>{
ProcessManager: () => FakeProcessManager.any(),
FileSystem: () => fileSystem,
Logger: () => logger,
Platform: () => macPlatform,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(projectInfo: null),
Xcode: () => xcode,
});
testUsingContext('with buildable app', () async { testUsingContext('with buildable app', () async {
final IOSDevice iosDevice = setUpIOSDevice( final IOSDevice iosDevice = setUpIOSDevice(
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -244,7 +314,8 @@ IOSDevice setUpIOSDevice({ ...@@ -244,7 +314,8 @@ IOSDevice setUpIOSDevice({
); );
logger ??= BufferLogger.test(); logger ??= BufferLogger.test();
return IOSDevice('123', return IOSDevice(
'123',
name: 'iPhone 1', name: 'iPhone 1',
sdkVersion: sdkVersion, sdkVersion: sdkVersion,
fileSystem: fileSystem ?? MemoryFileSystem.test(), fileSystem: fileSystem ?? MemoryFileSystem.test(),
...@@ -270,12 +341,27 @@ IOSDevice setUpIOSDevice({ ...@@ -270,12 +341,27 @@ IOSDevice setUpIOSDevice({
} }
class FakeXcodeProjectInterpreter extends Fake implements XcodeProjectInterpreter { class FakeXcodeProjectInterpreter extends Fake implements XcodeProjectInterpreter {
FakeXcodeProjectInterpreter({
@required this.projectInfo,
this.buildSettings = const <String, String>{
'TARGET_BUILD_DIR': 'build/ios/Release-iphoneos',
'WRAPPER_NAME': 'My Super Awesome App.app',
'DEVELOPMENT_TEAM': '3333CCCC33',
},
});
final Map<String, String> buildSettings;
final XcodeProjectInfo projectInfo;
@override @override
final bool isInstalled = true; final bool isInstalled = true;
@override @override
final Version version = Version(1000, 0, 0); final Version version = Version(1000, 0, 0);
@override
String get versionText => version.toString();
@override @override
List<String> xcrunCommand() => <String>['xcrun']; List<String> xcrunCommand() => <String>['xcrun'];
...@@ -283,23 +369,12 @@ class FakeXcodeProjectInterpreter extends Fake implements XcodeProjectInterprete ...@@ -283,23 +369,12 @@ class FakeXcodeProjectInterpreter extends Fake implements XcodeProjectInterprete
Future<XcodeProjectInfo> getInfo( Future<XcodeProjectInfo> getInfo(
String projectPath, { String projectPath, {
String projectFilename, String projectFilename,
}) async => }) async => projectInfo;
XcodeProjectInfo(
<String>['Runner'],
<String>['Debug', 'Release'],
<String>['Runner'],
BufferLogger.test(),
);
@override @override
Future<Map<String, String>> getBuildSettings( Future<Map<String, String>> getBuildSettings(
String projectPath, { String projectPath, {
@required XcodeProjectBuildContext buildContext, @required XcodeProjectBuildContext buildContext,
Duration timeout = const Duration(minutes: 1), Duration timeout = const Duration(minutes: 1),
}) async => }) async => buildSettings;
<String, String>{
'TARGET_BUILD_DIR': 'build/ios/Release-iphoneos',
'WRAPPER_NAME': 'My Super Awesome App.app',
'DEVELOPMENT_TEAM': '3333CCCC33',
};
} }
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/artifacts.dart';
...@@ -23,15 +21,15 @@ import '../../src/fake_process_manager.dart'; ...@@ -23,15 +21,15 @@ import '../../src/fake_process_manager.dart';
import '../../src/fakes.dart'; import '../../src/fakes.dart';
void main() { void main() {
BufferLogger logger; late BufferLogger logger;
setUp(() { setUp(() {
logger = BufferLogger.test(); logger = BufferLogger.test();
}); });
group('IMobileDevice', () { group('IMobileDevice', () {
Artifacts artifacts; late Artifacts artifacts;
Cache cache; late Cache cache;
setUp(() { setUp(() {
artifacts = Artifacts.test(); artifacts = Artifacts.test();
...@@ -44,8 +42,8 @@ void main() { ...@@ -44,8 +42,8 @@ void main() {
}); });
group('screenshot', () { group('screenshot', () {
FakeProcessManager fakeProcessManager; late FakeProcessManager fakeProcessManager;
File outputFile; late File outputFile;
setUp(() { setUp(() {
fakeProcessManager = FakeProcessManager.empty(); fakeProcessManager = FakeProcessManager.empty();
...@@ -131,8 +129,8 @@ void main() { ...@@ -131,8 +129,8 @@ void main() {
}); });
group('Diagnose Xcode build failure', () { group('Diagnose Xcode build failure', () {
Map<String, String> buildSettings; late Map<String, String> buildSettings;
TestUsage testUsage; late TestUsage testUsage;
setUp(() { setUp(() {
buildSettings = <String, String>{ buildSettings = <String, String>{
...@@ -445,7 +443,7 @@ Exited (sigterm)''', ...@@ -445,7 +443,7 @@ Exited (sigterm)''',
}); });
group('remove Finder extended attributes', () { group('remove Finder extended attributes', () {
Directory projectDirectory; late Directory projectDirectory;
setUp(() { setUp(() {
final MemoryFileSystem fs = MemoryFileSystem.test(); final MemoryFileSystem fs = MemoryFileSystem.test();
projectDirectory = fs.directory('flutter_project'); projectDirectory = fs.directory('flutter_project');
...@@ -494,5 +492,5 @@ class FakeIosProject extends Fake implements IosProject { ...@@ -494,5 +492,5 @@ class FakeIosProject extends Fake implements IosProject {
Future<String> hostAppBundleName(BuildInfo buildInfo) async => 'UnitTestRunner.app'; Future<String> hostAppBundleName(BuildInfo buildInfo) async => 'UnitTestRunner.app';
@override @override
final Directory xcodeProject = null; Directory get xcodeProject => xcodeProjectInfoFile.fileSystem.directory('Runner.xcodeproj');
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment