38e250b4d5
Includes all the files which required no manual treatment. Change-Id: I3d493bcbc238a2016579a0f804d32f4829efb87b Cq-Include-Trybots: dart/try:vm-aot-android-release-arm_x64-try,vm-aot-linux-debug-x64-try,vm-aot-linux-debug-x64c-try,vm-aot-mac-release-arm64-try,vm-aot-mac-release-x64-try,vm-aot-win-debug-x64c-try,vm-checked-mac-release-arm64-try,vm-ffi-qemu-linux-release-arm-try,vm-ffi-qemu-linux-release-riscv64-try,vm-linux-debug-ia32-try,vm-linux-debug-x64-try,vm-linux-debug-x64c-try,vm-mac-debug-arm64-try,vm-reload-linux-debug-x64-try,vm-reload-rollback-linux-debug-x64-try,vm-win-release-ia32-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/399102 Reviewed-by: Bob Nystrom <rnystrom@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
236 lines
6.1 KiB
Dart
236 lines
6.1 KiB
Dart
// Copyright (c) 2023, 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 test program for testing dart:ffi async callbacks.
|
|
//
|
|
// VMOptions=
|
|
// VMOptions=--stacktrace-every=100
|
|
// VMOptions=--use-slow-path
|
|
// VMOptions=--use-slow-path --stacktrace-every=100
|
|
// VMOptions=--dwarf_stack_traces --no-retain_function_objects --no-retain_code_objects
|
|
// VMOptions=--test_il_serialization
|
|
// VMOptions=--profiler --profile_vm=true
|
|
// VMOptions=--profiler --profile_vm=false
|
|
// SharedObjects=ffi_test_functions
|
|
|
|
import 'dart:async';
|
|
import 'dart:ffi';
|
|
import 'dart:isolate';
|
|
|
|
import "package:expect/expect.dart";
|
|
|
|
import 'dylib_utils.dart';
|
|
|
|
main(args, message) async {
|
|
testNativeCallableStatic();
|
|
testNativeCallableClosure();
|
|
testNativeCallableDoubleCloseError();
|
|
testNativeCallableNestedCloseCallStatic();
|
|
testNativeCallableNestedCloseCallClosure();
|
|
testNativeCallableExceptionalReturnStatic();
|
|
testNativeCallableExceptionalReturnClosure();
|
|
await testNativeCallableDontKeepAliveStatic();
|
|
await testNativeCallableDontKeepAliveClosure();
|
|
testNativeCallableKeepAliveGetter();
|
|
print("All tests completed :)");
|
|
}
|
|
|
|
final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
|
|
|
|
typedef TwoIntFnNativeType = Int32 Function(Pointer, Int32, Int32);
|
|
typedef TwoIntFnType = int Function(Pointer, int, int);
|
|
final callTwoIntFunction = ffiTestFunctions
|
|
.lookupFunction<TwoIntFnNativeType, TwoIntFnType>("CallTwoIntFunction");
|
|
|
|
typedef CallbackNativeType = Int32 Function(Int32, Int32);
|
|
int add(int a, int b) {
|
|
return a + b;
|
|
}
|
|
|
|
testNativeCallableStatic() {
|
|
final callback = NativeCallable<CallbackNativeType>.isolateLocal(
|
|
add,
|
|
exceptionalReturn: 0,
|
|
);
|
|
|
|
Expect.equals(1234, callTwoIntFunction(callback.nativeFunction, 1000, 234));
|
|
|
|
callback.close();
|
|
}
|
|
|
|
testNativeCallableClosure() {
|
|
int c = 70000;
|
|
|
|
final callback = NativeCallable<CallbackNativeType>.isolateLocal(
|
|
(int a, int b) => a + b + c,
|
|
exceptionalReturn: 0,
|
|
);
|
|
|
|
Expect.equals(71234, callTwoIntFunction(callback.nativeFunction, 1000, 234));
|
|
|
|
c = 80000;
|
|
Expect.equals(81234, callTwoIntFunction(callback.nativeFunction, 1000, 234));
|
|
|
|
callback.close();
|
|
}
|
|
|
|
testNativeCallableDoubleCloseError() {
|
|
final callback = NativeCallable<CallbackNativeType>.isolateLocal(
|
|
add,
|
|
exceptionalReturn: 0,
|
|
);
|
|
Expect.notEquals(nullptr, callback.nativeFunction);
|
|
callback.close();
|
|
|
|
Expect.throwsStateError(() {
|
|
final _ = callback.nativeFunction;
|
|
});
|
|
|
|
// Expect that these do not throw.
|
|
callback.close();
|
|
callback.keepIsolateAlive = true;
|
|
Expect.isFalse(callback.keepIsolateAlive);
|
|
}
|
|
|
|
late NativeCallable selfClosingStaticCallback;
|
|
int selfClosingStatic(int a, int b) {
|
|
selfClosingStaticCallback.close();
|
|
return a + b;
|
|
}
|
|
|
|
testNativeCallableNestedCloseCallStatic() {
|
|
selfClosingStaticCallback = NativeCallable<CallbackNativeType>.isolateLocal(
|
|
selfClosingStatic,
|
|
exceptionalReturn: 0,
|
|
);
|
|
|
|
Expect.equals(
|
|
1234,
|
|
callTwoIntFunction(selfClosingStaticCallback.nativeFunction, 1000, 234),
|
|
);
|
|
|
|
// The callback is already closed.
|
|
Expect.throwsStateError(() {
|
|
final _ = selfClosingStaticCallback.nativeFunction;
|
|
});
|
|
}
|
|
|
|
testNativeCallableNestedCloseCallClosure() {
|
|
late NativeCallable callback;
|
|
|
|
callback = NativeCallable<CallbackNativeType>.isolateLocal((int a, int b) {
|
|
callback.close();
|
|
return a + b;
|
|
}, exceptionalReturn: 0);
|
|
|
|
Expect.equals(1234, callTwoIntFunction(callback.nativeFunction, 1000, 234));
|
|
|
|
// The callback is already closed.
|
|
Expect.throwsStateError(() {
|
|
final _ = callback.nativeFunction;
|
|
});
|
|
}
|
|
|
|
int throwerCallback(int a, int b) {
|
|
if (a != 1000) {
|
|
throw "Oh no!";
|
|
}
|
|
return a + b;
|
|
}
|
|
|
|
testNativeCallableExceptionalReturnStatic() {
|
|
final callback = NativeCallable<CallbackNativeType>.isolateLocal(
|
|
throwerCallback,
|
|
exceptionalReturn: 5678,
|
|
);
|
|
|
|
Expect.equals(1234, callTwoIntFunction(callback.nativeFunction, 1000, 234));
|
|
Expect.equals(5678, callTwoIntFunction(callback.nativeFunction, 0, 0));
|
|
|
|
callback.close();
|
|
}
|
|
|
|
testNativeCallableExceptionalReturnClosure() {
|
|
final callback = NativeCallable<CallbackNativeType>.isolateLocal((
|
|
int a,
|
|
int b,
|
|
) {
|
|
if (a != 1000) {
|
|
throw "Oh no!";
|
|
}
|
|
return a + b;
|
|
}, exceptionalReturn: 5678);
|
|
|
|
Expect.equals(1234, callTwoIntFunction(callback.nativeFunction, 1000, 234));
|
|
Expect.equals(5678, callTwoIntFunction(callback.nativeFunction, 0, 0));
|
|
|
|
callback.close();
|
|
}
|
|
|
|
Future<void> testNativeCallableDontKeepAliveStatic() async {
|
|
final exitPort = ReceivePort();
|
|
await Isolate.spawn(
|
|
(_) async {
|
|
final callback = NativeCallable<CallbackNativeType>.isolateLocal(
|
|
add,
|
|
exceptionalReturn: 0,
|
|
);
|
|
|
|
Expect.equals(
|
|
1234,
|
|
callTwoIntFunction(callback.nativeFunction, 1000, 234),
|
|
);
|
|
|
|
callback.keepIsolateAlive = false;
|
|
},
|
|
null,
|
|
onExit: exitPort.sendPort,
|
|
);
|
|
await exitPort.first;
|
|
exitPort.close();
|
|
}
|
|
|
|
Future<void> testNativeCallableDontKeepAliveClosure() async {
|
|
int c = 70000;
|
|
|
|
final exitPort = ReceivePort();
|
|
await Isolate.spawn(
|
|
(_) async {
|
|
final callback = NativeCallable<CallbackNativeType>.isolateLocal(
|
|
(int a, int b) => a + b + c,
|
|
exceptionalReturn: 0,
|
|
);
|
|
|
|
Expect.equals(
|
|
71234,
|
|
callTwoIntFunction(callback.nativeFunction, 1000, 234),
|
|
);
|
|
|
|
callback.keepIsolateAlive = false;
|
|
},
|
|
null,
|
|
onExit: exitPort.sendPort,
|
|
);
|
|
await exitPort.first;
|
|
exitPort.close();
|
|
}
|
|
|
|
testNativeCallableKeepAliveGetter() {
|
|
final callback = NativeCallable<CallbackNativeType>.isolateLocal(
|
|
add,
|
|
exceptionalReturn: 0,
|
|
);
|
|
// Check that only the flag changes are counted by decrementing and
|
|
// incrementing a lot, and by different amounts.
|
|
for (int i = 0; i < 100; ++i) {
|
|
callback.keepIsolateAlive = false;
|
|
Expect.isFalse(callback.keepIsolateAlive);
|
|
}
|
|
for (int i = 0; i < 200; ++i) {
|
|
callback.keepIsolateAlive = true;
|
|
Expect.isTrue(callback.keepIsolateAlive);
|
|
}
|
|
callback.close();
|
|
}
|