|  | // Copyright (c) 2024, the Dart project authors.  Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | import 'dart:convert'; | 
|  | import 'dart:isolate' show Isolate, ReceivePort, SendPort; | 
|  |  | 
|  | import 'package:testing/src/log.dart' show Logger; | 
|  | import 'package:testing/src/suite.dart'; | 
|  | import 'package:testing/testing.dart' as testing; | 
|  |  | 
|  | import 'presubmit_helper.dart'; | 
|  | import 'test/deps_git_test.dart' as deps_test; | 
|  | import 'test/compile_and_lint_impl.dart' show runCompileAndLintTest; | 
|  | import 'test/messages_suite.dart' as messages_suite; | 
|  | import 'test/lint_suite.dart' as lint_suite; | 
|  | import 'test/spelling_test_not_src_suite.dart' as spelling_test_not_src; | 
|  | import 'test/spelling_test_src_suite.dart' as spelling_test_src; | 
|  |  | 
|  | Future<void> main(List<String> args, [SendPort? sendPort]) async { | 
|  | if (sendPort == null) throw "Need a send-port."; | 
|  | var isolateReceivePort = ReceivePort(); | 
|  | isolateReceivePort.listen((rawData) async { | 
|  | if (rawData is! String) { | 
|  | print("Got unexpected data of type ${rawData.runtimeType}"); | 
|  | sendPort.send(false); | 
|  | return; | 
|  | } | 
|  | Work work = Work.workFromJson(json.decode(rawData)); | 
|  | Stopwatch stopwatch = new Stopwatch()..start(); | 
|  | switch (work) { | 
|  | case CompileAndLintWork(): | 
|  | int compileAndLintErrorsFound = -1; | 
|  | try { | 
|  | compileAndLintErrorsFound = await Isolate.run( | 
|  | () => runCompileAndLintTest( | 
|  | includedFiles: work.includedFiles, | 
|  | includedDirectoryUris: work.includedDirectoryUris, | 
|  | repoDir: work.repoDir, | 
|  | ), | 
|  | ); | 
|  | } catch (e, st) { | 
|  | // This will make it send false. | 
|  | compileAndLintErrorsFound = -1; | 
|  |  | 
|  | StringBuffer sb = new StringBuffer(); | 
|  | sb.writeln("void main() {"); | 
|  | sb.writeln("  runCompileAndLintTest(includedFiles: {"); | 
|  | String comma = ""; | 
|  | for (Uri uri in work.includedFiles) { | 
|  | sb.writeln("    ${comma}Uri.parse('$uri')"); | 
|  | comma = ", "; | 
|  | } | 
|  | sb.writeln("    }, includedDirectoryUris: {"); | 
|  | comma = ""; | 
|  | for (Uri uri in work.includedDirectoryUris) { | 
|  | sb.writeln("    ${comma}Uri.parse('$uri')"); | 
|  | comma = ", "; | 
|  | } | 
|  | sb.writeln("    }, repoDir: Uri.parse('${work.repoDir}'));"); | 
|  | sb.writeln("}"); | 
|  |  | 
|  | print(""" | 
|  | WARNING: '${work.name}' crashed: | 
|  | ============ | 
|  | ${e.toString().trim()} | 
|  | ============ | 
|  | $st | 
|  | ============ | 
|  |  | 
|  | To reproduce open up compile_and_lint_impl.dart and insert | 
|  |  | 
|  | $sb | 
|  |  | 
|  | Then run that file through your debugger or similar. | 
|  |  | 
|  | """); | 
|  | print("Got error for ${work.name}: $e"); | 
|  | } | 
|  | print( | 
|  | "Sending ok = ${compileAndLintErrorsFound == 0} " | 
|  | "for ${work.name} after ${stopwatch.elapsed}", | 
|  | ); | 
|  | sendPort.send(compileAndLintErrorsFound == 0); | 
|  |  | 
|  | case MessagesWork(): | 
|  | bool ok; | 
|  | try { | 
|  | ok = await Isolate.run(() async { | 
|  | ErrorNotingLogger logger = new ErrorNotingLogger(); | 
|  | await testing.runMe( | 
|  | ["-DfastOnly=true", "--", ...work.filters], | 
|  | messages_suite.createContext, | 
|  | me: work.repoDir.resolve( | 
|  | "pkg/front_end/test/messages_suite.dart", | 
|  | ), | 
|  | configurationPath: "../testing.json", | 
|  | logger: logger, | 
|  | ); | 
|  | return !logger.gotFailure; | 
|  | }); | 
|  | } catch (e) { | 
|  | ok = false; | 
|  | } | 
|  | print( | 
|  | "Sending ok = $ok " | 
|  | "for ${work.name} after ${stopwatch.elapsed}", | 
|  | ); | 
|  | sendPort.send(ok); | 
|  | case SpellNotSourceWork(): | 
|  | bool ok; | 
|  | try { | 
|  | ok = await Isolate.run(() async { | 
|  | ErrorNotingLogger logger = new ErrorNotingLogger(); | 
|  | await testing.runMe( | 
|  | ["--", ...work.filters], | 
|  | spelling_test_not_src.createContext, | 
|  | me: work.repoDir.resolve( | 
|  | "pkg/front_end/test/spelling_test_not_src_suite.dart", | 
|  | ), | 
|  | configurationPath: "../testing.json", | 
|  | logger: logger, | 
|  | ); | 
|  | return !logger.gotFailure; | 
|  | }); | 
|  | } catch (e) { | 
|  | ok = false; | 
|  | } | 
|  | print( | 
|  | "Sending ok = $ok " | 
|  | "for ${work.name} after ${stopwatch.elapsed}", | 
|  | ); | 
|  | sendPort.send(ok); | 
|  | case SpellSourceWork(): | 
|  | bool ok; | 
|  | try { | 
|  | ok = await Isolate.run(() async { | 
|  | ErrorNotingLogger logger = new ErrorNotingLogger(); | 
|  | await testing.runMe( | 
|  | ["--", ...work.filters], | 
|  | spelling_test_src.createContext, | 
|  | me: work.repoDir.resolve( | 
|  | "pkg/front_end/test/spelling_test_src_suite.dart", | 
|  | ), | 
|  | configurationPath: "../testing.json", | 
|  | logger: logger, | 
|  | ); | 
|  | return !logger.gotFailure; | 
|  | }); | 
|  | } catch (e) { | 
|  | ok = false; | 
|  | } | 
|  | print( | 
|  | "Sending ok = $ok " | 
|  | "for ${work.name} after ${stopwatch.elapsed}", | 
|  | ); | 
|  | sendPort.send(ok); | 
|  | case LintWork(): | 
|  | bool ok; | 
|  | try { | 
|  | ok = await Isolate.run(() async { | 
|  | ErrorNotingLogger logger = new ErrorNotingLogger(); | 
|  | await testing.runMe( | 
|  | ["--", ...work.filters], | 
|  | lint_suite.createContext, | 
|  | me: work.repoDir.resolve("pkg/front_end/test/lint_suite.dart"), | 
|  | configurationPath: "../testing.json", | 
|  | logger: logger, | 
|  | ); | 
|  | return !logger.gotFailure; | 
|  | }); | 
|  | } catch (e) { | 
|  | ok = false; | 
|  | } | 
|  | print( | 
|  | "Sending ok = $ok " | 
|  | "for ${work.name} after ${stopwatch.elapsed}", | 
|  | ); | 
|  | sendPort.send(ok); | 
|  | case DepsTestWork(): | 
|  | bool ok; | 
|  | try { | 
|  | ok = await Isolate.run(() { | 
|  | return deps_test.main(); | 
|  | }); | 
|  | } catch (e) { | 
|  | ok = false; | 
|  | } | 
|  | print( | 
|  | "Sending ok = $ok " | 
|  | "for ${work.name} after ${stopwatch.elapsed}", | 
|  | ); | 
|  | sendPort.send(ok); | 
|  | } | 
|  | }); | 
|  | sendPort.send(isolateReceivePort.sendPort); | 
|  | } | 
|  |  | 
|  | class ErrorNotingLogger implements Logger { | 
|  | bool gotFailure = false; | 
|  |  | 
|  | @override | 
|  | void logExpectedResult( | 
|  | Suite suite, | 
|  | testing.TestDescription description, | 
|  | testing.Result result, | 
|  | Set<testing.Expectation> expectedOutcomes, | 
|  | ) {} | 
|  |  | 
|  | @override | 
|  | void logMessage(Object message) {} | 
|  |  | 
|  | @override | 
|  | void logNumberedLines(String text) {} | 
|  |  | 
|  | @override | 
|  | void logProgress(String message) {} | 
|  |  | 
|  | @override | 
|  | void logStepComplete( | 
|  | int completed, | 
|  | int failed, | 
|  | int total, | 
|  | Suite suite, | 
|  | testing.TestDescription description, | 
|  | testing.Step<dynamic, dynamic, testing.ChainContext> step, | 
|  | ) {} | 
|  |  | 
|  | @override | 
|  | void logStepStart( | 
|  | int completed, | 
|  | int failed, | 
|  | int total, | 
|  | Suite suite, | 
|  | testing.TestDescription description, | 
|  | testing.Step<dynamic, dynamic, testing.ChainContext> step, | 
|  | ) {} | 
|  |  | 
|  | @override | 
|  | void logSuiteComplete(Suite suite) {} | 
|  |  | 
|  | @override | 
|  | void logSuiteStarted(Suite suite) {} | 
|  |  | 
|  | @override | 
|  | void logTestComplete( | 
|  | int completed, | 
|  | int failed, | 
|  | int total, | 
|  | Suite suite, | 
|  | testing.TestDescription description, | 
|  | ) {} | 
|  |  | 
|  | @override | 
|  | void logTestStart( | 
|  | int completed, | 
|  | int failed, | 
|  | int total, | 
|  | Suite suite, | 
|  | testing.TestDescription description, | 
|  | ) {} | 
|  |  | 
|  | @override | 
|  | void logUncaughtError(error, StackTrace stackTrace) { | 
|  | print("Uncaught Error: $error\n$stackTrace"); | 
|  | gotFailure = true; | 
|  | } | 
|  |  | 
|  | // package:testing logs the result twice: As it happens and at the end. | 
|  | // I don't want that so for now I'll maintain a set of already reported | 
|  | // test results. | 
|  | Set<testing.Result> alreadyReportedResults = {}; | 
|  |  | 
|  | @override | 
|  | void logUnexpectedResult( | 
|  | Suite suite, | 
|  | testing.TestDescription description, | 
|  | testing.Result result, | 
|  | Set<testing.Expectation> expectedOutcomes, | 
|  | ) { | 
|  | if (!alreadyReportedResults.add(result)) return; | 
|  |  | 
|  | String log = result.log; | 
|  | if (log.isNotEmpty) { | 
|  | print(log); | 
|  | } | 
|  | if (result.error != null) { | 
|  | print(result.error); | 
|  | if (result.trace != null) { | 
|  | print(result.trace); | 
|  | } | 
|  | } | 
|  |  | 
|  | gotFailure = true; | 
|  | } | 
|  |  | 
|  | @override | 
|  | void noticeFrameworkCatchError(error, StackTrace stackTrace) { | 
|  | print("Framework Catch Error: $error\n$stackTrace"); | 
|  | gotFailure = true; | 
|  | } | 
|  | } |