Unverified Commit f796e047 authored by Christopher Fujino's avatar Christopher Fujino Committed by GitHub

Verbose process exceptions (#61552)

parent 9ef81927
......@@ -226,6 +226,7 @@ class _PosixUtils extends OperatingSystemUtils {
_processUtils.runSync(
<String>['unzip', '-o', '-q', file.path, '-d', targetDirectory.path],
throwOnError: true,
verboseExceptions: true,
);
}
......
......@@ -231,6 +231,7 @@ abstract class ProcessUtils {
RunResult runSync(
List<String> cmd, {
bool throwOnError = false,
bool verboseExceptions = false,
RunResultChecker allowedFailures,
bool hideStdout = false,
String workingDirectory,
......@@ -408,6 +409,7 @@ class _DefaultProcessUtils implements ProcessUtils {
RunResult runSync(
List<String> cmd, {
bool throwOnError = false,
bool verboseExceptions = false,
RunResultChecker allowedFailures,
bool hideStdout = false,
String workingDirectory,
......@@ -449,7 +451,12 @@ class _DefaultProcessUtils implements ProcessUtils {
}
if (failedExitCode && throwOnError) {
runResult.throwException('The command failed');
String message = 'The command failed';
if (verboseExceptions) {
message = 'The command failed\nStdout:\n${runResult.stdout}\n'
'Stderr:\n${runResult.stderr}';
}
runResult.throwException(message);
}
return runResult;
......
......@@ -89,6 +89,31 @@ void main() {
});
});
testWithoutContext('If unzip fails, include stderr in exception text', () {
const String exceptionMessage = 'Something really bad happened.';
when(mockProcessManager.runSync(
<String>['unzip', '-o', '-q', null, '-d', null],
)).thenReturn(ProcessResult(0, 1, '', exceptionMessage));
final MockFileSystem fileSystem = MockFileSystem();
final MockFile mockFile = MockFile();
final MockDirectory mockDirectory = MockDirectory();
when(fileSystem.file(any)).thenReturn(mockFile);
when(mockFile.readAsBytesSync()).thenThrow(
const FileSystemException(exceptionMessage),
);
final OperatingSystemUtils osUtils = OperatingSystemUtils(
fileSystem: fileSystem,
logger: BufferLogger.test(),
platform: FakePlatform(operatingSystem: 'linux'),
processManager: mockProcessManager,
);
expect(
() => osUtils.unzip(mockFile, mockDirectory),
throwsProcessException(message: exceptionMessage),
);
});
group('gzip on Windows:', () {
testWithoutContext('verifyGzip returns false on a FileSystemException', () {
final MockFileSystem fileSystem = MockFileSystem();
......@@ -148,5 +173,6 @@ void main() {
}
class MockProcessManager extends Mock implements ProcessManager {}
class MockDirectory extends Mock implements Directory {}
class MockFileSystem extends Mock implements FileSystem {}
class MockFile extends Mock implements File {}
......@@ -286,12 +286,33 @@ void main() {
expect(processUtils.runSync(<String>['boohoo']).exitCode, 1);
});
testWithoutContext(' throws on failure with throwOnError', () async {
testWithoutContext('throws on failure with throwOnError', () async {
const String stderr = 'Something went wrong.';
when(mockProcessManager.runSync(<String>['kaboom'])).thenReturn(
ProcessResult(0, 1, '', '')
ProcessResult(0, 1, '', stderr),
);
try {
processUtils.runSync(<String>['kaboom'], throwOnError: true);
fail('ProcessException expected.');
} on ProcessException catch (e) {
expect(e, isA<ProcessException>());
expect(e.message.contains(stderr), false);
}
});
testWithoutContext('throws with stderr in exception on failure with verboseExceptions', () async {
const String stderr = 'Something went wrong.';
when(mockProcessManager.runSync(<String>['verybad'])).thenReturn(
ProcessResult(0, 1, '', stderr),
);
expect(
() => processUtils.runSync(
<String>['verybad'],
throwOnError: true,
verboseExceptions: true,
),
throwsProcessException(message: stderr),
);
expect(() => processUtils.runSync(<String>['kaboom'], throwOnError: true),
throwsA(isA<ProcessException>()));
});
testWithoutContext(' does not throw on allowed Failures', () async {
......
......@@ -13,7 +13,7 @@ import 'package:vm_service/vm_service.dart' as vm_service;
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/process.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/commands/create.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart';
import 'package:flutter_tools/src/runner/flutter_command_runner.dart';
......@@ -106,15 +106,17 @@ Matcher throwsToolExit({ int exitCode, Pattern message }) {
/// Matcher for [ToolExit]s.
final test_package.TypeMatcher<ToolExit> isToolExit = isA<ToolExit>();
/// Matcher for functions that throw [ProcessExit].
Matcher throwsProcessExit([ dynamic exitCode ]) {
return exitCode == null
? throwsA(isProcessExit)
: throwsA(allOf(isProcessExit, (ProcessExit e) => e.exitCode == exitCode));
/// Matcher for functions that throw [ProcessException].
Matcher throwsProcessException({ Pattern message }) {
Matcher matcher = isProcessException;
if (message != null) {
matcher = allOf(matcher, (ProcessException e) => e.message?.contains(message));
}
return throwsA(matcher);
}
/// Matcher for [ProcessExit]s.
final test_package.TypeMatcher<ProcessExit> isProcessExit = isA<ProcessExit>();
/// Matcher for [ProcessException]s.
final test_package.TypeMatcher<ProcessException> isProcessException = isA<ProcessException>();
/// Creates a flutter project in the [temp] directory using the
/// [arguments] list if specified, or `--no-pub` if not.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment