Add tests for iOS doctor validaton (#7794)

diff --git a/packages/flutter_tools/lib/src/ios/ios_workflow.dart b/packages/flutter_tools/lib/src/ios/ios_workflow.dart
index 07ebfb0..213f505 100644
--- a/packages/flutter_tools/lib/src/ios/ios_workflow.dart
+++ b/packages/flutter_tools/lib/src/ios/ios_workflow.dart
@@ -38,6 +38,8 @@
 
   String get iosDeployVersionText => runSync(<String>['ios-deploy', '--version']).replaceAll('\n', '');
 
+  bool get hasHomebrew => os.which('brew') != null;
+
   bool get _iosDeployIsInstalledAndMeetsVersionCheck {
     if (!hasIosDeploy)
       return false;
@@ -89,7 +91,7 @@
     }
 
     // brew installed
-    if (os.which('brew') != null) {
+    if (hasHomebrew) {
       brewStatus = ValidationType.installed;
 
       if (!exitsHappy(<String>['ideviceinstaller', '-h'])) {
@@ -132,9 +134,13 @@
     }
 
     return new ValidationResult(
-      xcodeStatus == brewStatus ? xcodeStatus : ValidationType.partial,
+      <ValidationType>[xcodeStatus, brewStatus].reduce(_mergeValidationTypes),
       messages,
       statusInfo: xcodeVersionInfo
     );
   }
+
+  ValidationType _mergeValidationTypes(ValidationType t1, ValidationType t2) {
+    return t1 == t2 ? t1 : ValidationType.partial;
+  }
 }
diff --git a/packages/flutter_tools/test/src/ios/ios_workflow_test.dart b/packages/flutter_tools/test/src/ios/ios_workflow_test.dart
new file mode 100644
index 0000000..1c077a6
--- /dev/null
+++ b/packages/flutter_tools/test/src/ios/ios_workflow_test.dart
@@ -0,0 +1,118 @@
+// 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 '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:test/test.dart';
+
+import '../context.dart';
+
+void main() {
+  group('iOS Workflow validation', () {
+    MockXCode xcode;
+    setUp(() {
+      xcode = new MockXCode();
+    });
+
+    testUsingContext('Emit missing status when nothing is installed', () async {
+      when(xcode.isInstalled).thenReturn(false);
+      IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget()
+        ..hasHomebrew = false
+        ..hasIosDeploy = false;
+      ValidationResult result = await workflow.validate();
+      expect(result.type, ValidationType.missing);
+    }, overrides: <Type, Generator>{ XCode: () => xcode });
+
+    testUsingContext('Emits partial status when Xcode is not installed', () async {
+      when(xcode.isInstalled).thenReturn(false);
+      IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget();
+      ValidationResult result = await workflow.validate();
+      expect(result.type, ValidationType.partial);
+    }, overrides: <Type, Generator>{ XCode: () => xcode });
+
+    testUsingContext('Emits partial status when Xcode version too low', () async {
+      when(xcode.isInstalled).thenReturn(true);
+      when(xcode.xcodeVersionText)
+          .thenReturn('Xcode 7.0.1\nBuild version 7C1002\n');
+      when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(false);
+      when(xcode.eulaSigned).thenReturn(true);
+      IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget();
+      ValidationResult result = await workflow.validate();
+      expect(result.type, ValidationType.partial);
+    }, overrides: <Type, Generator>{ XCode: () => xcode });
+
+    testUsingContext('Emits partial status when Xcode EULA not signed', () async {
+      when(xcode.isInstalled).thenReturn(true);
+      when(xcode.xcodeVersionText)
+          .thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
+      when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
+      when(xcode.eulaSigned).thenReturn(false);
+      IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget();
+      ValidationResult result = await workflow.validate();
+      expect(result.type, ValidationType.partial);
+    }, overrides: <Type, Generator>{ XCode: () => xcode });
+
+    testUsingContext('Emits partial status when homebrew not installed', () async {
+      when(xcode.isInstalled).thenReturn(true);
+      when(xcode.xcodeVersionText)
+          .thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
+      when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
+      when(xcode.eulaSigned).thenReturn(true);
+      IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget()
+        ..hasHomebrew = false;
+      ValidationResult result = await workflow.validate();
+      expect(result.type, ValidationType.partial);
+    }, overrides: <Type, Generator>{ XCode: () => xcode });
+
+    testUsingContext('Emits partial status when ios-deploy is not installed', () async {
+      when(xcode.isInstalled).thenReturn(true);
+      when(xcode.xcodeVersionText)
+          .thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
+      when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
+      when(xcode.eulaSigned).thenReturn(true);
+      IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget()
+        ..hasIosDeploy = false;
+      ValidationResult result = await workflow.validate();
+      expect(result.type, ValidationType.partial);
+    }, overrides: <Type, Generator>{ XCode: () => xcode });
+
+    testUsingContext('Emits partial status when ios-deploy version is too low', () async {
+      when(xcode.isInstalled).thenReturn(true);
+      when(xcode.xcodeVersionText)
+          .thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
+      when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
+      when(xcode.eulaSigned).thenReturn(true);
+      IOSWorkflowTestTarget workflow = new IOSWorkflowTestTarget()
+        ..iosDeployVersionText = '1.8.0';
+      ValidationResult result = await workflow.validate();
+      expect(result.type, ValidationType.partial);
+    }, overrides: <Type, Generator>{ XCode: () => xcode });
+
+    testUsingContext('Succeeds when all checks pass', () async {
+      when(xcode.isInstalled).thenReturn(true);
+      when(xcode.xcodeVersionText)
+          .thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
+      when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
+      when(xcode.eulaSigned).thenReturn(true);
+      ValidationResult result = await new IOSWorkflowTestTarget().validate();
+      expect(result.type, ValidationType.installed);
+    }, overrides: <Type, Generator>{ XCode: () => xcode });
+  });
+}
+
+class MockXCode extends Mock implements XCode {}
+
+class IOSWorkflowTestTarget extends IOSWorkflow {
+  @override
+  bool hasHomebrew = true;
+
+  @override
+  bool hasIosDeploy = true;
+
+  @override
+  String iosDeployVersionText = '1.9.0';
+}