Skip to content

Commit 2202f10

Browse files
nshahanCommit Queue
authored andcommitted
[ddc] Refactor options for hot reload tests
Centralizes the parsing into a single location to simplify upcoming refactors of rest of the library. Change-Id: I7847ccbace72897a65d119bbcf76a178144db407 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391686 Commit-Queue: Nicholas Shahan <[email protected]> Reviewed-by: Mark Zhou <[email protected]> Reviewed-by: Samuel Rawlins <[email protected]>
1 parent 48e0dbe commit 2202f10

File tree

1 file changed

+111
-67
lines changed

1 file changed

+111
-67
lines changed

pkg/dev_compiler/test/hot_reload_suite.dart

Lines changed: 111 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -29,62 +29,107 @@ final testTimeoutSeconds = 10;
2929
// All contents after this separator are considered are diff comments.
3030
final testDiffSeparator = '/** DIFF **/';
3131

32-
final argParser = ArgParser()
33-
..addFlag('help', abbr: 'h', help: 'Display this message.', negatable: false)
34-
..addOption('runtime',
35-
abbr: 'r',
36-
defaultsTo: 'd8',
37-
allowed: RuntimePlatforms.values.map((v) => v.text),
38-
help: 'runtime platform used to run tests.')
39-
..addOption('named-configuration',
40-
abbr: 'n',
41-
defaultsTo: 'no-configuration',
42-
help: 'configuration name to use for emitting test result files.')
43-
..addOption('output-directory', help: 'directory to emit test results files.')
44-
..addOption(
45-
'filter',
46-
abbr: 'f',
47-
defaultsTo: r'.*',
48-
help: 'regexp filter over tests to run.',
49-
)
50-
..addOption('diff',
51-
allowed: ['check', 'write', 'ignore'],
52-
allowedHelp: {
53-
'check': 'validate that reload test diffs are generated and correct.',
54-
'write': 'write diffs for reload tests.',
55-
'ignore': 'ignore reload diffs.',
32+
/// Command line options for the hot reload test suite.
33+
class Options {
34+
final bool help;
35+
final RuntimePlatforms runtime;
36+
final String namedConfiguration;
37+
final Uri? testResultsOutputDir;
38+
final RegExp testNameFilter;
39+
final DiffMode diffMode;
40+
final bool debug;
41+
final bool verbose;
42+
43+
Options._({
44+
required this.help,
45+
required this.runtime,
46+
required this.namedConfiguration,
47+
required this.testResultsOutputDir,
48+
required this.testNameFilter,
49+
required this.diffMode,
50+
required this.debug,
51+
required this.verbose,
52+
});
53+
54+
static final _parser = ArgParser()
55+
..addFlag('help',
56+
abbr: 'h',
57+
help: 'Display this message.',
58+
negatable: false,
59+
defaultsTo: false)
60+
..addOption('runtime',
61+
abbr: 'r',
62+
defaultsTo: 'd8',
63+
allowed: RuntimePlatforms.values.map((v) => v.text),
64+
help: 'runtime platform used to run tests.')
65+
..addOption('named-configuration',
66+
abbr: 'n',
67+
defaultsTo: 'no-configuration',
68+
help: 'configuration name to use for emitting test result files.')
69+
..addOption('output-directory',
70+
help: 'directory to emit test results files.')
71+
..addOption('filter',
72+
abbr: 'f', defaultsTo: r'.*', help: 'regexp filter over tests to run.')
73+
..addOption('diff',
74+
allowed: ['check', 'write', 'ignore'],
75+
allowedHelp: {
76+
'check': 'validate that reload test diffs are generated and correct.',
77+
'write': 'write diffs for reload tests.',
78+
'ignore': 'ignore reload diffs.',
79+
},
80+
defaultsTo: 'check',
81+
help: 'selects whether test diffs should be checked, written, or '
82+
'ignored.')
83+
..addFlag('debug',
84+
abbr: 'd',
85+
defaultsTo: false,
86+
negatable: true,
87+
help: 'enables additional debug behavior and logging.')
88+
..addFlag('verbose',
89+
abbr: 'v',
90+
defaultsTo: true,
91+
negatable: true,
92+
help: 'enables verbose logging.');
93+
94+
/// Usage description for these command line options.
95+
String get usage => _parser.usage;
96+
97+
factory Options.parse(List<String> args) {
98+
final results = _parser.parse(args);
99+
return Options._(
100+
help: results.flag('help'),
101+
runtime: RuntimePlatforms.values.byName(results.option('runtime')!),
102+
namedConfiguration: results.option('named-configuration')!,
103+
testResultsOutputDir: results.wasParsed('output-directory')
104+
? Uri.directory(results.option('output-directory')!)
105+
: null,
106+
testNameFilter: RegExp(results.option('filter')!),
107+
diffMode: switch (results.option('diff')!) {
108+
'check' => DiffMode.check,
109+
'write' => DiffMode.write,
110+
'ignore' => DiffMode.ignore,
111+
_ => throw Exception('Invalid diff mode: ${results.option('diff')}'),
56112
},
57-
defaultsTo: 'check',
58-
help:
59-
'selects whether test diffs should be checked, written, or ignored.')
60-
..addFlag('debug',
61-
abbr: 'd',
62-
defaultsTo: false,
63-
negatable: true,
64-
help: 'enables additional debug behavior and logging.')
65-
..addFlag('verbose',
66-
abbr: 'v',
67-
defaultsTo: true,
68-
negatable: true,
69-
help: 'enables verbose logging.');
113+
debug: results.flag('debug'),
114+
verbose: results.flag('verbose'),
115+
);
116+
}
117+
}
70118

71-
late final bool verbose;
72-
late final bool debug;
119+
/// Modes for running diff check tests on the hot reload suite.
120+
enum DiffMode { check, write, ignore }
73121

122+
late final bool verbose;
74123
Future<void> main(List<String> args) async {
75-
final argResults = argParser.parse(args);
76-
if (argResults['help'] as bool) {
77-
print(argParser.usage);
124+
final options = Options.parse(args);
125+
if (options.help) {
126+
print(options.usage);
78127
return;
79128
}
80-
final runtimePlatform =
81-
RuntimePlatforms.values.byName(argResults['runtime'] as String);
82-
final testNameFilter = RegExp(argResults['filter'] as String);
83-
debug = argResults['debug'] as bool;
84-
verbose = argResults['verbose'] as bool;
129+
verbose = options.verbose;
85130

86131
// Used to communicate individual test failures to our test bots.
87-
final emitTestResultsJson = argResults['output-directory'] != null;
132+
final emitTestResultsJson = options.testResultsOutputDir != null;
88133
final buildRootUri = fe.computePlatformBinariesLocation(forceBuildDir: true);
89134
// We can use the outline instead of the full SDK dill here.
90135
final ddcPlatformDillUri = buildRootUri.resolve('ddc_outline.dill');
@@ -135,9 +180,9 @@ Future<void> main(List<String> args) async {
135180
'--output-incremental-dill=${outputIncrementalDillUri.toFilePath()}',
136181
'--packages=${packageConfigUri.toFilePath()}',
137182
'--sdk-root=${sdkRoot.toFilePath()}',
138-
'--verbosity=${verbose ? 'all' : 'info'}',
183+
'--verbosity=${options.verbose ? 'all' : 'info'}',
139184
];
140-
switch (runtimePlatform) {
185+
switch (options.runtime) {
141186
case RuntimePlatforms.d8:
142187
case RuntimePlatforms.chrome:
143188
final ddcPlatformDillFromSdkRoot = fe_shared.relativizeUri(
@@ -175,13 +220,13 @@ Future<void> main(List<String> args) async {
175220

176221
// Only allow Chrome when debugging a single test.
177222
// TODO(markzipan): Add support for full Chrome testing.
178-
if (runtimePlatform == RuntimePlatforms.chrome) {
223+
if (options.runtime == RuntimePlatforms.chrome) {
179224
var matchingTests =
180225
Directory.fromUri(allTestsUri).listSync().where((testDir) {
181226
if (testDir is! Directory) return false;
182227
final testDirParts = testDir.uri.pathSegments;
183228
final testName = testDirParts[testDirParts.length - 2];
184-
return testNameFilter.hasMatch(testName);
229+
return options.testNameFilter.hasMatch(testName);
185230
});
186231

187232
if (matchingTests.length > 1) {
@@ -205,13 +250,13 @@ Future<void> main(List<String> args) async {
205250
final testName = testDirParts[testDirParts.length - 2];
206251

207252
// Skip tests that don't match the name filter.
208-
if (!testNameFilter.hasMatch(testName)) {
253+
if (!options.testNameFilter.hasMatch(testName)) {
209254
_print('Skipping test', label: testName);
210255
continue;
211256
}
212257

213258
var outcome = TestResultOutcome(
214-
configuration: argResults['named-configuration'] as String,
259+
configuration: options.namedConfiguration,
215260
testName: testName,
216261
);
217262
var stopwatch = Stopwatch()..start();
@@ -235,7 +280,7 @@ Future<void> main(List<String> args) async {
235280
final filePath = fileUri.path;
236281
final relativeFilePath = p.relative(filePath, from: allTestsUri.path);
237282
var outcome = TestResultOutcome(
238-
configuration: argResults['named-configuration'] as String,
283+
configuration: options.namedConfiguration,
239284
testName: '$relativeFilePath-diff',
240285
testOutput: testOutput,
241286
);
@@ -305,14 +350,14 @@ Future<void> main(List<String> args) async {
305350
'(requested: $maxGenerations, max: $globalMaxGenerations).');
306351
}
307352

308-
var diffMode = argResults['diff']!;
309-
if (fe_shared.isWindows && diffMode != 'ignore') {
353+
var diffMode = options.diffMode;
354+
if (fe_shared.isWindows && diffMode != DiffMode.ignore) {
310355
_print("Diffing isn't supported on Windows. Defaulting to 'ignore'.",
311356
label: testName);
312-
diffMode = 'ignore';
357+
diffMode = DiffMode.ignore;
313358
}
314359
switch (diffMode) {
315-
case 'check':
360+
case DiffMode.check:
316361
_print('Checking source file diffs.', label: testName);
317362
filesByGeneration.forEach((basename, filesQueue) {
318363
final files = filesQueue.toList();
@@ -378,7 +423,7 @@ Future<void> main(List<String> args) async {
378423
});
379424
});
380425
break;
381-
case 'write':
426+
case DiffMode.write:
382427
_print('Generating source file diffs.', label: testName);
383428
filesByGeneration.forEach((basename, filesQueue) {
384429
final files = filesQueue.toList();
@@ -416,7 +461,7 @@ Future<void> main(List<String> args) async {
416461
});
417462
});
418463
break;
419-
case 'ignore':
464+
case DiffMode.ignore:
420465
_print('Ignoring source file diffs.', label: testName);
421466
filesByGeneration.forEach((basename, filesQueue) {
422467
filesQueue.unorderedElements.forEach(((int, Uri) element) {
@@ -428,8 +473,8 @@ Future<void> main(List<String> args) async {
428473
}
429474

430475
// Skip this test directory if this platform is excluded.
431-
if (testConfig.excludedPlatforms.contains(runtimePlatform)) {
432-
_print('Skipping test on platform: ${runtimePlatform.text}',
476+
if (testConfig.excludedPlatforms.contains(options.runtime)) {
477+
_print('Skipping test on platform: ${options.runtime.text}',
433478
label: testName);
434479
continue;
435480
}
@@ -536,7 +581,7 @@ Future<void> main(List<String> args) async {
536581
'$outputDirectoryPath',
537582
label: testName);
538583

539-
if (runtimePlatform.emitsJS) {
584+
if (options.runtime.emitsJS) {
540585
// Update the memory filesystem with the newly-created JS files
541586
_print(
542587
'Loading generation $currentGeneration files '
@@ -589,7 +634,7 @@ Future<void> main(List<String> args) async {
589634
.transform(utf8.decoder)
590635
.listen(testOutputBuffer.write);
591636
var testPassed = false;
592-
switch (runtimePlatform) {
637+
switch (options.runtime) {
593638
case RuntimePlatforms.d8:
594639
// Run the compiled JS generations with D8.
595640
_print('Creating D8 hot reload test suite.', label: testName);
@@ -687,8 +732,7 @@ Future<void> main(List<String> args) async {
687732
if (emitTestResultsJson) {
688733
final testOutcomeResults = testOutcomes.map((o) => o.toRecordJson());
689734
final testOutcomeLogs = testOutcomes.map((o) => o.toLogJson());
690-
final testResultsOutputDir =
691-
Uri.directory(argResults['output-directory'] as String);
735+
final testResultsOutputDir = options.testResultsOutputDir!;
692736
_print('Saving test results to ${testResultsOutputDir.toFilePath()}.');
693737

694738
// Test outputs must have one JSON blob per line and be newline-terminated.

0 commit comments

Comments
 (0)