[flutter_tools] Use process matcher for multidex test (#127996)
Part of https://github.com/flutter/flutter/issues/127135 Part of https://github.com/flutter/flutter/issues/125115
This commit is contained in:
parent
420f442e5c
commit
7f1f765521
@ -32,10 +32,11 @@ HostPlatform _identifyMacBinaryArch(String path) {
|
||||
<String>['file', _dartBinary.path],
|
||||
);
|
||||
expect(
|
||||
result,
|
||||
ProcessResultMatcher(
|
||||
stdoutSubstring: '${_dartBinary.path}: Mach-O 64-bit executable',
|
||||
));
|
||||
result,
|
||||
ProcessResultMatcher(
|
||||
stdoutPattern: '${_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}"');
|
||||
|
@ -44,18 +44,22 @@ void main() {
|
||||
);
|
||||
|
||||
// Pre-cache iOS engine Flutter.xcframework artifacts.
|
||||
processManager.runSync(<String>[
|
||||
flutterBin,
|
||||
...getLocalEngineArguments(),
|
||||
'precache',
|
||||
'--ios',
|
||||
], workingDirectory: tempDir.path);
|
||||
ProcessResult result = processManager.runSync(
|
||||
<String>[
|
||||
flutterBin,
|
||||
...getLocalEngineArguments(),
|
||||
'precache',
|
||||
'--ios',
|
||||
],
|
||||
workingDirectory: tempDir.path,
|
||||
);
|
||||
expect(result, const ProcessResultMatcher());
|
||||
|
||||
// Pretend the SDK was on an external drive with stray "._" files in the xcframework
|
||||
hiddenFile = xcframeworkArtifact.childFile('._Info.plist')..createSync();
|
||||
|
||||
// Test a plugin example app to allow plugins validation.
|
||||
processManager.runSync(<String>[
|
||||
result = processManager.runSync(<String>[
|
||||
flutterBin,
|
||||
...getLocalEngineArguments(),
|
||||
'create',
|
||||
@ -65,6 +69,7 @@ void main() {
|
||||
'plugin',
|
||||
'hello',
|
||||
], workingDirectory: tempDir.path);
|
||||
expect(result, const ProcessResultMatcher());
|
||||
|
||||
pluginRoot = tempDir.childDirectory('hello');
|
||||
projectRoot = pluginRoot.childDirectory('example').path;
|
||||
|
@ -9,6 +9,7 @@ import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
import '../src/test_flutter_command_runner.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
void main() {
|
||||
group('pass analyze template:', () {
|
||||
@ -38,7 +39,7 @@ void main() {
|
||||
final ProcessResult result = await globals.processManager
|
||||
.run(<String>['flutter', 'analyze'], workingDirectory: projectPath);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(result, const ProcessResultMatcher());
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -30,10 +30,10 @@ void main() {
|
||||
'--target-platform=android-arm64',
|
||||
], workingDirectory: workingDirectory);
|
||||
|
||||
printOnFailure('Output of flutter build apk:');
|
||||
printOnFailure(result.stdout.toString());
|
||||
printOnFailure(result.stderr.toString());
|
||||
expect(result.stdout.toString(), contains('app-release.apk (total compressed)'));
|
||||
expect(
|
||||
result,
|
||||
const ProcessResultMatcher(stdoutPattern: 'app-release.apk (total compressed)'),
|
||||
);
|
||||
|
||||
final String line = result.stdout.toString()
|
||||
.split('\n')
|
||||
@ -49,8 +49,6 @@ void main() {
|
||||
final String commandArguments = devToolsCommand.split(runDevToolsMessage).last.trim();
|
||||
final String relativeAppSizePath = outputFilePath.split('.flutter-devtools/').last.trim();
|
||||
expect(commandArguments.contains('--appSizeBase=$relativeAppSizePath'), isTrue);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
});
|
||||
|
||||
testWithoutContext('--analyze-size flag produces expected output on hello_world for iOS', () async {
|
||||
@ -68,10 +66,10 @@ void main() {
|
||||
'--no-codesign',
|
||||
], workingDirectory: workingDirectory);
|
||||
|
||||
printOnFailure('Output of flutter build ios:');
|
||||
printOnFailure(result.stdout.toString());
|
||||
printOnFailure(result.stderr.toString());
|
||||
expect(result.stdout.toString(), contains('Dart AOT symbols accounted decompressed size'));
|
||||
expect(
|
||||
result,
|
||||
const ProcessResultMatcher(stdoutPattern: 'Dart AOT symbols accounted decompressed size'),
|
||||
);
|
||||
|
||||
final String line = result.stdout.toString()
|
||||
.split('\n')
|
||||
@ -88,7 +86,6 @@ void main() {
|
||||
|
||||
expect(commandArguments.contains('--appSizeBase=$relativeAppSizePath'), isTrue);
|
||||
expect(codeSizeDir.existsSync(), true);
|
||||
expect(result.exitCode, 0);
|
||||
tempDir.deleteSync(recursive: true);
|
||||
}, skip: !platform.isMacOS); // [intended] iOS can only be built on macos.
|
||||
|
||||
@ -105,6 +102,11 @@ void main() {
|
||||
'--enable-macos-desktop',
|
||||
], workingDirectory: workingDirectory);
|
||||
|
||||
expect(
|
||||
configResult,
|
||||
const ProcessResultMatcher(),
|
||||
);
|
||||
|
||||
printOnFailure('Output of flutter config:');
|
||||
printOnFailure(configResult.stdout.toString());
|
||||
printOnFailure(configResult.stderr.toString());
|
||||
@ -117,10 +119,10 @@ void main() {
|
||||
'--code-size-directory=${codeSizeDir.path}',
|
||||
], workingDirectory: workingDirectory);
|
||||
|
||||
printOnFailure('Output of flutter build macos:');
|
||||
printOnFailure(result.stdout.toString());
|
||||
printOnFailure(result.stderr.toString());
|
||||
expect(result.stdout.toString(), contains('Dart AOT symbols accounted decompressed size'));
|
||||
expect(
|
||||
result,
|
||||
const ProcessResultMatcher(stdoutPattern: 'Dart AOT symbols accounted decompressed size'),
|
||||
);
|
||||
|
||||
final String line = result.stdout.toString()
|
||||
.split('\n')
|
||||
@ -137,7 +139,6 @@ void main() {
|
||||
|
||||
expect(commandArguments.contains('--appSizeBase=$relativeAppSizePath'), isTrue);
|
||||
expect(codeSizeDir.existsSync(), true);
|
||||
expect(result.exitCode, 0);
|
||||
tempDir.deleteSync(recursive: true);
|
||||
}, skip: !platform.isMacOS); // [intended] this is a macos only test.
|
||||
|
||||
@ -152,13 +153,13 @@ void main() {
|
||||
'--target-platform=android-arm64',
|
||||
'--debug',
|
||||
], workingDirectory: fileSystem.path.join(getFlutterRoot(), 'examples', 'hello_world'));
|
||||
|
||||
printOnFailure('Output of flutter build apk:');
|
||||
printOnFailure(result.stdout.toString());
|
||||
printOnFailure(result.stderr.toString());
|
||||
expect(result.stderr.toString(), contains('"--analyze-size" can only be used on release builds'));
|
||||
|
||||
expect(result.exitCode, 1);
|
||||
expect(
|
||||
result,
|
||||
const ProcessResultMatcher(
|
||||
exitCode: 1,
|
||||
stderrPattern: '"--analyze-size" can only be used on release builds',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('--analyze-size is not supported in combination with --split-debug-info', () async {
|
||||
@ -177,14 +178,13 @@ void main() {
|
||||
final ProcessResult result =
|
||||
await processManager.run(command, workingDirectory: workingDirectory);
|
||||
|
||||
printOnFailure('workingDirectory: $workingDirectory');
|
||||
printOnFailure('command:\n${command.join(" ")}');
|
||||
printOnFailure('stdout:\n${result.stdout}');
|
||||
printOnFailure('stderr:\n${result.stderr}');
|
||||
|
||||
expect(result.stderr.toString(), contains('"--analyze-size" cannot be combined with "--split-debug-info"'));
|
||||
|
||||
expect(result.exitCode, 1);
|
||||
expect(
|
||||
result,
|
||||
const ProcessResultMatcher(
|
||||
exitCode: 1,
|
||||
stderrPattern: '"--analyze-size" cannot be combined with "--split-debug-info"',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('--analyze-size allows overriding the directory for code size files', () async {
|
||||
@ -211,15 +211,14 @@ void main() {
|
||||
workingDirectory: workingDirectory,
|
||||
);
|
||||
|
||||
printOnFailure('workingDirectory: $workingDirectory');
|
||||
printOnFailure('command:\n${command.join(" ")}');
|
||||
printOnFailure('stdout:\n${result.stdout}');
|
||||
printOnFailure('stderr:\n${result.stderr}');
|
||||
expect(
|
||||
result,
|
||||
const ProcessResultMatcher(),
|
||||
);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(tempDir.existsSync(), true);
|
||||
expect(tempDir.childFile('snapshot.arm64-v8a.json').existsSync(), true);
|
||||
expect(tempDir.childFile('trace.arm64-v8a.json').existsSync(), true);
|
||||
expect(tempDir, exists);
|
||||
expect(tempDir.childFile('snapshot.arm64-v8a.json'), exists);
|
||||
expect(tempDir.childFile('trace.arm64-v8a.json'), exists);
|
||||
|
||||
tempDir.deleteSync(recursive: true);
|
||||
});
|
||||
|
@ -79,7 +79,7 @@ void main() {
|
||||
'--verbose',
|
||||
], workingDirectory: exampleDir.path);
|
||||
|
||||
expect(result, ProcessResultMatcher());
|
||||
expect(result, const ProcessResultMatcher());
|
||||
|
||||
final String exampleAppApk = fileSystem.path.join(
|
||||
exampleDir.path,
|
||||
|
@ -36,8 +36,7 @@ void main() {
|
||||
'--debug',
|
||||
], workingDirectory: tempDir.path);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stdout.toString(), contains('app-debug.apk'));
|
||||
expect(result, const ProcessResultMatcher(stdoutPattern: 'app-debug.apk'));
|
||||
});
|
||||
|
||||
testWithoutContext('simple build apk without FlutterMultiDexApplication fails', () async {
|
||||
@ -52,8 +51,8 @@ void main() {
|
||||
'--debug',
|
||||
], workingDirectory: tempDir.path);
|
||||
|
||||
expect(result, const ProcessResultMatcher(exitCode: 1));
|
||||
expect(result.stderr.toString(), contains('Cannot fit requested classes in a single dex file'));
|
||||
expect(result.stderr.toString(), contains('The number of method references in a .dex file cannot exceed 64K.'));
|
||||
expect(result.exitCode, 1);
|
||||
});
|
||||
}
|
||||
|
@ -32,21 +32,27 @@ final List<String> integrationTestExtraArgs = <String>['-d', 'flutter-tester'];
|
||||
|
||||
void main() {
|
||||
setUpAll(() async {
|
||||
await processManager.run(
|
||||
<String>[
|
||||
flutterBin,
|
||||
'pub',
|
||||
'get',
|
||||
],
|
||||
workingDirectory: flutterTestDirectory
|
||||
expect(
|
||||
await processManager.run(
|
||||
<String>[
|
||||
flutterBin,
|
||||
'pub',
|
||||
'get',
|
||||
],
|
||||
workingDirectory: flutterTestDirectory
|
||||
),
|
||||
const ProcessResultMatcher(),
|
||||
);
|
||||
await processManager.run(
|
||||
<String>[
|
||||
flutterBin,
|
||||
'pub',
|
||||
'get',
|
||||
],
|
||||
workingDirectory: missingDependencyDirectory
|
||||
expect(
|
||||
await processManager.run(
|
||||
<String>[
|
||||
flutterBin,
|
||||
'pub',
|
||||
'get',
|
||||
],
|
||||
workingDirectory: missingDependencyDirectory
|
||||
),
|
||||
const ProcessResultMatcher(),
|
||||
);
|
||||
});
|
||||
|
||||
@ -112,71 +118,109 @@ void main() {
|
||||
});
|
||||
|
||||
testWithoutContext('flutter test should run a test when its name matches a regexp', () async {
|
||||
final ProcessResult result = await _runFlutterTest('filtering', automatedTestsDirectory, flutterTestDirectory,
|
||||
extraArguments: const <String>['--name', 'inc.*de']);
|
||||
expect(result.stdout, contains(RegExp(r'\+\d+: All tests passed!')));
|
||||
expect(result.exitCode, 0);
|
||||
final ProcessResult result = await _runFlutterTest(
|
||||
'filtering',
|
||||
automatedTestsDirectory,
|
||||
flutterTestDirectory,
|
||||
extraArguments: const <String>['--name', 'inc.*de'],
|
||||
);
|
||||
expect(
|
||||
result,
|
||||
ProcessResultMatcher(stdoutPattern: RegExp(r'\+\d+: All tests passed!')),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('flutter test should run a test when its name contains a string', () async {
|
||||
final ProcessResult result = await _runFlutterTest('filtering', automatedTestsDirectory, flutterTestDirectory,
|
||||
extraArguments: const <String>['--plain-name', 'include']);
|
||||
expect(result.stdout, contains(RegExp(r'\+\d+: All tests passed!')));
|
||||
expect(result.exitCode, 0);
|
||||
final ProcessResult result = await _runFlutterTest(
|
||||
'filtering',
|
||||
automatedTestsDirectory,
|
||||
flutterTestDirectory,
|
||||
extraArguments: const <String>['--plain-name', 'include'],
|
||||
);
|
||||
expect(
|
||||
result,
|
||||
ProcessResultMatcher(stdoutPattern: RegExp(r'\+\d+: All tests passed!')),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('flutter test should run a test with a given tag', () async {
|
||||
final ProcessResult result = await _runFlutterTest('filtering_tag', automatedTestsDirectory, flutterTestDirectory,
|
||||
extraArguments: const <String>['--tags', 'include-tag']);
|
||||
expect(result.stdout, contains(RegExp(r'\+\d+: All tests passed!')));
|
||||
expect(result.exitCode, 0);
|
||||
final ProcessResult result = await _runFlutterTest(
|
||||
'filtering_tag',
|
||||
automatedTestsDirectory,
|
||||
flutterTestDirectory,
|
||||
extraArguments: const <String>['--tags', 'include-tag'],
|
||||
);
|
||||
expect(
|
||||
result,
|
||||
ProcessResultMatcher(stdoutPattern: RegExp(r'\+\d+: All tests passed!')),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('flutter test should not run a test with excluded tag', () async {
|
||||
final ProcessResult result = await _runFlutterTest('filtering_tag', automatedTestsDirectory, flutterTestDirectory,
|
||||
extraArguments: const <String>['--exclude-tags', 'exclude-tag']);
|
||||
expect(result.stdout, contains(RegExp(r'\+\d+: All tests passed!')));
|
||||
expect(result.exitCode, 0);
|
||||
expect(
|
||||
result,
|
||||
ProcessResultMatcher(stdoutPattern: RegExp(r'\+\d+: All tests passed!')),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('flutter test should run all tests when tags are unspecified', () async {
|
||||
final ProcessResult result = await _runFlutterTest('filtering_tag', automatedTestsDirectory, flutterTestDirectory);
|
||||
expect(result.stdout, contains(RegExp(r'\+\d+ -1: Some tests failed\.')));
|
||||
expect(result.exitCode, 1);
|
||||
expect(
|
||||
result,
|
||||
ProcessResultMatcher(
|
||||
exitCode: 1,
|
||||
stdoutPattern: RegExp(r'\+\d+ -1: Some tests failed\.'),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('flutter test should run a widgetTest with a given tag', () async {
|
||||
final ProcessResult result = await _runFlutterTest('filtering_tag_widget', automatedTestsDirectory, flutterTestDirectory,
|
||||
extraArguments: const <String>['--tags', 'include-tag']);
|
||||
expect(result.stdout, contains(RegExp(r'\+\d+: All tests passed!')));
|
||||
expect(result.exitCode, 0);
|
||||
expect(
|
||||
result,
|
||||
ProcessResultMatcher(stdoutPattern: RegExp(r'\+\d+: All tests passed!')),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('flutter test should not run a widgetTest with excluded tag', () async {
|
||||
final ProcessResult result = await _runFlutterTest('filtering_tag_widget', automatedTestsDirectory, flutterTestDirectory,
|
||||
extraArguments: const <String>['--exclude-tags', 'exclude-tag']);
|
||||
expect(result.stdout, contains(RegExp(r'\+\d+: All tests passed!')));
|
||||
expect(result.exitCode, 0);
|
||||
expect(
|
||||
result,
|
||||
ProcessResultMatcher(stdoutPattern: RegExp(r'\+\d+: All tests passed!')),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('flutter test should run all widgetTest when tags are unspecified', () async {
|
||||
final ProcessResult result = await _runFlutterTest('filtering_tag_widget', automatedTestsDirectory, flutterTestDirectory);
|
||||
expect(result.stdout, contains(RegExp(r'\+\d+ -1: Some tests failed\.')));
|
||||
expect(result.exitCode, 1);
|
||||
expect(
|
||||
result,
|
||||
ProcessResultMatcher(
|
||||
exitCode: 1,
|
||||
stdoutPattern: RegExp(r'\+\d+ -1: Some tests failed\.'),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('flutter test should run a test with an exact name in URI format', () async {
|
||||
final ProcessResult result = await _runFlutterTest('uri_format', automatedTestsDirectory, flutterTestDirectory,
|
||||
query: 'full-name=exactTestName');
|
||||
expect(result.stdout, contains(RegExp(r'\+\d+: All tests passed!')));
|
||||
expect(result.exitCode, 0);
|
||||
expect(
|
||||
result,
|
||||
ProcessResultMatcher(stdoutPattern: RegExp(r'\+\d+: All tests passed!')),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('flutter test should run a test by line number in URI format', () async {
|
||||
final ProcessResult result = await _runFlutterTest('uri_format', automatedTestsDirectory, flutterTestDirectory,
|
||||
query: 'line=11');
|
||||
expect(result.stdout, contains(RegExp(r'\+\d+: All tests passed!')));
|
||||
expect(result.exitCode, 0);
|
||||
expect(
|
||||
result,
|
||||
ProcessResultMatcher(stdoutPattern: RegExp(r'\+\d+: All tests passed!')),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('flutter test should test runs to completion', () async {
|
||||
@ -214,8 +258,8 @@ void main() {
|
||||
});
|
||||
|
||||
testWithoutContext('flutter test should respect --serve-observatory', () async {
|
||||
late final Process process;
|
||||
late final StreamSubscription<String> sub;
|
||||
Process? process;
|
||||
StreamSubscription<String>? sub;
|
||||
try {
|
||||
process = await _runFlutterTestConcurrent('trivial', automatedTestsDirectory, flutterTestDirectory,
|
||||
extraArguments: const <String>['--start-paused', '--serve-observatory']);
|
||||
@ -231,16 +275,16 @@ void main() {
|
||||
final HttpClientRequest request = await client.getUrl(vmServiceUri);
|
||||
final HttpClientResponse response = await request.close();
|
||||
final String content = await response.transform(utf8.decoder).join();
|
||||
expect(content.contains('Dart VM Observatory'), true);
|
||||
expect(content, contains('Dart VM Observatory'));
|
||||
} finally {
|
||||
await sub.cancel();
|
||||
process.kill();
|
||||
await sub?.cancel();
|
||||
process?.kill();
|
||||
}
|
||||
});
|
||||
|
||||
testWithoutContext('flutter test should serve DevTools', () async {
|
||||
late final Process process;
|
||||
late final StreamSubscription<String> sub;
|
||||
Process? process;
|
||||
StreamSubscription<String>? sub;
|
||||
try {
|
||||
process = await _runFlutterTestConcurrent('trivial', automatedTestsDirectory, flutterTestDirectory,
|
||||
extraArguments: const <String>['--start-paused']);
|
||||
@ -256,10 +300,10 @@ void main() {
|
||||
final HttpClientRequest request = await client.getUrl(devToolsUri);
|
||||
final HttpClientResponse response = await request.close();
|
||||
final String content = await response.transform(utf8.decoder).join();
|
||||
expect(content.contains('DevTools'), true);
|
||||
expect(content, contains('DevTools'));
|
||||
} finally {
|
||||
await sub.cancel();
|
||||
process.kill();
|
||||
await sub?.cancel();
|
||||
process?.kill();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -285,7 +329,12 @@ Future<void> _testFile(
|
||||
extraArguments: extraArguments,
|
||||
);
|
||||
|
||||
expect(exec.exitCode, exitCode);
|
||||
expect(
|
||||
exec.exitCode,
|
||||
exitCode,
|
||||
reason: '"$testName" returned code ${exec.exitCode}\n\nstdout:\n'
|
||||
'${exec.stdout}\nstderr:\n${exec.stderr}',
|
||||
);
|
||||
final List<String> output = (exec.stdout as String).split('\n');
|
||||
if (output.first.startsWith('Waiting for another flutter command to release the startup lock...')) {
|
||||
output.removeAt(0);
|
||||
|
@ -128,35 +128,32 @@ abstract final class AppleTestUtils {
|
||||
/// 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
|
||||
/// The default for [exitCode] will be 0 while
|
||||
/// [stdoutPattern] and [stderrPattern] are both optional
|
||||
class ProcessResultMatcher extends Matcher {
|
||||
ProcessResultMatcher({
|
||||
this.expectedExitCode = 0,
|
||||
this.stdoutSubstring,
|
||||
this.stderrSubstring,
|
||||
const ProcessResultMatcher({
|
||||
this.exitCode = 0,
|
||||
this.stdoutPattern,
|
||||
this.stderrPattern,
|
||||
});
|
||||
|
||||
/// The expected exit code to get returned from a process run
|
||||
final int expectedExitCode;
|
||||
final int exitCode;
|
||||
|
||||
/// Substring to find in the process's stdout
|
||||
final String? stdoutSubstring;
|
||||
final Pattern? stdoutPattern;
|
||||
|
||||
/// Substring to find in the process's stderr
|
||||
final String? stderrSubstring;
|
||||
|
||||
bool _foundStdout = true;
|
||||
bool _foundStderr = true;
|
||||
final Pattern? stderrPattern;
|
||||
|
||||
@override
|
||||
Description describe(Description description) {
|
||||
description.add('a process with exit code $expectedExitCode');
|
||||
if (stdoutSubstring != null) {
|
||||
description.add(' and stdout: "$stdoutSubstring"');
|
||||
description.add('a process with exit code $exitCode');
|
||||
if (stdoutPattern != null) {
|
||||
description.add(' and stdout: "$stdoutPattern"');
|
||||
}
|
||||
if (stderrSubstring != null) {
|
||||
description.add(' and stderr: "$stderrSubstring"');
|
||||
if (stderrPattern != null) {
|
||||
description.add(' and stderr: "$stderrPattern"');
|
||||
}
|
||||
|
||||
return description;
|
||||
@ -165,18 +162,27 @@ class ProcessResultMatcher extends Matcher {
|
||||
@override
|
||||
bool matches(dynamic item, Map<dynamic, dynamic> matchState) {
|
||||
final ProcessResult result = item as ProcessResult;
|
||||
bool foundStdout = true;
|
||||
bool foundStderr = true;
|
||||
|
||||
if (stdoutSubstring != null) {
|
||||
_foundStdout = (result.stdout as String).contains(stdoutSubstring!);
|
||||
matchState['stdout'] = result.stdout;
|
||||
final String stdout = result.stdout as String;
|
||||
final String stderr = result.stderr as String;
|
||||
if (stdoutPattern != null) {
|
||||
foundStdout = stdout.contains(stdoutPattern!);
|
||||
matchState['stdout'] = stdout;
|
||||
} else if (stdout.isNotEmpty) {
|
||||
// even if we were not asserting on stdout, show stdout for debug purposes
|
||||
matchState['stdout'] = stdout;
|
||||
}
|
||||
|
||||
if (stderrSubstring != null) {
|
||||
_foundStderr = (result.stderr as String).contains(stderrSubstring!);
|
||||
matchState['stderr'] = result.stderr;
|
||||
if (stderrPattern != null) {
|
||||
foundStderr = stderr.contains(stderrPattern!);
|
||||
matchState['stderr'] = stderr;
|
||||
} else if (stderr.isNotEmpty) {
|
||||
matchState['stderr'] = stderr;
|
||||
}
|
||||
|
||||
return result.exitCode == expectedExitCode && _foundStdout && _foundStderr;
|
||||
return result.exitCode == exitCode && foundStdout && foundStderr;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -188,16 +194,16 @@ class ProcessResultMatcher extends Matcher {
|
||||
) {
|
||||
final ProcessResult result = item! as ProcessResult;
|
||||
|
||||
if (result.exitCode != expectedExitCode) {
|
||||
mismatchDescription.add('Actual exitCode was ${result.exitCode}');
|
||||
if (result.exitCode != exitCode) {
|
||||
mismatchDescription.add('Actual exitCode was ${result.exitCode}\n');
|
||||
}
|
||||
|
||||
if (matchState.containsKey('stdout')) {
|
||||
mismatchDescription.add('Actual stdout:\n${matchState["stdout"]}');
|
||||
mismatchDescription.add('Actual stdout:\n${matchState["stdout"]}\n');
|
||||
}
|
||||
|
||||
if (matchState.containsKey('stderr')) {
|
||||
mismatchDescription.add('Actual stderr:\n${matchState["stderr"]}');
|
||||
mismatchDescription.add('Actual stderr:\n${matchState["stderr"]}\n');
|
||||
}
|
||||
|
||||
return mismatchDescription;
|
||||
|
@ -20,8 +20,13 @@ void main() {
|
||||
'debug',
|
||||
]);
|
||||
|
||||
expect(result.exitCode, 1);
|
||||
expect(result.stderr, contains('PROJECT_DIR environment variable must be set to the location of Flutter project to be built.'));
|
||||
expect(
|
||||
result,
|
||||
const ProcessResultMatcher(
|
||||
exitCode: 1,
|
||||
stderrPattern: 'PROJECT_DIR environment variable must be set to the location of Flutter project to be built.',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('tool_backend.dart exits if FLUTTER_ROOT is not set', () async {
|
||||
@ -37,8 +42,13 @@ void main() {
|
||||
'PROJECT_DIR': examplePath,
|
||||
}, includeParentEnvironment: false); // Prevent FLUTTER_ROOT set by test environment from leaking
|
||||
|
||||
expect(result.exitCode, 1);
|
||||
expect(result.stderr, contains('FLUTTER_ROOT environment variable must be set to the location of the Flutter SDK.'));
|
||||
expect(
|
||||
result,
|
||||
const ProcessResultMatcher(
|
||||
exitCode: 1,
|
||||
stderrPattern: 'FLUTTER_ROOT environment variable must be set to the location of the Flutter SDK.',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('tool_backend.dart exits if local engine does not match build mode', () async {
|
||||
@ -52,7 +62,12 @@ void main() {
|
||||
'LOCAL_ENGINE': 'release_foo_bar', // Does not contain "debug",
|
||||
});
|
||||
|
||||
expect(result.exitCode, 1);
|
||||
expect(result.stderr, contains("ERROR: Requested build with Flutter local engine at 'release_foo_bar'"));
|
||||
expect(
|
||||
result,
|
||||
const ProcessResultMatcher(
|
||||
exitCode: 1,
|
||||
stderrPattern: "ERROR: Requested build with Flutter local engine at 'release_foo_bar'",
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user