| // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| // @dart = 2.9 |
| |
| import 'dart:isolate'; |
| import 'dart:async'; |
| import 'package:async_helper/async_helper.dart'; |
| import 'package:expect/expect.dart'; |
| |
| void main() async { |
| asyncStart(); |
| // Sending result back. |
| await testValue(); |
| await testAsyncValue(); |
| // Sending error from computation back. |
| await testError(); |
| await testAsyncError(); |
| // Sending uncaught async error back. |
| await testUncaughtError(); |
| // Not sending anything back before isolate dies. |
| await testIsolateHangs(); |
| await testIsolateKilled(); |
| await testIsolateExits(); |
| // Failing to start. |
| await testInvalidMessage(); |
| asyncEnd(); |
| } |
| |
| final StackTrace stack = StackTrace.fromString("Known Stacktrace"); |
| final ArgumentError error = ArgumentError.value(42, "name"); |
| |
| var variable = 0; |
| |
| Future<void> testValue() async { |
| var value = await Isolate.run<int>(() { |
| variable = 1; // Changed in other isolate! |
| Expect.equals(1, variable); |
| return 42; |
| }); |
| Expect.equals(42, value); |
| Expect.equals(0, variable); |
| } |
| |
| Future<void> testAsyncValue() async { |
| var value = await Isolate.run<int>(() async { |
| variable = 1; |
| return 42; |
| }); |
| Expect.equals(42, value); |
| Expect.equals(0, variable); |
| } |
| |
| Future<void> testError() async { |
| var e = await asyncExpectThrows<ArgumentError>(Isolate.run<int>(() { |
| variable = 1; |
| Error.throwWithStackTrace(error, stack); |
| })); |
| Expect.equals(42, e.invalidValue); |
| Expect.equals("name", e.name); |
| Expect.equals(0, variable); |
| } |
| |
| Future<void> testAsyncError() async { |
| var e = await asyncExpectThrows<ArgumentError>(Isolate.run<int>(() async { |
| variable = 1; |
| Error.throwWithStackTrace(error, stack); |
| })); |
| Expect.equals(42, e.invalidValue); |
| Expect.equals("name", e.name); |
| Expect.equals(0, variable); |
| } |
| |
| Future<void> testUncaughtError() async { |
| var e = await asyncExpectThrows<RemoteError>(Isolate.run<int>(() async { |
| variable = 1; |
| unawaited(Future.error(error, stack)); // Uncaught error |
| await Completer().future; // Never completes. |
| return -1; |
| })); |
| |
| Expect.type<RemoteError>(e); |
| Expect.equals(error.toString(), e.toString()); |
| Expect.equals(0, variable); |
| } |
| |
| Future<void> testIsolateHangs() async { |
| var e = await asyncExpectThrows<RemoteError>(Isolate.run<int>(() async { |
| variable = 1; |
| await Completer<Never>().future; // Never completes. |
| // Isolate should end while hanging here, because its event loop is empty. |
| })); |
| Expect.type<RemoteError>(e); |
| Expect.equals("Computation ended without result", e.toString()); |
| Expect.equals(0, variable); |
| } |
| |
| Future<void> testIsolateKilled() async { |
| var e = await asyncExpectThrows<RemoteError>(Isolate.run<int>(() async { |
| variable = 1; |
| Isolate.current.kill(); // Send kill request. |
| await Completer<Never>().future; // Never completes. |
| // Isolate should get killed while hanging here. |
| })); |
| Expect.type<RemoteError>(e); |
| Expect.equals("Computation ended without result", e.toString()); |
| Expect.equals(0, variable); |
| } |
| |
| Future<void> testIsolateExits() async { |
| var e = await asyncExpectThrows<RemoteError>(Isolate.run<int>(() async { |
| variable = 1; |
| Isolate.exit(); // Dies here without sending anything back. |
| })); |
| Expect.type<RemoteError>(e); |
| Expect.equals("Computation ended without result", e.toString()); |
| Expect.equals(0, variable); |
| } |
| |
| Future<void> testInvalidMessage() async { |
| // Regression test for http://dartbug.com/48516 |
| var unsendable = RawReceivePort(); |
| await asyncExpectThrows<Error>(Isolate.run<void>(() => unsendable)); |
| unsendable.close(); |
| // Test should not hang. |
| } |