// Copyright (c) 2021, 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.md file. import 'dart:async' show Future; import 'dart:convert' show LineSplitter, utf8; import 'dart:io' show File, Platform, Process, exitCode; main(List args) async { // General idea: Launch - in separate processes - whatever we want to run // concurrently, capturing the stdout and stderr, printing it with some // prepended identification. // When all runs are done, fail if any fails. // Later we might be able to move it to the "testRunner"-system, if that // offers any advantages. print("NOTE: This machine has ${Platform.numberOfProcessors} processors!" "\n\n"); List startedProcesses = []; { // Very slow: Leak-test. Uri leakTester = Platform.script.resolve("flutter_gallery_leak_tester.dart"); if (!new File.fromUri(leakTester).existsSync()) { exitCode = 1; print("Couldn't find $leakTester"); } else { // The tools/bots/flutter/compile_flutter.sh script passes `--path` // --- we'll just pass everything along. startedProcesses .add(await run([leakTester.toString(), ...args], "leak test")); } } { // Slow: Leak-test with alternative invalidation. Uri leakTester = Platform.script.resolve("flutter_gallery_leak_tester.dart"); if (!new File.fromUri(leakTester).existsSync()) { exitCode = 1; print("Couldn't find $leakTester"); } else { // Note that the leak test run above will start checking out flutter // gallery (etc) and that it has to finish before starting this. // We therefore wait for the observatory line being printed before // starting. Wait at most 10 minutes though. // ignore: unawaited_futures () async { for (int i = 0; i < 10 * 60; i++) { if (observatoryLines.isNotEmpty) break; await Future.delayed(new Duration(seconds: 1)); } // The tools/bots/flutter/compile_flutter.sh script passes `--path` // --- we'll just pass everything along. startedProcesses.add(await run( [leakTester.toString(), ...args, "--alternativeInvalidation"], "leak test alternative invalidation")); }(); } } { // Weak suite with fuzzing. Uri weakSuite = Platform.script.resolve("fasta/weak_suite.dart"); if (!new File.fromUri(weakSuite).existsSync()) { exitCode = 1; print("Couldn't find $weakSuite"); } else { startedProcesses.add( await run([weakSuite.toString(), "-DsemiFuzz=true"], "weak suite")); } } { // Strong suite with fuzzing. Uri strongSuite = Platform.script.resolve("fasta/strong_suite.dart"); if (!new File.fromUri(strongSuite).existsSync()) { exitCode = 1; print("Couldn't find $strongSuite"); } else { startedProcesses.add(await run( [strongSuite.toString(), "-DsemiFuzz=true"], "strong suite")); } } // Wait for everything to finish. List exitCodes = await Future.wait(startedProcesses.map((e) => e.process.exitCode)); if (exitCodes.where((e) => e != 0).isNotEmpty) { // At least one failed. exitCode = 1; for (WrappedProcess p in startedProcesses) { int pExitCode = await p.process.exitCode; if (pExitCode != 0) { print("${p.id} failed with exist-code $pExitCode"); } } } } List observatoryLines = []; Future run(List args, String id) async { Process process = await Process.start( Platform.resolvedExecutable, ["--enable-asserts", ...args]); process.stderr .transform(utf8.decoder) .transform(new LineSplitter()) .listen((line) { print("$id stderr> $line"); if (line.contains("Observatory listening on")) { observatoryLines.add(line); } }); process.stdout .transform(utf8.decoder) .transform(new LineSplitter()) .listen((line) { print("$id stdout> $line"); if (line.contains("Observatory listening on")) { observatoryLines.add(line); } }); return new WrappedProcess(process, id); } class WrappedProcess { final Process process; final String id; WrappedProcess(this.process, this.id); }