mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Print errors in all build modes (#69046)
This commit is contained in:
parent
2e54c4a8ea
commit
7a10b46ee0
@ -776,9 +776,12 @@ Future<void> _runWebUnitTests() async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _runWebIntegrationTests() async {
|
Future<void> _runWebIntegrationTests() async {
|
||||||
await _runWebStackTraceTest('profile');
|
await _runWebStackTraceTest('profile', 'lib/stack_trace.dart');
|
||||||
await _runWebStackTraceTest('release');
|
await _runWebStackTraceTest('release', 'lib/stack_trace.dart');
|
||||||
|
await _runWebStackTraceTest('profile', 'lib/framework_stack_trace.dart');
|
||||||
|
await _runWebStackTraceTest('release', 'lib/framework_stack_trace.dart');
|
||||||
await _runWebDebugTest('lib/stack_trace.dart');
|
await _runWebDebugTest('lib/stack_trace.dart');
|
||||||
|
await _runWebDebugTest('lib/framework_stack_trace.dart');
|
||||||
await _runWebDebugTest('lib/web_directory_loading.dart');
|
await _runWebDebugTest('lib/web_directory_loading.dart');
|
||||||
await _runWebDebugTest('test/test.dart');
|
await _runWebDebugTest('test/test.dart');
|
||||||
await _runWebDebugTest('lib/null_assert_main.dart', enableNullSafety: true);
|
await _runWebDebugTest('lib/null_assert_main.dart', enableNullSafety: true);
|
||||||
@ -807,7 +810,7 @@ Future<void> _runWebIntegrationTests() async {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _runWebStackTraceTest(String buildMode) async {
|
Future<void> _runWebStackTraceTest(String buildMode, String entrypoint) async {
|
||||||
final String testAppDirectory = path.join(flutterRoot, 'dev', 'integration_tests', 'web');
|
final String testAppDirectory = path.join(flutterRoot, 'dev', 'integration_tests', 'web');
|
||||||
final String appBuildDirectory = path.join(testAppDirectory, 'build', 'web');
|
final String appBuildDirectory = path.join(testAppDirectory, 'build', 'web');
|
||||||
|
|
||||||
@ -824,7 +827,7 @@ Future<void> _runWebStackTraceTest(String buildMode) async {
|
|||||||
'web',
|
'web',
|
||||||
'--$buildMode',
|
'--$buildMode',
|
||||||
'-t',
|
'-t',
|
||||||
'lib/stack_trace.dart',
|
entrypoint,
|
||||||
],
|
],
|
||||||
workingDirectory: testAppDirectory,
|
workingDirectory: testAppDirectory,
|
||||||
environment: <String, String>{
|
environment: <String, String>{
|
||||||
|
96
dev/integration_tests/web/lib/framework_stack_trace.dart
Normal file
96
dev/integration_tests/web/lib/framework_stack_trace.dart
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// Copyright 2014 The Flutter Authors. 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:html' as html;
|
||||||
|
|
||||||
|
import 'package:meta/dart2js.dart';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
// Tests that the framework prints stack traces in all build modes.
|
||||||
|
//
|
||||||
|
// Regression test for https://github.com/flutter/flutter/issues/68616.
|
||||||
|
//
|
||||||
|
// See also `dev/integration_tests/web/lib/stack_trace.dart` that tests the
|
||||||
|
// framework's ability to parse stack traces in all build modes.
|
||||||
|
void main() async {
|
||||||
|
final StringBuffer errorMessage = StringBuffer();
|
||||||
|
debugPrint = (String message, { int wrapWidth }) {
|
||||||
|
errorMessage.writeln(message);
|
||||||
|
};
|
||||||
|
|
||||||
|
runApp(ThrowingWidget());
|
||||||
|
|
||||||
|
// Let the framework flush error messages.
|
||||||
|
await Future<void>.delayed(Duration.zero);
|
||||||
|
|
||||||
|
final StringBuffer output = StringBuffer();
|
||||||
|
if (_errorMessageFormattedCorrectly(errorMessage.toString())) {
|
||||||
|
output.writeln('--- TEST SUCCEEDED ---');
|
||||||
|
} else {
|
||||||
|
output.writeln('--- UNEXPECTED ERROR MESSAGE FORMAT ---');
|
||||||
|
output.writeln(errorMessage);
|
||||||
|
output.writeln('--- TEST FAILED ---');
|
||||||
|
}
|
||||||
|
|
||||||
|
print(output);
|
||||||
|
html.HttpRequest.request(
|
||||||
|
'/test-result',
|
||||||
|
method: 'POST',
|
||||||
|
sendData: '$output',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _errorMessageFormattedCorrectly(String errorMessage) {
|
||||||
|
if (!errorMessage.contains('Test error message')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In release mode symbols are minified. No sense testing the contents of the stack trace.
|
||||||
|
if (kReleaseMode) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const List<String> expectedFunctions = <String>[
|
||||||
|
'topLevelFunction',
|
||||||
|
'secondLevelFunction',
|
||||||
|
'thirdLevelFunction',
|
||||||
|
];
|
||||||
|
|
||||||
|
return expectedFunctions.every(errorMessage.contains);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThrowingWidget extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_ThrowingWidgetState createState() => _ThrowingWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ThrowingWidgetState extends State<ThrowingWidget> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
topLevelFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@noInline
|
||||||
|
void topLevelFunction() {
|
||||||
|
secondLevelFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
@noInline
|
||||||
|
void secondLevelFunction() {
|
||||||
|
thirdLevelFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
@noInline
|
||||||
|
void thirdLevelFunction() {
|
||||||
|
throw Exception('Test error message');
|
||||||
|
}
|
@ -944,15 +944,18 @@ class FlutterError extends Error with DiagnosticableTreeMixin implements Asserti
|
|||||||
static void dumpErrorToConsole(FlutterErrorDetails details, { bool forceReport = false }) {
|
static void dumpErrorToConsole(FlutterErrorDetails details, { bool forceReport = false }) {
|
||||||
assert(details != null);
|
assert(details != null);
|
||||||
assert(details.exception != null);
|
assert(details.exception != null);
|
||||||
bool reportError = details.silent != true; // could be null
|
bool isInDebugMode = false;
|
||||||
assert(() {
|
assert(() {
|
||||||
// In checked mode, we ignore the "silent" flag.
|
// In checked mode, we ignore the "silent" flag.
|
||||||
reportError = true;
|
isInDebugMode = true;
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
|
final bool reportError = isInDebugMode || details.silent != true; // could be null
|
||||||
if (!reportError && !forceReport)
|
if (!reportError && !forceReport)
|
||||||
return;
|
return;
|
||||||
if (_errorCount == 0 || forceReport) {
|
if (_errorCount == 0 || forceReport) {
|
||||||
|
// Diagnostics is only available in debug mode. In profile and release modes fallback to plain print.
|
||||||
|
if (isInDebugMode) {
|
||||||
debugPrint(
|
debugPrint(
|
||||||
TextTreeRenderer(
|
TextTreeRenderer(
|
||||||
wrapWidth: wrapWidth,
|
wrapWidth: wrapWidth,
|
||||||
@ -960,6 +963,13 @@ class FlutterError extends Error with DiagnosticableTreeMixin implements Asserti
|
|||||||
maxDescendentsTruncatableNode: 5,
|
maxDescendentsTruncatableNode: 5,
|
||||||
).render(details.toDiagnosticsNode(style: DiagnosticsTreeStyle.error)).trimRight(),
|
).render(details.toDiagnosticsNode(style: DiagnosticsTreeStyle.error)).trimRight(),
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
debugPrintStack(
|
||||||
|
stackTrace: details.stack,
|
||||||
|
label: details.exception.toString(),
|
||||||
|
maxFrames: 100,
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
debugPrint('Another exception was thrown: ${details.summary}');
|
debugPrint('Another exception was thrown: ${details.summary}');
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user