Skip to content

Commit 7a16a14

Browse files
committed
Supporting passing a filename that contains a list of arguments as the last argument
Allows the final argument to be `@filename` where `filename` is a path (relative to `cwd`) to a file that contains arguments to replace it before parsing. This allows arguments longer than Windows supports to be provided (see Dart-Code/Dart-Code#5473).
1 parent 84eba11 commit 7a16a14

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

pkgs/test/CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
## 1.25.16-wip
22

3+
* Allow the final argument to be a filename prefixed with `@` that contains a
4+
list of arguments as if they had been provided on the command line directly.
5+
36
## 1.25.15
47

58
* Allow the latest version of `package:shelf_web_socket`.

pkgs/test/test/runner/runner_test.dart

+37
Original file line numberDiff line numberDiff line change
@@ -868,4 +868,41 @@ void main() {
868868
await test.shouldExit(0);
869869
}, skip: 'https://github.com/dart-lang/test/issues/1803');
870870
});
871+
872+
group('using @file as the final argument', () {
873+
test('prints a suitable message if the file does not exist', () async {
874+
var test = await runTest(['@mytestfile']);
875+
expect(
876+
test.stderr,
877+
emitsThrough(
878+
contains('Failed to read the file "mytestfile" for arguments')));
879+
await test.shouldExit(64);
880+
});
881+
882+
test('runs test suites provided in the file', () async {
883+
await d.file('test.dart', _success).create();
884+
await d.file('mytestargs.txt', 'test.dart').create();
885+
var test = await runTest(['@mytestargs.txt']);
886+
expect(test.stdout, emitsThrough(contains('+1: All tests passed!')));
887+
await test.shouldExit(0);
888+
});
889+
890+
test('handles empty lines in the file', () async {
891+
await d.file('test.dart', _success).create();
892+
await d.file('mytestargs.txt', '\n\r\ntest.dart\r\n').create();
893+
var test = await runTest(['@mytestargs.txt']);
894+
expect(test.stdout, emitsThrough(contains('+1: All tests passed!')));
895+
await test.shouldExit(0);
896+
});
897+
898+
test('handles other arguments in the file', () async {
899+
await d.file('mytestargs.txt', '--help').create();
900+
var test = await runTest(['@mytestargs.txt']);
901+
expectStdoutEquals(test, '''
902+
Runs tests in this package.
903+
904+
$_usage''');
905+
await test.shouldExit(0);
906+
});
907+
});
871908
}

pkgs/test_core/lib/src/executable.dart

+23
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,29 @@ Future<void> _execute(List<String> args) async {
6868
: StreamGroup.merge(
6969
[ProcessSignal.sigterm.watch(), ProcessSignal.sigint.watch()]);
7070

71+
// The last arg can start with @ and is a file that contains a list
72+
// of args that should replace the filename as if they were just provided
73+
// inline.
74+
// It is up to the calling code to clean up this file (if required) after
75+
// the test process terminates.
76+
if (args.isNotEmpty) {
77+
args = args.toList(); // Ensure mutable
78+
var lastArg = args.last;
79+
if (lastArg.startsWith('@')) {
80+
lastArg = lastArg.substring(1); // Strip @
81+
var argsFile = File(lastArg); // Path must be relative to cwd
82+
try {
83+
args.removeLast();
84+
args.addAll(
85+
argsFile.readAsLinesSync().where((line) => line.trim().isNotEmpty));
86+
} catch (e) {
87+
_printUsage('Failed to read the file "$lastArg" for arguments: $e');
88+
exitCode = exit_codes.usage;
89+
return;
90+
}
91+
}
92+
}
93+
7194
Configuration configuration;
7295
try {
7396
configuration = Configuration.parse(args);

0 commit comments

Comments
 (0)