Unverified Commit 515003e4 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Migrate xcode.dart and xcode_validator.dart to null safety (#80614)

parent 2c7309c7
...@@ -9,7 +9,7 @@ import 'package:meta/meta.dart'; ...@@ -9,7 +9,7 @@ import 'package:meta/meta.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/logger.dart'; import '../base/logger.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../globals.dart' as globals; import '../globals_null_migrated.dart' as globals;
import '../ios/xcodeproj.dart'; import '../ios/xcodeproj.dart';
import '../project.dart'; import '../project.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
......
...@@ -12,12 +12,10 @@ import 'device.dart'; ...@@ -12,12 +12,10 @@ import 'device.dart';
import 'doctor.dart'; import 'doctor.dart';
import 'fuchsia/fuchsia_sdk.dart'; import 'fuchsia/fuchsia_sdk.dart';
import 'globals_null_migrated.dart' as globals; import 'globals_null_migrated.dart' as globals;
import 'ios/ios_workflow.dart';
import 'ios/simulators.dart'; import 'ios/simulators.dart';
import 'macos/cocoapods.dart'; import 'macos/cocoapods.dart';
import 'macos/cocoapods_validator.dart'; import 'macos/cocoapods_validator.dart';
import 'macos/xcdevice.dart'; import 'macos/xcdevice.dart';
import 'macos/xcode.dart';
import 'project.dart'; import 'project.dart';
import 'reporting/crash_reporting.dart'; import 'reporting/crash_reporting.dart';
import 'runner/local_engine.dart'; import 'runner/local_engine.dart';
...@@ -44,8 +42,6 @@ LocalEngineLocator get localEngineLocator => context.get<LocalEngineLocator>(); ...@@ -44,8 +42,6 @@ LocalEngineLocator get localEngineLocator => context.get<LocalEngineLocator>();
CocoaPods get cocoaPods => context.get<CocoaPods>(); CocoaPods get cocoaPods => context.get<CocoaPods>();
FuchsiaArtifacts get fuchsiaArtifacts => context.get<FuchsiaArtifacts>(); FuchsiaArtifacts get fuchsiaArtifacts => context.get<FuchsiaArtifacts>();
IOSSimulatorUtils get iosSimulatorUtils => context.get<IOSSimulatorUtils>(); IOSSimulatorUtils get iosSimulatorUtils => context.get<IOSSimulatorUtils>();
IOSWorkflow get iosWorkflow => context.get<IOSWorkflow>();
Xcode get xcode => context.get<Xcode>();
XCDevice get xcdevice => context.get<XCDevice>(); XCDevice get xcdevice => context.get<XCDevice>();
......
...@@ -23,8 +23,10 @@ import 'base/terminal.dart'; ...@@ -23,8 +23,10 @@ import 'base/terminal.dart';
import 'base/time.dart'; import 'base/time.dart';
import 'base/user_messages.dart'; import 'base/user_messages.dart';
import 'cache.dart'; import 'cache.dart';
import 'ios/ios_workflow.dart';
import 'ios/plist_parser.dart'; import 'ios/plist_parser.dart';
import 'ios/xcodeproj.dart'; import 'ios/xcodeproj.dart';
import 'macos/xcode.dart';
import 'persistent_tool_state.dart'; import 'persistent_tool_state.dart';
import 'reporting/reporting.dart'; import 'reporting/reporting.dart';
import 'version.dart'; import 'version.dart';
...@@ -40,6 +42,8 @@ AndroidSdk? get androidSdk => context.get<AndroidSdk>(); ...@@ -40,6 +42,8 @@ AndroidSdk? get androidSdk => context.get<AndroidSdk>();
FlutterVersion get flutterVersion => context.get<FlutterVersion>()!; FlutterVersion get flutterVersion => context.get<FlutterVersion>()!;
Usage get flutterUsage => context.get<Usage>()!; Usage get flutterUsage => context.get<Usage>()!;
XcodeProjectInterpreter? get xcodeProjectInterpreter => context.get<XcodeProjectInterpreter>(); XcodeProjectInterpreter? get xcodeProjectInterpreter => context.get<XcodeProjectInterpreter>();
Xcode? get xcode => context.get<Xcode>();
IOSWorkflow? get iosWorkflow => context.get<IOSWorkflow>();
PersistentToolState? get persistentToolState => PersistentToolState.instance; PersistentToolState? get persistentToolState => PersistentToolState.instance;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
import '../base/process.dart'; import '../base/process.dart';
import '../device.dart'; import '../device.dart';
import '../emulator.dart'; import '../emulator.dart';
import '../globals.dart' as globals; import '../globals_null_migrated.dart' as globals;
import 'simulators.dart'; import 'simulators.dart';
class IOSEmulators extends EmulatorDiscovery { class IOSEmulators extends EmulatorDiscovery {
......
...@@ -2,10 +2,6 @@ ...@@ -2,10 +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 '../base/platform.dart'; import '../base/platform.dart';
import '../doctor_validator.dart'; import '../doctor_validator.dart';
import '../features.dart'; import '../features.dart';
...@@ -13,9 +9,9 @@ import '../macos/xcode.dart'; ...@@ -13,9 +9,9 @@ import '../macos/xcode.dart';
class IOSWorkflow implements Workflow { class IOSWorkflow implements Workflow {
const IOSWorkflow({ const IOSWorkflow({
@required Platform platform, required Platform platform,
@required FeatureFlags featureFlags, required FeatureFlags featureFlags,
@required Xcode xcode, required Xcode xcode,
}) : _platform = platform, }) : _platform = platform,
_featureFlags = featureFlags, _featureFlags = featureFlags,
_xcode = xcode; _xcode = xcode;
......
...@@ -18,7 +18,7 @@ import '../base/utils.dart'; ...@@ -18,7 +18,7 @@ import '../base/utils.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../cache.dart'; import '../cache.dart';
import '../flutter_manifest.dart'; import '../flutter_manifest.dart';
import '../globals.dart' as globals; import '../globals_null_migrated.dart' as globals;
import '../macos/cocoapod_utils.dart'; import '../macos/cocoapod_utils.dart';
import '../macos/xcode.dart'; import '../macos/xcode.dart';
import '../project.dart'; import '../project.dart';
......
...@@ -22,7 +22,7 @@ import '../convert.dart'; ...@@ -22,7 +22,7 @@ import '../convert.dart';
import '../devfs.dart'; import '../devfs.dart';
import '../device.dart'; import '../device.dart';
import '../device_port_forwarder.dart'; import '../device_port_forwarder.dart';
import '../globals.dart' as globals; import '../globals_null_migrated.dart' as globals;
import '../macos/xcode.dart'; import '../macos/xcode.dart';
import '../project.dart'; import '../project.dart';
import '../protocol_discovery.dart'; import '../protocol_discovery.dart';
......
...@@ -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 'dart:async'; import 'dart:async';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
...@@ -41,11 +39,11 @@ String getSDKNameForIOSEnvironmentType(EnvironmentType environmentType) { ...@@ -41,11 +39,11 @@ String getSDKNameForIOSEnvironmentType(EnvironmentType environmentType) {
/// A utility class for interacting with Xcode command line tools. /// A utility class for interacting with Xcode command line tools.
class Xcode { class Xcode {
Xcode({ Xcode({
@required Platform platform, required Platform platform,
@required ProcessManager processManager, required ProcessManager processManager,
@required Logger logger, required Logger logger,
@required FileSystem fileSystem, required FileSystem fileSystem,
@required XcodeProjectInterpreter xcodeProjectInterpreter, required XcodeProjectInterpreter xcodeProjectInterpreter,
}) : _platform = platform, }) : _platform = platform,
_fileSystem = fileSystem, _fileSystem = fileSystem,
_xcodeProjectInterpreter = xcodeProjectInterpreter, _xcodeProjectInterpreter = xcodeProjectInterpreter,
...@@ -58,10 +56,10 @@ class Xcode { ...@@ -58,10 +56,10 @@ class Xcode {
/// buffer logger, and test [XcodeProjectInterpreter]. /// buffer logger, and test [XcodeProjectInterpreter].
@visibleForTesting @visibleForTesting
factory Xcode.test({ factory Xcode.test({
@required ProcessManager processManager, required ProcessManager processManager,
XcodeProjectInterpreter xcodeProjectInterpreter, XcodeProjectInterpreter? xcodeProjectInterpreter,
Platform platform, Platform? platform,
FileSystem fileSystem, FileSystem? fileSystem,
}) { }) {
platform ??= FakePlatform( platform ??= FakePlatform(
operatingSystem: 'macos', operatingSystem: 'macos',
...@@ -83,8 +81,8 @@ class Xcode { ...@@ -83,8 +81,8 @@ class Xcode {
bool get isInstalledAndMeetsVersionCheck => _platform.isMacOS && isInstalled && isRequiredVersionSatisfactory; bool get isInstalledAndMeetsVersionCheck => _platform.isMacOS && isInstalled && isRequiredVersionSatisfactory;
String _xcodeSelectPath; String? _xcodeSelectPath;
String get xcodeSelectPath { String? get xcodeSelectPath {
if (_xcodeSelectPath == null) { if (_xcodeSelectPath == null) {
try { try {
_xcodeSelectPath = _processUtils.runSync( _xcodeSelectPath = _processUtils.runSync(
...@@ -101,11 +99,11 @@ class Xcode { ...@@ -101,11 +99,11 @@ class Xcode {
bool get isInstalled => _xcodeProjectInterpreter.isInstalled; bool get isInstalled => _xcodeProjectInterpreter.isInstalled;
Version get currentVersion => _xcodeProjectInterpreter.version; Version? get currentVersion => _xcodeProjectInterpreter.version;
String get versionText => _xcodeProjectInterpreter.versionText; String? get versionText => _xcodeProjectInterpreter.versionText;
bool _eulaSigned; bool? _eulaSigned;
/// Has the EULA been signed? /// Has the EULA been signed?
bool get eulaSigned { bool get eulaSigned {
if (_eulaSigned == null) { if (_eulaSigned == null) {
...@@ -124,10 +122,10 @@ class Xcode { ...@@ -124,10 +122,10 @@ class Xcode {
_eulaSigned = false; _eulaSigned = false;
} }
} }
return _eulaSigned; return _eulaSigned ?? false;
} }
bool _isSimctlInstalled; bool? _isSimctlInstalled;
/// Verifies that simctl is installed by trying to run it. /// Verifies that simctl is installed by trying to run it.
bool get isSimctlInstalled { bool get isSimctlInstalled {
...@@ -143,21 +141,23 @@ class Xcode { ...@@ -143,21 +141,23 @@ class Xcode {
_isSimctlInstalled = false; _isSimctlInstalled = false;
} }
} }
return _isSimctlInstalled; return _isSimctlInstalled ?? false;
} }
bool get isRequiredVersionSatisfactory { bool get isRequiredVersionSatisfactory {
if (!_xcodeProjectInterpreter.isInstalled) { final Version? version = currentVersion;
if (version == null) {
return false; return false;
} }
return currentVersion >= xcodeRequiredVersion; return version >= xcodeRequiredVersion;
} }
bool get isRecommendedVersionSatisfactory { bool get isRecommendedVersionSatisfactory {
if (!_xcodeProjectInterpreter.isInstalled) { final Version? version = currentVersion;
if (version == null) {
return false; return false;
} }
return currentVersion >= xcodeRecommendedVersion; return version >= xcodeRecommendedVersion;
} }
/// See [XcodeProjectInterpreter.xcrunCommand]. /// See [XcodeProjectInterpreter.xcrunCommand].
...@@ -188,21 +188,17 @@ class Xcode { ...@@ -188,21 +188,17 @@ class Xcode {
return runResult.stdout.trim(); return runResult.stdout.trim();
} }
String getSimulatorPath() { String? getSimulatorPath() {
if (xcodeSelectPath == null) { final String? selectPath = xcodeSelectPath;
if (selectPath == null) {
return null; return null;
} }
final List<String> searchPaths = <String>[ final String appPath = _fileSystem.path.join(selectPath, 'Applications', 'Simulator.app');
_fileSystem.path.join(xcodeSelectPath, 'Applications', 'Simulator.app'), return _fileSystem.directory(appPath).existsSync() ? appPath : null;
];
return searchPaths.where((String p) => p != null).firstWhere(
(String p) => _fileSystem.directory(p).existsSync(),
orElse: () => null,
);
} }
} }
EnvironmentType environmentTypeFromSdkroot(Directory sdkroot) { EnvironmentType? environmentTypeFromSdkroot(Directory sdkroot) {
assert(sdkroot != null); assert(sdkroot != null);
// iPhoneSimulator.sdk or iPhoneOS.sdk // iPhoneSimulator.sdk or iPhoneOS.sdk
final String sdkName = sdkroot.basename.toLowerCase(); final String sdkName = sdkroot.basename.toLowerCase();
......
...@@ -2,18 +2,14 @@ ...@@ -2,18 +2,14 @@
// 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 '../base/user_messages.dart'; import '../base/user_messages.dart';
import '../doctor_validator.dart'; import '../doctor_validator.dart';
import 'xcode.dart'; import 'xcode.dart';
class XcodeValidator extends DoctorValidator { class XcodeValidator extends DoctorValidator {
XcodeValidator({ XcodeValidator({
@required Xcode xcode, required Xcode xcode,
@required UserMessages userMessages, required UserMessages userMessages,
}) : _xcode = xcode, }) : _xcode = xcode,
_userMessages = userMessages, _userMessages = userMessages,
super('Xcode - develop for iOS and macOS'); super('Xcode - develop for iOS and macOS');
...@@ -25,13 +21,19 @@ class XcodeValidator extends DoctorValidator { ...@@ -25,13 +21,19 @@ class XcodeValidator extends DoctorValidator {
Future<ValidationResult> validate() async { Future<ValidationResult> validate() async {
final List<ValidationMessage> messages = <ValidationMessage>[]; final List<ValidationMessage> messages = <ValidationMessage>[];
ValidationType xcodeStatus = ValidationType.missing; ValidationType xcodeStatus = ValidationType.missing;
String xcodeVersionInfo; String? xcodeVersionInfo;
final String? xcodeSelectPath = _xcode.xcodeSelectPath;
if (_xcode.isInstalled) { if (_xcode.isInstalled) {
xcodeStatus = ValidationType.installed; xcodeStatus = ValidationType.installed;
if (xcodeSelectPath != null) {
messages.add(ValidationMessage(_userMessages.xcodeLocation(_xcode.xcodeSelectPath))); messages.add(ValidationMessage(_userMessages.xcodeLocation(xcodeSelectPath)));
messages.add(ValidationMessage(_xcode.versionText)); }
final String? versionText = _xcode.versionText;
if (versionText != null) {
messages.add(ValidationMessage(versionText));
}
if (!_xcode.isInstalledAndMeetsVersionCheck) { if (!_xcode.isInstalledAndMeetsVersionCheck) {
xcodeStatus = ValidationType.partial; xcodeStatus = ValidationType.partial;
...@@ -58,7 +60,7 @@ class XcodeValidator extends DoctorValidator { ...@@ -58,7 +60,7 @@ class XcodeValidator extends DoctorValidator {
} else { } else {
xcodeStatus = ValidationType.missing; xcodeStatus = ValidationType.missing;
if (_xcode.xcodeSelectPath == null || _xcode.xcodeSelectPath.isEmpty) { if (xcodeSelectPath == null || xcodeSelectPath.isEmpty) {
messages.add(ValidationMessage.error(_userMessages.xcodeMissing)); messages.add(ValidationMessage.error(_userMessages.xcodeMissing));
} else { } else {
messages.add(ValidationMessage.error(_userMessages.xcodeIncomplete)); messages.add(ValidationMessage.error(_userMessages.xcodeIncomplete));
......
...@@ -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:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/version.dart'; import 'package:flutter_tools/src/base/version.dart';
import 'package:flutter_tools/src/ios/ios_workflow.dart'; import 'package:flutter_tools/src/ios/ios_workflow.dart';
......
...@@ -2,52 +2,55 @@ ...@@ -2,52 +2,55 @@
// 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:flutter_tools/src/base/user_messages.dart'; import 'package:flutter_tools/src/base/user_messages.dart';
import 'package:flutter_tools/src/base/version.dart'; import 'package:flutter_tools/src/base/version.dart';
import 'package:flutter_tools/src/doctor_validator.dart'; import 'package:flutter_tools/src/doctor_validator.dart';
import 'package:flutter_tools/src/ios/xcodeproj.dart';
import 'package:flutter_tools/src/macos/xcode.dart'; import 'package:flutter_tools/src/macos/xcode.dart';
import 'package:flutter_tools/src/macos/xcode_validator.dart'; import 'package:flutter_tools/src/macos/xcode_validator.dart';
import 'package:mockito/mockito.dart';
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/fake_process_manager.dart';
class MockXcode extends Mock implements Xcode {}
void main() { void main() {
group('Xcode validation', () { group('Xcode validation', () {
MockXcode xcode;
setUp(() {
xcode = MockXcode();
});
testWithoutContext('Emits missing status when Xcode is not installed', () async { testWithoutContext('Emits missing status when Xcode is not installed', () async {
when(xcode.isInstalled).thenReturn(false); final ProcessManager processManager = FakeProcessManager.any();
when(xcode.xcodeSelectPath).thenReturn(null); final Xcode xcode = Xcode.test(
processManager: processManager,
xcodeProjectInterpreter: XcodeProjectInterpreter.test(processManager: processManager, version: null),
);
final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages()); final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages());
final ValidationResult result = await validator.validate(); final ValidationResult result = await validator.validate();
expect(result.type, ValidationType.missing); expect(result.type, ValidationType.missing);
expect(result.messages.last.type, ValidationMessageType.error);
expect(result.messages.last.message, contains('Xcode not installed'));
}); });
testWithoutContext('Emits missing status when Xcode installation is incomplete', () async { testWithoutContext('Emits missing status when Xcode installation is incomplete', () async {
when(xcode.isInstalled).thenReturn(false); final ProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
when(xcode.xcodeSelectPath).thenReturn('/Library/Developer/CommandLineTools'); const FakeCommand(
command: <String>['/usr/bin/xcode-select', '--print-path'],
stdout: '/Library/Developer/CommandLineTools',
),
]);
final Xcode xcode = Xcode.test(
processManager: processManager,
xcodeProjectInterpreter: XcodeProjectInterpreter.test(processManager: processManager, version: null),
);
final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages()); final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages());
final ValidationResult result = await validator.validate(); final ValidationResult result = await validator.validate();
expect(result.type, ValidationType.missing); expect(result.type, ValidationType.missing);
expect(result.messages.last.type, ValidationMessageType.error);
expect(result.messages.last.message, contains('Xcode installation is incomplete'));
}); });
testWithoutContext('Emits partial status when Xcode version too low', () async { testWithoutContext('Emits partial status when Xcode version too low', () async {
when(xcode.isInstalled).thenReturn(true); final ProcessManager processManager = FakeProcessManager.any();
when(xcode.versionText) final Xcode xcode = Xcode.test(
.thenReturn('Xcode 7.0.1\nBuild version 7C1002\n'); processManager: processManager,
when(xcode.currentVersion).thenReturn(Version(7, 0, 1)); xcodeProjectInterpreter: XcodeProjectInterpreter.test(processManager: processManager, version: Version(7, 0, 1)),
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(false); );
when(xcode.isRecommendedVersionSatisfactory).thenReturn(false);
when(xcode.eulaSigned).thenReturn(true);
when(xcode.isSimctlInstalled).thenReturn(true);
final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages()); final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages());
final ValidationResult result = await validator.validate(); final ValidationResult result = await validator.validate();
expect(result.type, ValidationType.partial); expect(result.type, ValidationType.partial);
...@@ -56,14 +59,11 @@ void main() { ...@@ -56,14 +59,11 @@ void main() {
}); });
testWithoutContext('Emits partial status when Xcode below recommended version', () async { testWithoutContext('Emits partial status when Xcode below recommended version', () async {
when(xcode.isInstalled).thenReturn(true); final ProcessManager processManager = FakeProcessManager.any();
when(xcode.versionText) final Xcode xcode = Xcode.test(
.thenReturn('Xcode 11.0\nBuild version 11A420a\n'); processManager: processManager,
when(xcode.currentVersion).thenReturn(Version(11, 0, 0)); xcodeProjectInterpreter: XcodeProjectInterpreter.test(processManager: processManager, version: Version(11, 0, 0)),
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true); );
when(xcode.isRecommendedVersionSatisfactory).thenReturn(false);
when(xcode.eulaSigned).thenReturn(true);
when(xcode.isSimctlInstalled).thenReturn(true);
final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages()); final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages());
final ValidationResult result = await validator.validate(); final ValidationResult result = await validator.validate();
expect(result.type, ValidationType.partial); expect(result.type, ValidationType.partial);
...@@ -72,40 +72,113 @@ void main() { ...@@ -72,40 +72,113 @@ void main() {
}, skip: true); // Unskip and update when minimum and required check versions diverge. }, skip: true); // Unskip and update when minimum and required check versions diverge.
testWithoutContext('Emits partial status when Xcode EULA not signed', () async { testWithoutContext('Emits partial status when Xcode EULA not signed', () async {
when(xcode.isInstalled).thenReturn(true); final ProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
when(xcode.versionText) const FakeCommand(
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n'); command: <String>['/usr/bin/xcode-select', '--print-path'],
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true); stdout: '/Library/Developer/CommandLineTools',
when(xcode.isRecommendedVersionSatisfactory).thenReturn(true); ),
when(xcode.eulaSigned).thenReturn(false); const FakeCommand(
when(xcode.isSimctlInstalled).thenReturn(true); command: <String>[
'which',
'sysctl',
],
),
const FakeCommand(
command: <String>[
'sysctl',
'hw.optional.arm64',
],
exitCode: 1,
),
const FakeCommand(
command: <String>['xcrun', 'clang'],
exitCode: 1,
stderr:
'Xcode EULA has not been accepted.\nLaunch Xcode and accept the license.',
),
const FakeCommand(
command: <String>['xcrun', 'simctl', 'list'],
),
]);
final Xcode xcode = Xcode.test(
processManager: processManager,
xcodeProjectInterpreter: XcodeProjectInterpreter.test(processManager: processManager),
);
final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages()); final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages());
final ValidationResult result = await validator.validate(); final ValidationResult result = await validator.validate();
expect(result.type, ValidationType.partial); expect(result.type, ValidationType.partial);
expect(result.messages.last.type, ValidationMessageType.error);
expect(result.messages.last.message, contains('code end user license agreement not signed'));
}); });
testWithoutContext('Emits partial status when simctl is not installed', () async { testWithoutContext('Emits partial status when simctl is not installed', () async {
when(xcode.isInstalled).thenReturn(true); final ProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
when(xcode.versionText) const FakeCommand(
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n'); command: <String>['/usr/bin/xcode-select', '--print-path'],
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true); stdout: '/Library/Developer/CommandLineTools',
when(xcode.isRecommendedVersionSatisfactory).thenReturn(true); ),
when(xcode.eulaSigned).thenReturn(true); const FakeCommand(
when(xcode.isSimctlInstalled).thenReturn(false); command: <String>[
'which',
'sysctl',
],
),
const FakeCommand(
command: <String>[
'sysctl',
'hw.optional.arm64',
],
exitCode: 1,
),
const FakeCommand(
command: <String>['xcrun', 'clang'],
),
const FakeCommand(
command: <String>['xcrun', 'simctl', 'list'],
exitCode: 1,
),
]);
final Xcode xcode = Xcode.test(
processManager: processManager,
xcodeProjectInterpreter: XcodeProjectInterpreter.test(processManager: processManager),
);
final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages()); final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages());
final ValidationResult result = await validator.validate(); final ValidationResult result = await validator.validate();
expect(result.type, ValidationType.partial); expect(result.type, ValidationType.partial);
expect(result.messages.last.type, ValidationMessageType.error);
expect(result.messages.last.message, contains('Xcode requires additional components'));
}); });
testWithoutContext('Succeeds when all checks pass', () async { testWithoutContext('Succeeds when all checks pass', () async {
when(xcode.isInstalled).thenReturn(true); final ProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
when(xcode.versionText) const FakeCommand(
.thenReturn('Xcode 8.2.1\nBuild version 8C1002\n'); command: <String>['/usr/bin/xcode-select', '--print-path'],
when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true); stdout: '/Library/Developer/CommandLineTools',
when(xcode.isRecommendedVersionSatisfactory).thenReturn(true); ),
when(xcode.eulaSigned).thenReturn(true); const FakeCommand(
when(xcode.isSimctlInstalled).thenReturn(true); command: <String>[
'which',
'sysctl',
],
),
const FakeCommand(
command: <String>[
'sysctl',
'hw.optional.arm64',
],
exitCode: 1,
),
const FakeCommand(
command: <String>['xcrun', 'clang'],
),
const FakeCommand(
command: <String>['xcrun', 'simctl', 'list'],
),
]);
final Xcode xcode = Xcode.test(
processManager: processManager,
xcodeProjectInterpreter: XcodeProjectInterpreter.test(processManager: processManager),
);
final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages()); final XcodeValidator validator = XcodeValidator(xcode: xcode, userMessages: UserMessages());
final ValidationResult result = await validator.validate(); final ValidationResult result = await validator.validate();
expect(result.type, ValidationType.installed); expect(result.type, ValidationType.installed);
......
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