diff --git a/packages/flutter_tools/test/host_cross_arch.shard/cache_test.dart b/packages/flutter_tools/test/host_cross_arch.shard/cache_test.dart index 4cacee849c..e1c62e96c2 100644 --- a/packages/flutter_tools/test/host_cross_arch.shard/cache_test.dart +++ b/packages/flutter_tools/test/host_cross_arch.shard/cache_test.dart @@ -31,6 +31,11 @@ HostPlatform _identifyMacBinaryArch(String path) { final ProcessResult result = processManager.runSync( ['file', _dartBinary.path], ); + expect( + result, + ProcessResultMatcher( + stdoutSubstring: '${_dartBinary.path}: Mach-O 64-bit executable', + )); final RegExpMatch? match = pattern.firstMatch(result.stdout as String); if (match == null) { fail('Unrecognized STDOUT from `file`: "${result.stdout}"'); diff --git a/packages/flutter_tools/test/integration.shard/gradle_non_android_plugin_test.dart b/packages/flutter_tools/test/integration.shard/gradle_non_android_plugin_test.dart index 3703ed600f..96aebe812a 100644 --- a/packages/flutter_tools/test/integration.shard/gradle_non_android_plugin_test.dart +++ b/packages/flutter_tools/test/integration.shard/gradle_non_android_plugin_test.dart @@ -4,6 +4,7 @@ import 'package:file/file.dart'; import 'package:file_testing/file_testing.dart'; +import 'package:flutter_tools/src/base/io.dart'; import '../src/common.dart'; import 'test_utils.dart'; @@ -68,7 +69,7 @@ void main() { // Build example APK final Directory exampleDir = projectRoot.childDirectory('example'); - processManager.runSync([ + final ProcessResult result = processManager.runSync([ flutterBin, ...getLocalEngineArguments(), 'build', @@ -78,6 +79,8 @@ void main() { '--verbose', ], workingDirectory: exampleDir.path); + expect(result, ProcessResultMatcher()); + final String exampleAppApk = fileSystem.path.join( exampleDir.path, 'build', diff --git a/packages/flutter_tools/test/integration.shard/test_utils.dart b/packages/flutter_tools/test/integration.shard/test_utils.dart index ceb90a5084..c1c65ce253 100644 --- a/packages/flutter_tools/test/integration.shard/test_utils.dart +++ b/packages/flutter_tools/test/integration.shard/test_utils.dart @@ -124,3 +124,82 @@ abstract final class AppleTestUtils { return nmOutput.isEmpty ? const [] : nmOutput.split('\n'); } } + +/// Matcher to be used for [ProcessResult] returned +/// from a process run +/// +/// The default for [expectedExitCode] will be 0 while +/// [stdoutSubstring] and [stderrSubstring] are both optional +class ProcessResultMatcher extends Matcher { + ProcessResultMatcher({ + this.expectedExitCode = 0, + this.stdoutSubstring, + this.stderrSubstring, + }); + + /// The expected exit code to get returned from a process run + final int expectedExitCode; + + /// Substring to find in the process's stdout + final String? stdoutSubstring; + + /// Substring to find in the process's stderr + final String? stderrSubstring; + + bool _foundStdout = true; + bool _foundStderr = true; + + @override + Description describe(Description description) { + description.add('a process with exit code $expectedExitCode'); + if (stdoutSubstring != null) { + description.add(' and stdout: "$stdoutSubstring"'); + } + if (stderrSubstring != null) { + description.add(' and stderr: "$stderrSubstring"'); + } + + return description; + } + + @override + bool matches(dynamic item, Map matchState) { + final ProcessResult result = item as ProcessResult; + + if (stdoutSubstring != null) { + _foundStdout = (result.stdout as String).contains(stdoutSubstring!); + matchState['stdout'] = result.stdout; + } + + if (stderrSubstring != null) { + _foundStderr = (result.stderr as String).contains(stderrSubstring!); + matchState['stderr'] = result.stderr; + } + + return result.exitCode == expectedExitCode && _foundStdout && _foundStderr; + } + + @override + Description describeMismatch( + Object? item, + Description mismatchDescription, + Map matchState, + bool verbose, + ) { + final ProcessResult result = item! as ProcessResult; + + if (result.exitCode != expectedExitCode) { + mismatchDescription.add('Actual exitCode was ${result.exitCode}'); + } + + if (matchState.containsKey('stdout')) { + mismatchDescription.add('Actual stdout:\n${matchState["stdout"]}'); + } + + if (matchState.containsKey('stderr')) { + mismatchDescription.add('Actual stderr:\n${matchState["stderr"]}'); + } + + return mismatchDescription; + } +}