blob: 7b8450e4661f3db1ba66a7a6c82812f9aaa33ed4 [file] [log] [blame]
// Copyright (c) 2021, 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.
// VMOptions=--no-enable-fast-object-copy
// VMOptions=--enable-fast-object-copy
// VMOptions=--no-enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation
// VMOptions=--enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation
// The tests in this file will only succeed when isolate groups are enabled
// (hence the VMOptions above).
import 'dart:async';
import 'dart:isolate';
import 'package:expect/expect.dart';
import 'fast_object_copy_test.dart' show ClassWithNativeFields;
class HashThrower {
static bool throwOnHashCode = true;
const HashThrower();
int get hashCode => throwOnHashCode ? throw 'failing' : 2;
bool operator ==(other) => identical(this, other);
}
Future testWithClosure<T>(
void Function(SendPort) entrypoint, T expectedResult) async {
final rp = ReceivePort();
try {
await Isolate.spawn(entrypoint, rp.sendPort);
Expect.equals(expectedResult, await rp.first);
} finally {
rp.close();
}
}
class ClosureEntrypointTester {
int instanceValue = 42;
void send42(SendPort sendPort) => sendPort.send(42);
Future run() async {
await noCapturedVariablesTest();
await capturedInt();
await capturedInstanceInt();
await captureThisViaMethodTearOff();
await captureInvalidObject();
await captureRehashThrower();
}
Future noCapturedVariablesTest() async {
print('noCapturedVariablesTest');
await testWithClosure((SendPort s) => s.send(42), 42);
}
Future capturedInt() async {
print('capturedInt');
int value = 42;
await testWithClosure((SendPort s) => s.send(value), 42);
}
Future capturedInstanceInt() async {
print('capturedInstanceValue');
await testWithClosure((SendPort s) => s.send(this.instanceValue), 42);
}
Future captureThisViaMethodTearOff() async {
print('captureThisViaMethodTearOff');
await testWithClosure(send42, 42);
}
Future captureInvalidObject() async {
print('captureInvalidObject');
final invalidObject = ClassWithNativeFields();
send42(SendPort sendPort) {
'$invalidObject'; // Use an object that cannot be copied.
sendPort.send(42);
}
throwsAsync<ArgumentError>(() => testWithClosure(send42, 42));
}
Future captureRehashThrower() async {
print('captureRehashThrower');
HashThrower.throwOnHashCode = false;
final hashThrower = {HashThrower()};
send42(SendPort sendPort) {
'$hashThrower'; // Use an object that cannot be deserialized.
sendPort.send(42);
}
throwsAsync<IsolateSpawnException>(() => testWithClosure(send42, 42));
}
Future throwsAsync<T>(Future Function() fun) async {
try {
await fun();
} catch (e) {
if (e is T) return;
rethrow;
}
throw 'Function failed to throw ArgumentError';
}
}
main() async {
await ClosureEntrypointTester().run();
}