From 00dfa224d113c1146fa46523b357bf56b214d50b Mon Sep 17 00:00:00 2001 From: Ian Hickson Date: Thu, 13 Apr 2017 12:31:04 -0700 Subject: [PATCH] Be more consistent about how stack traces are output from flutter_test (#9361) --- .../exception_handling_expectation.txt | 58 +++++++++++++++++++ .../flutter_test/exception_handling_test.dart | 18 ++++++ packages/flutter_test/lib/src/binding.dart | 13 ++++- packages/flutter_test/pubspec.yaml | 5 ++ packages/flutter_tools/test/test_test.dart | 5 ++ 5 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 dev/automated_tests/flutter_test/exception_handling_expectation.txt create mode 100644 dev/automated_tests/flutter_test/exception_handling_test.dart diff --git a/dev/automated_tests/flutter_test/exception_handling_expectation.txt b/dev/automated_tests/flutter_test/exception_handling_expectation.txt new file mode 100644 index 0000000000..b824288eb2 --- /dev/null +++ b/dev/automated_tests/flutter_test/exception_handling_expectation.txt @@ -0,0 +1,58 @@ +[^═]*(this line contains the test framework's output with the clock and so forth)? +══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════ +The following message was thrown running a test: +Who lives, who dies, who tells your story\? + +When the exception was thrown, this was the stack: +#0 main. \(.+[/\\]dev[/\\]automated_tests[/\\]flutter_test[/\\]exception_handling_test\.dart:10:5\) + +#1 .+ \(package:flutter_test[/\\]src[/\\]widget_tester\.dart:[0-9]+:[0-9]+\) +<> +^\(elided [0-9]+ .+[^)]$ +^.+\)$ + +The test description was: +Exception handling in test harness - string +════════════════════════════════════════════════════════════════════════════════════════════════════ +.*(this line has more of the test framework's output)? + Test failed\. See exception logs above\. + * +[^═]*(this line contains the test framework's output with the clock and so forth)? +══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════ +The following assertion was thrown running a test: +Who lives, who dies, who tells your story\? + +When the exception was thrown, this was the stack: +#0 main. \(.+[/\\]dev[/\\]automated_tests[/\\]flutter_test[/\\]exception_handling_test\.dart:13:5\) + +#1 .+ \(package:flutter_test[/\\]src[/\\]widget_tester\.dart:[0-9]+:[0-9]+\) +<> +^\(elided [0-9]+ .+[^)]$ +^.+\)$ + +The test description was: +Exception handling in test harness - FlutterError +════════════════════════════════════════════════════════════════════════════════════════════════════ +.*(this line has more of the test framework's output)? + Test failed\. See exception logs above\. + * +[^═]*(this line contains the test framework's output with the clock and so forth)? +══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════ +The following message was thrown running a test: +Who lives, who dies, who tells your story\? + +When the exception was thrown, this was the stack: +#[0-9]+ +main. \(.+[/\\]dev[/\\]automated_tests[/\\]flutter_test[/\\]exception_handling_test\.dart:16:9\) +#[0-9]+ +main. \(.+[/\\]dev[/\\]automated_tests[/\\]flutter_test[/\\]exception_handling_test\.dart:15:105\) +#[0-9]+ +.+ \(package:flutter_test[/\\]src[/\\]widget_tester\.dart:[0-9]+:[0-9]+\) +<> +^\(elided [0-9]+ .+[^)]$ +^.+\)$ + +The test description was: +Exception handling in test harness - uncaught Future error +════════════════════════════════════════════════════════════════════════════════════════════════════ +.*(this line has more of the test framework's output)? + Test failed\. See exception logs above\. + * +.*..:.. \+0 -3: Some tests failed\. * diff --git a/dev/automated_tests/flutter_test/exception_handling_test.dart b/dev/automated_tests/flutter_test/exception_handling_test.dart new file mode 100644 index 0000000000..04dc1a1fa6 --- /dev/null +++ b/dev/automated_tests/flutter_test/exception_handling_test.dart @@ -0,0 +1,18 @@ +// Copyright 2017 The Chromium 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 'package:flutter/foundation.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('Exception handling in test harness - string', (WidgetTester tester) async { + throw 'Who lives, who dies, who tells your story?'; + }); + testWidgets('Exception handling in test harness - FlutterError', (WidgetTester tester) async { + throw new FlutterError('Who lives, who dies, who tells your story?'); + }); + testWidgets('Exception handling in test harness - uncaught Future error', (WidgetTester tester) async { + new Future.error('Who lives, who dies, who tells your story?'); + }); +} diff --git a/packages/flutter_test/lib/src/binding.dart b/packages/flutter_test/lib/src/binding.dart index 5c4e50bd09..076f0ac2bd 100644 --- a/packages/flutter_test/lib/src/binding.dart +++ b/packages/flutter_test/lib/src/binding.dart @@ -18,6 +18,7 @@ import 'package:meta/meta.dart'; import 'package:quiver/testing/async.dart'; import 'package:quiver/time.dart'; import 'package:test/test.dart' as test_package; +import 'package:stack_trace/stack_trace.dart' as stack_trace; import 'package:vector_math/vector_math_64.dart'; import 'stack_manipulation.dart'; @@ -353,7 +354,7 @@ abstract class TestWidgetsFlutterBinding extends BindingBase // will see them in the logs at some point. FlutterError.dumpErrorToConsole(new FlutterErrorDetails( exception: exception, - stack: stack, + stack: _unmangle(stack), context: 'running a test (but after the test had completed)', library: 'Flutter test framework' ), forceReport: true); @@ -394,7 +395,7 @@ abstract class TestWidgetsFlutterBinding extends BindingBase final int stackLinesToOmit = reportExpectCall(stack, expectLine); FlutterError.reportError(new FlutterErrorDetails( exception: exception, - stack: stack, + stack: _unmangle(stack), context: 'running a test', library: 'Flutter test framework', stackFilter: (Iterable frames) { @@ -1021,3 +1022,11 @@ class _EmptyStack implements StackTrace { @override String toString() => ''; } + +StackTrace _unmangle(StackTrace stack) { + if (stack is stack_trace.Trace) + return stack.vmTrace; + if (stack is stack_trace.Chain) + return stack.toTrace().vmTrace; + return stack; +} diff --git a/packages/flutter_test/pubspec.yaml b/packages/flutter_test/pubspec.yaml index ed8f72f04b..4e9bcd46e9 100644 --- a/packages/flutter_test/pubspec.yaml +++ b/packages/flutter_test/pubspec.yaml @@ -9,3 +9,8 @@ dependencies: flutter: sdk: flutter + + # We import stack_trace because the test packages uses it and we + # need to be able to unmangle the stack traces that it passed to + # stack_trace. See https://github.com/dart-lang/test/issues/590 + stack_trace: any # use version expected by test package diff --git a/packages/flutter_tools/test/test_test.dart b/packages/flutter_tools/test/test_test.dart index c3e52e6eab..e6e6622306 100644 --- a/packages/flutter_tools/test/test_test.dart +++ b/packages/flutter_tools/test/test_test.dart @@ -23,6 +23,11 @@ void main() { final String automatedTestsDirectory = fs.path.join('..', '..', 'dev', 'automated_tests'); final String flutterTestDirectory = fs.path.join(automatedTestsDirectory, 'flutter_test'); + testUsingContext('Exception handling in test harness', () async { + Cache.flutterRoot = '../..'; + return _testFile('exception_handling', automatedTestsDirectory, flutterTestDirectory); + }); + testUsingContext('TestAsyncUtils guarded function test', () async { Cache.flutterRoot = '../..'; return _testFile('test_async_utils_guarded', automatedTestsDirectory, flutterTestDirectory);