blob: b598029bb35b18206fc9cef4e6bdba8be43d49c1 [file] [log] [blame]
// 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.
}