sdk
sdk copied to clipboard
Test failed after update flutter on 3.3.1 (dart 2.18.0)
Original issue
import 'dart:async';
import 'package:flutter_test/flutter_test.dart';
void main() {
test('test case', () async {
await expectLater(
// create stream that emit Completer, and wait it
((() async* {
try {
final completer = Completer<void>();
yield completer;
await completer.future;
} catch (_) {
// handle error
}
})())
.map((event) {
// add error to completer
event.completeError(Exception());
return event;
}),
emitsThrough(anything),
);
});
}
with 3.0.5 results:
flutter doctor -v
[✓] Flutter (Channel stable, 3.0.5, on macOS 12.2.1 21D62 darwin-x64, locale ru-RU)
• Flutter version 3.0.5 at /Users/boriskarabanov/dev/sdk/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision f1875d570e (8 weeks ago), 2022-07-13 11:24:16 -0700
• Engine revision e85ea0e79c
• Dart version 2.17.6
• DevTools version 2.12.2
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0-rc1)
• Android SDK at /Users/boriskarabanov/Library/Android/sdk
• Platform android-33, build-tools 33.0.0-rc1
• ANDROID_HOME = /Users/boriskarabanov/Library/Android/sdk
• ANDROID_SDK_ROOT = /Users/boriskarabanov/Library/Android/sdk
• Java binary at: /Users/boriskarabanov/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/212.5712.43.2112.8815526/Android Studio.app/Contents/jre/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• CocoaPods version 1.11.3
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2021.2)
• Android Studio at /Users/boriskarabanov/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/212.5712.43.2112.8815526/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
[✓] Android Studio (version 2021.2)
• Android Studio at /Users/boriskarabanov/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/212.5712.43.2112.8609683/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
[✓] IntelliJ IDEA Ultimate Edition (version 2022.2.1)
• IntelliJ at /Users/boriskarabanov/Applications/JetBrains Toolbox/IntelliJ IDEA Ultimate.app
• Flutter plugin version 69.0.5
• Dart plugin version 222.3739.24
[✓] IntelliJ IDEA Ultimate Edition (version 2022.2.1)
• IntelliJ at /Users/boriskarabanov/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/222.3739.54/IntelliJ IDEA.app
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
[✓] IntelliJ IDEA Ultimate Edition (version 2022.2)
• IntelliJ at /Users/boriskarabanov/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/222.3345.118/IntelliJ IDEA.app
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
[✓] VS Code (version 1.69.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.46.0
[✓] Connected device (2 available)
• macOS (desktop) • macos • darwin-x64 • macOS 12.2.1 21D62 darwin-x64
• Chrome (web) • chrome • web-javascript • Google Chrome 105.0.5195.102
! Error: DNS s4502 has recently restarted. Xcode will continue when DNS s4502 is unlocked. (code -14)
[✓] HTTP Host Availability
• All required HTTP hosts are available
• No issues found!
00:08 +1: All tests passed!
with 3.3.1 results:
flutter doctor -v
[✓] Flutter (Channel stable, 3.3.1, on macOS 12.2.1 21D62 darwin-x64, locale ru-RU)
• Flutter version 3.3.1 on channel stable at /Users/boriskarabanov/dev/sdk/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 4f9d92fbbd (34 hours ago), 2022-09-06 17:54:53 -0700
• Engine revision 3efdf03e73
• Dart version 2.18.0
• DevTools version 2.15.0
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0-rc1)
• Android SDK at /Users/boriskarabanov/Library/Android/sdk
• Platform android-33, build-tools 33.0.0-rc1
• ANDROID_HOME = /Users/boriskarabanov/Library/Android/sdk
• ANDROID_SDK_ROOT = /Users/boriskarabanov/Library/Android/sdk
• Java binary at: /Users/boriskarabanov/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/212.5712.43.2112.8815526/Android Studio.app/Contents/jre/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 13F100
• CocoaPods version 1.11.3
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2021.2)
• Android Studio at /Users/boriskarabanov/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/212.5712.43.2112.8815526/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
[✓] Android Studio (version 2021.2)
• Android Studio at /Users/boriskarabanov/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/212.5712.43.2112.8609683/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
[✓] IntelliJ IDEA Ultimate Edition (version 2022.2.1)
• IntelliJ at /Users/boriskarabanov/Applications/JetBrains Toolbox/IntelliJ IDEA Ultimate.app
• Flutter plugin version 69.0.5
• Dart plugin version 222.3739.24
[✓] IntelliJ IDEA Ultimate Edition (version 2022.2.1)
• IntelliJ at /Users/boriskarabanov/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/222.3739.54/IntelliJ IDEA.app
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
[✓] IntelliJ IDEA Ultimate Edition (version 2022.2)
• IntelliJ at /Users/boriskarabanov/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/222.3345.118/IntelliJ IDEA.app
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
[✓] VS Code (version 1.69.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.46.0
[✓] Connected device (2 available)
• macOS (desktop) • macos • darwin-x64 • macOS 12.2.1 21D62 darwin-x64
• Chrome (web) • chrome • web-javascript • Google Chrome 105.0.5195.102
! Error: DNS s4502 has recently restarted. Xcode will continue when DNS s4502 is unlocked. (code -14)
[✓] HTTP Host Availability
• All required HTTP hosts are available
• No issues found!
00:09 +0 -1: test case [E]
Exception
dart:async _Completer.completeError
test/tst.dart 20:15 main.<fn>.<fn>
dart:async _AsyncStarStreamController.add
test/tst.dart main.<fn>.<fn>
===== asynchronous gap ===========================
dart:async _ForwardingStream.listen
package:async/src/stream_queue.dart 475:31 StreamQueue._ensureListening
package:async/src/stream_queue.dart 531:7 StreamQueue._addRequest
package:async/src/stream_queue.dart 291:5 StreamQueue.startTransaction
package:test_api expectLater
package:flutter_test/src/widget_tester.dart 497:23 expectLater
test/tst.dart 7:11
same on pure dart
import 'dart:async';
void main(List<String> arguments) {
// create stream that emit Completer, and wait it
((() async* {
try {
final completer = Completer<void>();
yield completer;
await completer.future;
} catch (_) {
// handle error
}
})())
.map((event) {
// add error to completer
event.completeError(Exception());
return event;
}).listen((_) => print('done'));
}
on Dart version 2.17.6
done
on Dart version 2.18.0
done
Unhandled exception:
Exception
/cc @alexmarkov likely result of async changes
Bisected this change in behavior to https://github.com/dart-lang/sdk/commit/efdffab8b77f5ca21ee08e2b7bb8b05a312a1317. /cc @mkustermann @lrhn
Before that change, execution of async* closure continued up to await completer.future and the exception from event.completeError(Exception()) was thrown and caught in catch (_), so it was not printed as an unhandled exception.
After that change, async* generator no longer runs past yield completer, so completer.future is not awaited and the error is printed as an unhandled exception, similarly to the following code:
import 'dart:async';
void main(List<String> args) {
final completer = Completer<void>();
completer.completeError(Exception());
}
The new behavior looks correct to me - async* generator should not continue running until the generated event is delivered.
@alexmarkov so, how should i handle this error now?
Something like this looks strange.
import 'dart:async';
void main(List<String> arguments) {
// create stream that emit Completer, and wait it
((() async* {
try {
final completer = Completer<void>();
yield completer;
await completer.future;
} catch (e) {
// handle error
print(e);
}
})())
.map((event) {
// add error to completer
event.completeError(Exception());
// looks strange
event.future.onError((error, stackTrace) => null);
return event;
}).listen((_) => print('done'));
}
So, now I can see different behavior on the web and on android/ios. When i run this code on android i get an unhandled exception. When I ran it on the web I didn't get an exception.
Is it ok? I prefer see same behavior on each platforms.))
The error doesn't necessarily have ti be uncaught, because it's valid behavior for the async* method to continue running immediately after synchronously delivering the event. In that case, the await on the future should happen before the future completes.
It's also valid behavior to pause the async* method and continue in a later microtask. In that case, the future might complete with its exception before the await, and that seems to be what happens here.
Either is valid, we do not promise how unrelated asynchronous events are interleaved, and you should be coding defensively when ordering matters.
The solution I'd use is to make the future not to cause unhandled errors if it completes with an error. I'd do that by adding:
completer.future.ignore();
before the yield.
(That's effectively what event.future.onError((_, __) => null) does too, just more verbosely and less efficiently. I'd put it in the async* function instead, because that's the place where the delayed await happens, so it is in a position to know that it might not start listening in time.)
Closing issue as 'works as intended' based on https://github.com/dart-lang/sdk/issues/49932#issuecomment-1242211731