Add more debugging logs to overall_experience_test (#86368)
This commit is contained in:
parent
d2094a5dbc
commit
1133921c4d
@ -722,7 +722,7 @@ Future<void> _runFrameworkTests() async {
|
|||||||
Future<void> runMisc() async {
|
Future<void> runMisc() async {
|
||||||
print('${green}Running package tests$reset for directories other than packages/flutter');
|
print('${green}Running package tests$reset for directories other than packages/flutter');
|
||||||
await _pubRunTest(path.join(flutterRoot, 'dev', 'bots'));
|
await _pubRunTest(path.join(flutterRoot, 'dev', 'bots'));
|
||||||
await _pubRunTest(path.join(flutterRoot, 'dev', 'devicelab'), ensurePrecompiledTool: false);
|
await _pubRunTest(path.join(flutterRoot, 'dev', 'devicelab'), ensurePrecompiledTool: false); // See https://github.com/flutter/flutter/issues/86209
|
||||||
await _pubRunTest(path.join(flutterRoot, 'dev', 'snippets'));
|
await _pubRunTest(path.join(flutterRoot, 'dev', 'snippets'));
|
||||||
// TODO(fujino): Move this to its own test shard
|
// TODO(fujino): Move this to its own test shard
|
||||||
await _pubRunTest(path.join(flutterRoot, 'dev', 'conductor'), forceSingleCore: true);
|
await _pubRunTest(path.join(flutterRoot, 'dev', 'conductor'), forceSingleCore: true);
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
// to the runFlutter function.
|
// to the runFlutter function.
|
||||||
|
|
||||||
// @dart = 2.8
|
// @dart = 2.8
|
||||||
|
// This file is ready to transition, just uncomment /*?*/, /*!*/, and /*late*/.
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
@ -113,21 +114,29 @@ class Multiple extends Transition {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
|
if (_originalPatterns.length == patterns.length) {
|
||||||
|
return '${_originalPatterns.map(describe).join(', ')} (all matched)';
|
||||||
|
}
|
||||||
return '${_originalPatterns.map(describe).join(', ')} (matched ${_originalPatterns.length - patterns.length} so far)';
|
return '${_originalPatterns.map(describe).join(', ')} (matched ${_originalPatterns.length - patterns.length} so far)';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProcessTestResult {
|
class LogLine {
|
||||||
const ProcessTestResult(this.exitCode, this.stdout, this.stderr);
|
const LogLine(this.channel, this.stamp, this.message);
|
||||||
final int exitCode;
|
final String channel;
|
||||||
final List<String> stdout;
|
final String stamp;
|
||||||
final List<String> stderr;
|
final String message;
|
||||||
|
|
||||||
|
bool get couldBeCrash => message.contains('Oops; flutter has exited unexpectedly:');
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'exit code $exitCode\nstdout:\n ${stdout.join('\n ')}\nstderr:\n ${stderr.join('\n ')}\n';
|
String toString() => '$stamp $channel: $message';
|
||||||
|
|
||||||
|
void printClearly() {
|
||||||
|
print('$stamp $channel: ${clarify(message)}');
|
||||||
}
|
}
|
||||||
|
|
||||||
String clarify(String line) {
|
static String clarify(String line) {
|
||||||
return line.runes.map<String>((int rune) {
|
return line.runes.map<String>((int rune) {
|
||||||
if (rune >= 0x20 && rune <= 0x7F) {
|
if (rune >= 0x20 && rune <= 0x7F) {
|
||||||
return String.fromCharCode(rune);
|
return String.fromCharCode(rune);
|
||||||
@ -143,9 +152,29 @@ String clarify(String line) {
|
|||||||
return '<${rune.toRadixString(16).padLeft(rune <= 0xFF ? 2 : rune <= 0xFFFF ? 4 : 5, '0')}>';
|
return '<${rune.toRadixString(16).padLeft(rune <= 0xFF ? 2 : rune <= 0xFFFF ? 4 : 5, '0')}>';
|
||||||
}).join('');
|
}).join('');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void printClearly(String line) {
|
class ProcessTestResult {
|
||||||
print(clarify(line));
|
const ProcessTestResult(this.exitCode, this.logs);
|
||||||
|
final int exitCode;
|
||||||
|
final List<LogLine> logs;
|
||||||
|
|
||||||
|
List<String> get stdout {
|
||||||
|
return logs
|
||||||
|
.where((LogLine log) => log.channel == 'stdout')
|
||||||
|
.map<String>((LogLine log) => log.message)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> get stderr {
|
||||||
|
return logs
|
||||||
|
.where((LogLine log) => log.channel == 'stderr')
|
||||||
|
.map<String>((LogLine log) => log.message)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'exit code $exitCode\nlogs:\n ${logs.join('\n ')}\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ProcessTestResult> runFlutter(
|
Future<ProcessTestResult> runFlutter(
|
||||||
@ -156,13 +185,12 @@ Future<ProcessTestResult> runFlutter(
|
|||||||
bool logging = true,
|
bool logging = true,
|
||||||
Duration expectedMaxDuration = const Duration(seconds: 25), // must be less than test timeout of 30 seconds!
|
Duration expectedMaxDuration = const Duration(seconds: 25), // must be less than test timeout of 30 seconds!
|
||||||
}) async {
|
}) async {
|
||||||
|
final Stopwatch clock = Stopwatch()..start();
|
||||||
final Process process = await processManager.start(
|
final Process process = await processManager.start(
|
||||||
<String>[flutterBin, ...arguments],
|
<String>[flutterBin, ...arguments],
|
||||||
workingDirectory: workingDirectory,
|
workingDirectory: workingDirectory,
|
||||||
);
|
);
|
||||||
final List<String> stdoutLog = <String>[];
|
final List<LogLine> logs = <LogLine>[];
|
||||||
final List<String> stderrLog = <String>[];
|
|
||||||
final List<String> stdinLog = <String>[];
|
|
||||||
int nextTransition = 0;
|
int nextTransition = 0;
|
||||||
void describeStatus() {
|
void describeStatus() {
|
||||||
if (transitions.isNotEmpty) {
|
if (transitions.isNotEmpty) {
|
||||||
@ -175,13 +203,13 @@ Future<ProcessTestResult> runFlutter(
|
|||||||
' '} ${transitions[index]}');
|
' '} ${transitions[index]}');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stdoutLog.isEmpty && stderrLog.isEmpty && stdinLog.isEmpty) {
|
if (logs.isEmpty) {
|
||||||
print('So far nothing has been logged${ debug ? "" : "; use debug:true to print all output" }.');
|
print('So far nothing has been logged${ debug ? "" : "; use debug:true to print all output" }.');
|
||||||
} else {
|
} else {
|
||||||
print('Log${ debug ? "" : " (only contains logged lines; use debug:true to print all output)" }:');
|
print('Log${ debug ? "" : " (only contains logged lines; use debug:true to print all output)" }:');
|
||||||
stdoutLog.map<String>((String line) => 'stdout: $line').forEach(printClearly);
|
for (final LogLine log in logs) {
|
||||||
stderrLog.map<String>((String line) => 'stderr: $line').forEach(printClearly);
|
log.printClearly();
|
||||||
stdinLog.map<String>((String line) => 'stdin: $line').forEach(printClearly);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool streamingLogs = false;
|
bool streamingLogs = false;
|
||||||
@ -190,7 +218,7 @@ Future<ProcessTestResult> runFlutter(
|
|||||||
if (!streamingLogs) {
|
if (!streamingLogs) {
|
||||||
streamingLogs = true;
|
streamingLogs = true;
|
||||||
if (!debug) {
|
if (!debug) {
|
||||||
print('Test is taking a long time.');
|
print('Test is taking a long time (${clock.elapsed.inSeconds} seconds so far).');
|
||||||
}
|
}
|
||||||
describeStatus();
|
describeStatus();
|
||||||
print('(streaming all logs from this point on...)');
|
print('(streaming all logs from this point on...)');
|
||||||
@ -198,12 +226,14 @@ Future<ProcessTestResult> runFlutter(
|
|||||||
print('(taking a long time...)');
|
print('(taking a long time...)');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
String stamp() => '[${(clock.elapsed.inMilliseconds / 1000.0).toStringAsFixed(1).padLeft(5, " ")}s]';
|
||||||
void processStdout(String line) {
|
void processStdout(String line) {
|
||||||
|
final LogLine log = LogLine('stdout', stamp(), line);
|
||||||
if (logging) {
|
if (logging) {
|
||||||
stdoutLog.add(line);
|
logs.add(log);
|
||||||
}
|
}
|
||||||
if (streamingLogs) {
|
if (streamingLogs) {
|
||||||
print('stdout: $line');
|
log.printClearly();
|
||||||
}
|
}
|
||||||
if (nextTransition < transitions.length && transitions[nextTransition].matches(line)) {
|
if (nextTransition < transitions.length && transitions[nextTransition].matches(line)) {
|
||||||
if (streamingLogs) {
|
if (streamingLogs) {
|
||||||
@ -211,7 +241,7 @@ Future<ProcessTestResult> runFlutter(
|
|||||||
}
|
}
|
||||||
if (transitions[nextTransition].logging != null) {
|
if (transitions[nextTransition].logging != null) {
|
||||||
if (!logging && transitions[nextTransition].logging/*!*/) {
|
if (!logging && transitions[nextTransition].logging/*!*/) {
|
||||||
stdoutLog.add(line);
|
logs.add(log);
|
||||||
}
|
}
|
||||||
logging = transitions[nextTransition].logging/*!*/;
|
logging = transitions[nextTransition].logging/*!*/;
|
||||||
if (streamingLogs) {
|
if (streamingLogs) {
|
||||||
@ -225,9 +255,10 @@ Future<ProcessTestResult> runFlutter(
|
|||||||
if (transitions[nextTransition].handler != null) {
|
if (transitions[nextTransition].handler != null) {
|
||||||
final String/*?*/ command = transitions[nextTransition].handler/*!*/(line);
|
final String/*?*/ command = transitions[nextTransition].handler/*!*/(line);
|
||||||
if (command != null) {
|
if (command != null) {
|
||||||
stdinLog.add(command);
|
final LogLine inLog = LogLine('stdin', stamp(), command);
|
||||||
|
logs.add(inLog);
|
||||||
if (streamingLogs) {
|
if (streamingLogs) {
|
||||||
print('stdin: $command');
|
inLog.printClearly();
|
||||||
}
|
}
|
||||||
process.stdin.write(command);
|
process.stdin.write(command);
|
||||||
}
|
}
|
||||||
@ -238,9 +269,10 @@ Future<ProcessTestResult> runFlutter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void processStderr(String line) {
|
void processStderr(String line) {
|
||||||
stderrLog.add(line);
|
final LogLine log = LogLine('stdout', stamp(), line);
|
||||||
|
logs.add(log);
|
||||||
if (streamingLogs) {
|
if (streamingLogs) {
|
||||||
print('stderr: $line');
|
log.printClearly();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (debug) {
|
if (debug) {
|
||||||
@ -251,19 +283,24 @@ Future<ProcessTestResult> runFlutter(
|
|||||||
process.stdout.transform<String>(utf8.decoder).transform<String>(const LineSplitter()).listen(processStdout);
|
process.stdout.transform<String>(utf8.decoder).transform<String>(const LineSplitter()).listen(processStdout);
|
||||||
process.stderr.transform<String>(utf8.decoder).transform<String>(const LineSplitter()).listen(processStderr);
|
process.stderr.transform<String>(utf8.decoder).transform<String>(const LineSplitter()).listen(processStderr);
|
||||||
unawaited(process.exitCode.timeout(expectedMaxDuration, onTimeout: () {
|
unawaited(process.exitCode.timeout(expectedMaxDuration, onTimeout: () {
|
||||||
print('(process is not quitting, trying to send a "q" just in case that helps)');
|
print('${stamp()} (process is not quitting, trying to send a "q" just in case that helps)');
|
||||||
print('(a functional test should never reach this point)');
|
print('(a functional test should never reach this point)');
|
||||||
|
final LogLine inLog = LogLine('stdin', stamp(), 'q');
|
||||||
|
logs.add(inLog);
|
||||||
|
if (streamingLogs) {
|
||||||
|
inLog.printClearly();
|
||||||
|
}
|
||||||
process.stdin.write('q');
|
process.stdin.write('q');
|
||||||
return null;
|
return -1; // discarded
|
||||||
}).catchError((Object error) { /* ignore the error here, it'll be reported on the next line */ }));
|
}).catchError((Object error) { /* ignore the error here, it'll be reported on the next line */ }));
|
||||||
final int exitCode = await process.exitCode;
|
final int exitCode = await process.exitCode;
|
||||||
if (streamingLogs) {
|
if (streamingLogs) {
|
||||||
print('(process terminated with exit code $exitCode)');
|
print('${stamp()} (process terminated with exit code $exitCode)');
|
||||||
}
|
}
|
||||||
timeout?.cancel();
|
timeout?.cancel();
|
||||||
if (nextTransition < transitions.length) {
|
if (nextTransition < transitions.length) {
|
||||||
print('The subprocess terminated before all the expected transitions had been matched.');
|
print('The subprocess terminated before all the expected transitions had been matched.');
|
||||||
if (stderrLog.any((String line) => line.contains('Oops; flutter has exited unexpectedly:'))) {
|
if (logs.any((LogLine line) => line.couldBeCrash)) {
|
||||||
print('The subprocess may in fact have crashed. Check the stderr logs below.');
|
print('The subprocess may in fact have crashed. Check the stderr logs below.');
|
||||||
}
|
}
|
||||||
print('The transition that we were hoping to see next but that we never saw was:');
|
print('The transition that we were hoping to see next but that we never saw was:');
|
||||||
@ -275,9 +312,9 @@ Future<ProcessTestResult> runFlutter(
|
|||||||
throw TestFailure('Missed some expected transitions.');
|
throw TestFailure('Missed some expected transitions.');
|
||||||
}
|
}
|
||||||
if (streamingLogs) {
|
if (streamingLogs) {
|
||||||
print('(completed execution successfully!)');
|
print('${stamp()} (completed execution successfully!)');
|
||||||
}
|
}
|
||||||
return ProcessTestResult(exitCode, stdoutLog, stderrLog);
|
return ProcessTestResult(exitCode, logs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int progressMessageWidth = 64;
|
const int progressMessageWidth = 64;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user