flutter/packages/flutter_tools/test/ios/simulators_test.dart
Todd Volkert 137f0751b2
Add support for IOS_SIMULATOR_HOME environment variable in IOSSimulat… (#13236)
Add support for IOS_SIMULATOR_HOME environment variable in IOSSimulator.logFilePath

flutter_tools can be run on environments where the user's HOME directory
is not the root of the iOS simulators' configs. This change adds support
for such environments by allowing the caller to set the simulator root
directory via an environment variable.
2017-11-29 08:22:05 -08:00

268 lines
9.3 KiB
Dart

import 'dart:async';
import 'dart:io' show ProcessResult, Process;
import 'package:file/file.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/ios/mac.dart';
import 'package:flutter_tools/src/ios/simulators.dart';
import 'package:mockito/mockito.dart';
import 'package:platform/platform.dart';
import 'package:process/process.dart';
import 'package:test/test.dart';
import '../src/context.dart';
class MockXcode extends Mock implements Xcode {}
class MockFile extends Mock implements File {}
class MockProcessManager extends Mock implements ProcessManager {}
class MockProcess extends Mock implements Process {}
void main() {
FakePlatform osx;
setUp(() {
osx = new FakePlatform.fromPlatform(const LocalPlatform());
osx.operatingSystem = 'macos';
});
group('logFilePath', () {
testUsingContext('defaults to rooted from HOME', () {
osx.environment['HOME'] = '/foo/bar';
expect(new IOSSimulator('123').logFilePath, '/foo/bar/Library/Logs/CoreSimulator/123/system.log');
}, overrides: <Type, Generator>{
Platform: () => osx,
}, testOn: 'posix');
testUsingContext('respects IOS_SIMULATOR_LOG_FILE_PATH', () {
osx.environment['HOME'] = '/foo/bar';
osx.environment['IOS_SIMULATOR_LOG_FILE_PATH'] = '/baz/qux/%{id}/system.log';
expect(new IOSSimulator('456').logFilePath, '/baz/qux/456/system.log');
}, overrides: <Type, Generator>{
Platform: () => osx,
});
});
group('compareIosVersions', () {
test('compares correctly', () {
// This list must be sorted in ascending preference order
final List<String> testList = <String>[
'8', '8.0', '8.1', '8.2',
'9', '9.0', '9.1', '9.2',
'10', '10.0', '10.1',
];
for (int i = 0; i < testList.length; i++) {
expect(compareIosVersions(testList[i], testList[i]), 0);
}
for (int i = 0; i < testList.length - 1; i++) {
for (int j = i + 1; j < testList.length; j++) {
expect(compareIosVersions(testList[i], testList[j]), lessThan(0));
expect(compareIosVersions(testList[j], testList[i]), greaterThan(0));
}
}
});
});
group('compareIphoneVersions', () {
test('compares correctly', () {
// This list must be sorted in ascending preference order
final List<String> testList = <String>[
'com.apple.CoreSimulator.SimDeviceType.iPhone-4s',
'com.apple.CoreSimulator.SimDeviceType.iPhone-5',
'com.apple.CoreSimulator.SimDeviceType.iPhone-5s',
'com.apple.CoreSimulator.SimDeviceType.iPhone-6strange',
'com.apple.CoreSimulator.SimDeviceType.iPhone-6-Plus',
'com.apple.CoreSimulator.SimDeviceType.iPhone-6',
'com.apple.CoreSimulator.SimDeviceType.iPhone-6s-Plus',
'com.apple.CoreSimulator.SimDeviceType.iPhone-6s',
];
for (int i = 0; i < testList.length; i++) {
expect(compareIphoneVersions(testList[i], testList[i]), 0);
}
for (int i = 0; i < testList.length - 1; i++) {
for (int j = i + 1; j < testList.length; j++) {
expect(compareIphoneVersions(testList[i], testList[j]), lessThan(0));
expect(compareIphoneVersions(testList[j], testList[i]), greaterThan(0));
}
}
});
});
group('IOSSimulator.isSupported', () {
testUsingContext('Apple TV is unsupported', () {
expect(new IOSSimulator('x', name: 'Apple TV').isSupported(), false);
}, overrides: <Type, Generator>{
Platform: () => osx,
});
testUsingContext('Apple Watch is unsupported', () {
expect(new IOSSimulator('x', name: 'Apple Watch').isSupported(), false);
}, overrides: <Type, Generator>{
Platform: () => osx,
});
testUsingContext('iPad 2 is unsupported', () {
expect(new IOSSimulator('x', name: 'iPad 2').isSupported(), false);
}, overrides: <Type, Generator>{
Platform: () => osx,
});
testUsingContext('iPad Retina is unsupported', () {
expect(new IOSSimulator('x', name: 'iPad Retina').isSupported(), false);
}, overrides: <Type, Generator>{
Platform: () => osx,
});
testUsingContext('iPhone 5 is unsupported', () {
expect(new IOSSimulator('x', name: 'iPhone 5').isSupported(), false);
}, overrides: <Type, Generator>{
Platform: () => osx,
});
testUsingContext('iPhone 5s is supported', () {
expect(new IOSSimulator('x', name: 'iPhone 5s').isSupported(), true);
}, overrides: <Type, Generator>{
Platform: () => osx,
});
testUsingContext('iPhone SE is supported', () {
expect(new IOSSimulator('x', name: 'iPhone SE').isSupported(), true);
}, overrides: <Type, Generator>{
Platform: () => osx,
});
testUsingContext('iPhone 7 Plus is supported', () {
expect(new IOSSimulator('x', name: 'iPhone 7 Plus').isSupported(), true);
}, overrides: <Type, Generator>{
Platform: () => osx,
});
});
group('Simulator screenshot', () {
MockXcode mockXcode;
MockProcessManager mockProcessManager;
IOSSimulator deviceUnderTest;
setUp(() {
mockXcode = new MockXcode();
mockProcessManager = new MockProcessManager();
// Let everything else return exit code 0 so process.dart doesn't crash.
when(
mockProcessManager.run(any, environment: null, workingDirectory: null)
).thenReturn(
new Future<ProcessResult>.value(new ProcessResult(2, 0, '', ''))
);
// Doesn't matter what the device is.
deviceUnderTest = new IOSSimulator('x', name: 'iPhone SE');
});
testUsingContext(
'old Xcode doesn\'t support screenshot',
() {
when(mockXcode.xcodeMajorVersion).thenReturn(7);
when(mockXcode.xcodeMinorVersion).thenReturn(1);
expect(deviceUnderTest.supportsScreenshot, false);
},
overrides: <Type, Generator>{Xcode: () => mockXcode}
);
testUsingContext(
'Xcode 8.2+ supports screenshots',
() async {
when(mockXcode.xcodeMajorVersion).thenReturn(8);
when(mockXcode.xcodeMinorVersion).thenReturn(2);
expect(deviceUnderTest.supportsScreenshot, true);
final MockFile mockFile = new MockFile();
when(mockFile.path).thenReturn(fs.path.join('some', 'path', 'to', 'screenshot.png'));
await deviceUnderTest.takeScreenshot(mockFile);
verify(mockProcessManager.run(
<String>[
'/usr/bin/xcrun',
'simctl',
'io',
'x',
'screenshot',
fs.path.join('some', 'path', 'to', 'screenshot.png'),
],
environment: null,
workingDirectory: null
));
},
overrides: <Type, Generator>{
ProcessManager: () => mockProcessManager,
// Test a real one. Screenshot doesn't require instance states.
SimControl: () => new SimControl(),
Xcode: () => mockXcode,
}
);
});
group('launchDeviceLogTool', () {
MockProcessManager mockProcessManager;
setUp(() {
mockProcessManager = new MockProcessManager();
when(mockProcessManager.start(any, environment: null, workingDirectory: null))
.thenReturn(new Future<Process>.value(new MockProcess()));
});
testUsingContext('uses tail on iOS versions prior to iOS 11', () async {
final IOSSimulator device = new IOSSimulator('x', name: 'iPhone SE', category: 'iOS 9.3');
await launchDeviceLogTool(device);
expect(
verify(mockProcessManager.start(captureAny, environment: null, workingDirectory: null)).captured.single,
contains('tail'),
);
},
overrides: <Type, Generator>{
ProcessManager: () => mockProcessManager,
});
testUsingContext('uses /usr/bin/log on iOS 11 and above', () async {
final IOSSimulator device = new IOSSimulator('x', name: 'iPhone SE', category: 'iOS 11.0');
await launchDeviceLogTool(device);
expect(
verify(mockProcessManager.start(captureAny, environment: null, workingDirectory: null)).captured.single,
contains('/usr/bin/log'),
);
},
overrides: <Type, Generator>{
ProcessManager: () => mockProcessManager,
});
});
group('launchSystemLogTool', () {
MockProcessManager mockProcessManager;
setUp(() {
mockProcessManager = new MockProcessManager();
when(mockProcessManager.start(any, environment: null, workingDirectory: null))
.thenReturn(new Future<Process>.value(new MockProcess()));
});
testUsingContext('uses tail on iOS versions prior to iOS 11', () async {
final IOSSimulator device = new IOSSimulator('x', name: 'iPhone SE', category: 'iOS 9.3');
await launchSystemLogTool(device);
expect(
verify(mockProcessManager.start(captureAny, environment: null, workingDirectory: null)).captured.single,
contains('tail'),
);
},
overrides: <Type, Generator>{
ProcessManager: () => mockProcessManager,
});
testUsingContext('uses /usr/bin/log on iOS 11 and above', () async {
final IOSSimulator device = new IOSSimulator('x', name: 'iPhone SE', category: 'iOS 11.0');
await launchSystemLogTool(device);
verifyNever(mockProcessManager.start(any, environment: null, workingDirectory: null));
},
overrides: <Type, Generator>{
ProcessManager: () => mockProcessManager,
});
});
}