[pkg/testing] Replace top-level logging functions with an interface.

Change-Id: Id896436ab869d52c6e9befff885494b87690a342
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/118382
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Karl Klose <karlklose@google.com>
This commit is contained in:
Karl Klose 2019-09-23 07:57:39 +00:00 committed by commit-bot@chromium.org
parent 209180d280
commit 96f1abdaca
5 changed files with 157 additions and 123 deletions

View file

@ -21,15 +21,7 @@ import 'zone_helper.dart' show runGuarded;
import 'error_handling.dart' show withErrorHandling; import 'error_handling.dart' show withErrorHandling;
import 'log.dart' import 'log.dart' show Logger, StdoutLogger, splitLines;
show
logMessage,
logStepComplete,
logStepStart,
logSuiteComplete,
logTestComplete,
logUnexpectedResult,
splitLines;
import 'multitest.dart' show MultitestTransformer, isError; import 'multitest.dart' show MultitestTransformer, isError;
@ -112,7 +104,9 @@ abstract class ChainContext {
ExpectationSet get expectationSet => ExpectationSet.Default; ExpectationSet get expectationSet => ExpectationSet.Default;
Future<Null> run(Chain suite, Set<String> selectors, Future<Null> run(Chain suite, Set<String> selectors,
{int shards = 1, int shard = 0}) async { {int shards = 1,
int shard = 0,
Logger logger: const StdoutLogger()}) async {
assert(shards >= 1, "Invalid shards count: $shards"); assert(shards >= 1, "Invalid shards count: $shards");
assert(0 <= shard && shard < shards, assert(0 <= shard && shard < shards,
"Invalid shard index: $shard, not in range [0,$shards[."); "Invalid shard index: $shard, not in range [0,$shards[.");
@ -182,8 +176,8 @@ abstract class ChainContext {
Step step = iterator.current; Step step = iterator.current;
lastStepRun = step; lastStepRun = step;
isAsync = step.isAsync; isAsync = step.isAsync;
logStepStart(completed, unexpectedResults.length, descriptions.length, logger.logStepStart(completed, unexpectedResults.length,
suite, description, step); descriptions.length, suite, description, step);
// TODO(ahe): It's important to share the zone error reporting zone // TODO(ahe): It's important to share the zone error reporting zone
// between all the tasks. Otherwise, if a future completes with an // between all the tasks. Otherwise, if a future completes with an
// error in one zone, and gets stored, it becomes an uncaught error // error in one zone, and gets stored, it becomes an uncaught error
@ -201,7 +195,7 @@ abstract class ChainContext {
future = future.then((_currentResult) async { future = future.then((_currentResult) async {
Result currentResult = _currentResult; Result currentResult = _currentResult;
if (currentResult != null) { if (currentResult != null) {
logStepComplete(completed, unexpectedResults.length, logger.logStepComplete(completed, unexpectedResults.length,
descriptions.length, suite, description, lastStepRun); descriptions.length, suite, description, lastStepRun);
result = currentResult; result = currentResult;
if (currentResult.outcome == Expectation.Pass) { if (currentResult.outcome == Expectation.Pass) {
@ -217,12 +211,13 @@ abstract class ChainContext {
result.addLog("$sb"); result.addLog("$sb");
unexpectedResults[description] = result; unexpectedResults[description] = result;
unexpectedOutcomes[description] = expectedOutcomes; unexpectedOutcomes[description] = expectedOutcomes;
logUnexpectedResult(suite, description, result, expectedOutcomes); logger.logUnexpectedResult(
suite, description, result, expectedOutcomes);
exitCode = 1; exitCode = 1;
} else { } else {
logMessage(sb); logger.logMessage(sb);
} }
logTestComplete(++completed, unexpectedResults.length, logger.logTestComplete(++completed, unexpectedResults.length,
descriptions.length, suite, description); descriptions.length, suite, description);
}); });
if (isAsync) { if (isAsync) {
@ -233,14 +228,16 @@ abstract class ChainContext {
} }
} }
logger.logTestStart(completed, unexpectedResults.length,
descriptions.length, suite, description);
// The input of the first step is [description]. // The input of the first step is [description].
await doStep(description); await doStep(description);
} }
await Future.wait(futures); await Future.wait(futures);
logSuiteComplete(); logger.logSuiteComplete();
if (unexpectedResults.isNotEmpty) { if (unexpectedResults.isNotEmpty) {
unexpectedResults.forEach((TestDescription description, Result result) { unexpectedResults.forEach((TestDescription description, Result result) {
logUnexpectedResult( logger.logUnexpectedResult(
suite, description, result, unexpectedOutcomes[description]); suite, description, result, unexpectedOutcomes[description]);
}); });
print("${unexpectedResults.length} failed:"); print("${unexpectedResults.length} failed:");

View file

@ -38,6 +38,42 @@ void enableVerboseOutput() {
_isVerbose = true; _isVerbose = true;
} }
abstract class Logger {
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 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 logProgress(String message);
void logMessage(Object message);
void logNumberedLines(String text);
void logExpectedResult(Suite suite, TestDescription description,
Result result, Set<Expectation> expectedOutcomes);
void logUnexpectedResult(Suite suite, TestDescription description,
Result result, Set<Expectation> expectedOutcomes);
void logSuiteComplete();
void logUncaughtError(error, StackTrace stackTrace);
}
class StdoutLogger implements Logger {
const StdoutLogger();
void logTestStart(int completed, int failed, int total, Suite suite,
TestDescription description) {}
void logTestComplete(int completed, int failed, int total, Suite suite, void logTestComplete(int completed, int failed, int total, Suite suite,
TestDescription description) { TestDescription description) {
String message = formatProgress(completed, failed, total); String message = formatProgress(completed, failed, total);
@ -103,6 +139,9 @@ void logNumberedLines(String text) {
} }
} }
void logExpectedResult(Suite suite, TestDescription description,
Result result, Set<Expectation> expectedOutcomes) {}
void logUnexpectedResult(Suite suite, TestDescription description, void logUnexpectedResult(Suite suite, TestDescription description,
Result result, Set<Expectation> expectedOutcomes) { Result result, Set<Expectation> expectedOutcomes) {
print("${eraseLine}UNEXPECTED: ${suite.name}/${description.shortName}"); print("${eraseLine}UNEXPECTED: ${suite.name}/${description.shortName}");
@ -140,6 +179,7 @@ void logUncaughtError(error, StackTrace stackTrace) {
logMessage(stackTrace); logMessage(stackTrace);
} }
} }
}
String pad(Object o, int pad, {String filler: " "}) { String pad(Object o, int pad, {String filler: " "}) {
String result = (filler * pad) + "$o"; String result = (filler * pad) + "$o";

View file

@ -24,12 +24,7 @@ import '../testing.dart'
import 'analyze.dart' show Analyze; import 'analyze.dart' show Analyze;
import 'log.dart' import 'log.dart'
show show enableVerboseOutput, isVerbose, Logger, splitLines, StdoutLogger;
enableVerboseOutput,
isVerbose,
logMessage,
logNumberedLines,
splitLines;
import 'suite.dart' show Dart, Suite; import 'suite.dart' show Dart, Suite;
@ -55,7 +50,11 @@ Future<TestRoot> computeTestRoot(String configurationPath, Uri base) {
/// `testing.json` isn't located in the current working directory and is a path /// `testing.json` isn't located in the current working directory and is a path
/// relative to [me] which defaults to `Platform.script`. /// relative to [me] which defaults to `Platform.script`.
Future<Null> runMe(List<String> arguments, CreateContext f, Future<Null> runMe(List<String> arguments, CreateContext f,
{String configurationPath, Uri me, int shards = 1, int shard = 0}) { {String configurationPath,
Uri me,
int shards = 1,
int shard = 0,
Logger logger: const StdoutLogger()}) {
me ??= Platform.script; me ??= Platform.script;
return withErrorHandling(() async { return withErrorHandling(() async {
TestRoot testRoot = await computeTestRoot(configurationPath, me); TestRoot testRoot = await computeTestRoot(configurationPath, me);
@ -66,7 +65,7 @@ Future<Null> runMe(List<String> arguments, CreateContext f,
print("Running suite ${suite.name}..."); print("Running suite ${suite.name}...");
ChainContext context = await f(suite, cl.environment); ChainContext context = await f(suite, cl.environment);
await context.run(suite, new Set<String>.from(cl.selectors), await context.run(suite, new Set<String>.from(cl.selectors),
shards: shards, shard: shard); shards: shards, shard: shard, logger: logger);
} }
} }
}); });
@ -117,8 +116,8 @@ Future<Null> run(List<String> arguments, List<String> suiteNames,
} }
Future<Null> runProgram(String program, Uri packages) async { Future<Null> runProgram(String program, Uri packages) async {
logMessage("Running:"); const StdoutLogger().logMessage("Running:");
logNumberedLines(program); const StdoutLogger().logNumberedLines(program);
Uri dataUri = new Uri.dataFromString(program); Uri dataUri = new Uri.dataFromString(program);
ReceivePort exitPort = new ReceivePort(); ReceivePort exitPort = new ReceivePort();
Isolate isolate = await Isolate.spawnUri(dataUri, <String>[], null, Isolate isolate = await Isolate.spawnUri(dataUri, <String>[], null,

View file

@ -18,13 +18,7 @@ import 'test_root.dart' show TestRoot;
import 'zone_helper.dart' show runGuarded; import 'zone_helper.dart' show runGuarded;
import 'log.dart' import 'log.dart' show enableVerboseOutput, isVerbose, StdoutLogger;
show
enableVerboseOutput,
isVerbose,
logMessage,
logSuiteComplete,
logTestComplete;
import 'run.dart' show SuiteRunner, runProgram; import 'run.dart' show SuiteRunner, runProgram;
@ -115,7 +109,8 @@ class CommandLine {
} }
} }
} }
logMessage("Reading configuration file '$configurationPath'."); const StdoutLogger()
.logMessage("Reading configuration file '$configurationPath'.");
Uri configuration = Uri configuration =
await Isolate.resolvePackageUri(Uri.base.resolve(configurationPath)); await Isolate.resolvePackageUri(Uri.base.resolve(configurationPath));
if (configuration == null || if (configuration == null ||
@ -177,18 +172,21 @@ Future<void> runTests(Map<String, Function> tests) =>
withErrorHandling<void>(() async { withErrorHandling<void>(() async {
int completed = 0; int completed = 0;
for (String name in tests.keys) { for (String name in tests.keys) {
const StdoutLogger()
.logTestStart(completed, 0, tests.length, null, null);
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
try { try {
await runGuarded(() { await runGuarded(() {
print("Running test $name"); print("Running test $name");
return tests[name](); return tests[name]();
}, printLineOnStdout: sb.writeln); }, printLineOnStdout: sb.writeln);
logMessage(sb); const StdoutLogger().logMessage(sb);
} catch (e) { } catch (e) {
print(sb); print(sb);
rethrow; rethrow;
} }
logTestComplete(++completed, 0, tests.length, null, null); const StdoutLogger()
.logTestComplete(++completed, 0, tests.length, null, null);
} }
logSuiteComplete(); const StdoutLogger().logSuiteComplete();
}); });

View file

@ -11,7 +11,7 @@ import 'dart:io' show exit, stderr;
import 'dart:isolate' show Capability, Isolate, ReceivePort; import 'dart:isolate' show Capability, Isolate, ReceivePort;
import 'log.dart' show logUncaughtError; import 'log.dart' show StdoutLogger;
Future runGuarded(Future f(), Future runGuarded(Future f(),
{void printLineOnStdout(line), {void printLineOnStdout(line),
@ -26,7 +26,7 @@ Future runGuarded(Future f(),
Completer completer = new Completer(); Completer completer = new Completer();
handleUncaughtError(error, StackTrace stackTrace) { handleUncaughtError(error, StackTrace stackTrace) {
logUncaughtError(error, stackTrace); StdoutLogger().logUncaughtError(error, stackTrace);
if (!completer.isCompleted) { if (!completer.isCompleted) {
completer.completeError(error, stackTrace); completer.completeError(error, stackTrace);
} else if (handleLateError != null) { } else if (handleLateError != null) {