Add exception to FakeCommand (#75545)

This commit is contained in:
Jenn Magder 2021-02-09 10:07:46 -08:00 committed by GitHub
parent bbc1614aa9
commit 152d88a3df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 129 additions and 181 deletions

View file

@ -184,19 +184,17 @@ void main() {
});
testUsingContext('fetchLatestVersion throws toolExit if HEAD is detached', () async {
processManager.addCommands(<FakeCommand>[
const FakeCommand(command: <String>[
processManager.addCommands(const <FakeCommand>[
FakeCommand(command: <String>[
'git', 'fetch', '--tags'
]),
FakeCommand(
command: const <String>['git', 'rev-parse', '--verify', '@{u}'],
onRun: () {
throw const ProcessException(
'git',
<String>['rev-parse', '--verify', '@{u}'],
'fatal: HEAD does not point to a branch',
);
}
command: <String>['git', 'rev-parse', '--verify', '@{u}'],
exception: ProcessException(
'git',
<String>['rev-parse', '--verify', '@{u}'],
'fatal: HEAD does not point to a branch',
),
),
]);
@ -211,19 +209,17 @@ void main() {
});
testUsingContext('fetchRemoteRevision throws toolExit if no upstream configured', () async {
processManager.addCommands(<FakeCommand>[
const FakeCommand(command: <String>[
processManager.addCommands(const <FakeCommand>[
FakeCommand(command: <String>[
'git', 'fetch', '--tags'
]),
FakeCommand(
command: const <String>['git', 'rev-parse', '--verify', '@{u}'],
onRun: () {
throw const ProcessException(
'git',
<String>['rev-parse', '--verify', '@{u}'],
'fatal: no upstream configured for branch',
);
},
command: <String>['git', 'rev-parse', '--verify', '@{u}'],
exception: ProcessException(
'git',
<String>['rev-parse', '--verify', '@{u}'],
'fatal: no upstream configured for branch',
),
),
]);
@ -242,18 +238,16 @@ void main() {
testUsingContext('git exception during attemptReset throwsToolExit', () async {
const String revision = 'abc123';
const String errorMessage = 'fatal: Could not parse object ´$revision´';
processManager.addCommands(<FakeCommand>[
FakeCommand(
command: const <String>['git', 'reset', '--hard', revision],
onRun: () {
throw const ProcessException(
'git',
<String>['reset', '--hard', revision],
errorMessage,
);
},
processManager.addCommand(
const FakeCommand(
command: <String>['git', 'reset', '--hard', revision],
exception: ProcessException(
'git',
<String>['reset', '--hard', revision],
errorMessage,
),
),
]);
);
await expectLater(
() async => await realCommandRunner.attemptReset(revision),

View file

@ -46,14 +46,12 @@ void main() {
});
testUsingContext('AndroidStudioValidator gives doctor error on java crash', () async {
fakeProcessManager.addCommand(FakeCommand(
command: const <String>[
fakeProcessManager.addCommand(const FakeCommand(
command: <String>[
'/opt/android-studio-with-cheese-5.0/jre/bin/java',
'-version',
],
onRun: () {
throw const ProcessException('java', <String>['-version']);
},
exception: ProcessException('java', <String>['-version']),
));
const String installPath = '/opt/android-studio-with-cheese-5.0';
const String studioHome = '$home/.AndroidStudioWithCheese5.0';

View file

@ -228,18 +228,16 @@ void main() {
],
stdout: 'devtools 0.9.6',
),
FakeCommand(
command: const <String>[
'pub',
'global',
'run',
'devtools',
'--no-launch-browser',
'--vm-uri=http://127.0.0.1:1234/abcdefg',
],
onRun: () {
throw const ProcessException('pub', <String>[]);
}
const FakeCommand(
command: <String>[
'pub',
'global',
'run',
'devtools',
'--no-launch-browser',
'--vm-uri=http://127.0.0.1:1234/abcdefg',
],
exception: ProcessException('pub', <String>[]),
)
]),
);
@ -273,18 +271,16 @@ void main() {
],
stdout: 'devtools 0.9.6',
),
FakeCommand(
command: const <String>[
'pub',
'global',
'run',
'devtools',
'--no-launch-browser',
'--vm-uri=http://127.0.0.1:1234/abcdefg',
],
onRun: () {
throw const ProcessException('pub', <String>[]);
}
const FakeCommand(
command: <String>[
'pub',
'global',
'run',
'devtools',
'--no-launch-browser',
'--vm-uri=http://127.0.0.1:1234/abcdefg',
],
exception: ProcessException('pub', <String>[]),
)
]),
);

View file

@ -137,9 +137,7 @@ void main() {
], environment: const <String, String>{
'PATH': '/usr/bin:null',
...kDyLdLibEntry,
}, onRun: () {
throw const ProcessException('ios-deploy', <String>[]);
})
}, exception: const ProcessException('ios-deploy', <String>[])),
]);
final IOSDevice device = setUpIOSDevice(processManager: processManager, artifacts: artifacts);
final bool isAppInstalled = await device.isAppInstalled(iosApp);
@ -244,9 +242,7 @@ void main() {
], environment: const <String, String>{
'PATH': '/usr/bin:null',
...kDyLdLibEntry,
}, onRun: () {
throw const ProcessException('ios-deploy', <String>[]);
})
}, exception: const ProcessException('ios-deploy', <String>[])),
]);
final IOSDevice device = setUpIOSDevice(processManager: processManager, artifacts: artifacts);
final bool wasAppInstalled = await device.installApp(iosApp);
@ -267,9 +263,7 @@ void main() {
], environment: const <String, String>{
'PATH': '/usr/bin:null',
...kDyLdLibEntry,
}, onRun: () {
throw const ProcessException('ios-deploy', <String>[]);
})
}, exception: const ProcessException('ios-deploy', <String>[])),
]);
final IOSDevice device = setUpIOSDevice(processManager: processManager, artifacts: artifacts);
final bool wasAppUninstalled = await device.uninstallApp(iosApp);

View file

@ -799,17 +799,15 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text'''
});
testWithoutContext('.install() handles exceptions', () async {
fakeProcessManager.addCommand(FakeCommand(
command: const <String>[
fakeProcessManager.addCommand(const FakeCommand(
command: <String>[
'xcrun',
'simctl',
'install',
deviceId,
appId,
],
onRun: () {
throw const ProcessException('xcrun', <String>[]);
},
exception: ProcessException('xcrun', <String>[]),
));
expect(
@ -819,17 +817,15 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text'''
});
testWithoutContext('.uninstall() handles exceptions', () async {
fakeProcessManager.addCommand(FakeCommand(
command: const <String>[
fakeProcessManager.addCommand(const FakeCommand(
command: <String>[
'xcrun',
'simctl',
'uninstall',
deviceId,
appId,
],
onRun: () {
throw const ProcessException('xcrun', <String>[]);
},
exception: ProcessException('xcrun', <String>[]),
));
expect(
@ -839,17 +835,15 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text'''
});
testWithoutContext('.launch() handles exceptions', () async {
fakeProcessManager.addCommand(FakeCommand(
command: const <String>[
fakeProcessManager.addCommand(const FakeCommand(
command: <String>[
'xcrun',
'simctl',
'launch',
deviceId,
appId,
],
onRun: () {
throw const ProcessException('xcrun', <String>[]);
},
exception: ProcessException('xcrun', <String>[]),
));
expect(

View file

@ -50,18 +50,6 @@ void main() {
);
});
// Work around https://github.com/flutter/flutter/issues/56415.
testWithoutContext('xcodebuild versionText returns null when xcodebuild is not installed', () {
when(processManager.runSync(<String>['which', 'sysctl']))
.thenReturn(ProcessResult(0, 0, '', ''));
when(processManager.runSync(<String>['sysctl', 'hw.optional.arm64']))
.thenReturn(ProcessResult(0, 1, '', ''));
when(processManager.runSync(<String>['xcrun', 'xcodebuild', '-version']))
.thenThrow(const ProcessException(xcodebuild, <String>['-version']));
expect(xcodeProjectInterpreter.versionText, isNull);
});
testWithoutContext('xcodebuild build settings flakes', () async {
const Duration delay = Duration(seconds: 1);
processManager.processFactory = mocks.flakyProcessFactory(
@ -143,6 +131,19 @@ void main() {
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
testWithoutContext('xcodebuild versionText returns null when xcodebuild is not installed', () {
fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand,
kARMCheckCommand,
FakeCommand(
command: <String>['xcrun', 'xcodebuild', '-version'],
exception: ProcessException(xcodebuild, <String>['-version']),
),
]);
expect(xcodeProjectInterpreter.versionText, isNull);
});
testWithoutContext('xcodebuild versionText returns formatted version text', () {
fakeProcessManager.addCommands(const <FakeCommand>[
kWhichSysctlCommand,

View file

@ -7,7 +7,7 @@
import 'dart:async';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/io.dart' show ProcessException, ProcessResult;
import 'package:flutter_tools/src/base/io.dart' show ProcessException;
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/build_info.dart';
@ -29,89 +29,6 @@ void main() {
logger = BufferLogger.test();
});
// Group exists to work around https://github.com/flutter/flutter/issues/56415.
// Do not add more `MockProcessManager` tests.
group('MockProcessManager', () {
ProcessManager processManager;
setUp(() {
processManager = MockProcessManager();
});
group('Xcode', () {
Xcode xcode;
MockXcodeProjectInterpreter mockXcodeProjectInterpreter;
setUp(() {
mockXcodeProjectInterpreter = MockXcodeProjectInterpreter();
xcode = Xcode.test(
processManager: processManager,
xcodeProjectInterpreter: mockXcodeProjectInterpreter,
);
});
testWithoutContext('xcodeSelectPath returns null when xcode-select is not installed', () {
when(processManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']))
.thenThrow(const ProcessException('/usr/bin/xcode-select', <String>['--print-path']));
expect(xcode.xcodeSelectPath, isNull);
when(processManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']))
.thenThrow(ArgumentError('Invalid argument(s): Cannot find executable for /usr/bin/xcode-select'));
expect(xcode.xcodeSelectPath, isNull);
});
testWithoutContext('eulaSigned is false when clang is not installed', () {
when(mockXcodeProjectInterpreter.xcrunCommand()).thenReturn(<String>['xcrun']);
when(processManager.runSync(<String>['which', 'sysctl']))
.thenReturn(ProcessResult(1, 0, '', ''));
when(processManager.runSync(<String>['sysctl', 'hw.optional.arm64']))
.thenReturn(ProcessResult(123, 1, '', ''));
when(processManager.runSync(<String>['xcrun', 'clang']))
.thenThrow(const ProcessException('xcrun', <String>['clang']));
expect(xcode.eulaSigned, isFalse);
});
});
group('xcdevice', () {
XCDevice xcdevice;
Xcode xcode;
setUp(() {
xcode = Xcode.test(
processManager: FakeProcessManager.any(),
xcodeProjectInterpreter: XcodeProjectInterpreter.test(
processManager: FakeProcessManager.any(),
),
);
xcdevice = XCDevice(
processManager: processManager,
logger: logger,
xcode: xcode,
platform: null,
artifacts: Artifacts.test(),
cache: Cache.test(),
iproxy: IProxy.test(logger: logger, processManager: processManager),
);
});
testWithoutContext('available devices xcdevice fails', () async {
when(processManager.run(<String>['xcrun', 'xcdevice', 'list', '--timeout', '2']))
.thenThrow(const ProcessException('xcrun', <String>['xcdevice', 'list', '--timeout', '2']));
expect(await xcdevice.getAvailableIOSDevices(), isEmpty);
});
testWithoutContext('diagnostics xcdevice fails', () async {
when(processManager.run(<String>['xcrun', 'xcdevice', 'list', '--timeout', '2']))
.thenThrow(const ProcessException('xcrun', <String>['xcdevice', 'list', '--timeout', '2']));
expect(await xcdevice.getDiagnostics(), isEmpty);
});
});
});
group('FakeProcessManager', () {
FakeProcessManager fakeProcessManager;
@ -200,6 +117,24 @@ void main() {
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
testWithoutContext('xcodeSelectPath returns null when xcode-select is not installed', () {
fakeProcessManager.addCommand(const FakeCommand(
command: <String>['/usr/bin/xcode-select', '--print-path'],
exception: ProcessException('/usr/bin/xcode-select', <String>['--print-path']),
));
expect(xcode.xcodeSelectPath, isNull);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
fakeProcessManager.addCommand(FakeCommand(
command: const <String>['/usr/bin/xcode-select', '--print-path'],
exception: ArgumentError('Invalid argument(s): Cannot find executable for /usr/bin/xcode-select'),
));
expect(xcode.xcodeSelectPath, isNull);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
testWithoutContext('xcodeVersionSatisfactory is false when version is less than minimum', () {
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(9);
@ -343,6 +278,18 @@ void main() {
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
testWithoutContext('eulaSigned is false when clang is not installed', () {
when(mockXcodeProjectInterpreter.xcrunCommand()).thenReturn(<String>['xcrun']);
fakeProcessManager.addCommand(
const FakeCommand(
command: <String>['xcrun', 'clang'],
exception: ProcessException('xcrun', <String>['clang']),
),
);
expect(xcode.eulaSigned, isFalse);
});
testWithoutContext('eulaSigned is true when clang output indicates EULA has been accepted', () {
fakeProcessManager.addCommands(
const <FakeCommand>[
@ -609,6 +556,15 @@ void main() {
Artifacts: () => Artifacts.test(),
});
testWithoutContext('available devices xcdevice fails', () async {
fakeProcessManager.addCommand(const FakeCommand(
command: <String>['xcrun', 'xcdevice', 'list', '--timeout', '2'],
exception: ProcessException('xcrun', <String>['xcdevice', 'list', '--timeout', '2']),
));
expect(await xcdevice.getAvailableIOSDevices(), isEmpty);
});
testWithoutContext('uses timeout', () async {
fakeProcessManager.addCommand(const FakeCommand(
command: <String>['xcrun', 'xcdevice', 'list', '--timeout', '20'],
@ -737,6 +693,15 @@ void main() {
Platform: () => macPlatform,
});
testWithoutContext('diagnostics xcdevice fails', () async {
fakeProcessManager.addCommand(const FakeCommand(
command: <String>['xcrun', 'xcdevice', 'list', '--timeout', '2'],
exception: ProcessException('xcrun', <String>['xcdevice', 'list', '--timeout', '2']),
));
expect(await xcdevice.getDiagnostics(), isEmpty);
});
testUsingContext('returns error message', () async {
const String devicesOutput = '''
[
@ -843,5 +808,4 @@ void main() {
});
}
class MockProcessManager extends Mock implements ProcessManager {}
class MockXcodeProjectInterpreter extends Mock implements XcodeProjectInterpreter {}

View file

@ -33,6 +33,7 @@ class FakeCommand {
this.stderr = '',
this.completer,
this.stdin,
this.exception,
}) : assert(command != null),
assert(duration != null),
assert(exitCode != null);
@ -97,6 +98,9 @@ class FakeCommand {
/// [FakeProcess].
final IOSink stdin;
/// If provided, this exception will be thrown when the fake command is run.
final dynamic exception;
void _matches(
List<String> command,
String workingDirectory,
@ -229,6 +233,9 @@ abstract class FakeProcessManager implements ProcessManager {
) {
_pid += 1;
final FakeCommand fakeCommand = findCommand(command, workingDirectory, environment, encoding);
if (fakeCommand.exception != null) {
throw fakeCommand.exception;
}
if (fakeCommand.onRun != null) {
fakeCommand.onRun();
}