diff --git a/pkg/testing/lib/src/analyze.dart b/pkg/testing/lib/src/analyze.dart index d7238ce43ed..46a1a045727 100644 --- a/pkg/testing/lib/src/analyze.dart +++ b/pkg/testing/lib/src/analyze.dart @@ -28,21 +28,34 @@ class Analyze extends Suite { final List? gitGrepPatterns; - Analyze(this.analysisOptions, this.uris, this.exclude, this.gitGrepPathspecs, - this.gitGrepPatterns) - : super("analyze", "analyze", null); + Analyze( + this.analysisOptions, + this.uris, + this.exclude, + this.gitGrepPathspecs, + this.gitGrepPatterns, + ) : super("analyze", "analyze", null); Future run(Uri packages, List? extraUris) { List allUris = List.from(uris); if (extraUris != null) { allUris.addAll(extraUris); } - return analyzeUris(analysisOptions, packages, allUris, exclude, - gitGrepPathspecs, gitGrepPatterns); + return analyzeUris( + analysisOptions, + packages, + allUris, + exclude, + gitGrepPathspecs, + gitGrepPatterns, + ); } static Future fromJsonMap( - Uri base, Map json, List suites) async { + Uri base, + Map json, + List suites, + ) async { String? optionsPath = json["options"]; Uri? optionsUri = optionsPath == null ? null : base.resolve(optionsPath); @@ -51,8 +64,9 @@ class Analyze extends Suite { return base.resolve(r); }).toList(); - List exclude = - json["exclude"].map((p) => RegExp(p)).toList(); + List exclude = json["exclude"] + .map((p) => RegExp(p)) + .toList(); Map? gitGrep = json["git grep"]; List? gitGrepPathspecs; @@ -67,7 +81,12 @@ class Analyze extends Suite { } return Analyze( - optionsUri, uris, exclude, gitGrepPathspecs, gitGrepPatterns); + optionsUri, + uris, + exclude, + gitGrepPathspecs, + gitGrepPatterns, + ); } @override @@ -95,20 +114,30 @@ class AnalyzerDiagnostic { static final Pattern unescapePattern = RegExp(r"\\(.)"); - AnalyzerDiagnostic(this.kind, this.detailedKind, this.code, this.uri, - this.line, this.startColumn, this.endColumn, this.message); + AnalyzerDiagnostic( + this.kind, + this.detailedKind, + this.code, + this.uri, + this.line, + this.startColumn, + this.endColumn, + this.message, + ); AnalyzerDiagnostic.malformed(String line) - : this(null, null, null, null, -1, -1, -1, line); + : this(null, null, null, null, -1, -1, -1, line); factory AnalyzerDiagnostic.fromLine(String line) { List parts = []; int start = 0; int index = line.indexOf(potentialSplitPattern); void addPart() { - parts.add(line - .substring(start, index == -1 ? null : index) - .replaceAllMapped(unescapePattern, (Match m) => m[1]!)); + parts.add( + line + .substring(start, index == -1 ? null : index) + .replaceAllMapped(unescapePattern, (Match m) => m[1]!), + ); } while (index != -1) { @@ -125,14 +154,15 @@ class AnalyzerDiagnostic { return AnalyzerDiagnostic.malformed(line); } return AnalyzerDiagnostic( - parts[0], - parts[1], - parts[2], - Uri.base.resolveUri(Uri.file(parts[3])), - int.parse(parts[4]), - int.parse(parts[5]), - int.parse(parts[6]), - parts[7]); + parts[0], + parts[1], + parts[2], + Uri.base.resolveUri(Uri.file(parts[3])), + int.parse(parts[4]), + int.parse(parts[5]), + int.parse(parts[6]), + parts[7], + ); } @override @@ -140,15 +170,17 @@ class AnalyzerDiagnostic { return kind == null ? "Malformed output from dartanalyzer:\n$message" : "${uri!.toFilePath()}:$line:$startColumn: " - "${kind == 'INFO' ? 'warning: hint' : kind!.toLowerCase()}:\n" - "[$code] $message"; + "${kind == 'INFO' ? 'warning: hint' : kind!.toLowerCase()}:\n" + "[$code] $message"; } } Stream parseAnalyzerOutput( - Stream> stream) async* { - Stream lines = - stream.transform(utf8.decoder).transform(LineSplitter()); + Stream> stream, +) async* { + Stream lines = stream + .transform(utf8.decoder) + .transform(LineSplitter()); await for (String line in lines) { if (line.startsWith(">>> ")) continue; yield AnalyzerDiagnostic.fromLine(line); @@ -157,18 +189,19 @@ Stream parseAnalyzerOutput( /// Run dartanalyzer on all tests in [uris]. Future analyzeUris( - Uri? analysisOptions, - Uri packages, - List uris, - List exclude, - List? gitGrepPathspecs, - List? gitGrepPatterns) async { + Uri? analysisOptions, + Uri packages, + List uris, + List exclude, + List? gitGrepPathspecs, + List? gitGrepPatterns, +) async { if (uris.isEmpty) return; String topLevel; try { topLevel = Uri.directory( - (await git("rev-parse", ["--show-toplevel"])).trimRight()) - .toFilePath(windows: false); + (await git("rev-parse", ["--show-toplevel"])).trimRight(), + ).toFilePath(windows: false); } catch (e) { topLevel = Uri.base.toFilePath(windows: false); } @@ -190,8 +223,9 @@ Future analyzeUris( for (Uri uri in uris) { if (await Directory.fromUri(uri).exists()) { - await for (FileSystemEntity entity - in Directory.fromUri(uri).list(recursive: true, followLinks: false)) { + await for (FileSystemEntity entity in Directory.fromUri( + uri, + ).list(recursive: true, followLinks: false)) { if (entity is File && entity.path.endsWith(".dart")) { filesToAnalyze.add(toFilePath(entity.uri)); } @@ -206,11 +240,15 @@ Future analyzeUris( if (gitGrepPatterns != null) { List arguments = ["-l"]; arguments.addAll( - gitGrepPatterns.expand((String pattern) => ["-e", pattern])); + gitGrepPatterns.expand((String pattern) => ["-e", pattern]), + ); arguments.add("--"); arguments.addAll(gitGrepPathspecs!); - filesToAnalyze.addAll(splitLines(await git("grep", arguments)) - .map((String line) => line.trimRight())); + filesToAnalyze.addAll( + splitLines( + await git("grep", arguments), + ).map((String line) => line.trimRight()), + ); } const String analyzerPath = "pkg/analyzer_cli/bin/analyzer.dart"; @@ -237,8 +275,9 @@ Future analyzeUris( print("Running dartanalyzer."); } Stopwatch sw = Stopwatch()..start(); - Process process = await startDart( - analyzer, const ["--batch"], dartArguments..remove("-c")); + Process process = await startDart(analyzer, const [ + "--batch", + ], dartArguments..remove("-c")); process.stdin.writeln(arguments.join(" ")); await process.stdin.close(); @@ -246,7 +285,8 @@ Future analyzeUris( Set seen = {}; Future processAnalyzerOutput( - Stream diagnostics) async { + Stream diagnostics, + ) async { await for (AnalyzerDiagnostic diagnostic in diagnostics) { if (diagnostic.uri != null) { String path = toFilePath(diagnostic.uri!); @@ -260,10 +300,12 @@ Future analyzeUris( } } - Future stderrFuture = - processAnalyzerOutput(parseAnalyzerOutput(process.stderr)); - Future stdoutFuture = - processAnalyzerOutput(parseAnalyzerOutput(process.stdout)); + Future stderrFuture = processAnalyzerOutput( + parseAnalyzerOutput(process.stderr), + ); + Future stdoutFuture = processAnalyzerOutput( + parseAnalyzerOutput(process.stdout), + ); await process.exitCode; await stdoutFuture; await stderrFuture; @@ -278,16 +320,20 @@ String _findSdkPath() { var executableUri = Uri.file(Platform.executable); if (File.fromUri(executableUri.resolve('../version')).existsSync()) { return executableUri.resolve('..').toFilePath(); - } else if (File.fromUri(executableUri.resolve('dart-sdk/version')) - .existsSync()) { + } else if (File.fromUri( + executableUri.resolve('dart-sdk/version'), + ).existsSync()) { return executableUri.resolve('dart-sdk').toFilePath(); } else { throw StateError('Cannot find dart-sdk for $executableUri'); } } -Future git(String command, Iterable arguments, - {String? workingDirectory}) async { +Future git( + String command, + Iterable arguments, { + String? workingDirectory, +}) async { ProcessResult result = await Process.run( Platform.isWindows ? "git.bat" : "git", [command, ...arguments], diff --git a/pkg/testing/lib/src/chain.dart b/pkg/testing/lib/src/chain.dart index 59a285d314d..04adbc55c79 100644 --- a/pkg/testing/lib/src/chain.dart +++ b/pkg/testing/lib/src/chain.dart @@ -22,8 +22,8 @@ import 'log.dart' show Logger, StdoutLogger, splitLines; import 'expectation.dart' show Expectation, ExpectationGroup, ExpectationSet; -typedef CreateContext = Future Function( - Chain suite, Map environment); +typedef CreateContext = + Future Function(Chain suite, Map environment); /// A test suite for tool chains, for example, a compiler. class Chain extends Suite { @@ -39,9 +39,17 @@ class Chain extends Suite { final List exclude; - Chain(String name, String kind, this.source, this.root, this.subRoots, - Uri statusFile, this.includeEndsWith, this.pattern, this.exclude) - : super(name, kind, statusFile); + Chain( + String name, + String kind, + this.source, + this.root, + this.subRoots, + Uri statusFile, + this.includeEndsWith, + this.pattern, + this.exclude, + ) : super(name, kind, statusFile); factory Chain.fromJsonMap(Uri base, Map json, String name, String kind) { Uri source = base.resolve(json["source"]); @@ -63,16 +71,26 @@ class Chain extends Suite { subRoots.add(rootUri); } Uri statusFile = base.resolve(json["status"]); - List includeEndsWith = - List.from(json['includeEndsWith'] ?? const []); + List includeEndsWith = List.from( + json['includeEndsWith'] ?? const [], + ); List pattern = [ - for (final p in json['pattern'] ?? const []) RegExp(p) + for (final p in json['pattern'] ?? const []) RegExp(p), ]; List exclude = [ - for (final e in json['exclude'] ?? const []) RegExp(e) + for (final e in json['exclude'] ?? const []) RegExp(e), ]; - return Chain(name, kind, source, rootUri, subRoots, statusFile, - includeEndsWith, pattern, exclude); + return Chain( + name, + kind, + source, + rootUri, + subRoots, + statusFile, + includeEndsWith, + pattern, + exclude, + ); } void writeImportOn(StringSink sink) { @@ -89,8 +107,10 @@ class Chain extends Suite { sink.writeln(".createContext, {...environment}, selectors, r'''"); const String jsonExtraIndent = " "; sink.write(jsonExtraIndent); - sink.writeAll(splitLines(JsonEncoder.withIndent(" ").convert(this)), - jsonExtraIndent); + sink.writeAll( + splitLines(JsonEncoder.withIndent(" ").convert(this)), + jsonExtraIndent, + ); sink.writeln("''');"); } @@ -115,14 +135,19 @@ abstract class ChainContext { ExpectationSet get expectationSet => ExpectationSet.defaultExpectations; - Future run(Chain suite, Set selectors, - {int shards = 1, - int shard = 0, - int? limitTo, - Logger logger = const StdoutLogger()}) async { + Future run( + Chain suite, + Set selectors, { + int shards = 1, + int shard = 0, + int? limitTo, + Logger logger = const StdoutLogger(), + }) async { assert(shards >= 1, "Invalid shards count: $shards"); - assert(0 <= shard && shard < shards, - "Invalid shard index: $shard, not in range [0,$shards[."); + assert( + 0 <= shard && shard < shards, + "Invalid shard index: $shard, not in range [0,$shards[.", + ); List tripleDotSelectors = selectors .where((s) => s.endsWith('...')) .map((s) => s.substring(0, s.length - 3)) @@ -131,8 +156,9 @@ abstract class ChainContext { .where((s) => s.contains('*')) .map((s) => _createRegExpForAsterisk(s)) .toList(); - TestExpectations expectations = readTestExpectations( - [suite.statusFile!.toFilePath()], expectationSet); + TestExpectations expectations = readTestExpectations([ + suite.statusFile!.toFilePath(), + ], expectationSet); List descriptions = await list(suite); descriptions.sort(); @@ -168,7 +194,9 @@ abstract class ChainContext { continue; } final Set expectedOutcomes = processExpectedOutcomes( - expectations.expectations(description.shortName), description); + expectations.expectations(description.shortName), + description, + ); bool shouldSkip = false; for (Expectation expectation in expectedOutcomes) { if (expectation.group == ExpectationGroup.skip) { @@ -205,8 +233,14 @@ abstract class ChainContext { Step step = iterator.current; lastStepRun = step; isAsync = step.isAsync; - logger.logStepStart(completed, unexpectedResults.length, - descriptions.length, suite, description, step); + logger.logStepStart( + completed, + unexpectedResults.length, + descriptions.length, + suite, + description, + step, + ); // TODO(ahe): It's important to share the zone error reporting zone // between all the tasks. Otherwise, if a future completes with an // error in one zone, and gets stored, it becomes an uncaught error @@ -223,8 +257,14 @@ abstract class ChainContext { } future = future.then((currentResult) async { if (currentResult != null) { - logger.logStepComplete(completed, unexpectedResults.length, - descriptions.length, suite, description, lastStepRun!); + logger.logStepComplete( + completed, + unexpectedResults.length, + descriptions.length, + suite, + description, + lastStepRun!, + ); result = currentResult; if ((currentResult as Result).outcome == Expectation.pass) { // The input to the next step is the output of this step. @@ -238,15 +278,28 @@ abstract class ChainContext { unexpectedResults[description] = result!; unexpectedOutcomes[description] = expectedOutcomes; logger.logUnexpectedResult( - suite, description, result!, expectedOutcomes); + suite, + description, + result!, + expectedOutcomes, + ); exitCode = 1; } else { logger.logExpectedResult( - suite, description, result!, expectedOutcomes); + suite, + description, + result!, + expectedOutcomes, + ); logger.logMessage(sb); } - logger.logTestComplete(++completed, unexpectedResults.length, - descriptions.length, suite, description); + logger.logTestComplete( + ++completed, + unexpectedResults.length, + descriptions.length, + suite, + description, + ); }); if (isAsync) { futures.add(future); @@ -256,8 +309,13 @@ abstract class ChainContext { } } - logger.logTestStart(completed, unexpectedResults.length, - descriptions.length, suite, description); + logger.logTestStart( + completed, + unexpectedResults.length, + descriptions.length, + suite, + description, + ); // The input of the first step is [description]. await doStep(description); } @@ -266,7 +324,11 @@ abstract class ChainContext { if (unexpectedResults.isNotEmpty) { unexpectedResults.forEach((TestDescription description, Result result) { logger.logUnexpectedResult( - suite, description, result, unexpectedOutcomes[description]!); + suite, + description, + result, + unexpectedOutcomes[description]!, + ); }); print("${unexpectedResults.length} failed:"); unexpectedResults.forEach((TestDescription description, Result result) { @@ -281,8 +343,10 @@ abstract class ChainContext { for (Uri subRoot in suite.subRoots) { Directory testRoot = Directory.fromUri(subRoot); if (testRoot.existsSync()) { - for (FileSystemEntity entity - in testRoot.listSync(recursive: true, followLinks: false)) { + for (FileSystemEntity entity in testRoot.listSync( + recursive: true, + followLinks: false, + )) { if (entity is! File) continue; // Use `.uri.path` instead of just `.path` to ensure forward slashes. String path = entity.uri.path; @@ -308,7 +372,9 @@ abstract class ChainContext { } Set processExpectedOutcomes( - Set outcomes, TestDescription description) { + Set outcomes, + TestDescription description, + ) { return outcomes; } @@ -394,10 +460,10 @@ class Result { Result.pass(O output) : this(output, Expectation.pass, null); Result.crash(Object? error, StackTrace trace) - : this(null, Expectation.crash, error, trace: trace); + : this(null, Expectation.crash, error, trace: trace); Result.fail(O output, [error, StackTrace? trace]) - : this(output, Expectation.fail, error, trace: trace); + : this(output, Expectation.fail, error, trace: trace); bool get isPass => outcome == Expectation.pass; @@ -408,17 +474,24 @@ class Result { } Result copyWithOutput(O2 output) { - return Result(output, outcome, error, - trace: trace, - autoFixCommand: autoFixCommand, - canBeFixWithUpdateExpectations: canBeFixWithUpdateExpectations) - ..logs.addAll(logs); + return Result( + output, + outcome, + error, + trace: trace, + autoFixCommand: autoFixCommand, + canBeFixWithUpdateExpectations: canBeFixWithUpdateExpectations, + )..logs.addAll(logs); } } /// This is called from generated code. -Future runChain(CreateContext f, Map environment, - Set selectors, String jsonText) { +Future runChain( + CreateContext f, + Map environment, + Set selectors, + String jsonText, +) { return withErrorHandling(() async { Chain suite = Suite.fromJsonMap(Uri.base, json.decode(jsonText)) as Chain; print("Running ${suite.name}"); diff --git a/pkg/testing/lib/src/discover.dart b/pkg/testing/lib/src/discover.dart index 04fe42fa0e2..a2aa9b2e985 100644 --- a/pkg/testing/lib/src/discover.dart +++ b/pkg/testing/lib/src/discover.dart @@ -14,11 +14,15 @@ final Uri packageConfig = computePackageConfig(); /// Common arguments when running a dart program. Returns a copy that can /// safely be modified by caller. -List get dartArguments => - ["-c", "--packages=${packageConfig.toFilePath()}"]; +List get dartArguments => [ + "-c", + "--packages=${packageConfig.toFilePath()}", +]; -Stream listTests(List testRoots, - {Pattern? pattern}) { +Stream listTests( + List testRoots, { + Pattern? pattern, +}) { StreamController controller = StreamController(); Map subscriptions = {}; @@ -27,23 +31,32 @@ Stream listTests(List testRoots, Directory testRoot = Directory.fromUri(testRootUri); testRoot.exists().then((bool exists) { if (exists) { - Stream stream = - testRoot.list(recursive: true, followLinks: false); - var subscription = stream.listen((FileSystemEntity entity) { - FileBasedTestDescription? description = FileBasedTestDescription.from( - testRootUri, entity, - pattern: pattern); - if (description != null) { - controller.add(description); - } - }, onError: (error, StackTrace trace) { - controller.addError(error, trace); - }, onDone: () { - subscriptions.remove(testRootUri); - if (subscriptions.isEmpty) { - controller.close(); // TODO(ahe): catchError??? - } - }); + Stream stream = testRoot.list( + recursive: true, + followLinks: false, + ); + var subscription = stream.listen( + (FileSystemEntity entity) { + FileBasedTestDescription? description = + FileBasedTestDescription.from( + testRootUri, + entity, + pattern: pattern, + ); + if (description != null) { + controller.add(description); + } + }, + onError: (error, StackTrace trace) { + controller.addError(error, trace); + }, + onDone: () { + subscriptions.remove(testRootUri); + if (subscriptions.isEmpty) { + controller.close(); // TODO(ahe): catchError??? + } + }, + ); subscriptions[testRootUri] = subscription; } else { controller.addError("$testRootUri isn't a directory"); @@ -63,8 +76,11 @@ Uri computePackageConfig() { return Uri.base.resolve(".dart_tool/package_config.json"); } -Future startDart(Uri program, - [List? arguments, List? vmArguments]) { +Future startDart( + Uri program, [ + List? arguments, + List? vmArguments, +]) { List allArguments = []; allArguments.addAll(vmArguments ?? dartArguments); allArguments.add(program.toFilePath()); diff --git a/pkg/testing/lib/src/error_handling.dart b/pkg/testing/lib/src/error_handling.dart index 6c6fbe4bdd8..10236a3148e 100644 --- a/pkg/testing/lib/src/error_handling.dart +++ b/pkg/testing/lib/src/error_handling.dart @@ -12,8 +12,10 @@ import 'dart:isolate' show ReceivePort; import 'log.dart'; -Future withErrorHandling(Future Function() f, - {Logger? logger}) async { +Future withErrorHandling( + Future Function() f, { + Logger? logger, +}) async { final ReceivePort port = ReceivePort(); try { return await f(); diff --git a/pkg/testing/lib/src/expectation.dart b/pkg/testing/lib/src/expectation.dart index 07f2939f51c..994c7ecf817 100644 --- a/pkg/testing/lib/src/expectation.dart +++ b/pkg/testing/lib/src/expectation.dart @@ -17,8 +17,10 @@ class Expectation { static const Expectation crash = Expectation("Crash", ExpectationGroup.crash); - static const Expectation timeout = - Expectation("Timeout", ExpectationGroup.timeout); + static const Expectation timeout = Expectation( + "Timeout", + ExpectationGroup.timeout, + ); static const Expectation fail = Expectation("Fail", ExpectationGroup.fail); @@ -56,20 +58,23 @@ class Expectation { } class ExpectationSet { - static const ExpectationSet defaultExpectations = ExpectationSet( - { - "pass": Expectation.pass, - "crash": Expectation.crash, - "timeout": Expectation.timeout, - "fail": Expectation.fail, - "skip": Expectation.skip, - "missingcompiletimeerror": - Expectation("MissingCompileTimeError", ExpectationGroup.fail), - "missingruntimeerror": - Expectation("MissingRuntimeError", ExpectationGroup.fail), - "runtimeerror": Expectation("RuntimeError", ExpectationGroup.fail), - }, - ); + static const ExpectationSet defaultExpectations = + ExpectationSet({ + "pass": Expectation.pass, + "crash": Expectation.crash, + "timeout": Expectation.timeout, + "fail": Expectation.fail, + "skip": Expectation.skip, + "missingcompiletimeerror": Expectation( + "MissingCompileTimeError", + ExpectationGroup.fail, + ), + "missingruntimeerror": Expectation( + "MissingRuntimeError", + ExpectationGroup.fail, + ), + "runtimeerror": Expectation("RuntimeError", ExpectationGroup.fail), + }); final Map internalMap; @@ -81,8 +86,9 @@ class ExpectationSet { } factory ExpectationSet.fromJsonList(List data) { - Map internalMap = - Map.from(defaultExpectations.internalMap); + Map internalMap = Map.from( + defaultExpectations.internalMap, + ); for (Map map in data) { String? name; String? group; @@ -115,14 +121,7 @@ class ExpectationSet { } } -enum ExpectationGroup { - crash, - fail, - meta, - pass, - skip, - timeout, -} +enum ExpectationGroup { crash, fail, meta, pass, skip, timeout } ExpectationGroup groupFromString(String name) { switch (name) { diff --git a/pkg/testing/lib/src/log.dart b/pkg/testing/lib/src/log.dart index d4eb3fe11d7..5013557fbd3 100644 --- a/pkg/testing/lib/src/log.dart +++ b/pkg/testing/lib/src/log.dart @@ -39,17 +39,39 @@ void enableVerboseOutput() { } abstract class Logger { - void logTestStart(int completed, int failed, int total, Suite suite, - TestDescription description); + void logTestStart( + int completed, + int failed, + int total, + Suite suite, + TestDescription description, + ); - void logTestComplete(int completed, int failed, int total, Suite suite, - TestDescription description); + void logTestComplete( + int completed, + int failed, + int total, + Suite suite, + TestDescription description, + ); - void logStepStart(int completed, int failed, int total, Suite suite, - TestDescription description, Step step); + void logStepStart( + int completed, + int failed, + int total, + Suite suite, + TestDescription description, + Step step, + ); - void logStepComplete(int completed, int failed, int total, Suite suite, - TestDescription description, Step step); + void logStepComplete( + int completed, + int failed, + int total, + Suite suite, + TestDescription description, + Step step, + ); void logProgress(String message); @@ -57,11 +79,19 @@ abstract class Logger { void logNumberedLines(String text); - void logExpectedResult(Suite suite, TestDescription description, - Result result, Set expectedOutcomes); + void logExpectedResult( + Suite suite, + TestDescription description, + Result result, + Set expectedOutcomes, + ); - void logUnexpectedResult(Suite suite, TestDescription description, - Result result, Set expectedOutcomes); + void logUnexpectedResult( + Suite suite, + TestDescription description, + Result result, + Set expectedOutcomes, + ); void logSuiteStarted(Suite suite); @@ -79,12 +109,22 @@ class StdoutLogger implements Logger { const StdoutLogger(); @override - void logTestStart(int completed, int failed, int total, Suite? suite, - TestDescription? description) {} + void logTestStart( + int completed, + int failed, + int total, + Suite? suite, + TestDescription? description, + ) {} @override - void logTestComplete(int completed, int failed, int total, Suite? suite, - TestDescription? description) { + void logTestComplete( + int completed, + int failed, + int total, + Suite? suite, + TestDescription? description, + ) { String message = formatProgress(completed, failed, total); if (suite != null) { message += ": ${formatTestDescription(suite, description!)}"; @@ -93,8 +133,14 @@ class StdoutLogger implements Logger { } @override - void logStepStart(int completed, int failed, int total, Suite? suite, - TestDescription description, Step step) { + void logStepStart( + int completed, + int failed, + int total, + Suite? suite, + TestDescription description, + Step step, + ) { String message = formatProgress(completed, failed, total); if (suite != null) { message += ": ${formatTestDescription(suite, description)} ${step.name}"; @@ -106,8 +152,14 @@ class StdoutLogger implements Logger { } @override - void logStepComplete(int completed, int failed, int total, Suite? suite, - TestDescription description, Step step) { + void logStepComplete( + int completed, + int failed, + int total, + Suite? suite, + TestDescription description, + Step step, + ) { if (!step.isAsync) return; String message = formatProgress(completed, failed, total); if (suite != null) { @@ -154,12 +206,20 @@ class StdoutLogger implements Logger { } @override - void logExpectedResult(Suite suite, TestDescription description, - Result result, Set expectedOutcomes) {} + void logExpectedResult( + Suite suite, + TestDescription description, + Result result, + Set expectedOutcomes, + ) {} @override - void logUnexpectedResult(Suite suite, TestDescription description, - Result result, Set expectedOutcomes) { + void logUnexpectedResult( + Suite suite, + TestDescription description, + Result result, + Set expectedOutcomes, + ) { print("${eraseLine}UNEXPECTED: ${suite.name}/${description.shortName}"); Uri? statusFile = suite.statusFile; if (statusFile != null) { @@ -167,8 +227,10 @@ class StdoutLogger implements Logger { if (result.outcome == Expectation.pass) { print("The test unexpectedly passed, please update $path."); } else { - print("The test had the outcome ${result.outcome}, but the status file " - "($path) allows these outcomes: ${expectedOutcomes.join(' ')}"); + print( + "The test had the outcome ${result.outcome}, but the status file " + "($path) allows these outcomes: ${expectedOutcomes.join(' ')}", + ); } } String log = result.log; @@ -218,8 +280,9 @@ String numberedLines(String text) { String fill = " " * pad; for (String line in lines) { String paddedLineNumber = "$fill$lineNumber"; - paddedLineNumber = - paddedLineNumber.substring(paddedLineNumber.length - pad); + paddedLineNumber = paddedLineNumber.substring( + paddedLineNumber.length - pad, + ); result.write("$paddedLineNumber: $line"); lineNumber++; } diff --git a/pkg/testing/lib/src/run.dart b/pkg/testing/lib/src/run.dart index f015be3706a..f3c998f35ee 100644 --- a/pkg/testing/lib/src/run.dart +++ b/pkg/testing/lib/src/run.dart @@ -46,13 +46,16 @@ Future computeTestRoot(String? configurationPath, Uri? base) { /// The optional argument [configurationPath] should be used when /// `testing.json` isn't located in the current working directory and is a path /// relative to [me] which defaults to `Platform.script`. -Future runMe(List arguments, CreateContext f, - {String? configurationPath, - Uri? me, - int shards = 1, - int shard = 0, - int? limitTo, - Logger logger = const StdoutLogger()}) { +Future runMe( + List arguments, + CreateContext f, { + String? configurationPath, + Uri? me, + int shards = 1, + int shard = 0, + int? limitTo, + Logger logger = const StdoutLogger(), +}) { me ??= Platform.script; return withErrorHandling(() async { TestRoot testRoot = await computeTestRoot(configurationPath, me); @@ -61,8 +64,14 @@ Future runMe(List arguments, CreateContext f, for (Chain suite in testRoot.toolChains) { if (me == suite.source) { ChainContext context = await f(suite, cl.environment); - await context.run(suite, Set.from(cl.selectors), - shards: shards, shard: shard, limitTo: limitTo, logger: logger); + await context.run( + suite, + Set.from(cl.selectors), + shards: shards, + shard: shard, + limitTo: limitTo, + logger: logger, + ); } } }, logger: logger); @@ -94,15 +103,23 @@ Future runMe(List arguments, CreateContext f, /// The optional argument [configurationPath] should be used when /// `testing.json` isn't located in the current working directory and is a path /// relative to `Uri.base`. -Future run(List arguments, List suiteNames, - [String? configurationPath]) { +Future run( + List arguments, + List suiteNames, [ + String? configurationPath, +]) { return withErrorHandling(() async { TestRoot root = await computeTestRoot(configurationPath, Uri.base); List suites = root.suites .where((Suite suite) => suiteNames.contains(suite.name)) .toList(); SuiteRunner runner = SuiteRunner( - suites, {}, const [], {}, {}); + suites, + {}, + const [], + {}, + {}, + ); String? program = await runner.generateDartProgram(); await runner.analyze(root.packages); if (program != null) { @@ -116,12 +133,16 @@ Future runProgram(String program, Uri packages) async { const StdoutLogger().logNumberedLines(program); Uri dataUri = Uri.dataFromString(program); ReceivePort exitPort = ReceivePort(); - Isolate isolate = await Isolate.spawnUri(dataUri, [], null, - paused: true, - onExit: exitPort.sendPort, - errorsAreFatal: false, - checked: true, - packageConfig: packages); + Isolate isolate = await Isolate.spawnUri( + dataUri, + [], + null, + paused: true, + onExit: exitPort.sendPort, + errorsAreFatal: false, + checked: true, + packageConfig: packages, + ); List? error; var subscription = isolate.errors.listen((data) { error = data; @@ -150,9 +171,13 @@ class SuiteRunner { final List testUris = []; - SuiteRunner(this.suites, this.environment, Iterable selectors, - this.selectedSuites, this.skippedSuites) - : selectors = selectors.toList(growable: false); + SuiteRunner( + this.suites, + this.environment, + Iterable selectors, + this.selectedSuites, + this.skippedSuites, + ) : selectors = selectors.toList(growable: false); bool shouldRunSuite(Suite suite) { return !skippedSuites.contains(suite.name) && diff --git a/pkg/testing/lib/src/run_tests.dart b/pkg/testing/lib/src/run_tests.dart index 1ca735ea202..9447bec70ad 100644 --- a/pkg/testing/lib/src/run_tests.dart +++ b/pkg/testing/lib/src/run_tests.dart @@ -33,11 +33,13 @@ class CommandLine { Set get skip => commaSeparated("--skip="); Set commaSeparated(String prefix) { - return Set.from(options.expand((String s) { - if (!s.startsWith(prefix)) return const []; - s = s.substring(prefix.length); - return s.split(","); - })); + return Set.from( + options.expand((String s) { + if (!s.startsWith(prefix)) return const []; + s = s.substring(prefix.length); + return s.split(","); + }), + ); } Map get environment { @@ -91,8 +93,10 @@ class CommandLine { List candidates = await test .list(recursive: true, followLinks: false) .where((FileSystemEntity entity) { - return entity is File && entity.uri.path.endsWith("/testing.json"); - }).toList(); + return entity is File && + entity.uri.path.endsWith("/testing.json"); + }) + .toList(); switch (candidates.length) { case 0: fail("Couldn't locate: '$configurationPath'."); @@ -103,18 +107,22 @@ class CommandLine { break; default: - fail("Usage: run_tests.dart [$configPrefix=configuration_file]\n" - "Where configuration_file is one of:\n " - "${candidates.map((file) => file.path).join('\n ')}"); + fail( + "Usage: run_tests.dart [$configPrefix=configuration_file]\n" + "Where configuration_file is one of:\n " + "${candidates.map((file) => file.path).join('\n ')}", + ); return null; } } } } - const StdoutLogger() - .logMessage("Reading configuration file '$configurationPath'."); - Uri? configuration = - await Isolate.resolvePackageUri(Uri.base.resolve(configurationPath)); + const StdoutLogger().logMessage( + "Reading configuration file '$configurationPath'.", + ); + Uri? configuration = await Isolate.resolvePackageUri( + Uri.base.resolve(configurationPath), + ); if (configuration == null || !await File.fromUri(configuration).exists()) { fail("Couldn't locate: '$configurationPath'."); return null; @@ -130,8 +138,9 @@ class CommandLine { arguments = arguments.sublist(index + 1); } else { options = arguments.where((argument) => argument.startsWith("-")).toSet(); - arguments = - arguments.where((argument) => !argument.startsWith("-")).toList(); + arguments = arguments + .where((argument) => !argument.startsWith("-")) + .toList(); } return CommandLine(options, arguments); } @@ -156,7 +165,12 @@ Future main(List arguments) { } TestRoot root = await TestRoot.fromUri(configuration); SuiteRunner runner = SuiteRunner( - root.suites, environment, cl.selectors, cl.selectedSuites, cl.skip); + root.suites, + environment, + cl.selectors, + cl.selectedSuites, + cl.skip, + ); String? program = await runner.generateDartProgram(); bool hasAnalyzerSuites = await runner.analyze(root.packages); Stopwatch sw = Stopwatch()..start(); @@ -171,24 +185,29 @@ Future main(List arguments) { }); } -Future runTests(Map tests) => - withErrorHandling(() async { - int completed = 0; - for (String name in tests.keys) { - const StdoutLogger() - .logTestStart(completed, 0, tests.length, null, null); - StringBuffer sb = StringBuffer(); - try { - await runGuarded(() { - print("Running test $name"); - return tests[name]!(); - }, printLineOnStdout: sb.writeln); - const StdoutLogger().logMessage(sb); - } catch (e) { - print(sb); - rethrow; - } - const StdoutLogger() - .logTestComplete(++completed, 0, tests.length, null, null); +Future runTests(Map tests) => withErrorHandling( + () async { + int completed = 0; + for (String name in tests.keys) { + const StdoutLogger().logTestStart(completed, 0, tests.length, null, null); + StringBuffer sb = StringBuffer(); + try { + await runGuarded(() { + print("Running test $name"); + return tests[name]!(); + }, printLineOnStdout: sb.writeln); + const StdoutLogger().logMessage(sb); + } catch (e) { + print(sb); + rethrow; } - }); + const StdoutLogger().logTestComplete( + ++completed, + 0, + tests.length, + null, + null, + ); + } + }, +); diff --git a/pkg/testing/lib/src/status_file_parser.dart b/pkg/testing/lib/src/status_file_parser.dart index 362626cf76b..2afd1374c24 100644 --- a/pkg/testing/lib/src/status_file_parser.dart +++ b/pkg/testing/lib/src/status_file_parser.dart @@ -9,7 +9,9 @@ import "dart:io"; import 'expectation.dart' show Expectation, ExpectationSet; TestExpectations readTestExpectations( - List statusFilePaths, ExpectationSet expectationSet) { + List statusFilePaths, + ExpectationSet expectationSet, +) { TestExpectations testExpectations = TestExpectations(expectationSet); for (String path in statusFilePaths) { readTestExpectationsInto(testExpectations, path); @@ -18,7 +20,9 @@ TestExpectations readTestExpectations( } void readTestExpectationsInto( - TestExpectations expectations, String statusFilePath) { + TestExpectations expectations, + String statusFilePath, +) { File file = File(statusFilePath); for (String line in file.readAsLinesSync()) { // Remove comments if any. diff --git a/pkg/testing/lib/src/stdio_process.dart b/pkg/testing/lib/src/stdio_process.dart index 2f2c6ab3a53..1bed1c14912 100644 --- a/pkg/testing/lib/src/stdio_process.dart +++ b/pkg/testing/lib/src/stdio_process.dart @@ -28,25 +28,35 @@ class StdioProcess { return Result.pass(exitCode); } else { return Result( - exitCode, ExpectationSet.defaultExpectations["RuntimeError"], output); + exitCode, + ExpectationSet.defaultExpectations["RuntimeError"], + output, + ); } } static StreamTransformer transformToStdio(Stdout stdio) { return StreamTransformer.fromHandlers( - handleData: (String data, EventSink sink) { - sink.add(data); - stdio.write(data); - }); + handleData: (String data, EventSink sink) { + sink.add(data); + stdio.write(data); + }, + ); } - static Future run(String executable, List arguments, - {String? input, - Duration? timeout = const Duration(seconds: 60), - bool suppressOutput = true, - bool runInShell = false}) async { - Process process = - await Process.start(executable, arguments, runInShell: runInShell); + static Future run( + String executable, + List arguments, { + String? input, + Duration? timeout = const Duration(seconds: 60), + bool suppressOutput = true, + bool runInShell = false, + }) async { + Process process = await Process.start( + executable, + arguments, + runInShell: runInShell, + ); Timer? timer; StringBuffer sb = StringBuffer(); if (timeout != null) { diff --git a/pkg/testing/lib/src/test_description.dart b/pkg/testing/lib/src/test_description.dart index a76e40c9f33..8dec54b8ec2 100644 --- a/pkg/testing/lib/src/test_description.dart +++ b/pkg/testing/lib/src/test_description.dart @@ -48,8 +48,11 @@ class FileBasedTestDescription extends TestDescription { sink.writeln('.main,'); } - static FileBasedTestDescription? from(Uri root, FileSystemEntity entity, - {Pattern? pattern}) { + static FileBasedTestDescription? from( + Uri root, + FileSystemEntity entity, { + Pattern? pattern, + }) { if (entity is! File) return null; pattern ??= "_test.dart"; String path = entity.uri.path; diff --git a/pkg/testing/lib/src/zone_helper.dart b/pkg/testing/lib/src/zone_helper.dart index 1c1a1cb1e14..f734e065471 100644 --- a/pkg/testing/lib/src/zone_helper.dart +++ b/pkg/testing/lib/src/zone_helper.dart @@ -75,8 +75,9 @@ Future runGuarded( errorPort.close(); Isolate.current.setErrorsFatal(true); Isolate.current.removeErrorListener(errorPort.sendPort); - return acknowledgeControlMessages(Isolate.current) - .then((_) => errorFuture); + return acknowledgeControlMessages( + Isolate.current, + ).then((_) => errorFuture); }); }); } diff --git a/pkg/testing/test/analyze_test.dart b/pkg/testing/test/analyze_test.dart index 92e7bb56036..1f3e344bf05 100644 --- a/pkg/testing/test/analyze_test.dart +++ b/pkg/testing/test/analyze_test.dart @@ -7,6 +7,9 @@ import "package:testing/src/run_tests.dart" as testing show main; Future main() { // This method is async, but keeps a port open to prevent the VM from exiting // prematurely. - return testing.main( - ["--config=pkg/testing/testing.json", "--verbose", "analyze"]); + return testing.main([ + "--config=pkg/testing/testing.json", + "--verbose", + "analyze", + ]); }