blob: a2e374530629bc47904cb9fcbdb6d39024f06408 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/doctor.dart';
import 'package:flutter_tools/src/ios/ios_workflow.dart';
import 'package:flutter_tools/src/ios/mac.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
import '../src/common.dart';
import '../src/context.dart';
void main() {
group('iOS Workflow validation', () {
MockIMobileDevice iMobileDevice;
MockIMobileDevice iMobileDeviceUninstalled;
MockProcessManager processManager;
FileSystem fs;
setUp(() {
iMobileDevice = MockIMobileDevice();
iMobileDeviceUninstalled = MockIMobileDevice(isInstalled: false);
processManager = MockProcessManager();
fs = MemoryFileSystem();
});
testUsingContext('Emit missing status when nothing is installed', () async {
final IOSWorkflowTestTarget workflow = IOSWorkflowTestTarget(
hasHomebrew: false,
hasIosDeploy: false,
hasIDeviceInstaller: false,
iosDeployVersionText: '0.0.0',
);
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.missing);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDeviceUninstalled,
});
testUsingContext('Emits installed status when homebrew not installed, but not needed', () async {
final IOSWorkflowTestTarget workflow = IOSWorkflowTestTarget(hasHomebrew: false);
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.installed);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
});
testUsingContext('Emits partial status when libimobiledevice is not installed', () async {
final IOSWorkflowTestTarget workflow = IOSWorkflowTestTarget();
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => MockIMobileDevice(isInstalled: false, isWorking: false),
});
testUsingContext('Emits partial status when libimobiledevice is installed but not working', () async {
final IOSWorkflowTestTarget workflow = IOSWorkflowTestTarget();
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => MockIMobileDevice(isWorking: false),
});
testUsingContext('Emits partial status when libimobiledevice is installed but not working', () async {
when(processManager.run(
<String>['ideviceinfo', '-u', '00008020-001C2D903C42002E'],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment')),
).thenAnswer((Invocation _) async {
final MockProcessResult result = MockProcessResult();
when<String>(result.stdout).thenReturn(r'''
Usage: ideviceinfo [OPTIONS]
Show information about a connected device.
-d, --debug enable communication debugging
-s, --simple use a simple connection to avoid auto-pairing with the device
-u, --udid UDID target specific device by its 40-digit device UDID
-q, --domain NAME set domain of query to NAME. Default: None
-k, --key NAME only query key specified by NAME. Default: All keys.
-x, --xml output information as xml plist instead of key/value pairs
-h, --help prints usage information
''');
return null;
});
final IOSWorkflowTestTarget workflow = IOSWorkflowTestTarget();
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
});
testUsingContext('Emits partial status when ios-deploy is not installed', () async {
final IOSWorkflowTestTarget workflow = IOSWorkflowTestTarget(hasIosDeploy: false);
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
});
testUsingContext('Emits partial status when ios-deploy version is too low', () async {
final IOSWorkflowTestTarget workflow = IOSWorkflowTestTarget(iosDeployVersionText: '1.8.0');
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
});
testUsingContext('Emits partial status when ios-deploy version is a known bad version', () async {
final IOSWorkflowTestTarget workflow = IOSWorkflowTestTarget(iosDeployVersionText: '2.0.0');
final ValidationResult result = await workflow.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
IMobileDevice: () => iMobileDevice,
});
testUsingContext('Succeeds when all checks pass', () async {
final ValidationResult result = await IOSWorkflowTestTarget().validate();
expect(result.type, ValidationType.installed);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
IMobileDevice: () => iMobileDevice,
ProcessManager: () => processManager,
});
});
}
final ProcessResult exitsHappy = ProcessResult(
1, // pid
0, // exitCode
'', // stdout
'', // stderr
);
class MockIMobileDevice extends IMobileDevice {
MockIMobileDevice({
this.isInstalled = true,
bool isWorking = true,
}) : isWorking = Future<bool>.value(isWorking);
@override
final bool isInstalled;
@override
final Future<bool> isWorking;
}
class MockProcessManager extends Mock implements ProcessManager {}
class MockProcessResult extends Mock implements ProcessResult {}
class IOSWorkflowTestTarget extends IOSValidator {
IOSWorkflowTestTarget({
this.hasHomebrew = true,
bool hasIosDeploy = true,
String iosDeployVersionText = '1.9.4',
bool hasIDeviceInstaller = true,
}) : hasIosDeploy = Future<bool>.value(hasIosDeploy),
iosDeployVersionText = Future<String>.value(iosDeployVersionText),
hasIDeviceInstaller = Future<bool>.value(hasIDeviceInstaller);
@override
final bool hasHomebrew;
@override
final Future<bool> hasIosDeploy;
@override
final Future<String> iosDeployVersionText;
@override
final Future<bool> hasIDeviceInstaller;
}