Skip to content

Commit f95c0f5

Browse files
authored
Allow empty test source when parsing metadata (#2583)
Some use cases with precompiled tests pass an empty test source file and skip any of the behavior of configuration metadata annotations. This isn't the golden path design for the runner, but we can avoid breaking it easily. In this scenario the specific problem of a missing `main` will have already been handled by other infrastructure, so whether the error is clear is out of our control. This change does restore the less direct error about missing main in the case where a typical test runner user tries to run a completely empty test suite, but this is unlikely in practice.
1 parent c970e00 commit f95c0f5

File tree

2 files changed

+16
-5
lines changed

2 files changed

+16
-5
lines changed

pkgs/test/test/runner/parse_metadata_test.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ void main() {
5454
);
5555
});
5656

57+
test('allows completely empty files', () {
58+
expect(() => parseMetadata(_path, '', {}), returnsNormally);
59+
});
60+
5761
group('@TestOn:', () {
5862
test('parses a valid annotation', () {
5963
var metadata = parseMetadata(

pkgs/test_core/lib/src/runner/parse_metadata.dart

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,12 @@ class _Parser {
5252
///
5353
/// When main is missing a call to [parse] will throw a [FormatException] with
5454
/// a descriptive message.
55-
late final bool _hasMain;
55+
///
56+
/// An empty file may indicate an atypical use of the test runner in
57+
/// precompiled mode without the test source available. In these cases the
58+
/// definition is not required and it is assumed it is checked by whatever
59+
/// compilation approach is used.
60+
late final bool _hasMainOrEmpty;
5661

5762
_Parser(this._path, this._contents, this._platformVariables) {
5863
var result = parseString(
@@ -63,9 +68,11 @@ class _Parser {
6368
var directives = result.unit.directives;
6469
_annotations = directives.isEmpty ? [] : directives.first.metadata;
6570
_languageVersionComment = result.unit.languageVersionToken?.value();
66-
_hasMain = result.unit.declarations.any(
67-
(d) => d is FunctionDeclaration && d.name.lexeme == 'main',
68-
);
71+
_hasMainOrEmpty =
72+
_contents.isEmpty ||
73+
result.unit.declarations.any(
74+
(d) => d is FunctionDeclaration && d.name.lexeme == 'main',
75+
);
6976

7077
// We explicitly *don't* just look for "package:test" imports here,
7178
// because it could be re-exported from another library.
@@ -84,7 +91,7 @@ class _Parser {
8491

8592
/// Parses the metadata.
8693
Metadata parse() {
87-
if (!_hasMain) {
94+
if (!_hasMainOrEmpty) {
8895
throw const FormatException('Missing definition of `main` method.');
8996
}
9097
Timeout? timeout;

0 commit comments

Comments
 (0)