dart-sdk/tests/ffi/ffi_native_test.dart
Clement Skau bf2691c2fe [VM] Moves FfiNative fields to function parent.
Previously the synthetic field that holds the FfiNative
function pointer was injected into the current library.
This change makes sure we instead add the field to the
relevant parent - Class or Library.

TEST=Added regression test for name collision.

Bug: https://github.com/dart-lang/sdk/issues/43889
Change-Id: Ifbf2d70de00e4748c179fe7d626c495675c2b338
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/208502
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Clement Skau <cskau@google.com>
2021-08-09 09:13:38 +00:00

78 lines
2.8 KiB
Dart

// 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.
//
// SharedObjects=ffi_test_functions
// NOTE: There is no `test/ffi_2/...` version of this test since annotations
// with type arguments isn't supported in that version of Dart.
import 'dart:ffi';
import 'package:expect/expect.dart';
import 'dylib_utils.dart';
final nativeLib = dlopenPlatformSpecific('ffi_test_functions');
final getRootLibraryUrl = nativeLib
.lookupFunction<Handle Function(), Object Function()>('GetRootLibraryUrl');
final setFfiNativeResolverForTest = nativeLib
.lookupFunction<Void Function(Handle), void Function(Object)>('SetFfiNativeResolverForTest');
@FfiNative<IntPtr Function(IntPtr)>('ReturnIntPtr')
external int returnIntPtr(int x);
@FfiNative<IntPtr Function(IntPtr)>('ReturnIntPtr', isLeaf: true)
external int returnIntPtrLeaf(int x);
@FfiNative<IntPtr Function()>('IsThreadInGenerated')
external int isThreadInGenerated();
@FfiNative<IntPtr Function()>('IsThreadInGenerated', isLeaf: true)
external int isThreadInGeneratedLeaf();
// Error: FFI leaf call must not have Handle return type.
@FfiNative<Handle Function()>("foo", isLeaf: true) //# 01: compile-time error
external Object foo(); //# 01: compile-time error
// Error: FFI leaf call must not have Handle argument types.
@FfiNative<Void Function(Handle)>("bar", isLeaf: true) //# 02: compile-time error
external void bar(Object); //# 02: compile-time error
class Classy {
@FfiNative<IntPtr Function(IntPtr)>('ReturnIntPtr')
external static int returnIntPtrStatic(int x);
// Error: FfiNative annotations can only be used on static functions.
@FfiNative<IntPtr Function(IntPtr)>('ReturnIntPtr') //# 03: compile-time error
external int returnIntPtrMethod(int x); //# 03: compile-time error
}
// Regression test: Ensure same-name FfiNative functions don't collide in the
// top-level namespace, but instead live under their parent (Library, Class).
class A {
@FfiNative<Void Function()>('nop')
external static void foo();
}
class B {
@FfiNative<Void Function()>('nop')
external static void foo();
}
void main() {
// Register test resolver for top-level functions above.
final root_lib_url = getRootLibraryUrl();
setFfiNativeResolverForTest(root_lib_url);
// Test we can call FfiNative functions.
Expect.equals(123, returnIntPtr(123));
Expect.equals(123, returnIntPtrLeaf(123));
Expect.equals(123, Classy.returnIntPtrStatic(123));
// Test FfiNative leaf calls remain in generated code.
// Regular calls should transition generated -> native.
Expect.equals(0, isThreadInGenerated());
// Leaf calls should remain in generated state.
Expect.equals(1, isThreadInGeneratedLeaf());
}