[flutter_tool] process.dart cleanup (#39899)

diff --git a/packages/flutter_tools/test/general.shard/application_package_test.dart b/packages/flutter_tools/test/general.shard/application_package_test.dart
index c2fbedb..a374142 100644
--- a/packages/flutter_tools/test/general.shard/application_package_test.dart
+++ b/packages/flutter_tools/test/general.shard/application_package_test.dart
@@ -87,7 +87,7 @@
           workingDirectory: anyNamed('workingDirectory'),
           environment: anyNamed('environment'),
         ),
-      ).thenReturn(ProcessResult(0, 0, _aaptDataWithDefaultEnabledAndMainLauncherActivity, null));
+      ).thenReturn(ProcessResult(0, 0, _aaptDataWithDefaultEnabledAndMainLauncherActivity, ''));
 
       final ApplicationPackage applicationPackage = await ApplicationPackageFactory.instance.getPackageForPlatform(
         TargetPlatform.android_arm,
diff --git a/packages/flutter_tools/test/general.shard/base/process_test.dart b/packages/flutter_tools/test/general.shard/base/process_test.dart
index 9c8981c..88e7dd2 100644
--- a/packages/flutter_tools/test/general.shard/base/process_test.dart
+++ b/packages/flutter_tools/test/general.shard/base/process_test.dart
@@ -26,10 +26,11 @@
       mockProcessManager = PlainMockProcessManager();
     });
 
-    testUsingContext('runCheckedAsync exceptions should be ProcessException objects', () async {
-      when(mockProcessManager.run(<String>['false']))
-          .thenAnswer((Invocation invocation) => Future<ProcessResult>.value(ProcessResult(0, 1, '', '')));
-      expect(() async => await runCheckedAsync(<String>['false']), throwsA(isInstanceOf<ProcessException>()));
+    testUsingContext('runAsync throwOnError: exceptions should be ProcessException objects', () async {
+      when(mockProcessManager.run(<String>['false'])).thenAnswer(
+          (Invocation invocation) => Future<ProcessResult>.value(ProcessResult(0, 1, '', '')));
+      expect(() async => await processUtils.run(<String>['false'], throwOnError: true),
+             throwsA(isInstanceOf<ProcessException>()));
     }, overrides: <Type, Generator>{ProcessManager: () => mockProcessManager});
   });
 
@@ -86,7 +87,7 @@
     testUsingContext('Command output is not wrapped.', () async {
       final List<String> testString = <String>['0123456789' * 10];
       mockProcessManager.processFactory = processMetaFactory(testString, stderr: testString);
-      await runCommandAndStreamOutput(<String>['command']);
+      await processUtils.stream(<String>['command']);
       expect(mockLogger.statusText, equals('${testString[0]}\n'));
       expect(mockLogger.errorText, equals('${testString[0]}\n'));
     }, overrides: <Type, Generator>{
@@ -97,22 +98,82 @@
     });
   });
 
-  group('runAsync timeout and retry', () {
+  group('run', () {
     const Duration delay = Duration(seconds: 2);
     MockProcessManager flakyProcessManager;
+    ProcessManager mockProcessManager;
 
     setUp(() {
       // MockProcessManager has an implementation of start() that returns the
       // result of processFactory.
       flakyProcessManager = MockProcessManager();
+      mockProcessManager = MockProcessManager();
     });
 
-    testUsingContext('flaky process fails without retry', () async {
+    testUsingContext(' succeeds on success', () async {
+      when(mockProcessManager.run(<String>['whoohoo'])).thenAnswer((_) {
+        return Future<ProcessResult>.value(ProcessResult(0, 0, '', ''));
+      });
+      expect((await processUtils.run(<String>['whoohoo'])).exitCode, 0);
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+
+    testUsingContext(' fails on failure', () async {
+      when(mockProcessManager.run(<String>['boohoo'])).thenAnswer((_) {
+        return Future<ProcessResult>.value(ProcessResult(0, 1, '', ''));
+      });
+      expect((await processUtils.run(<String>['boohoo'])).exitCode, 1);
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+
+    testUsingContext(' throws on failure with throwOnError', () async {
+      when(mockProcessManager.run(<String>['kaboom'])).thenAnswer((_) {
+        return Future<ProcessResult>.value(ProcessResult(0, 1, '', ''));
+      });
+      expect(() => processUtils.run(<String>['kaboom'], throwOnError: true),
+             throwsA(isA<ProcessException>()));
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+
+    testUsingContext(' does not throw on failure with whitelist', () async {
+      when(mockProcessManager.run(<String>['kaboom'])).thenAnswer((_) {
+        return Future<ProcessResult>.value(ProcessResult(0, 1, '', ''));
+      });
+      expect(
+        (await processUtils.run(
+          <String>['kaboom'],
+          throwOnError: true,
+          whiteListFailures: (int c) => c == 1,
+        )).exitCode,
+        1);
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+
+    testUsingContext(' throws on failure when not in whitelist', () async {
+      when(mockProcessManager.run(<String>['kaboom'])).thenAnswer((_) {
+        return Future<ProcessResult>.value(ProcessResult(0, 2, '', ''));
+      });
+      expect(
+        () => processUtils.run(
+          <String>['kaboom'],
+          throwOnError: true,
+          whiteListFailures: (int c) => c == 1,
+        ),
+        throwsA(isA<ProcessException>()));
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+
+    testUsingContext(' flaky process fails without retry', () async {
       flakyProcessManager.processFactory = flakyProcessFactory(
         flakes: 1,
         delay: delay,
       );
-      final RunResult result = await runAsync(
+      final RunResult result = await processUtils.run(
         <String>['dummy'],
         timeout: delay + const Duration(seconds: 1),
       );
@@ -121,12 +182,12 @@
       ProcessManager: () => flakyProcessManager,
     });
 
-    testUsingContext('flaky process succeeds with retry', () async {
+    testUsingContext(' flaky process succeeds with retry', () async {
       flakyProcessManager.processFactory = flakyProcessFactory(
         flakes: 1,
         delay: delay,
       );
-      final RunResult result = await runAsync(
+      final RunResult result = await processUtils.run(
         <String>['dummy'],
         timeout: delay - const Duration(milliseconds: 500),
         timeoutRetries: 1,
@@ -136,7 +197,7 @@
       ProcessManager: () => flakyProcessManager,
     });
 
-    testUsingContext('flaky process generates ProcessException on timeout', () async {
+    testUsingContext(' flaky process generates ProcessException on timeout', () async {
       final Completer<List<int>> flakyStderr = Completer<List<int>>();
       final Completer<List<int>> flakyStdout = Completer<List<int>>();
       flakyProcessManager.processFactory = flakyProcessFactory(
@@ -153,7 +214,7 @@
         flakyStdout.complete(<int>[]);
         return true;
       });
-      expect(() async => await runAsync(
+      expect(() => processUtils.run(
         <String>['dummy'],
         timeout: delay - const Duration(milliseconds: 500),
         timeoutRetries: 0,
@@ -162,6 +223,159 @@
       ProcessManager: () => flakyProcessManager,
     });
   });
+
+  group('runSync', () {
+    ProcessManager mockProcessManager;
+
+    setUp(() {
+      mockProcessManager = MockProcessManager();
+    });
+
+    testUsingContext(' succeeds on success', () async {
+      when(mockProcessManager.runSync(<String>['whoohoo'])).thenReturn(
+        ProcessResult(0, 0, '', '')
+      );
+      expect(processUtils.runSync(<String>['whoohoo']).exitCode, 0);
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+
+    testUsingContext(' fails on failure', () async {
+      when(mockProcessManager.runSync(<String>['boohoo'])).thenReturn(
+        ProcessResult(0, 1, '', '')
+      );
+      expect(processUtils.runSync(<String>['boohoo']).exitCode, 1);
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+
+    testUsingContext(' throws on failure with throwOnError', () async {
+      when(mockProcessManager.runSync(<String>['kaboom'])).thenReturn(
+        ProcessResult(0, 1, '', '')
+      );
+      expect(() => processUtils.runSync(<String>['kaboom'], throwOnError: true),
+             throwsA(isA<ProcessException>()));
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+
+    testUsingContext(' does not throw on failure with whitelist', () async {
+      when(mockProcessManager.runSync(<String>['kaboom'])).thenReturn(
+        ProcessResult(0, 1, '', '')
+      );
+      expect(
+        processUtils.runSync(
+          <String>['kaboom'],
+          throwOnError: true,
+          whiteListFailures: (int c) => c == 1,
+        ).exitCode,
+        1);
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+
+    testUsingContext(' throws on failure when not in whitelist', () async {
+      when(mockProcessManager.runSync(<String>['kaboom'])).thenReturn(
+        ProcessResult(0, 2, '', '')
+      );
+      expect(
+        () => processUtils.runSync(
+          <String>['kaboom'],
+          throwOnError: true,
+          whiteListFailures: (int c) => c == 1,
+        ),
+        throwsA(isA<ProcessException>()));
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+
+    testUsingContext(' prints stdout and stderr to trace on success', () async {
+      when(mockProcessManager.runSync(<String>['whoohoo'])).thenReturn(
+        ProcessResult(0, 0, 'stdout', 'stderr')
+      );
+      expect(processUtils.runSync(<String>['whoohoo']).exitCode, 0);
+      expect(testLogger.traceText, contains('stdout'));
+      expect(testLogger.traceText, contains('stderr'));
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+
+    testUsingContext(' prints stdout to status and stderr to error on failure with throwOnError', () async {
+      when(mockProcessManager.runSync(<String>['kaboom'])).thenReturn(
+        ProcessResult(0, 1, 'stdout', 'stderr')
+      );
+      expect(() => processUtils.runSync(<String>['kaboom'], throwOnError: true),
+             throwsA(isA<ProcessException>()));
+      expect(testLogger.statusText, contains('stdout'));
+      expect(testLogger.errorText, contains('stderr'));
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+
+    testUsingContext(' does not print stdout with hideStdout', () async {
+      when(mockProcessManager.runSync(<String>['whoohoo'])).thenReturn(
+        ProcessResult(0, 0, 'stdout', 'stderr')
+      );
+      expect(processUtils.runSync(<String>['whoohoo'], hideStdout: true).exitCode, 0);
+      expect(testLogger.traceText.contains('stdout'), isFalse);
+      expect(testLogger.traceText, contains('stderr'));
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+  });
+
+  group('exitsHappySync', () {
+    ProcessManager mockProcessManager;
+
+    setUp(() {
+      mockProcessManager = MockProcessManager();
+    });
+
+    testUsingContext(' succeeds on success', () async {
+      when(mockProcessManager.runSync(<String>['whoohoo'])).thenReturn(
+        ProcessResult(0, 0, '', '')
+      );
+      expect(processUtils.exitsHappySync(<String>['whoohoo']), isTrue);
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+
+    testUsingContext(' fails on failure', () async {
+      when(mockProcessManager.runSync(<String>['boohoo'])).thenReturn(
+        ProcessResult(0, 1, '', '')
+      );
+      expect(processUtils.exitsHappySync(<String>['boohoo']), isFalse);
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+  });
+
+  group('exitsHappy', () {
+    ProcessManager mockProcessManager;
+
+    setUp(() {
+      mockProcessManager = MockProcessManager();
+    });
+
+    testUsingContext(' succeeds on success', () async {
+      when(mockProcessManager.run(<String>['whoohoo'])).thenAnswer((_) {
+        return Future<ProcessResult>.value(ProcessResult(0, 0, '', ''));
+      });
+      expect(await processUtils.exitsHappy(<String>['whoohoo']), isTrue);
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+
+    testUsingContext(' fails on failure', () async {
+      when(mockProcessManager.run(<String>['boohoo'])).thenAnswer((_) {
+        return Future<ProcessResult>.value(ProcessResult(0, 1, '', ''));
+      });
+      expect(await processUtils.exitsHappy(<String>['boohoo']), isFalse);
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => mockProcessManager,
+    });
+  });
+
 }
 
 class PlainMockProcessManager extends Mock implements ProcessManager {}
diff --git a/packages/flutter_tools/test/general.shard/ios/code_signing_test.dart b/packages/flutter_tools/test/general.shard/ios/code_signing_test.dart
index b709295..1d85a9a 100644
--- a/packages/flutter_tools/test/general.shard/ios/code_signing_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/code_signing_test.dart
@@ -59,8 +59,8 @@
     });
 
     testUsingContext('No auto-sign if security or openssl not available', () async {
-      when(mockProcessManager.runSync(<String>['which', 'security']))
-          .thenReturn(exitsFail);
+      when(mockProcessManager.run(<String>['which', 'security']))
+          .thenAnswer((_) => Future<ProcessResult>.value(exitsFail));
       final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
       expect(signingConfigs, isNull);
     },
@@ -69,15 +69,21 @@
     });
 
     testUsingContext('No valid code signing certificates shows instructions', () async {
-      when(mockProcessManager.runSync(<String>['which', 'security']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(<String>['which', 'openssl']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(
-      argThat(contains('find-identity')),
+      when(mockProcessManager.run(
+        <String>['which', 'security'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        <String>['which', 'openssl'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        argThat(contains('find-identity')),
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
-      )).thenReturn(exitsHappy);
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
 
 
       Map<String, String> signingConfigs;
@@ -95,39 +101,45 @@
     });
 
     testUsingContext('Test single identity and certificate organization works', () async {
-      when(mockProcessManager.runSync(<String>['which', 'security']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(<String>['which', 'openssl']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(
-      argThat(contains('find-identity')),
+      when(mockProcessManager.run(
+        <String>['which', 'security'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        <String>['which', 'openssl'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        argThat(contains('find-identity')),
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
-      )).thenReturn(ProcessResult(
+      )).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
         1, // pid
         0, // exitCode
         '''
 1) 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 "iPhone Developer: Profile 1 (1111AAAA11)"
     1 valid identities found''',
         '',
-      ));
-      when(mockProcessManager.runSync(
+      )));
+      when(mockProcessManager.run(
         <String>['security', 'find-certificate', '-c', '1111AAAA11', '-p'],
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
-      )).thenReturn(ProcessResult(
+      )).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
         1, // pid
         0, // exitCode
         'This is a mock certificate',
         '',
-      ));
+      )));
 
       final MockProcess mockProcess = MockProcess();
       final MockStdIn mockStdIn = MockStdIn();
       final MockStream mockStdErr = MockStream();
 
       when(mockProcessManager.start(
-      argThat(contains('openssl')),
+        argThat(contains('openssl')),
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
       )).thenAnswer((Invocation invocation) => Future<Process>.value(mockProcess));
@@ -156,39 +168,45 @@
 
 
     testUsingContext('Test single identity (Catalina format) and certificate organization works', () async {
-      when(mockProcessManager.runSync(<String>['which', 'security']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(<String>['which', 'openssl']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(
-      argThat(contains('find-identity')),
+      when(mockProcessManager.run(
+        <String>['which', 'security'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        <String>['which', 'openssl'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        argThat(contains('find-identity')),
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
-      )).thenReturn(ProcessResult(
+      )).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
         1, // pid
         0, // exitCode
         '''
 1) 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 "Apple Development: Profile 1 (1111AAAA11)"
     1 valid identities found''',
         '',
-      ));
-      when(mockProcessManager.runSync(
+      )));
+      when(mockProcessManager.run(
         <String>['security', 'find-certificate', '-c', '1111AAAA11', '-p'],
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
-      )).thenReturn(ProcessResult(
+      )).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
         1, // pid
         0, // exitCode
         'This is a mock certificate',
         '',
-      ));
+      )));
 
       final MockProcess mockProcess = MockProcess();
       final MockStdIn mockStdIn = MockStdIn();
       final MockStream mockStdErr = MockStream();
 
       when(mockProcessManager.start(
-      argThat(contains('openssl')),
+        argThat(contains('openssl')),
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
       )).thenAnswer((Invocation invocation) => Future<Process>.value(mockProcess));
@@ -222,15 +240,21 @@
     });
 
     testUsingContext('Test multiple identity and certificate organization works', () async {
-      when(mockProcessManager.runSync(<String>['which', 'security']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(<String>['which', 'openssl']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(
-      argThat(contains('find-identity')),
+      when(mockProcessManager.run(
+        <String>['which', 'security'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        <String>['which', 'openssl'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        argThat(contains('find-identity')),
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
-      )).thenReturn(ProcessResult(
+      )).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
         1, // pid
         0, // exitCode
         '''
@@ -239,26 +263,26 @@
 3) 5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 "iPhone Developer: Profile 3 (3333CCCC33)"
     3 valid identities found''',
         '',
-      ));
+      )));
       mockTerminalStdInStream =
           Stream<String>.fromFuture(Future<String>.value('3'));
-      when(mockProcessManager.runSync(
+      when(mockProcessManager.run(
         <String>['security', 'find-certificate', '-c', '3333CCCC33', '-p'],
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
-      )).thenReturn(ProcessResult(
+      )).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
         1, // pid
         0, // exitCode
         'This is a mock certificate',
         '',
-      ));
+      )));
 
       final MockProcess mockOpenSslProcess = MockProcess();
       final MockStdIn mockOpenSslStdIn = MockStdIn();
       final MockStream mockOpenSslStdErr = MockStream();
 
       when(mockProcessManager.start(
-      argThat(contains('openssl')),
+        argThat(contains('openssl')),
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
       )).thenAnswer((Invocation invocation) => Future<Process>.value(mockOpenSslProcess));
@@ -298,15 +322,21 @@
 
     testUsingContext('Test multiple identity in machine mode works', () async {
       testTerminal.usesTerminalUi = false;
-      when(mockProcessManager.runSync(<String>['which', 'security']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(<String>['which', 'openssl']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(
-      argThat(contains('find-identity')),
+      when(mockProcessManager.run(
+        <String>['which', 'security'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        <String>['which', 'openssl'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        argThat(contains('find-identity')),
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
-      )).thenReturn(ProcessResult(
+      )).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
         1, // pid
         0, // exitCode
         '''
@@ -315,26 +345,26 @@
 3) 5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 "iPhone Developer: Profile 3 (3333CCCC33)"
     3 valid identities found''',
           '',
-      ));
+      )));
       mockTerminalStdInStream =
         Stream<String>.fromFuture(Future<String>.error(Exception('Cannot read from StdIn')));
-      when(mockProcessManager.runSync(
+      when(mockProcessManager.run(
         <String>['security', 'find-certificate', '-c', '1111AAAA11', '-p'],
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
-      )).thenReturn(ProcessResult(
+      )).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
         1, // pid
         0, // exitCode
         'This is a mock certificate',
         '',
-      ));
+      )));
 
       final MockProcess mockOpenSslProcess = MockProcess();
       final MockStdIn mockOpenSslStdIn = MockStdIn();
       final MockStream mockOpenSslStdErr = MockStream();
 
       when(mockProcessManager.start(
-      argThat(contains('openssl')),
+        argThat(contains('openssl')),
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
       )).thenAnswer((Invocation invocation) => Future<Process>.value(mockOpenSslProcess));
@@ -367,15 +397,21 @@
     });
 
     testUsingContext('Test saved certificate used', () async {
-      when(mockProcessManager.runSync(<String>['which', 'security']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(<String>['which', 'openssl']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(
-      argThat(contains('find-identity')),
+      when(mockProcessManager.run(
+        <String>['which', 'security'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        <String>['which', 'openssl'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        argThat(contains('find-identity')),
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
-      )).thenReturn(ProcessResult(
+      )).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
         1, // pid
         0, // exitCode
         '''
@@ -384,24 +420,24 @@
 3) 5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 "iPhone Developer: Profile 3 (3333CCCC33)"
     3 valid identities found''',
         '',
-      ));
-      when(mockProcessManager.runSync(
+      )));
+      when(mockProcessManager.run(
         <String>['security', 'find-certificate', '-c', '3333CCCC33', '-p'],
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
-      )).thenReturn(ProcessResult(
+      )).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
         1, // pid
         0, // exitCode
         'This is a mock certificate',
         '',
-      ));
+      )));
 
       final MockProcess mockOpenSslProcess = MockProcess();
       final MockStdIn mockOpenSslStdIn = MockStdIn();
       final MockStream mockOpenSslStdErr = MockStream();
 
       when(mockProcessManager.start(
-      argThat(contains('openssl')),
+        argThat(contains('openssl')),
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
       )).thenAnswer((Invocation invocation) => Future<Process>.value(mockOpenSslProcess));
@@ -438,15 +474,21 @@
     });
 
     testUsingContext('Test invalid saved certificate shows error and prompts again', () async {
-      when(mockProcessManager.runSync(<String>['which', 'security']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(<String>['which', 'openssl']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(
-      argThat(contains('find-identity')),
+      when(mockProcessManager.run(
+        <String>['which', 'security'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        <String>['which', 'openssl'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        argThat(contains('find-identity')),
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
-      )).thenReturn(ProcessResult(
+      )).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
         1, // pid
         0, // exitCode
         '''
@@ -455,19 +497,19 @@
 3) 5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 "iPhone Developer: Profile 3 (3333CCCC33)"
     3 valid identities found''',
         '',
-      ));
+      )));
       mockTerminalStdInStream =
           Stream<String>.fromFuture(Future<String>.value('3'));
-      when(mockProcessManager.runSync(
+      when(mockProcessManager.run(
         <String>['security', 'find-certificate', '-c', '3333CCCC33', '-p'],
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
-      )).thenReturn(ProcessResult(
+      )).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
         1, // pid
         0, // exitCode
         'This is a mock certificate',
         '',
-      ));
+      )));
 
 
       final MockProcess mockOpenSslProcess = MockProcess();
@@ -475,7 +517,7 @@
       final MockStream mockOpenSslStdErr = MockStream();
 
       when(mockProcessManager.start(
-      argThat(contains('openssl')),
+        argThat(contains('openssl')),
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
       )).thenAnswer((Invocation invocation) => Future<Process>.value(mockOpenSslProcess));
@@ -511,15 +553,23 @@
     });
 
     testUsingContext('find-identity failure', () async {
-      when(mockProcessManager.runSync(<String>['which', 'security']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(<String>['which', 'openssl']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(
-          argThat(contains('find-identity')),
-            environment: anyNamed('environment'),
-            workingDirectory: anyNamed('workingDirectory'),
-          )).thenReturn(ProcessResult(0, 1, '', ''));
+      when(mockProcessManager.run(
+        <String>['which', 'security'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        <String>['which', 'openssl'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        argThat(contains('find-identity')),
+        environment: anyNamed('environment'),
+        workingDirectory: anyNamed('workingDirectory'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(
+        ProcessResult(0, 1, '', '')
+      ));
 
       final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
       expect(signingConfigs, isNull);
@@ -531,15 +581,21 @@
     });
 
     testUsingContext('find-certificate failure', () async {
-      when(mockProcessManager.runSync(<String>['which', 'security']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(<String>['which', 'openssl']))
-          .thenReturn(exitsHappy);
-      when(mockProcessManager.runSync(
-          argThat(contains('find-identity')),
-            environment: anyNamed('environment'),
-            workingDirectory: anyNamed('workingDirectory'),
-          )).thenReturn(ProcessResult(
+      when(mockProcessManager.run(
+        <String>['which', 'security'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        <String>['which', 'openssl'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(exitsHappy));
+      when(mockProcessManager.run(
+        argThat(contains('find-identity')),
+        environment: anyNamed('environment'),
+        workingDirectory: anyNamed('workingDirectory'),
+      )).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
             1, // pid
             0, // exitCode
             '''
@@ -548,14 +604,16 @@
 3) 5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 "iPhone Developer: Profile 3 (3333CCCC33)"
     3 valid identities found''',
             '',
-          ));
+      )));
       mockTerminalStdInStream =
           Stream<String>.fromFuture(Future<String>.value('3'));
-      when(mockProcessManager.runSync(
+      when(mockProcessManager.run(
         <String>['security', 'find-certificate', '-c', '3333CCCC33', '-p'],
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'),
-      )).thenReturn(ProcessResult(1, 1, '', '' ));
+      )).thenAnswer((_) => Future<ProcessResult>.value(
+        ProcessResult(1, 1, '', '' ))
+      );
 
       final Map<String, String> signingConfigs = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
       expect(signingConfigs, isNull);
diff --git a/packages/flutter_tools/test/general.shard/ios/devices_test.dart b/packages/flutter_tools/test/general.shard/ios/devices_test.dart
index f2b38c0..a05f1d0 100644
--- a/packages/flutter_tools/test/general.shard/ios/devices_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/devices_test.dart
@@ -142,10 +142,13 @@
         final MockDirectory directory = MockDirectory();
         when(mockFileSystem.directory(bundlePath)).thenReturn(directory);
         when(directory.existsSync()).thenReturn(true);
-        when(mockProcessManager.run(installArgs, environment: env))
-            .thenAnswer(
-                (_) => Future<ProcessResult>.value(ProcessResult(1, 0, '', ''))
-            );
+        when(mockProcessManager.run(
+          installArgs,
+          workingDirectory: anyNamed('workingDirectory'),
+          environment: env
+        )).thenAnswer(
+          (_) => Future<ProcessResult>.value(ProcessResult(1, 0, '', ''))
+        );
 
         when(mockIMobileDevice.getInfoForDevice(any, 'CPUArchitecture'))
             .thenAnswer((_) => Future<String>.value('arm64'));
@@ -259,6 +262,21 @@
             return Future<ProcessResult>.value(ProcessResult(0, 0, '', ''));
           });
 
+          when(mockProcessManager.run(
+            argThat(contains('find-identity')),
+            environment: anyNamed('environment'),
+            workingDirectory: anyNamed('workingDirectory'),
+          )).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
+                1, // pid
+                0, // exitCode
+                '''
+    1) 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 "iPhone Developer: Profile 1 (1111AAAA11)"
+    2) da4b9237bacccdf19c0760cab7aec4a8359010b0 "iPhone Developer: Profile 2 (2222BBBB22)"
+    3) 5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 "iPhone Developer: Profile 3 (3333CCCC33)"
+        3 valid identities found''',
+                '',
+          )));
+
           // Deploy works.
           when(mockIosDeploy.runApp(
             deviceId: anyNamed('deviceId'),
diff --git a/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart b/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
index cf74b33..6870c50 100644
--- a/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
@@ -146,7 +146,10 @@
     });
 
     testUsingOsxContext('build settings is empty when xcodebuild failed to get the build settings', () {
-      when(mockProcessManager.runSync(argThat(contains(xcodebuild))))
+      when(mockProcessManager.runSync(
+               argThat(contains(xcodebuild)),
+               workingDirectory: anyNamed('workingDirectory'),
+               environment: anyNamed('environment')))
           .thenReturn(ProcessResult(0, 1, '', ''));
       expect(xcodeProjectInterpreter.getBuildSettings('', ''), const <String, String>{});
     });
diff --git a/packages/flutter_tools/test/general.shard/windows/visual_studio_test.dart b/packages/flutter_tools/test/general.shard/windows/visual_studio_test.dart
index 26a591b..d6da8bf 100644
--- a/packages/flutter_tools/test/general.shard/windows/visual_studio_test.dart
+++ b/packages/flutter_tools/test/general.shard/windows/visual_studio_test.dart
@@ -69,18 +69,23 @@
     final String finalResponse =
         json.encode(<Map<String, dynamic>>[response]);
     when<String>(result.stdout).thenReturn(finalResponse);
+    when<String>(result.stderr).thenReturn('');
     final List<String> requirementArguments = requiredComponents == null
         ? <String>[]
         : <String>['-requires', ...requiredComponents];
-    when(mockProcessManager.runSync(<String>[
-      vswherePath,
-      '-format',
-      'json',
-      '-utf8',
-      '-latest',
-      ...?additionalArguments,
-      ...?requirementArguments,
-    ])).thenAnswer((Invocation invocation) {
+    when(mockProcessManager.runSync(
+      <String>[
+        vswherePath,
+          '-format',
+          'json',
+          '-utf8',
+          '-latest',
+          ...?additionalArguments,
+          ...?requirementArguments,
+      ],
+      workingDirectory: anyNamed('workingDirectory'),
+      environment: anyNamed('environment'),
+    )).thenAnswer((Invocation invocation) {
       return result;
     });
   }
@@ -111,8 +116,11 @@
     });
 
     testUsingContext('isInstalled returns false when vswhere is missing', () {
-      when(mockProcessManager.runSync(any))
-          .thenThrow(const ProcessException('vswhere', <String>[]));
+      when(mockProcessManager.runSync(
+        any,
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenThrow(const ProcessException('vswhere', <String>[]));
 
       visualStudio = VisualStudio();
       expect(visualStudio.isInstalled, false);
@@ -123,8 +131,11 @@
     });
 
     testUsingContext('vcvarsPath returns null when vswhere is missing', () {
-      when(mockProcessManager.runSync(any))
-          .thenThrow(const ProcessException('vswhere', <String>[]));
+      when(mockProcessManager.runSync(
+        any,
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenThrow(const ProcessException('vswhere', <String>[]));
 
       visualStudio = VisualStudio();
       expect(visualStudio.vcvarsPath, isNull);
@@ -135,13 +146,24 @@
     });
 
     testUsingContext('isInstalled returns false when vswhere returns non-zero', () {
-      when(mockProcessManager.runSync(any))
-          .thenThrow(const ProcessException('vswhere', <String>[]));
+
+      when(mockProcessManager.runSync(
+        any,
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenThrow(const ProcessException('vswhere', <String>[]));
+
       final MockProcessResult result = MockProcessResult();
       when(result.exitCode).thenReturn(1);
-      when(mockProcessManager.runSync(any)).thenAnswer((Invocation invocation) {
+      when(mockProcessManager.runSync(
+        any,
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment'),
+      )).thenAnswer((Invocation invocation) {
         return result;
       });
+      when<String>(result.stdout).thenReturn('');
+      when<String>(result.stderr).thenReturn('');
 
       visualStudio = VisualStudio();
       expect(visualStudio.isInstalled, false);
diff --git a/packages/flutter_tools/test/general.shard/windows/windows_device_test.dart b/packages/flutter_tools/test/general.shard/windows/windows_device_test.dart
index c1d650f..755d08f 100644
--- a/packages/flutter_tools/test/general.shard/windows/windows_device_test.dart
+++ b/packages/flutter_tools/test/general.shard/windows/windows_device_test.dart
@@ -26,18 +26,23 @@
 
     when(notWindows.isWindows).thenReturn(false);
     when(notWindows.environment).thenReturn(const <String, String>{});
-    when(mockProcessManager.runSync(<String>[
-      'powershell', '-script="Get-CimInstance Win32_Process"'
-    ])).thenAnswer((Invocation invocation) {
+    when(mockProcessManager.runSync(
+      <String>['powershell', '-script="Get-CimInstance Win32_Process"'],
+      workingDirectory: anyNamed('workingDirectory'),
+      environment: anyNamed('environment'),
+    )).thenAnswer((Invocation invocation) {
       // The flutter tool process is returned as output to the powershell script
       final MockProcessResult result = MockProcessResult();
       when(result.exitCode).thenReturn(0);
       when<String>(result.stdout).thenReturn('$pid  $flutterToolBinary');
+      when<String>(result.stderr).thenReturn('');
       return result;
     });
-    when(mockProcessManager.run(<String>[
-      'Taskkill', '/PID', '$pid', '/F'
-    ])).thenThrow(Exception('Flutter tool process has been killed'));
+    when(mockProcessManager.run(
+      <String>['Taskkill', '/PID', '$pid', '/F'],
+      workingDirectory: anyNamed('workingDirectory'),
+      environment: anyNamed('environment'),
+    )).thenThrow(Exception('Flutter tool process has been killed'));
 
     testUsingContext('defaults', () async {
       final PrebuiltWindowsApp windowsApp = PrebuiltWindowsApp(executable: 'foo');