72534f18fa
Change-Id: I0a678e971395f70d09a3faf004e6476a9b5a48cb Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/395000 Commit-Queue: Johnni Winther <johnniwinther@google.com> Reviewed-by: Jens Johansen <jensj@google.com>
138 lines
4.7 KiB
Dart
138 lines
4.7 KiB
Dart
// Copyright (c) 2022, 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:io';
|
|
|
|
import 'package:testing/src/chain.dart' show CreateContext;
|
|
import 'package:testing/src/log.dart' show Logger, StdoutLogger;
|
|
import 'package:testing/src/suite.dart' as testing show Suite;
|
|
import 'package:testing/testing.dart' show Step, TestDescription;
|
|
|
|
import '../coverage_helper.dart';
|
|
import '../testing/suite.dart';
|
|
|
|
const String limitToArgument = "--limitTo=";
|
|
|
|
Future<void> internalMain(
|
|
CreateContext createContext, {
|
|
List<String> arguments = const [],
|
|
int? shards,
|
|
int? shard,
|
|
required String displayName,
|
|
required String configurationPath,
|
|
}) async {
|
|
Logger logger = const StdoutLogger();
|
|
List<String>? argumentsTrimmed;
|
|
Uri? coverageUri;
|
|
int? limitTo;
|
|
for (int i = 0; i < arguments.length; i++) {
|
|
String argument = arguments[i];
|
|
bool trimmed = false;
|
|
if (argument == "--traceStepTiming") {
|
|
logger = new TracingLogger();
|
|
trimmed = true;
|
|
} else if (argument.startsWith("--coverage=")) {
|
|
coverageUri = Uri.base
|
|
.resolveUri(Uri.file(argument.substring("--coverage=".length)));
|
|
trimmed = true;
|
|
} else if (argument.startsWith("--shards=")) {
|
|
shards = int.parse(argument.substring("--shards=".length));
|
|
trimmed = true;
|
|
} else if (argument.startsWith("--shard=")) {
|
|
// Have this 1-indexed when given as an input.
|
|
shard = int.parse(argument.substring("--shard=".length)) - 1;
|
|
trimmed = true;
|
|
} else if (argument.startsWith(limitToArgument)) {
|
|
limitTo = int.tryParse(argument.substring(limitToArgument.length));
|
|
trimmed = true;
|
|
}
|
|
|
|
if (trimmed && argumentsTrimmed == null) {
|
|
argumentsTrimmed = []..addAll(arguments.sublist(0, i));
|
|
} else if (!trimmed && argumentsTrimmed != null) {
|
|
argumentsTrimmed.add(argument);
|
|
}
|
|
}
|
|
if (argumentsTrimmed != null) {
|
|
arguments = argumentsTrimmed;
|
|
}
|
|
|
|
shards ??= 1;
|
|
shard ??= 0;
|
|
|
|
await runMe(
|
|
arguments,
|
|
createContext,
|
|
configurationPath: configurationPath,
|
|
shards: shards,
|
|
shard: shard,
|
|
limitTo: limitTo,
|
|
logger: logger,
|
|
);
|
|
if (coverageUri != null) {
|
|
File f = new File.fromUri(
|
|
coverageUri.resolve("$displayName.$shard.$shards.coverage"));
|
|
// Suites generally takes a while to run --- so setting force compile to
|
|
// true shouldn't be a big issue. It seems to add something like a second
|
|
// to the collection time.
|
|
(await collectCoverage(displayName: displayName, forceCompile: true))
|
|
?.writeToFile(f);
|
|
}
|
|
}
|
|
|
|
class TracingLogger extends StdoutLogger {
|
|
Map<TestDescription, Map<Step, Stopwatch>> stopwatches = {};
|
|
|
|
@override
|
|
void logStepStart(int completed, int failed, int total, testing.Suite? suite,
|
|
TestDescription description, Step step) {
|
|
Map<Step, Stopwatch> map = stopwatches[description] ??= {};
|
|
Stopwatch stopwatch = map[step] ??= new Stopwatch();
|
|
if (stopwatch.isRunning) throw "unexpectedly already running @ $step";
|
|
stopwatch.start();
|
|
super.logStepStart(completed, failed, total, suite, description, step);
|
|
}
|
|
|
|
@override
|
|
void logStepComplete(int completed, int failed, int total,
|
|
testing.Suite? suite, TestDescription description, Step step) {
|
|
Map<Step, Stopwatch> map = stopwatches[description]!;
|
|
Stopwatch stopwatch = map[step] = map[step]!;
|
|
if (!stopwatch.isRunning) throw "unexpectedly not running";
|
|
stopwatch.stop();
|
|
super.logStepComplete(completed, failed, total, suite, description, step);
|
|
}
|
|
|
|
@override
|
|
void logSuiteComplete(testing.Suite suite) {
|
|
Map<String, Duration> totalRuntimesForSteps = {};
|
|
// Make sure not to overwrite existing text about number of tests run,
|
|
// failures etc.
|
|
print("");
|
|
print("");
|
|
|
|
for (MapEntry<TestDescription, Map<Step, Stopwatch>> entryMap
|
|
in stopwatches.entries) {
|
|
for (MapEntry<Step, Stopwatch> entry in entryMap.value.entries) {
|
|
if (entry.value.isRunning) throw "unexpectedly already running";
|
|
entry.value.elapsed + entry.value.elapsed;
|
|
totalRuntimesForSteps[entry.key.name] =
|
|
(totalRuntimesForSteps[entry.key.name] ?? new Duration()) +
|
|
entry.value.elapsed;
|
|
}
|
|
}
|
|
List<MapEntry<String, Duration>> entries =
|
|
totalRuntimesForSteps.entries.toList();
|
|
entries.sort((a, b) => a.value.compareTo(b.value));
|
|
for (MapEntry<String, Duration> entry in entries) {
|
|
const int maxLength = 25;
|
|
String key = (entry.key.length > maxLength)
|
|
? entry.key.substring(0, maxLength)
|
|
: entry.key.padLeft(maxLength);
|
|
print("$key: ${entry.value} ms");
|
|
}
|
|
super.logSuiteComplete(suite);
|
|
}
|
|
}
|