dart-sdk/tests/lib/isolate/isolate_run_test.dart
Lasse R.H. Nielsen a5f25ee3ba Add Isolate.run.
Adds static method on `Isolate` to run an asynchronous function
in a separate isolate.

Change-Id: I673373fa02524f1d0b88099027cfaf1b796eb344
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/254960
Commit-Queue: Lasse Nielsen <lrn@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2022-08-18 10:42:55 +00:00

125 lines
3.7 KiB
Dart

// 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.
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.
}