mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
[flutter_tools] Remove context from Xcode and most of Xcodeproj (#48661)
This commit is contained in:
parent
7cf2ff1f1e
commit
ef15eac821
@ -145,8 +145,20 @@ Future<T> runInContext<T>(
|
|||||||
VisualStudioValidator: () => const VisualStudioValidator(),
|
VisualStudioValidator: () => const VisualStudioValidator(),
|
||||||
WebWorkflow: () => const WebWorkflow(),
|
WebWorkflow: () => const WebWorkflow(),
|
||||||
WindowsWorkflow: () => const WindowsWorkflow(),
|
WindowsWorkflow: () => const WindowsWorkflow(),
|
||||||
Xcode: () => Xcode(),
|
Xcode: () => Xcode(
|
||||||
XcodeProjectInterpreter: () => XcodeProjectInterpreter(),
|
logger: globals.logger,
|
||||||
|
processManager: globals.processManager,
|
||||||
|
platform: globals.platform,
|
||||||
|
fileSystem: globals.fs,
|
||||||
|
xcodeProjectInterpreter: xcodeProjectInterpreter,
|
||||||
|
),
|
||||||
|
XcodeProjectInterpreter: () => XcodeProjectInterpreter(
|
||||||
|
logger: globals.logger,
|
||||||
|
processManager: globals.processManager,
|
||||||
|
platform: globals.platform,
|
||||||
|
fileSystem: globals.fs,
|
||||||
|
terminal: globals.terminal,
|
||||||
|
),
|
||||||
XcodeValidator: () => const XcodeValidator(),
|
XcodeValidator: () => const XcodeValidator(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -458,7 +458,7 @@ Future<XcodeBuildResult> buildXcodeProject({
|
|||||||
// e.g. `flutter build bundle`.
|
// e.g. `flutter build bundle`.
|
||||||
buildCommands.add('FLUTTER_SUPPRESS_ANALYTICS=true');
|
buildCommands.add('FLUTTER_SUPPRESS_ANALYTICS=true');
|
||||||
buildCommands.add('COMPILER_INDEX_STORE_ENABLE=NO');
|
buildCommands.add('COMPILER_INDEX_STORE_ENABLE=NO');
|
||||||
buildCommands.addAll(environmentVariablesAsXcodeBuildSettings());
|
buildCommands.addAll(environmentVariablesAsXcodeBuildSettings(globals.platform));
|
||||||
|
|
||||||
final Stopwatch sw = Stopwatch()..start();
|
final Stopwatch sw = Stopwatch()..start();
|
||||||
initialBuildStatus = globals.logger.startProgress('Running Xcode build...', timeout: timeoutConfiguration.fastOperation);
|
initialBuildStatus = globals.logger.startProgress('Running Xcode build...', timeout: timeoutConfiguration.fastOperation);
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
import 'package:platform/platform.dart';
|
||||||
|
import 'package:process/process.dart';
|
||||||
|
|
||||||
import '../artifacts.dart';
|
import '../artifacts.dart';
|
||||||
import '../base/common.dart';
|
import '../base/common.dart';
|
||||||
@ -14,6 +16,7 @@ import '../base/io.dart';
|
|||||||
import '../base/logger.dart';
|
import '../base/logger.dart';
|
||||||
import '../base/os.dart';
|
import '../base/os.dart';
|
||||||
import '../base/process.dart';
|
import '../base/process.dart';
|
||||||
|
import '../base/terminal.dart';
|
||||||
import '../base/utils.dart';
|
import '../base/utils.dart';
|
||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../cache.dart';
|
import '../cache.dart';
|
||||||
@ -221,15 +224,33 @@ XcodeProjectInterpreter get xcodeProjectInterpreter => context.get<XcodeProjectI
|
|||||||
|
|
||||||
/// Interpreter of Xcode projects.
|
/// Interpreter of Xcode projects.
|
||||||
class XcodeProjectInterpreter {
|
class XcodeProjectInterpreter {
|
||||||
|
XcodeProjectInterpreter({
|
||||||
|
@required Platform platform,
|
||||||
|
@required ProcessManager processManager,
|
||||||
|
@required Logger logger,
|
||||||
|
@required FileSystem fileSystem,
|
||||||
|
@required AnsiTerminal terminal,
|
||||||
|
}) : _platform = platform,
|
||||||
|
_fileSystem = fileSystem,
|
||||||
|
_terminal = terminal,
|
||||||
|
_logger = logger,
|
||||||
|
_processUtils = ProcessUtils(logger: logger, processManager: processManager);
|
||||||
|
|
||||||
|
final Platform _platform;
|
||||||
|
final FileSystem _fileSystem;
|
||||||
|
final ProcessUtils _processUtils;
|
||||||
|
final AnsiTerminal _terminal;
|
||||||
|
final Logger _logger;
|
||||||
|
|
||||||
static const String _executable = '/usr/bin/xcodebuild';
|
static const String _executable = '/usr/bin/xcodebuild';
|
||||||
static final RegExp _versionRegex = RegExp(r'Xcode ([0-9.]+)');
|
static final RegExp _versionRegex = RegExp(r'Xcode ([0-9.]+)');
|
||||||
|
|
||||||
void _updateVersion() {
|
void _updateVersion() {
|
||||||
if (!globals.platform.isMacOS || !globals.fs.file(_executable).existsSync()) {
|
if (!_platform.isMacOS || !_fileSystem.file(_executable).existsSync()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
final RunResult result = processUtils.runSync(
|
final RunResult result = _processUtils.runSync(
|
||||||
<String>[_executable, '-version'],
|
<String>[_executable, '-version'],
|
||||||
);
|
);
|
||||||
if (result.exitCode != 0) {
|
if (result.exitCode != 0) {
|
||||||
@ -283,26 +304,26 @@ class XcodeProjectInterpreter {
|
|||||||
Duration timeout = const Duration(minutes: 1),
|
Duration timeout = const Duration(minutes: 1),
|
||||||
}) async {
|
}) async {
|
||||||
final Status status = Status.withSpinner(
|
final Status status = Status.withSpinner(
|
||||||
timeout: timeoutConfiguration.fastOperation,
|
timeout: const TimeoutConfiguration().fastOperation,
|
||||||
timeoutConfiguration: timeoutConfiguration,
|
timeoutConfiguration: const TimeoutConfiguration(),
|
||||||
platform: globals.platform,
|
platform: _platform,
|
||||||
stopwatch: Stopwatch(),
|
stopwatch: Stopwatch(),
|
||||||
supportsColor: globals.terminal.supportsColor,
|
supportsColor: _terminal.supportsColor,
|
||||||
);
|
);
|
||||||
final List<String> showBuildSettingsCommand = <String>[
|
final List<String> showBuildSettingsCommand = <String>[
|
||||||
_executable,
|
_executable,
|
||||||
'-project',
|
'-project',
|
||||||
globals.fs.path.absolute(projectPath),
|
_fileSystem.path.absolute(projectPath),
|
||||||
'-target',
|
'-target',
|
||||||
target,
|
target,
|
||||||
'-showBuildSettings',
|
'-showBuildSettings',
|
||||||
...environmentVariablesAsXcodeBuildSettings()
|
...environmentVariablesAsXcodeBuildSettings(_platform)
|
||||||
];
|
];
|
||||||
try {
|
try {
|
||||||
// showBuildSettings is reported to occasionally timeout. Here, we give it
|
// showBuildSettings is reported to occasionally timeout. Here, we give it
|
||||||
// a lot of wiggle room (locally on Flutter Gallery, this takes ~1s).
|
// a lot of wiggle room (locally on Flutter Gallery, this takes ~1s).
|
||||||
// When there is a timeout, we retry once.
|
// When there is a timeout, we retry once.
|
||||||
final RunResult result = await processUtils.run(
|
final RunResult result = await _processUtils.run(
|
||||||
showBuildSettingsCommand,
|
showBuildSettingsCommand,
|
||||||
throwOnError: true,
|
throwOnError: true,
|
||||||
workingDirectory: projectPath,
|
workingDirectory: projectPath,
|
||||||
@ -317,7 +338,7 @@ class XcodeProjectInterpreter {
|
|||||||
command: showBuildSettingsCommand.join(' '),
|
command: showBuildSettingsCommand.join(' '),
|
||||||
).send();
|
).send();
|
||||||
}
|
}
|
||||||
globals.printTrace('Unexpected failure to get the build settings: $error.');
|
_logger.printTrace('Unexpected failure to get the build settings: $error.');
|
||||||
return const <String, String>{};
|
return const <String, String>{};
|
||||||
} finally {
|
} finally {
|
||||||
status.stop();
|
status.stop();
|
||||||
@ -325,7 +346,7 @@ class XcodeProjectInterpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cleanWorkspace(String workspacePath, String scheme) {
|
void cleanWorkspace(String workspacePath, String scheme) {
|
||||||
processUtils.runSync(<String>[
|
_processUtils.runSync(<String>[
|
||||||
_executable,
|
_executable,
|
||||||
'-workspace',
|
'-workspace',
|
||||||
workspacePath,
|
workspacePath,
|
||||||
@ -333,8 +354,8 @@ class XcodeProjectInterpreter {
|
|||||||
scheme,
|
scheme,
|
||||||
'-quiet',
|
'-quiet',
|
||||||
'clean',
|
'clean',
|
||||||
...environmentVariablesAsXcodeBuildSettings()
|
...environmentVariablesAsXcodeBuildSettings(_platform)
|
||||||
], workingDirectory: globals.fs.currentDirectory.path);
|
], workingDirectory: _fileSystem.currentDirectory.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<XcodeProjectInfo> getInfo(String projectPath, {String projectFilename}) async {
|
Future<XcodeProjectInfo> getInfo(String projectPath, {String projectFilename}) async {
|
||||||
@ -342,7 +363,7 @@ class XcodeProjectInterpreter {
|
|||||||
// * -project is passed and the given project isn't there, or
|
// * -project is passed and the given project isn't there, or
|
||||||
// * no -project is passed and there isn't a project.
|
// * no -project is passed and there isn't a project.
|
||||||
const int missingProjectExitCode = 66;
|
const int missingProjectExitCode = 66;
|
||||||
final RunResult result = await processUtils.run(
|
final RunResult result = await _processUtils.run(
|
||||||
<String>[
|
<String>[
|
||||||
_executable,
|
_executable,
|
||||||
'-list',
|
'-list',
|
||||||
@ -363,9 +384,9 @@ class XcodeProjectInterpreter {
|
|||||||
/// This allows developers to pass arbitrary build settings in without the tool needing to make a flag
|
/// This allows developers to pass arbitrary build settings in without the tool needing to make a flag
|
||||||
/// for or be aware of each one. This could be used to set code signing build settings in a CI
|
/// for or be aware of each one. This could be used to set code signing build settings in a CI
|
||||||
/// environment without requiring settings changes in the Xcode project.
|
/// environment without requiring settings changes in the Xcode project.
|
||||||
List<String> environmentVariablesAsXcodeBuildSettings() {
|
List<String> environmentVariablesAsXcodeBuildSettings(Platform platform) {
|
||||||
const String xcodeBuildSettingPrefix = 'FLUTTER_XCODE_';
|
const String xcodeBuildSettingPrefix = 'FLUTTER_XCODE_';
|
||||||
return globals.platform.environment.entries.where((MapEntry<String, String> mapEntry) {
|
return platform.environment.entries.where((MapEntry<String, String> mapEntry) {
|
||||||
return mapEntry.key.startsWith(xcodeBuildSettingPrefix);
|
return mapEntry.key.startsWith(xcodeBuildSettingPrefix);
|
||||||
}).expand<String>((MapEntry<String, String> mapEntry) {
|
}).expand<String>((MapEntry<String, String> mapEntry) {
|
||||||
// Remove FLUTTER_XCODE_ prefix from the environment variable to get the build setting.
|
// Remove FLUTTER_XCODE_ prefix from the environment variable to get the build setting.
|
||||||
|
@ -85,7 +85,7 @@ Future<void> buildMacOS({
|
|||||||
'OBJROOT=${globals.fs.path.join(flutterBuildDir.absolute.path, 'Build', 'Intermediates.noindex')}',
|
'OBJROOT=${globals.fs.path.join(flutterBuildDir.absolute.path, 'Build', 'Intermediates.noindex')}',
|
||||||
'SYMROOT=${globals.fs.path.join(flutterBuildDir.absolute.path, 'Build', 'Products')}',
|
'SYMROOT=${globals.fs.path.join(flutterBuildDir.absolute.path, 'Build', 'Products')}',
|
||||||
'COMPILER_INDEX_STORE_ENABLE=NO',
|
'COMPILER_INDEX_STORE_ENABLE=NO',
|
||||||
...environmentVariablesAsXcodeBuildSettings()
|
...environmentVariablesAsXcodeBuildSettings(globals.platform)
|
||||||
], trace: true);
|
], trace: true);
|
||||||
} finally {
|
} finally {
|
||||||
status.cancel();
|
status.cancel();
|
||||||
|
@ -4,11 +4,16 @@
|
|||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
|
import 'package:platform/platform.dart';
|
||||||
|
import 'package:process/process.dart';
|
||||||
|
|
||||||
import '../base/common.dart';
|
import '../base/common.dart';
|
||||||
import '../base/context.dart';
|
import '../base/context.dart';
|
||||||
|
import '../base/file_system.dart';
|
||||||
import '../base/io.dart';
|
import '../base/io.dart';
|
||||||
|
import '../base/logger.dart';
|
||||||
import '../base/process.dart';
|
import '../base/process.dart';
|
||||||
import '../globals.dart' as globals;
|
|
||||||
import '../ios/xcodeproj.dart';
|
import '../ios/xcodeproj.dart';
|
||||||
|
|
||||||
const int kXcodeRequiredVersionMajor = 10;
|
const int kXcodeRequiredVersionMajor = 10;
|
||||||
@ -41,14 +46,31 @@ String getNameForSdk(SdkType sdk) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A utility class for interacting with Xcode command line tools.
|
||||||
class Xcode {
|
class Xcode {
|
||||||
bool get isInstalledAndMeetsVersionCheck => globals.platform.isMacOS && isInstalled && isVersionSatisfactory;
|
Xcode({
|
||||||
|
@required Platform platform,
|
||||||
|
@required ProcessManager processManager,
|
||||||
|
@required Logger logger,
|
||||||
|
@required FileSystem fileSystem,
|
||||||
|
@required XcodeProjectInterpreter xcodeProjectInterpreter,
|
||||||
|
}) : _platform = platform,
|
||||||
|
_fileSystem = fileSystem,
|
||||||
|
_xcodeProjectInterpreter = xcodeProjectInterpreter,
|
||||||
|
_processUtils = ProcessUtils(logger: logger, processManager: processManager);
|
||||||
|
|
||||||
|
final Platform _platform;
|
||||||
|
final ProcessUtils _processUtils;
|
||||||
|
final FileSystem _fileSystem;
|
||||||
|
final XcodeProjectInterpreter _xcodeProjectInterpreter;
|
||||||
|
|
||||||
|
bool get isInstalledAndMeetsVersionCheck => _platform.isMacOS && isInstalled && isVersionSatisfactory;
|
||||||
|
|
||||||
String _xcodeSelectPath;
|
String _xcodeSelectPath;
|
||||||
String get xcodeSelectPath {
|
String get xcodeSelectPath {
|
||||||
if (_xcodeSelectPath == null) {
|
if (_xcodeSelectPath == null) {
|
||||||
try {
|
try {
|
||||||
_xcodeSelectPath = processUtils.runSync(
|
_xcodeSelectPath = _processUtils.runSync(
|
||||||
<String>['/usr/bin/xcode-select', '--print-path'],
|
<String>['/usr/bin/xcode-select', '--print-path'],
|
||||||
).stdout.trim();
|
).stdout.trim();
|
||||||
} on ProcessException {
|
} on ProcessException {
|
||||||
@ -64,21 +86,21 @@ class Xcode {
|
|||||||
if (xcodeSelectPath == null || xcodeSelectPath.isEmpty) {
|
if (xcodeSelectPath == null || xcodeSelectPath.isEmpty) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return xcodeProjectInterpreter.isInstalled;
|
return _xcodeProjectInterpreter.isInstalled;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get majorVersion => xcodeProjectInterpreter.majorVersion;
|
int get majorVersion => _xcodeProjectInterpreter.majorVersion;
|
||||||
|
|
||||||
int get minorVersion => xcodeProjectInterpreter.minorVersion;
|
int get minorVersion => _xcodeProjectInterpreter.minorVersion;
|
||||||
|
|
||||||
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) {
|
||||||
try {
|
try {
|
||||||
final RunResult result = processUtils.runSync(
|
final RunResult result = _processUtils.runSync(
|
||||||
<String>['/usr/bin/xcrun', 'clang'],
|
<String>['/usr/bin/xcrun', 'clang'],
|
||||||
);
|
);
|
||||||
if (result.stdout != null && result.stdout.contains('license')) {
|
if (result.stdout != null && result.stdout.contains('license')) {
|
||||||
@ -103,7 +125,7 @@ class Xcode {
|
|||||||
try {
|
try {
|
||||||
// This command will error if additional components need to be installed in
|
// This command will error if additional components need to be installed in
|
||||||
// xcode 9.2 and above.
|
// xcode 9.2 and above.
|
||||||
final RunResult result = processUtils.runSync(
|
final RunResult result = _processUtils.runSync(
|
||||||
<String>['/usr/bin/xcrun', 'simctl', 'list'],
|
<String>['/usr/bin/xcrun', 'simctl', 'list'],
|
||||||
);
|
);
|
||||||
_isSimctlInstalled = result.stderr == null || result.stderr == '';
|
_isSimctlInstalled = result.stderr == null || result.stderr == '';
|
||||||
@ -115,7 +137,7 @@ class Xcode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool get isVersionSatisfactory {
|
bool get isVersionSatisfactory {
|
||||||
if (!xcodeProjectInterpreter.isInstalled) {
|
if (!_xcodeProjectInterpreter.isInstalled) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (majorVersion > kXcodeRequiredVersionMajor) {
|
if (majorVersion > kXcodeRequiredVersionMajor) {
|
||||||
@ -128,14 +150,14 @@ class Xcode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<RunResult> cc(List<String> args) {
|
Future<RunResult> cc(List<String> args) {
|
||||||
return processUtils.run(
|
return _processUtils.run(
|
||||||
<String>['xcrun', 'cc', ...args],
|
<String>['xcrun', 'cc', ...args],
|
||||||
throwOnError: true,
|
throwOnError: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<RunResult> clang(List<String> args) {
|
Future<RunResult> clang(List<String> args) {
|
||||||
return processUtils.run(
|
return _processUtils.run(
|
||||||
<String>['xcrun', 'clang', ...args],
|
<String>['xcrun', 'clang', ...args],
|
||||||
throwOnError: true,
|
throwOnError: true,
|
||||||
);
|
);
|
||||||
@ -143,7 +165,7 @@ class Xcode {
|
|||||||
|
|
||||||
Future<String> sdkLocation(SdkType sdk) async {
|
Future<String> sdkLocation(SdkType sdk) async {
|
||||||
assert(sdk != null);
|
assert(sdk != null);
|
||||||
final RunResult runResult = await processUtils.run(
|
final RunResult runResult = await _processUtils.run(
|
||||||
<String>['xcrun', '--sdk', getNameForSdk(sdk), '--show-sdk-path'],
|
<String>['xcrun', '--sdk', getNameForSdk(sdk), '--show-sdk-path'],
|
||||||
throwOnError: true,
|
throwOnError: true,
|
||||||
);
|
);
|
||||||
@ -158,10 +180,10 @@ class Xcode {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final List<String> searchPaths = <String>[
|
final List<String> searchPaths = <String>[
|
||||||
globals.fs.path.join(xcodeSelectPath, 'Applications', 'Simulator.app'),
|
_fileSystem.path.join(xcodeSelectPath, 'Applications', 'Simulator.app'),
|
||||||
];
|
];
|
||||||
return searchPaths.where((String p) => p != null).firstWhere(
|
return searchPaths.where((String p) => p != null).firstWhere(
|
||||||
(String p) => globals.fs.directory(p).existsSync(),
|
(String p) => _fileSystem.directory(p).existsSync(),
|
||||||
orElse: () => null,
|
orElse: () => null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ import 'package:file/memory.dart';
|
|||||||
import 'package:flutter_tools/src/artifacts.dart';
|
import 'package:flutter_tools/src/artifacts.dart';
|
||||||
import 'package:flutter_tools/src/base/file_system.dart';
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
import 'package:flutter_tools/src/base/io.dart';
|
import 'package:flutter_tools/src/base/io.dart';
|
||||||
|
import 'package:flutter_tools/src/base/logger.dart';
|
||||||
|
import 'package:flutter_tools/src/base/terminal.dart';
|
||||||
import 'package:flutter_tools/src/build_info.dart';
|
import 'package:flutter_tools/src/build_info.dart';
|
||||||
import 'package:flutter_tools/src/ios/xcodeproj.dart';
|
import 'package:flutter_tools/src/ios/xcodeproj.dart';
|
||||||
import 'package:flutter_tools/src/project.dart';
|
import 'package:flutter_tools/src/project.dart';
|
||||||
@ -24,36 +26,41 @@ import '../../src/pubspec_schema.dart';
|
|||||||
const String xcodebuild = '/usr/bin/xcodebuild';
|
const String xcodebuild = '/usr/bin/xcodebuild';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
group('xcodebuild commands', () {
|
mocks.MockProcessManager processManager;
|
||||||
mocks.MockProcessManager mockProcessManager;
|
|
||||||
XcodeProjectInterpreter xcodeProjectInterpreter;
|
XcodeProjectInterpreter xcodeProjectInterpreter;
|
||||||
FakePlatform macOS;
|
FakePlatform platform;
|
||||||
FileSystem fs;
|
FileSystem fileSystem;
|
||||||
|
BufferLogger logger;
|
||||||
|
AnsiTerminal terminal;
|
||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
mockProcessManager = mocks.MockProcessManager();
|
processManager = mocks.MockProcessManager();
|
||||||
xcodeProjectInterpreter = XcodeProjectInterpreter();
|
platform = fakePlatform('macos');
|
||||||
macOS = fakePlatform('macos');
|
fileSystem = MemoryFileSystem();
|
||||||
fs = MemoryFileSystem();
|
fileSystem.file(xcodebuild).createSync(recursive: true);
|
||||||
fs.file(xcodebuild).createSync(recursive: true);
|
terminal = MockAnsiTerminal();
|
||||||
|
logger = BufferLogger(
|
||||||
|
outputPreferences: OutputPreferences.test(),
|
||||||
|
terminal: terminal
|
||||||
|
);
|
||||||
|
xcodeProjectInterpreter = XcodeProjectInterpreter(
|
||||||
|
logger: logger,
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
platform: platform,
|
||||||
|
processManager: processManager,
|
||||||
|
terminal: terminal,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
void testUsingOsxContext(String description, dynamic testMethod()) {
|
testWithoutContext('xcodebuild versionText returns null when xcodebuild is not installed', () {
|
||||||
testUsingContext(description, testMethod, overrides: <Type, Generator>{
|
when(processManager.runSync(<String>[xcodebuild, '-version']))
|
||||||
Platform: () => macOS,
|
|
||||||
FileSystem: () => fs,
|
|
||||||
ProcessManager: () => mockProcessManager,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
testUsingOsxContext('versionText returns null when xcodebuild is not installed', () {
|
|
||||||
when(mockProcessManager.runSync(<String>[xcodebuild, '-version']))
|
|
||||||
.thenThrow(const ProcessException(xcodebuild, <String>['-version']));
|
.thenThrow(const ProcessException(xcodebuild, <String>['-version']));
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.versionText, isNull);
|
expect(xcodeProjectInterpreter.versionText, isNull);
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingOsxContext('versionText returns null when xcodebuild is not fully installed', () {
|
testWithoutContext('xcodebuild versionText returns null when xcodebuild is not fully installed', () {
|
||||||
when(mockProcessManager.runSync(<String>[xcodebuild, '-version'])).thenReturn(
|
when(processManager.runSync(<String>[xcodebuild, '-version'])).thenReturn(
|
||||||
ProcessResult(
|
ProcessResult(
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
@ -63,65 +70,81 @@ void main() {
|
|||||||
'',
|
'',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.versionText, isNull);
|
expect(xcodeProjectInterpreter.versionText, isNull);
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingOsxContext('versionText returns formatted version text', () {
|
testWithoutContext('xcodebuild versionText returns formatted version text', () {
|
||||||
when(mockProcessManager.runSync(<String>[xcodebuild, '-version']))
|
when(processManager.runSync(<String>[xcodebuild, '-version']))
|
||||||
.thenReturn(ProcessResult(1, 0, 'Xcode 8.3.3\nBuild version 8E3004b', ''));
|
.thenReturn(ProcessResult(1, 0, 'Xcode 8.3.3\nBuild version 8E3004b', ''));
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.versionText, 'Xcode 8.3.3, Build version 8E3004b');
|
expect(xcodeProjectInterpreter.versionText, 'Xcode 8.3.3, Build version 8E3004b');
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingOsxContext('versionText handles Xcode version string with unexpected format', () {
|
testWithoutContext('xcodebuild versionText handles Xcode version string with unexpected format', () {
|
||||||
when(mockProcessManager.runSync(<String>[xcodebuild, '-version']))
|
when(processManager.runSync(<String>[xcodebuild, '-version']))
|
||||||
.thenReturn(ProcessResult(1, 0, 'Xcode Ultra5000\nBuild version 8E3004b', ''));
|
.thenReturn(ProcessResult(1, 0, 'Xcode Ultra5000\nBuild version 8E3004b', ''));
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.versionText, 'Xcode Ultra5000, Build version 8E3004b');
|
expect(xcodeProjectInterpreter.versionText, 'Xcode Ultra5000, Build version 8E3004b');
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingOsxContext('majorVersion returns major version', () {
|
testWithoutContext('xcodebuild majorVersion returns major version', () {
|
||||||
when(mockProcessManager.runSync(<String>[xcodebuild, '-version']))
|
when(processManager.runSync(<String>[xcodebuild, '-version']))
|
||||||
.thenReturn(ProcessResult(1, 0, 'Xcode 10.3.3\nBuild version 8E3004b', ''));
|
.thenReturn(ProcessResult(1, 0, 'Xcode 10.3.3\nBuild version 8E3004b', ''));
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.majorVersion, 10);
|
expect(xcodeProjectInterpreter.majorVersion, 10);
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingOsxContext('majorVersion is null when version has unexpected format', () {
|
testWithoutContext('xcodebuild majorVersion is null when version has unexpected format', () {
|
||||||
when(mockProcessManager.runSync(<String>[xcodebuild, '-version']))
|
when(processManager.runSync(<String>[xcodebuild, '-version']))
|
||||||
.thenReturn(ProcessResult(1, 0, 'Xcode Ultra5000\nBuild version 8E3004b', ''));
|
.thenReturn(ProcessResult(1, 0, 'Xcode Ultra5000\nBuild version 8E3004b', ''));
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.majorVersion, isNull);
|
expect(xcodeProjectInterpreter.majorVersion, isNull);
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingOsxContext('minorVersion returns minor version', () {
|
testWithoutContext('xcodebuild inorVersion returns minor version', () {
|
||||||
when(mockProcessManager.runSync(<String>[xcodebuild, '-version']))
|
when(processManager.runSync(<String>[xcodebuild, '-version']))
|
||||||
.thenReturn(ProcessResult(1, 0, 'Xcode 8.3.3\nBuild version 8E3004b', ''));
|
.thenReturn(ProcessResult(1, 0, 'Xcode 8.3.3\nBuild version 8E3004b', ''));
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.minorVersion, 3);
|
expect(xcodeProjectInterpreter.minorVersion, 3);
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingOsxContext('minorVersion returns 0 when minor version is unspecified', () {
|
testWithoutContext('xcodebuild minorVersion returns 0 when minor version is unspecified', () {
|
||||||
when(mockProcessManager.runSync(<String>[xcodebuild, '-version']))
|
when(processManager.runSync(<String>[xcodebuild, '-version']))
|
||||||
.thenReturn(ProcessResult(1, 0, 'Xcode 8\nBuild version 8E3004b', ''));
|
.thenReturn(ProcessResult(1, 0, 'Xcode 8\nBuild version 8E3004b', ''));
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.minorVersion, 0);
|
expect(xcodeProjectInterpreter.minorVersion, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingOsxContext('minorVersion is null when version has unexpected format', () {
|
testWithoutContext('xcodebuild minorVersion is null when version has unexpected format', () {
|
||||||
when(mockProcessManager.runSync(<String>[xcodebuild, '-version']))
|
when(processManager.runSync(<String>[xcodebuild, '-version']))
|
||||||
.thenReturn(ProcessResult(1, 0, 'Xcode Ultra5000\nBuild version 8E3004b', ''));
|
.thenReturn(ProcessResult(1, 0, 'Xcode Ultra5000\nBuild version 8E3004b', ''));
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.minorVersion, isNull);
|
expect(xcodeProjectInterpreter.minorVersion, isNull);
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('isInstalled is false when not on MacOS', () {
|
testWithoutContext('xcodebuild isInstalled is false when not on MacOS', () {
|
||||||
fs.file(xcodebuild).deleteSync();
|
final Platform platform = fakePlatform('notMacOS');
|
||||||
expect(xcodeProjectInterpreter.isInstalled, isFalse);
|
xcodeProjectInterpreter = XcodeProjectInterpreter(
|
||||||
}, overrides: <Type, Generator>{
|
logger: logger,
|
||||||
Platform: () => fakePlatform('notMacOS'),
|
fileSystem: fileSystem,
|
||||||
});
|
platform: platform,
|
||||||
|
processManager: processManager,
|
||||||
|
terminal: terminal,
|
||||||
|
);
|
||||||
|
fileSystem.file(xcodebuild).deleteSync();
|
||||||
|
|
||||||
testUsingOsxContext('isInstalled is false when xcodebuild does not exist', () {
|
|
||||||
fs.file(xcodebuild).deleteSync();
|
|
||||||
expect(xcodeProjectInterpreter.isInstalled, isFalse);
|
expect(xcodeProjectInterpreter.isInstalled, isFalse);
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingOsxContext('isInstalled is false when Xcode is not fully installed', () {
|
testWithoutContext('xcodebuild isInstalled is false when xcodebuild does not exist', () {
|
||||||
when(mockProcessManager.runSync(<String>[xcodebuild, '-version'])).thenReturn(
|
fileSystem.file(xcodebuild).deleteSync();
|
||||||
|
|
||||||
|
expect(xcodeProjectInterpreter.isInstalled, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWithoutContext('xcodebuild isInstalled is false when Xcode is not fully installed', () {
|
||||||
|
when(processManager.runSync(<String>[xcodebuild, '-version'])).thenReturn(
|
||||||
ProcessResult(
|
ProcessResult(
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
@ -131,58 +154,59 @@ void main() {
|
|||||||
'',
|
'',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.isInstalled, isFalse);
|
expect(xcodeProjectInterpreter.isInstalled, isFalse);
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingOsxContext('isInstalled is false when version has unexpected format', () {
|
testWithoutContext('xcodebuild isInstalled is false when version has unexpected format', () {
|
||||||
when(mockProcessManager.runSync(<String>[xcodebuild, '-version']))
|
when(processManager.runSync(<String>[xcodebuild, '-version']))
|
||||||
.thenReturn(ProcessResult(1, 0, 'Xcode Ultra5000\nBuild version 8E3004b', ''));
|
.thenReturn(ProcessResult(1, 0, 'Xcode Ultra5000\nBuild version 8E3004b', ''));
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.isInstalled, isFalse);
|
expect(xcodeProjectInterpreter.isInstalled, isFalse);
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingOsxContext('isInstalled is true when version has expected format', () {
|
testWithoutContext('xcodebuild isInstalled is true when version has expected format', () {
|
||||||
when(mockProcessManager.runSync(<String>[xcodebuild, '-version']))
|
when(processManager.runSync(<String>[xcodebuild, '-version']))
|
||||||
.thenReturn(ProcessResult(1, 0, 'Xcode 8.3.3\nBuild version 8E3004b', ''));
|
.thenReturn(ProcessResult(1, 0, 'Xcode 8.3.3\nBuild version 8E3004b', ''));
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.isInstalled, isTrue);
|
expect(xcodeProjectInterpreter.isInstalled, isTrue);
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingOsxContext('build settings is empty when xcodebuild failed to get the build settings', () async {
|
testWithoutContext('xcodebuild build settings is empty when xcodebuild failed to get the build settings', () async {
|
||||||
when(mockProcessManager.runSync(
|
when(processManager.runSync(
|
||||||
argThat(contains(xcodebuild)),
|
argThat(contains(xcodebuild)),
|
||||||
workingDirectory: anyNamed('workingDirectory'),
|
workingDirectory: anyNamed('workingDirectory'),
|
||||||
environment: anyNamed('environment')))
|
environment: anyNamed('environment')))
|
||||||
.thenReturn(ProcessResult(0, 1, '', ''));
|
.thenReturn(ProcessResult(0, 1, '', ''));
|
||||||
|
|
||||||
expect(await xcodeProjectInterpreter.getBuildSettings('', ''), const <String, String>{});
|
expect(await xcodeProjectInterpreter.getBuildSettings('', ''), const <String, String>{});
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('build settings flakes', () async {
|
testWithoutContext('xcodebuild build settings flakes', () async {
|
||||||
const Duration delay = Duration(seconds: 1);
|
const Duration delay = Duration(seconds: 1);
|
||||||
mockProcessManager.processFactory = mocks.flakyProcessFactory(
|
processManager.processFactory = mocks.flakyProcessFactory(
|
||||||
flakes: 1,
|
flakes: 1,
|
||||||
delay: delay + const Duration(seconds: 1),
|
delay: delay + const Duration(seconds: 1),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(await xcodeProjectInterpreter.getBuildSettings(
|
expect(await xcodeProjectInterpreter.getBuildSettings(
|
||||||
'', '', timeout: delay),
|
'', '', timeout: delay),
|
||||||
const <String, String>{});
|
const <String, String>{});
|
||||||
// build settings times out and is killed once, then succeeds.
|
// build settings times out and is killed once, then succeeds.
|
||||||
verify(mockProcessManager.killPid(any)).called(1);
|
verify(processManager.killPid(any)).called(1);
|
||||||
// The verbose logs should tell us something timed out.
|
// The verbose logs should tell us something timed out.
|
||||||
expect(testLogger.traceText, contains('timed out'));
|
expect(logger.traceText, contains('timed out'));
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
Platform: () => macOS,
|
|
||||||
FileSystem: () => fs,
|
|
||||||
ProcessManager: () => mockProcessManager,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingOsxContext('build settings contains Flutter Xcode environment variables', () async {
|
testWithoutContext('xcodebuild build settings contains Flutter Xcode environment variables', () async {
|
||||||
macOS.environment = Map<String, String>.unmodifiable(<String, String>{
|
platform.environment = Map<String, String>.unmodifiable(<String, String>{
|
||||||
'FLUTTER_XCODE_CODE_SIGN_STYLE': 'Manual',
|
'FLUTTER_XCODE_CODE_SIGN_STYLE': 'Manual',
|
||||||
'FLUTTER_XCODE_ARCHS': 'arm64'
|
'FLUTTER_XCODE_ARCHS': 'arm64'
|
||||||
});
|
});
|
||||||
when(mockProcessManager.runSync(<String>[
|
when(processManager.runSync(<String>[
|
||||||
xcodebuild,
|
xcodebuild,
|
||||||
'-project',
|
'-project',
|
||||||
macOS.pathSeparator,
|
platform.pathSeparator,
|
||||||
'-target',
|
'-target',
|
||||||
'',
|
'',
|
||||||
'-showBuildSettings',
|
'-showBuildSettings',
|
||||||
@ -195,20 +219,21 @@ void main() {
|
|||||||
expect(await xcodeProjectInterpreter.getBuildSettings('', ''), const <String, String>{});
|
expect(await xcodeProjectInterpreter.getBuildSettings('', ''), const <String, String>{});
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingOsxContext('clean contains Flutter Xcode environment variables', () async {
|
testWithoutContext('xcodebuild clean contains Flutter Xcode environment variables', () async {
|
||||||
macOS.environment = Map<String, String>.unmodifiable(<String, String>{
|
platform.environment = Map<String, String>.unmodifiable(<String, String>{
|
||||||
'FLUTTER_XCODE_CODE_SIGN_STYLE': 'Manual',
|
'FLUTTER_XCODE_CODE_SIGN_STYLE': 'Manual',
|
||||||
'FLUTTER_XCODE_ARCHS': 'arm64'
|
'FLUTTER_XCODE_ARCHS': 'arm64'
|
||||||
});
|
});
|
||||||
when(mockProcessManager.runSync(
|
when(processManager.runSync(
|
||||||
any,
|
any,
|
||||||
workingDirectory: anyNamed('workingDirectory')))
|
workingDirectory: anyNamed('workingDirectory')))
|
||||||
.thenReturn(ProcessResult(1, 0, '', ''));
|
.thenReturn(ProcessResult(1, 0, '', ''));
|
||||||
xcodeProjectInterpreter.cleanWorkspace('workspace_path', 'Runner');
|
xcodeProjectInterpreter.cleanWorkspace('workspace_path', 'Runner');
|
||||||
final List<dynamic> captured = verify(mockProcessManager.runSync(
|
final List<dynamic> captured = verify(processManager.runSync(
|
||||||
captureAny,
|
captureAny,
|
||||||
workingDirectory: anyNamed('workingDirectory'),
|
workingDirectory: anyNamed('workingDirectory'),
|
||||||
environment: anyNamed('environment'))).captured;
|
environment: anyNamed('environment'))).captured;
|
||||||
|
|
||||||
expect(captured.first, <String>[
|
expect(captured.first, <String>[
|
||||||
xcodebuild,
|
xcodebuild,
|
||||||
'-workspace',
|
'-workspace',
|
||||||
@ -221,60 +246,51 @@ void main() {
|
|||||||
'ARCHS=arm64'
|
'ARCHS=arm64'
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
group('xcodebuild -list', () {
|
testWithoutContext('xcodebuild -list getInfo returns something when xcodebuild -list succeeds', () async {
|
||||||
mocks.MockProcessManager mockProcessManager;
|
|
||||||
FakePlatform macOS;
|
|
||||||
FileSystem fs;
|
|
||||||
|
|
||||||
setUp(() {
|
|
||||||
mockProcessManager = mocks.MockProcessManager();
|
|
||||||
macOS = fakePlatform('macos');
|
|
||||||
fs = MemoryFileSystem();
|
|
||||||
fs.file(xcodebuild).createSync(recursive: true);
|
|
||||||
});
|
|
||||||
|
|
||||||
void testUsingOsxContext(String description, dynamic testMethod()) {
|
|
||||||
testUsingContext(description, testMethod, overrides: <Type, Generator>{
|
|
||||||
Platform: () => macOS,
|
|
||||||
FileSystem: () => fs,
|
|
||||||
ProcessManager: () => mockProcessManager,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
testUsingOsxContext('getInfo returns something when xcodebuild -list succeeds', () async {
|
|
||||||
const String workingDirectory = '/';
|
const String workingDirectory = '/';
|
||||||
when(mockProcessManager.run(
|
when(processManager.run(
|
||||||
<String>[xcodebuild, '-list'],
|
<String>[xcodebuild, '-list'],
|
||||||
environment: anyNamed('environment'),
|
environment: anyNamed('environment'),
|
||||||
workingDirectory: workingDirectory),
|
workingDirectory: workingDirectory),
|
||||||
).thenAnswer((_) {
|
).thenAnswer((_) {
|
||||||
return Future<ProcessResult>.value(ProcessResult(1, 0, '', ''));
|
return Future<ProcessResult>.value(ProcessResult(1, 0, '', ''));
|
||||||
});
|
});
|
||||||
final XcodeProjectInterpreter xcodeProjectInterpreter = XcodeProjectInterpreter();
|
final XcodeProjectInterpreter xcodeProjectInterpreter = XcodeProjectInterpreter(
|
||||||
|
logger: logger,
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
platform: platform,
|
||||||
|
processManager: processManager,
|
||||||
|
terminal: terminal,
|
||||||
|
);
|
||||||
|
|
||||||
expect(await xcodeProjectInterpreter.getInfo(workingDirectory), isNotNull);
|
expect(await xcodeProjectInterpreter.getInfo(workingDirectory), isNotNull);
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingOsxContext('getInfo throws a tool exit when it is unable to find a project', () async {
|
testWithoutContext('xcodebuild -list getInfo throws a tool exit when it is unable to find a project', () async {
|
||||||
const String workingDirectory = '/';
|
const String workingDirectory = '/';
|
||||||
const String stderr = 'Useful Xcode failure message about missing project.';
|
const String stderr = 'Useful Xcode failure message about missing project.';
|
||||||
when(mockProcessManager.run(
|
when(processManager.run(
|
||||||
<String>[xcodebuild, '-list'],
|
<String>[xcodebuild, '-list'],
|
||||||
environment: anyNamed('environment'),
|
environment: anyNamed('environment'),
|
||||||
workingDirectory: workingDirectory),
|
workingDirectory: workingDirectory),
|
||||||
).thenAnswer((_) {
|
).thenAnswer((_) {
|
||||||
return Future<ProcessResult>.value(ProcessResult(1, 66, '', stderr));
|
return Future<ProcessResult>.value(ProcessResult(1, 66, '', stderr));
|
||||||
});
|
});
|
||||||
final XcodeProjectInterpreter xcodeProjectInterpreter = XcodeProjectInterpreter();
|
final XcodeProjectInterpreter xcodeProjectInterpreter = XcodeProjectInterpreter(
|
||||||
|
logger: logger,
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
platform: platform,
|
||||||
|
processManager: processManager,
|
||||||
|
terminal: terminal,
|
||||||
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
() async => await xcodeProjectInterpreter.getInfo(workingDirectory),
|
() async => await xcodeProjectInterpreter.getInfo(workingDirectory),
|
||||||
throwsToolExit(message: stderr));
|
throwsToolExit(message: stderr));
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
group('Xcode project properties', () {
|
testWithoutContext('Xcode project properties from default project can be parsed', () {
|
||||||
test('properties from default project can be parsed', () {
|
|
||||||
const String output = '''
|
const String output = '''
|
||||||
Information about project "Runner":
|
Information about project "Runner":
|
||||||
Targets:
|
Targets:
|
||||||
@ -295,7 +311,8 @@ Information about project "Runner":
|
|||||||
expect(info.schemes, <String>['Runner']);
|
expect(info.schemes, <String>['Runner']);
|
||||||
expect(info.buildConfigurations, <String>['Debug', 'Release']);
|
expect(info.buildConfigurations, <String>['Debug', 'Release']);
|
||||||
});
|
});
|
||||||
test('properties from project with custom schemes can be parsed', () {
|
|
||||||
|
testWithoutContext('Xcode project properties from project with custom schemes can be parsed', () {
|
||||||
const String output = '''
|
const String output = '''
|
||||||
Information about project "Runner":
|
Information about project "Runner":
|
||||||
Targets:
|
Targets:
|
||||||
@ -319,63 +336,75 @@ Information about project "Runner":
|
|||||||
expect(info.schemes, <String>['Free', 'Paid']);
|
expect(info.schemes, <String>['Free', 'Paid']);
|
||||||
expect(info.buildConfigurations, <String>['Debug (Free)', 'Debug (Paid)', 'Release (Free)', 'Release (Paid)']);
|
expect(info.buildConfigurations, <String>['Debug (Free)', 'Debug (Paid)', 'Release (Free)', 'Release (Paid)']);
|
||||||
});
|
});
|
||||||
test('expected scheme for non-flavored build is Runner', () {
|
|
||||||
|
testWithoutContext('expected scheme for non-flavored build is Runner', () {
|
||||||
expect(XcodeProjectInfo.expectedSchemeFor(BuildInfo.debug), 'Runner');
|
expect(XcodeProjectInfo.expectedSchemeFor(BuildInfo.debug), 'Runner');
|
||||||
expect(XcodeProjectInfo.expectedSchemeFor(BuildInfo.profile), 'Runner');
|
expect(XcodeProjectInfo.expectedSchemeFor(BuildInfo.profile), 'Runner');
|
||||||
expect(XcodeProjectInfo.expectedSchemeFor(BuildInfo.release), 'Runner');
|
expect(XcodeProjectInfo.expectedSchemeFor(BuildInfo.release), 'Runner');
|
||||||
});
|
});
|
||||||
test('expected build configuration for non-flavored build is derived from BuildMode', () {
|
|
||||||
|
testWithoutContext('expected build configuration for non-flavored build is derived from BuildMode', () {
|
||||||
expect(XcodeProjectInfo.expectedBuildConfigurationFor(BuildInfo.debug, 'Runner'), 'Debug');
|
expect(XcodeProjectInfo.expectedBuildConfigurationFor(BuildInfo.debug, 'Runner'), 'Debug');
|
||||||
expect(XcodeProjectInfo.expectedBuildConfigurationFor(BuildInfo.profile, 'Runner'), 'Profile');
|
expect(XcodeProjectInfo.expectedBuildConfigurationFor(BuildInfo.profile, 'Runner'), 'Profile');
|
||||||
expect(XcodeProjectInfo.expectedBuildConfigurationFor(BuildInfo.release, 'Runner'), 'Release');
|
expect(XcodeProjectInfo.expectedBuildConfigurationFor(BuildInfo.release, 'Runner'), 'Release');
|
||||||
});
|
});
|
||||||
test('expected scheme for flavored build is the title-cased flavor', () {
|
|
||||||
|
testWithoutContext('expected scheme for flavored build is the title-cased flavor', () {
|
||||||
expect(XcodeProjectInfo.expectedSchemeFor(const BuildInfo(BuildMode.debug, 'hello')), 'Hello');
|
expect(XcodeProjectInfo.expectedSchemeFor(const BuildInfo(BuildMode.debug, 'hello')), 'Hello');
|
||||||
expect(XcodeProjectInfo.expectedSchemeFor(const BuildInfo(BuildMode.profile, 'HELLO')), 'HELLO');
|
expect(XcodeProjectInfo.expectedSchemeFor(const BuildInfo(BuildMode.profile, 'HELLO')), 'HELLO');
|
||||||
expect(XcodeProjectInfo.expectedSchemeFor(const BuildInfo(BuildMode.release, 'Hello')), 'Hello');
|
expect(XcodeProjectInfo.expectedSchemeFor(const BuildInfo(BuildMode.release, 'Hello')), 'Hello');
|
||||||
});
|
});
|
||||||
test('expected build configuration for flavored build is Mode-Flavor', () {
|
testWithoutContext('expected build configuration for flavored build is Mode-Flavor', () {
|
||||||
expect(XcodeProjectInfo.expectedBuildConfigurationFor(const BuildInfo(BuildMode.debug, 'hello'), 'Hello'), 'Debug-Hello');
|
expect(XcodeProjectInfo.expectedBuildConfigurationFor(const BuildInfo(BuildMode.debug, 'hello'), 'Hello'), 'Debug-Hello');
|
||||||
expect(XcodeProjectInfo.expectedBuildConfigurationFor(const BuildInfo(BuildMode.profile, 'HELLO'), 'Hello'), 'Profile-Hello');
|
expect(XcodeProjectInfo.expectedBuildConfigurationFor(const BuildInfo(BuildMode.profile, 'HELLO'), 'Hello'), 'Profile-Hello');
|
||||||
expect(XcodeProjectInfo.expectedBuildConfigurationFor(const BuildInfo(BuildMode.release, 'Hello'), 'Hello'), 'Release-Hello');
|
expect(XcodeProjectInfo.expectedBuildConfigurationFor(const BuildInfo(BuildMode.release, 'Hello'), 'Hello'), 'Release-Hello');
|
||||||
});
|
});
|
||||||
test('scheme for default project is Runner', () {
|
|
||||||
|
testWithoutContext('scheme for default project is Runner', () {
|
||||||
final XcodeProjectInfo info = XcodeProjectInfo(<String>['Runner'], <String>['Debug', 'Release'], <String>['Runner']);
|
final XcodeProjectInfo info = XcodeProjectInfo(<String>['Runner'], <String>['Debug', 'Release'], <String>['Runner']);
|
||||||
|
|
||||||
expect(info.schemeFor(BuildInfo.debug), 'Runner');
|
expect(info.schemeFor(BuildInfo.debug), 'Runner');
|
||||||
expect(info.schemeFor(BuildInfo.profile), 'Runner');
|
expect(info.schemeFor(BuildInfo.profile), 'Runner');
|
||||||
expect(info.schemeFor(BuildInfo.release), 'Runner');
|
expect(info.schemeFor(BuildInfo.release), 'Runner');
|
||||||
expect(info.schemeFor(const BuildInfo(BuildMode.debug, 'unknown')), isNull);
|
expect(info.schemeFor(const BuildInfo(BuildMode.debug, 'unknown')), isNull);
|
||||||
});
|
});
|
||||||
test('build configuration for default project is matched against BuildMode', () {
|
|
||||||
|
testWithoutContext('build configuration for default project is matched against BuildMode', () {
|
||||||
final XcodeProjectInfo info = XcodeProjectInfo(<String>['Runner'], <String>['Debug', 'Profile', 'Release'], <String>['Runner']);
|
final XcodeProjectInfo info = XcodeProjectInfo(<String>['Runner'], <String>['Debug', 'Profile', 'Release'], <String>['Runner']);
|
||||||
|
|
||||||
expect(info.buildConfigurationFor(BuildInfo.debug, 'Runner'), 'Debug');
|
expect(info.buildConfigurationFor(BuildInfo.debug, 'Runner'), 'Debug');
|
||||||
expect(info.buildConfigurationFor(BuildInfo.profile, 'Runner'), 'Profile');
|
expect(info.buildConfigurationFor(BuildInfo.profile, 'Runner'), 'Profile');
|
||||||
expect(info.buildConfigurationFor(BuildInfo.release, 'Runner'), 'Release');
|
expect(info.buildConfigurationFor(BuildInfo.release, 'Runner'), 'Release');
|
||||||
});
|
});
|
||||||
test('scheme for project with custom schemes is matched against flavor', () {
|
|
||||||
|
testWithoutContext('scheme for project with custom schemes is matched against flavor', () {
|
||||||
final XcodeProjectInfo info = XcodeProjectInfo(
|
final XcodeProjectInfo info = XcodeProjectInfo(
|
||||||
<String>['Runner'],
|
<String>['Runner'],
|
||||||
<String>['Debug (Free)', 'Debug (Paid)', 'Release (Free)', 'Release (Paid)'],
|
<String>['Debug (Free)', 'Debug (Paid)', 'Release (Free)', 'Release (Paid)'],
|
||||||
<String>['Free', 'Paid'],
|
<String>['Free', 'Paid'],
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(info.schemeFor(const BuildInfo(BuildMode.debug, 'free')), 'Free');
|
expect(info.schemeFor(const BuildInfo(BuildMode.debug, 'free')), 'Free');
|
||||||
expect(info.schemeFor(const BuildInfo(BuildMode.profile, 'Free')), 'Free');
|
expect(info.schemeFor(const BuildInfo(BuildMode.profile, 'Free')), 'Free');
|
||||||
expect(info.schemeFor(const BuildInfo(BuildMode.release, 'paid')), 'Paid');
|
expect(info.schemeFor(const BuildInfo(BuildMode.release, 'paid')), 'Paid');
|
||||||
expect(info.schemeFor(const BuildInfo(BuildMode.debug, null)), isNull);
|
expect(info.schemeFor(const BuildInfo(BuildMode.debug, null)), isNull);
|
||||||
expect(info.schemeFor(const BuildInfo(BuildMode.debug, 'unknown')), isNull);
|
expect(info.schemeFor(const BuildInfo(BuildMode.debug, 'unknown')), isNull);
|
||||||
});
|
});
|
||||||
test('build configuration for project with custom schemes is matched against BuildMode and flavor', () {
|
|
||||||
|
testWithoutContext('build configuration for project with custom schemes is matched against BuildMode and flavor', () {
|
||||||
final XcodeProjectInfo info = XcodeProjectInfo(
|
final XcodeProjectInfo info = XcodeProjectInfo(
|
||||||
<String>['Runner'],
|
<String>['Runner'],
|
||||||
<String>['debug (free)', 'Debug paid', 'profile - Free', 'Profile-Paid', 'release - Free', 'Release-Paid'],
|
<String>['debug (free)', 'Debug paid', 'profile - Free', 'Profile-Paid', 'release - Free', 'Release-Paid'],
|
||||||
<String>['Free', 'Paid'],
|
<String>['Free', 'Paid'],
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(info.buildConfigurationFor(const BuildInfo(BuildMode.debug, 'free'), 'Free'), 'debug (free)');
|
expect(info.buildConfigurationFor(const BuildInfo(BuildMode.debug, 'free'), 'Free'), 'debug (free)');
|
||||||
expect(info.buildConfigurationFor(const BuildInfo(BuildMode.debug, 'Paid'), 'Paid'), 'Debug paid');
|
expect(info.buildConfigurationFor(const BuildInfo(BuildMode.debug, 'Paid'), 'Paid'), 'Debug paid');
|
||||||
expect(info.buildConfigurationFor(const BuildInfo(BuildMode.profile, 'FREE'), 'Free'), 'profile - Free');
|
expect(info.buildConfigurationFor(const BuildInfo(BuildMode.profile, 'FREE'), 'Free'), 'profile - Free');
|
||||||
expect(info.buildConfigurationFor(const BuildInfo(BuildMode.release, 'paid'), 'Paid'), 'Release-Paid');
|
expect(info.buildConfigurationFor(const BuildInfo(BuildMode.release, 'paid'), 'Paid'), 'Release-Paid');
|
||||||
});
|
});
|
||||||
test('build configuration for project with inconsistent naming is null', () {
|
|
||||||
|
testWithoutContext('build configuration for project with inconsistent naming is null', () {
|
||||||
final XcodeProjectInfo info = XcodeProjectInfo(
|
final XcodeProjectInfo info = XcodeProjectInfo(
|
||||||
<String>['Runner'],
|
<String>['Runner'],
|
||||||
<String>['Debug-F', 'Dbg Paid', 'Rel Free', 'Release Full'],
|
<String>['Debug-F', 'Dbg Paid', 'Rel Free', 'Release Full'],
|
||||||
@ -385,8 +414,6 @@ Information about project "Runner":
|
|||||||
expect(info.buildConfigurationFor(const BuildInfo(BuildMode.profile, 'Free'), 'Free'), null);
|
expect(info.buildConfigurationFor(const BuildInfo(BuildMode.profile, 'Free'), 'Free'), null);
|
||||||
expect(info.buildConfigurationFor(const BuildInfo(BuildMode.release, 'Paid'), 'Paid'), null);
|
expect(info.buildConfigurationFor(const BuildInfo(BuildMode.release, 'Paid'), 'Paid'), null);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
group('environmentVariablesAsXcodeBuildSettings', () {
|
group('environmentVariablesAsXcodeBuildSettings', () {
|
||||||
FakePlatform platform;
|
FakePlatform platform;
|
||||||
|
|
||||||
@ -394,17 +421,15 @@ Information about project "Runner":
|
|||||||
platform = fakePlatform('ignored');
|
platform = fakePlatform('ignored');
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('environment variables as Xcode build settings', () {
|
testWithoutContext('environment variables as Xcode build settings', () {
|
||||||
platform.environment = Map<String, String>.unmodifiable(<String, String>{
|
platform.environment = Map<String, String>.unmodifiable(<String, String>{
|
||||||
'Ignored': 'Bogus',
|
'Ignored': 'Bogus',
|
||||||
'FLUTTER_NOT_XCODE': 'Bogus',
|
'FLUTTER_NOT_XCODE': 'Bogus',
|
||||||
'FLUTTER_XCODE_CODE_SIGN_STYLE': 'Manual',
|
'FLUTTER_XCODE_CODE_SIGN_STYLE': 'Manual',
|
||||||
'FLUTTER_XCODE_ARCHS': 'arm64'
|
'FLUTTER_XCODE_ARCHS': 'arm64'
|
||||||
});
|
});
|
||||||
final List<String> environmentVariablesAsBuildSettings = environmentVariablesAsXcodeBuildSettings();
|
final List<String> environmentVariablesAsBuildSettings = environmentVariablesAsXcodeBuildSettings(platform);
|
||||||
expect(environmentVariablesAsBuildSettings, <String>['CODE_SIGN_STYLE=Manual', 'ARCHS=arm64']);
|
expect(environmentVariablesAsBuildSettings, <String>['CODE_SIGN_STYLE=Manual', 'ARCHS=arm64']);
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
Platform: () => platform
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -729,4 +754,9 @@ FakePlatform fakePlatform(String name) {
|
|||||||
|
|
||||||
class MockLocalEngineArtifacts extends Mock implements LocalEngineArtifacts {}
|
class MockLocalEngineArtifacts extends Mock implements LocalEngineArtifacts {}
|
||||||
class MockProcessManager extends Mock implements ProcessManager {}
|
class MockProcessManager extends Mock implements ProcessManager {}
|
||||||
class MockXcodeProjectInterpreter extends Mock implements XcodeProjectInterpreter { }
|
class MockXcodeProjectInterpreter extends Mock implements XcodeProjectInterpreter {}
|
||||||
|
class MockLogger extends Mock implements Logger {}
|
||||||
|
class MockAnsiTerminal extends Mock implements AnsiTerminal {
|
||||||
|
@override
|
||||||
|
bool get supportsColor => false;
|
||||||
|
}
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
|
import 'package:file/memory.dart';
|
||||||
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
import 'package:flutter_tools/src/base/io.dart' show ProcessException, ProcessResult;
|
import 'package:flutter_tools/src/base/io.dart' show ProcessException, ProcessResult;
|
||||||
|
import 'package:flutter_tools/src/base/logger.dart';
|
||||||
import 'package:flutter_tools/src/ios/xcodeproj.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:mockito/mockito.dart';
|
import 'package:mockito/mockito.dart';
|
||||||
@ -17,184 +20,161 @@ class MockXcodeProjectInterpreter extends Mock implements XcodeProjectInterprete
|
|||||||
class MockPlatform extends Mock implements Platform {}
|
class MockPlatform extends Mock implements Platform {}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
group('Xcode', () {
|
ProcessManager processManager;
|
||||||
MockProcessManager mockProcessManager;
|
|
||||||
Xcode xcode;
|
Xcode xcode;
|
||||||
MockXcodeProjectInterpreter mockXcodeProjectInterpreter;
|
MockXcodeProjectInterpreter mockXcodeProjectInterpreter;
|
||||||
MockPlatform mockPlatform;
|
MockPlatform platform;
|
||||||
|
Logger logger;
|
||||||
|
FileSystem fileSystem;
|
||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
mockProcessManager = MockProcessManager();
|
logger = MockLogger();
|
||||||
|
fileSystem = MemoryFileSystem();
|
||||||
|
processManager = MockProcessManager();
|
||||||
mockXcodeProjectInterpreter = MockXcodeProjectInterpreter();
|
mockXcodeProjectInterpreter = MockXcodeProjectInterpreter();
|
||||||
xcode = Xcode();
|
platform = MockPlatform();
|
||||||
mockPlatform = MockPlatform();
|
xcode = Xcode(
|
||||||
|
logger: logger,
|
||||||
|
platform: platform,
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
processManager: processManager,
|
||||||
|
xcodeProjectInterpreter: mockXcodeProjectInterpreter,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('xcodeSelectPath returns null when xcode-select is not installed', () {
|
testWithoutContext('xcodeSelectPath returns null when xcode-select is not installed', () {
|
||||||
when(mockProcessManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']))
|
when(processManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']))
|
||||||
.thenThrow(const ProcessException('/usr/bin/xcode-select', <String>['--print-path']));
|
.thenThrow(const ProcessException('/usr/bin/xcode-select', <String>['--print-path']));
|
||||||
expect(xcode.xcodeSelectPath, isNull);
|
expect(xcode.xcodeSelectPath, isNull);
|
||||||
when(mockProcessManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']))
|
when(processManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']))
|
||||||
.thenThrow(ArgumentError('Invalid argument(s): Cannot find executable for /usr/bin/xcode-select'));
|
.thenThrow(ArgumentError('Invalid argument(s): Cannot find executable for /usr/bin/xcode-select'));
|
||||||
|
|
||||||
expect(xcode.xcodeSelectPath, isNull);
|
expect(xcode.xcodeSelectPath, isNull);
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
ProcessManager: () => mockProcessManager,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('xcodeSelectPath returns path when xcode-select is installed', () {
|
testWithoutContext('xcodeSelectPath returns path when xcode-select is installed', () {
|
||||||
const String xcodePath = '/Applications/Xcode8.0.app/Contents/Developer';
|
const String xcodePath = '/Applications/Xcode8.0.app/Contents/Developer';
|
||||||
when(mockProcessManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']))
|
when(processManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']))
|
||||||
.thenReturn(ProcessResult(1, 0, xcodePath, ''));
|
.thenReturn(ProcessResult(1, 0, xcodePath, ''));
|
||||||
|
|
||||||
expect(xcode.xcodeSelectPath, xcodePath);
|
expect(xcode.xcodeSelectPath, xcodePath);
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
ProcessManager: () => mockProcessManager,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('xcodeVersionSatisfactory is false when version is less than minimum', () {
|
testWithoutContext('xcodeVersionSatisfactory is false when version is less than minimum', () {
|
||||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(9);
|
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(9);
|
||||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
||||||
|
|
||||||
expect(xcode.isVersionSatisfactory, isFalse);
|
expect(xcode.isVersionSatisfactory, isFalse);
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('xcodeVersionSatisfactory is false when xcodebuild tools are not installed', () {
|
testWithoutContext('xcodeVersionSatisfactory is false when xcodebuild tools are not installed', () {
|
||||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(false);
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(false);
|
||||||
|
|
||||||
expect(xcode.isVersionSatisfactory, isFalse);
|
expect(xcode.isVersionSatisfactory, isFalse);
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('xcodeVersionSatisfactory is true when version meets minimum', () {
|
testWithoutContext('xcodeVersionSatisfactory is true when version meets minimum', () {
|
||||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(10);
|
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(10);
|
||||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(2);
|
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(2);
|
||||||
|
|
||||||
expect(xcode.isVersionSatisfactory, isTrue);
|
expect(xcode.isVersionSatisfactory, isTrue);
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('xcodeVersionSatisfactory is true when major version exceeds minimum', () {
|
testWithoutContext('xcodeVersionSatisfactory is true when major version exceeds minimum', () {
|
||||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
|
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
|
||||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(2);
|
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(2);
|
||||||
|
|
||||||
expect(xcode.isVersionSatisfactory, isTrue);
|
expect(xcode.isVersionSatisfactory, isTrue);
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('xcodeVersionSatisfactory is true when minor version exceeds minimum', () {
|
testWithoutContext('xcodeVersionSatisfactory is true when minor version exceeds minimum', () {
|
||||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(10);
|
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(10);
|
||||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(3);
|
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(3);
|
||||||
|
|
||||||
expect(xcode.isVersionSatisfactory, isTrue);
|
expect(xcode.isVersionSatisfactory, isTrue);
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('isInstalledAndMeetsVersionCheck is false when not macOS', () {
|
testWithoutContext('isInstalledAndMeetsVersionCheck is false when not macOS', () {
|
||||||
when(mockPlatform.isMacOS).thenReturn(false);
|
when(platform.isMacOS).thenReturn(false);
|
||||||
|
|
||||||
expect(xcode.isInstalledAndMeetsVersionCheck, isFalse);
|
expect(xcode.isInstalledAndMeetsVersionCheck, isFalse);
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
|
|
||||||
Platform: () => mockPlatform,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('isInstalledAndMeetsVersionCheck is false when not installed', () {
|
testWithoutContext('isInstalledAndMeetsVersionCheck is false when not installed', () {
|
||||||
when(mockPlatform.isMacOS).thenReturn(true);
|
when(platform.isMacOS).thenReturn(true);
|
||||||
|
|
||||||
const String xcodePath = '/Applications/Xcode8.0.app/Contents/Developer';
|
const String xcodePath = '/Applications/Xcode8.0.app/Contents/Developer';
|
||||||
when(mockProcessManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']))
|
when(processManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']))
|
||||||
.thenReturn(ProcessResult(1, 0, xcodePath, ''));
|
.thenReturn(ProcessResult(1, 0, xcodePath, ''));
|
||||||
|
|
||||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(false);
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(false);
|
||||||
|
|
||||||
expect(xcode.isInstalledAndMeetsVersionCheck, isFalse);
|
expect(xcode.isInstalledAndMeetsVersionCheck, isFalse);
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
|
|
||||||
Platform: () => mockPlatform,
|
|
||||||
ProcessManager: () => mockProcessManager,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('isInstalledAndMeetsVersionCheck is false when no xcode-select', () {
|
testWithoutContext('isInstalledAndMeetsVersionCheck is false when no xcode-select', () {
|
||||||
when(mockPlatform.isMacOS).thenReturn(true);
|
when(platform.isMacOS).thenReturn(true);
|
||||||
|
when(processManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']))
|
||||||
when(mockProcessManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']))
|
|
||||||
.thenReturn(ProcessResult(1, 127, '', 'ERROR'));
|
.thenReturn(ProcessResult(1, 127, '', 'ERROR'));
|
||||||
|
|
||||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(10);
|
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(10);
|
||||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(2);
|
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(2);
|
||||||
|
|
||||||
expect(xcode.isInstalledAndMeetsVersionCheck, isFalse);
|
expect(xcode.isInstalledAndMeetsVersionCheck, isFalse);
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
|
|
||||||
Platform: () => mockPlatform,
|
|
||||||
ProcessManager: () => mockProcessManager,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('isInstalledAndMeetsVersionCheck is false when version not satisfied', () {
|
testWithoutContext('isInstalledAndMeetsVersionCheck is false when version not satisfied', () {
|
||||||
when(mockPlatform.isMacOS).thenReturn(true);
|
when(platform.isMacOS).thenReturn(true);
|
||||||
|
|
||||||
const String xcodePath = '/Applications/Xcode8.0.app/Contents/Developer';
|
const String xcodePath = '/Applications/Xcode8.0.app/Contents/Developer';
|
||||||
when(mockProcessManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']))
|
when(processManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']))
|
||||||
.thenReturn(ProcessResult(1, 0, xcodePath, ''));
|
.thenReturn(ProcessResult(1, 0, xcodePath, ''));
|
||||||
|
|
||||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(9);
|
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(9);
|
||||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
||||||
|
|
||||||
expect(xcode.isInstalledAndMeetsVersionCheck, isFalse);
|
expect(xcode.isInstalledAndMeetsVersionCheck, isFalse);
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
|
|
||||||
Platform: () => mockPlatform,
|
|
||||||
ProcessManager: () => mockProcessManager,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('isInstalledAndMeetsVersionCheck is true when macOS and installed and version is satisfied', () {
|
testWithoutContext('isInstalledAndMeetsVersionCheck is true when macOS and installed and version is satisfied', () {
|
||||||
when(mockPlatform.isMacOS).thenReturn(true);
|
when(platform.isMacOS).thenReturn(true);
|
||||||
|
|
||||||
const String xcodePath = '/Applications/Xcode8.0.app/Contents/Developer';
|
const String xcodePath = '/Applications/Xcode8.0.app/Contents/Developer';
|
||||||
when(mockProcessManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']))
|
when(processManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']))
|
||||||
.thenReturn(ProcessResult(1, 0, xcodePath, ''));
|
.thenReturn(ProcessResult(1, 0, xcodePath, ''));
|
||||||
|
|
||||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(10);
|
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(10);
|
||||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(2);
|
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(2);
|
||||||
|
|
||||||
expect(xcode.isInstalledAndMeetsVersionCheck, isTrue);
|
expect(xcode.isInstalledAndMeetsVersionCheck, isTrue);
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
XcodeProjectInterpreter: () => mockXcodeProjectInterpreter,
|
|
||||||
Platform: () => mockPlatform,
|
|
||||||
ProcessManager: () => mockProcessManager,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('eulaSigned is false when clang is not installed', () {
|
testWithoutContext('eulaSigned is false when clang is not installed', () {
|
||||||
when(mockProcessManager.runSync(<String>['/usr/bin/xcrun', 'clang']))
|
when(processManager.runSync(<String>['/usr/bin/xcrun', 'clang']))
|
||||||
.thenThrow(const ProcessException('/usr/bin/xcrun', <String>['clang']));
|
.thenThrow(const ProcessException('/usr/bin/xcrun', <String>['clang']));
|
||||||
|
|
||||||
expect(xcode.eulaSigned, isFalse);
|
expect(xcode.eulaSigned, isFalse);
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
ProcessManager: () => mockProcessManager,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('eulaSigned is false when clang output indicates EULA not yet accepted', () {
|
testWithoutContext('eulaSigned is false when clang output indicates EULA not yet accepted', () {
|
||||||
when(mockProcessManager.runSync(<String>['/usr/bin/xcrun', 'clang']))
|
when(processManager.runSync(<String>['/usr/bin/xcrun', 'clang']))
|
||||||
.thenReturn(ProcessResult(1, 1, '', 'Xcode EULA has not been accepted.\nLaunch Xcode and accept the license.'));
|
.thenReturn(ProcessResult(1, 1, '', 'Xcode EULA has not been accepted.\nLaunch Xcode and accept the license.'));
|
||||||
|
|
||||||
expect(xcode.eulaSigned, isFalse);
|
expect(xcode.eulaSigned, isFalse);
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
ProcessManager: () => mockProcessManager,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('eulaSigned is true when clang output indicates EULA has been accepted', () {
|
testWithoutContext('eulaSigned is true when clang output indicates EULA has been accepted', () {
|
||||||
when(mockProcessManager.runSync(<String>['/usr/bin/xcrun', 'clang']))
|
when(processManager.runSync(<String>['/usr/bin/xcrun', 'clang']))
|
||||||
.thenReturn(ProcessResult(1, 1, '', 'clang: error: no input files'));
|
.thenReturn(ProcessResult(1, 1, '', 'clang: error: no input files'));
|
||||||
|
|
||||||
expect(xcode.eulaSigned, isTrue);
|
expect(xcode.eulaSigned, isTrue);
|
||||||
}, overrides: <Type, Generator>{
|
|
||||||
ProcessManager: () => mockProcessManager,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('SDK name', () {
|
testWithoutContext('SDK name', () {
|
||||||
expect(getNameForSdk(SdkType.iPhone), 'iphoneos');
|
expect(getNameForSdk(SdkType.iPhone), 'iphoneos');
|
||||||
expect(getNameForSdk(SdkType.iPhoneSimulator), 'iphonesimulator');
|
expect(getNameForSdk(SdkType.iPhoneSimulator), 'iphonesimulator');
|
||||||
expect(getNameForSdk(SdkType.macOS), 'macosx');
|
expect(getNameForSdk(SdkType.macOS), 'macosx');
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MockLogger extends Mock implements Logger {}
|
||||||
|
Loading…
Reference in New Issue
Block a user