// 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 main(List 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 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 step, ) {} @override void logStepStart( int completed, int failed, int total, Suite suite, testing.TestDescription description, testing.Step 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 alreadyReportedResults = {}; @override void logUnexpectedResult( Suite suite, testing.TestDescription description, testing.Result result, Set 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; } }