New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exceptions are swallowed #10511
Comments
This is a problem with async programming and testing in general. However, if the other error happens first, and the program is aborted (all the expectAsync's have been hit, so the framework has no reason not to end it), the error will not be reported. The unittest framework actually forcibly ends the program after the first error, and your test has two errors. Change the 44 to 100, and you will see the other error. |
This sounds like a bug in dart:async. The outcome is obviously unacceptable, and cannot be excused away as a "general problem with async programming and testing". Removed Area-UnitTest label. |
An additional point: the unittest framework is not "forcibly" ending the program. This program runs on both dart2js and Dart VM and only the latter has an "exit" primitive. As far as i know, the unittest framework is doing anything, it is throwing an exception from async code and closing a port. See pkg/unittest/lib/src/config.dart, the onDone method. |
If you are going to use Futures in a unittest, you need to return a Future from the test. fisk() { should be: fisk() { Then running with the VM should show: ERROR: fisk |
Graham: people make mistakes and exceptions should not be swallowed. When you make a mistake, an error should occur. |
I agree in principle - if we had a global exception handler then unittest could deal with this. |
Added Library-Async label. |
If changing expectAsync1 to expectAsync, the test now runs and prints: unittest-suite-wait-for-done It seems the unittest package now correctly handles this case. Added AssumedStale label. |
Consider the program and output below. The program contains an additional error, it calls a missing method "x". I had expected to see an exception and stack trace for that. Instead, I only see a stack trace for the subsequent failure.
This (and misreading a comment in dart2js) cost me a few hours debugging the wrong thing. I'm pretty sure if I had seen the swallowed exception, I would have realized my mistake earlier.
I'm tentatively pointing fingers at the unittest package, but this could just as well be a bug in dart:async, so I'm CC'ing Florian.
import 'dart:async';
import 'package:unittest/unittest.dart';
fisk() {
new Future(() => x());
new Future(() => 100).then(expectAsync1((x) {
expect(x, equals(44));
}));
}
main() {
test('fisk', fisk);
}
Running this program on dart2js/d8 looks like this:
swallow.dart:6:20: Warning: cannot resolve x
new Future(() => x());
^
Dart file swallow.dart compiled to JavaScript: out.js
unittest-suite-wait-for-done
FAIL: fisk
Expected: <44>
but: was <100>.
Expected: <44>
but: was <100>.
at Configuration.$$.Configuration.onExpectFailure$1 (out.js:3614:15)
at _ExpectFailureHandler.$$._ExpectFailureHandler.fail$1 (out.js:3559:18)
at $.expect (out.js:6116:20)
at fisk_anon1.$$.fisk_anon1.call$1 (out.js:3543:7)
at _SpreadArgsHelper.$$._SpreadArgsHelper.callback$1 (out.js:4312:26)
at _SpreadArgsHelper_invoke1_anon.$$._SpreadArgsHelper_invoke1_anon.call$0 (out.js:4369:17)
at $._guardAsync (out.js:6257:18)
at _SpreadArgsHelper.$$._SpreadArgsHelper.invoke1$1 (out.js:4346:14)
at BoundClosure$1.$$.BoundClosure$1.call$1 (out.js:4436:34)
at _ThenFuture.$$._ThenFuture._onValue$1 (out.js:2181:26)
0 PASSED, 1 FAILED, 0 ERRORS
out.js:2376: Exception: Some tests failed.
throw exception;
^
Exception: Some tests failed.
at $.throwExpression (out.js:5237:11)
at $._completeTests (out.js:6329:9)
at $._nextBatch (out.js:6287:9)
at _nextTestCase_anon.$$._nextTestCase_anon.call$0 (out.js:4376:7)
at Function.$._asyncRunCallback as call$0
at Timer_run_anon.$$.Timer_run_anon.call$0 (out.js:2368:18)
at _IsolateContext.$$._IsolateContext.eval$1 (out.js:683:21)
at _IsolateEvent.$$._IsolateEvent.process$0 (out.js:798:18)
at _EventLoop.$$._EventLoop.runIteration$0 (out.js:759:12)
at _EventLoop.$$._EventLoop._runHelper$0 (out.js:766:19)
Running this program on standalone Dart VM looks like this:
unittest-suite-wait-for-done
FAIL: fisk
Expected: <44>
but: was <100>.
fisk.fisk.<anonymous closure> file:///Users/ahe/Dart/all/dart/swallow.dart 8:11
_SpreadArgsHelper.invoke1.invoke1.<anonymous closure> package:unittest/unittest.dart 496:28
_guardAsync package:unittest/unittest.dart 739:19
_SpreadArgsHelper.invoke1.invoke1 package:unittest/unittest.dart 493:23
_ThenFuture._sendValue dart:async 397:24
_FutureImpl._setValue dart:async 294:26
_FutureImpl._setOrChainValue dart:async 371:16
_ThenFuture._sendValue dart:async 403:21
Future.Future.<anonymous closure> dart:async 66:37
_asyncRunCallback._asyncRunCallback dart:async 34:17
Timer.run.<anonymous closure> dart:async 2251:21
Timer.Timer.<anonymous closure> dart:async-patch 15:15
0 PASSED, 1 FAILED, 0 ERRORS
Unhandled exception:
Exception: Some tests failed.
0 Configuration.onDone (package:unittest/src/config.dart:213:9)
1 _completeTests (package:unittest/unittest.dart:805:17)
2 _nextBatch (package:unittest/unittest.dart:775:21)
3 _nextTestCase.<anonymous closure> (package:unittest/unittest.dart:673:15)
4 _asyncRunCallback._asyncRunCallback (dart:async:34:17)
5 _asyncRunCallback._asyncRunCallback (dart:async:44:9)
6 Timer.run.<anonymous closure> (dart:async:2251:21)
7 Timer.run.<anonymous closure> (dart:async:2259:13)
8 Timer.Timer.<anonymous closure> (dart:async-patch:15:15)
9 _Timer._createTimerHandler._handleTimeout (dart:io:6794:28)
10 _Timer._createTimerHandler._handleTimeout (dart:io:6802:7)
11 _Timer._createTimerHandler.<anonymous closure> (dart:io:6810:23)
12 _ReceivePortImpl._handleMessage (dart:isolate-patch:81:92)
The text was updated successfully, but these errors were encountered: