mirror of
https://github.com/dart-lang/sdk
synced 2024-11-05 18:22:09 +00:00
fc6cb0ac21
See dartbug.com/37229 for details. Change-Id: I63490e41c512ffc9312803985a6f6d4be1586c0a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/101291 Commit-Queue: Samir Jindel <sjindel@google.com> Reviewed-by: Daco Harkes <dacoharkes@google.com> Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
435 lines
12 KiB
Dart
435 lines
12 KiB
Dart
// Copyright (c) 2019, 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 extra checks
|
|
//
|
|
// SharedObjects=ffi_test_dynamic_library
|
|
|
|
library FfiTest;
|
|
|
|
import 'dart:ffi' as ffi;
|
|
import 'dart:ffi' show Pointer;
|
|
|
|
import 'dylib_utils.dart';
|
|
|
|
void main() {
|
|
testGetGeneric();
|
|
testGetGeneric2();
|
|
testGetVoid();
|
|
testGetNativeFunction();
|
|
testGetNativeType();
|
|
testGetTypeMismatch();
|
|
testSetGeneric();
|
|
testSetGeneric2();
|
|
testSetVoid();
|
|
testSetNativeFunction();
|
|
testSetNativeType();
|
|
testSetTypeMismatch();
|
|
testAsFunctionGeneric();
|
|
testAsFunctionGeneric2();
|
|
testAsFunctionWrongNativeFunctionSignature();
|
|
testAsFunctionTypeMismatch();
|
|
testFromFunctionGeneric();
|
|
testFromFunctionGeneric2();
|
|
testFromFunctionWrongNativeFunctionSignature();
|
|
testFromFunctionTypeMismatch();
|
|
testFromFunctionClosure();
|
|
testFromFunctionTearOff();
|
|
testLookupFunctionGeneric();
|
|
testLookupFunctionGeneric2();
|
|
testLookupFunctionWrongNativeFunctionSignature();
|
|
testLookupFunctionTypeMismatch();
|
|
testNativeFunctionSignatureInvalidReturn();
|
|
testNativeFunctionSignatureInvalidParam();
|
|
testNativeFunctionSignatureInvalidOptionalNamed();
|
|
testNativeFunctionSignatureInvalidOptionalPositional();
|
|
}
|
|
|
|
typedef Int8UnOp = ffi.Int8 Function(ffi.Int8);
|
|
typedef IntUnOp = int Function(int);
|
|
|
|
void testGetGeneric() {
|
|
int generic(ffi.Pointer p) {
|
|
int result;
|
|
result = p.load<int>(); //# 20: compile-time error
|
|
return result;
|
|
}
|
|
|
|
ffi.Pointer<ffi.Int8> p = Pointer.allocate();
|
|
p.store(123);
|
|
ffi.Pointer loseType = p;
|
|
generic(loseType);
|
|
p.free();
|
|
}
|
|
|
|
void testGetGeneric2() {
|
|
T generic<T extends Object>() {
|
|
Pointer<ffi.Int8> p = Pointer.allocate();
|
|
p.store(123);
|
|
T result;
|
|
result = p.load<T>(); //# 21: compile-time error
|
|
p.free();
|
|
return result;
|
|
}
|
|
|
|
generic<int>();
|
|
}
|
|
|
|
void testGetVoid() {
|
|
ffi.Pointer<ffi.IntPtr> p1 = Pointer.allocate();
|
|
ffi.Pointer<ffi.Void> p2 = p1.cast();
|
|
|
|
p2.load<int>(); //# 22: compile-time error
|
|
|
|
p1.free();
|
|
}
|
|
|
|
void testGetNativeFunction() {
|
|
Pointer<ffi.NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
|
|
IntUnOp f = p.load(); //# 23: compile-time error
|
|
}
|
|
|
|
void testGetNativeType() {
|
|
// Is it possible to obtain a ffi.Pointer<ffi.NativeType> at all?
|
|
}
|
|
|
|
void testGetTypeMismatch() {
|
|
ffi.Pointer<ffi.Pointer<ffi.Int16>> p = Pointer.allocate();
|
|
ffi.Pointer<ffi.Int16> typedNull = ffi.nullptr.cast();
|
|
p.store(typedNull);
|
|
|
|
// this fails to compile due to type mismatch
|
|
ffi.Pointer<ffi.Int8> p2 = p.load(); //# 25: compile-time error
|
|
|
|
p.free();
|
|
}
|
|
|
|
void testSetGeneric() {
|
|
void generic(ffi.Pointer p) {
|
|
p.store(123); //# 26: compile-time error
|
|
}
|
|
|
|
ffi.Pointer<ffi.Int8> p = Pointer.allocate();
|
|
p.store(123);
|
|
ffi.Pointer loseType = p;
|
|
generic(loseType);
|
|
p.free();
|
|
}
|
|
|
|
void testSetGeneric2() {
|
|
void generic<T extends Object>(T arg) {
|
|
ffi.Pointer<ffi.Int8> p = Pointer.allocate();
|
|
p.store(arg); //# 27: compile-time error
|
|
p.free();
|
|
}
|
|
|
|
generic<int>(123);
|
|
}
|
|
|
|
void testSetVoid() {
|
|
ffi.Pointer<ffi.IntPtr> p1 = Pointer.allocate();
|
|
ffi.Pointer<ffi.Void> p2 = p1.cast();
|
|
|
|
p2.store(1234); //# 28: compile-time error
|
|
|
|
p1.free();
|
|
}
|
|
|
|
void testSetNativeFunction() {
|
|
Pointer<ffi.NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
|
|
IntUnOp f = (a) => a + 1;
|
|
p.store(f); //# 29: compile-time error
|
|
}
|
|
|
|
void testSetNativeType() {
|
|
// Is it possible to obtain a ffi.Pointer<ffi.NativeType> at all?
|
|
}
|
|
|
|
void testSetTypeMismatch() {
|
|
// the pointer to pointer types must match up
|
|
ffi.Pointer<ffi.Int8> pHelper = Pointer.allocate();
|
|
pHelper.store(123);
|
|
|
|
ffi.Pointer<ffi.Pointer<ffi.Int16>> p = Pointer.allocate();
|
|
|
|
// this fails to compile due to type mismatch
|
|
p.store(pHelper); //# 40: compile-time error
|
|
|
|
pHelper.free();
|
|
p.free();
|
|
}
|
|
|
|
void testAsFunctionGeneric() {
|
|
T generic<T extends Function>() {
|
|
ffi.Pointer<ffi.NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
|
|
Function f;
|
|
f = p.asFunction<T>(); //# 11: compile-time error
|
|
return f;
|
|
}
|
|
|
|
generic<IntUnOp>();
|
|
}
|
|
|
|
void testAsFunctionGeneric2() {
|
|
generic(ffi.Pointer<ffi.NativeFunction> p) {
|
|
Function f;
|
|
f = p.asFunction<IntUnOp>(); //# 12: compile-time error
|
|
return f;
|
|
}
|
|
|
|
ffi.Pointer<ffi.NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
|
|
generic(p);
|
|
}
|
|
|
|
void testAsFunctionWrongNativeFunctionSignature() {
|
|
ffi.Pointer<ffi.NativeFunction<IntUnOp>> p;
|
|
Function f = p.asFunction<IntUnOp>(); //# 13: compile-time error
|
|
}
|
|
|
|
typedef IntBinOp = int Function(int, int);
|
|
|
|
void testAsFunctionTypeMismatch() {
|
|
ffi.Pointer<ffi.NativeFunction<Int8UnOp>> p = Pointer.fromAddress(1337);
|
|
IntBinOp f = p.asFunction(); //# 14: compile-time error
|
|
}
|
|
|
|
typedef NativeDoubleUnOp = ffi.Double Function(ffi.Double);
|
|
typedef DoubleUnOp = double Function(double);
|
|
|
|
double myTimesThree(double d) => d * 3;
|
|
|
|
int myTimesFour(int i) => i * 4;
|
|
|
|
void testFromFunctionGeneric() {
|
|
ffi.Pointer<ffi.NativeFunction> generic<T extends Function>(T f) {
|
|
ffi.Pointer<ffi.NativeFunction<NativeDoubleUnOp>> result;
|
|
result = ffi.fromFunction(f); //# 70: compile-time error
|
|
return result;
|
|
}
|
|
|
|
generic(myTimesThree);
|
|
}
|
|
|
|
void testFromFunctionGeneric2() {
|
|
ffi.Pointer<ffi.NativeFunction<T>> generic<T extends Function>() {
|
|
ffi.Pointer<ffi.NativeFunction<T>> result;
|
|
result = ffi.fromFunction(myTimesThree); //# 71: compile-time error
|
|
return result;
|
|
}
|
|
|
|
generic<NativeDoubleUnOp>();
|
|
}
|
|
|
|
void testFromFunctionWrongNativeFunctionSignature() {
|
|
ffi.fromFunction<IntUnOp>(myTimesFour); //# 72: compile-time error
|
|
}
|
|
|
|
void testFromFunctionTypeMismatch() {
|
|
ffi.Pointer<ffi.NativeFunction<NativeDoubleUnOp>> p;
|
|
p = ffi.fromFunction(myTimesFour); //# 73: compile-time error
|
|
}
|
|
|
|
void testFromFunctionClosure() {
|
|
DoubleUnOp someClosure = (double z) => z / 27.0;
|
|
ffi.Pointer<ffi.NativeFunction<NativeDoubleUnOp>> p;
|
|
p = ffi.fromFunction(someClosure); //# 74: compile-time error
|
|
}
|
|
|
|
class X {
|
|
double tearoff(double d) => d / 27.0;
|
|
}
|
|
|
|
DoubleUnOp fld = null;
|
|
|
|
void testFromFunctionTearOff() {
|
|
fld = X().tearoff;
|
|
ffi.Pointer<ffi.NativeFunction<NativeDoubleUnOp>> p;
|
|
p = ffi.fromFunction(fld); //# 75: compile-time error
|
|
}
|
|
|
|
void testLookupFunctionGeneric() {
|
|
Function generic<T extends Function>() {
|
|
ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
|
|
Function result;
|
|
result = l.lookupFunction<T, DoubleUnOp>("cos"); //# 15: compile-time error
|
|
return result;
|
|
}
|
|
|
|
generic<NativeDoubleUnOp>();
|
|
}
|
|
|
|
void testLookupFunctionGeneric2() {
|
|
Function generic<T extends Function>() {
|
|
ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
|
|
Function result;
|
|
result = //# 16: compile-time error
|
|
l.lookupFunction<NativeDoubleUnOp, T>("cos"); //# 16: compile-time error
|
|
return result;
|
|
}
|
|
|
|
generic<DoubleUnOp>();
|
|
}
|
|
|
|
void testLookupFunctionWrongNativeFunctionSignature() {
|
|
ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
|
|
l.lookupFunction<IntUnOp, IntUnOp>("cos"); //# 17: compile-time error
|
|
}
|
|
|
|
void testLookupFunctionTypeMismatch() {
|
|
ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
|
|
l.lookupFunction<NativeDoubleUnOp, IntUnOp>("cos"); //# 18: compile-time error
|
|
}
|
|
|
|
// TODO(dacoharkes): make the next 4 test compile errors
|
|
typedef Invalid1 = int Function(ffi.Int8);
|
|
typedef Invalid2 = ffi.Int8 Function(int);
|
|
typedef Invalid3 = ffi.Int8 Function({ffi.Int8 named});
|
|
typedef Invalid4 = ffi.Int8 Function([ffi.Int8 positional]);
|
|
|
|
void testNativeFunctionSignatureInvalidReturn() {
|
|
// ffi.Pointer<ffi.NativeFunction<Invalid1>> p = ffi.fromAddress(999);
|
|
}
|
|
|
|
void testNativeFunctionSignatureInvalidParam() {
|
|
// ffi.Pointer<ffi.NativeFunction<Invalid2>> p = ffi.fromAddress(999);
|
|
}
|
|
|
|
void testNativeFunctionSignatureInvalidOptionalNamed() {
|
|
// ffi.Pointer<ffi.NativeFunction<Invalid3>> p = ffi.fromAddress(999);
|
|
}
|
|
|
|
void testNativeFunctionSignatureInvalidOptionalPositional() {
|
|
// ffi.Pointer<ffi.NativeFunction<Invalid4>> p = ffi.fromAddress(999);
|
|
}
|
|
|
|
// error on missing field annotation
|
|
class TestStruct extends ffi.Struct<TestStruct> {
|
|
@ffi.Double()
|
|
double x;
|
|
|
|
double y; //# 50: compile-time error
|
|
}
|
|
|
|
// Cannot extend structs.
|
|
class TestStruct3 extends TestStruct {} //# 52: compile-time error
|
|
|
|
// error on double annotation
|
|
class TestStruct4 extends ffi.Struct<TestStruct4> {
|
|
@ffi.Double()
|
|
@ffi.Double() //# 53: compile-time error
|
|
double z;
|
|
}
|
|
|
|
// error on annotation not matching up
|
|
class TestStruct5 extends ffi.Struct<TestStruct5> {
|
|
@ffi.Int64() //# 54: compile-time error
|
|
double z; //# 54: compile-time error
|
|
}
|
|
|
|
// error on annotation not matching up
|
|
class TestStruct6 extends ffi.Struct<TestStruct6> {
|
|
@ffi.Void() //# 55: compile-time error
|
|
double z; //# 55: compile-time error
|
|
}
|
|
|
|
// error on annotation not matching up
|
|
class TestStruct7 extends ffi.Struct<TestStruct7> {
|
|
@ffi.NativeType() //# 56: compile-time error
|
|
double z; //# 56: compile-time error
|
|
}
|
|
|
|
// error on field initializer on field
|
|
class TestStruct8 extends ffi.Struct<TestStruct8> {
|
|
@ffi.Double() //# 57: compile-time error
|
|
double z = 10.0; //# 57: compile-time error
|
|
}
|
|
|
|
// error on field initializer in constructor
|
|
class TestStruct9 extends ffi.Struct<TestStruct9> {
|
|
@ffi.Double()
|
|
double z;
|
|
|
|
TestStruct9() : z = 0.0 {} //# 58: compile-time error
|
|
}
|
|
|
|
// A struct "C" must extend "Struct<C>", not "Struct<AnythingElse>".
|
|
class TestStruct10 extends ffi.Struct<ffi.Int8> {} //# 59: compile-time error
|
|
|
|
// Struct classes may not be generic.
|
|
class TestStruct11<T> extends ffi.Struct<TestStruct11<dynamic>> {} //# 60: compile-time error
|
|
|
|
// Structs may not appear inside structs (currently, there is no suitable
|
|
// annotation).
|
|
class TestStruct12 extends ffi.Struct<TestStruct12> {
|
|
@ffi.Pointer //# 61: compile-time error
|
|
TestStruct9 struct; //# 61: compile-time error
|
|
}
|
|
|
|
// Cannot extend native types.
|
|
|
|
class ENativeType extends ffi.NativeType {} //# 90: compile-time error
|
|
|
|
class EInt8 extends ffi.Int8 {} //# 91: compile-time error
|
|
|
|
class EInt16 extends ffi.Int16 {} //# 92: compile-time error
|
|
|
|
class EInt32 extends ffi.Int32 {} //# 93: compile-time error
|
|
|
|
class EInt64 extends ffi.Int64 {} //# 94: compile-time error
|
|
|
|
class EUint8 extends ffi.Uint8 {} //# 95: compile-time error
|
|
|
|
class EUint16 extends ffi.Uint16 {} //# 96: compile-time error
|
|
|
|
class EUint32 extends ffi.Uint32 {} //# 97: compile-time error
|
|
|
|
class EUint64 extends ffi.Uint64 {} //# 98: compile-time error
|
|
|
|
class EIntPtr extends ffi.IntPtr {} //# 99: compile-time error
|
|
|
|
class EFloat extends ffi.Float {} //# 910: compile-time error
|
|
|
|
class EDouble extends ffi.Double {} //# 911: compile-time error
|
|
|
|
class EVoid extends ffi.Void {} //# 912: compile-time error
|
|
|
|
class ENativeFunction extends ffi.NativeFunction {} //# 913: compile-time error
|
|
|
|
class EPointer extends ffi.Pointer {} //# 914: compile-time error
|
|
|
|
// Cannot implement native natives or Struct.
|
|
|
|
// Cannot extend native types.
|
|
|
|
class INativeType implements ffi.NativeType {} //# 80: compile-time error
|
|
|
|
class IInt8 implements ffi.Int8 {} //# 81: compile-time error
|
|
|
|
class IInt16 implements ffi.Int16 {} //# 82: compile-time error
|
|
|
|
class IInt32 implements ffi.Int32 {} //# 83: compile-time error
|
|
|
|
class IInt64 implements ffi.Int64 {} //# 84: compile-time error
|
|
|
|
class IUint8 implements ffi.Uint8 {} //# 85: compile-time error
|
|
|
|
class IUint16 implements ffi.Uint16 {} //# 86: compile-time error
|
|
|
|
class IUint32 implements ffi.Uint32 {} //# 87: compile-time error
|
|
|
|
class IUint64 implements ffi.Uint64 {} //# 88: compile-time error
|
|
|
|
class IIntPtr implements ffi.IntPtr {} //# 88: compile-time error
|
|
|
|
class IFloat implements ffi.Float {} //# 810: compile-time error
|
|
|
|
class IDouble implements ffi.Double {} //# 811: compile-time error
|
|
|
|
class IVoid implements ffi.Void {} //# 812: compile-time error
|
|
|
|
class INativeFunction implements ffi.NativeFunction {} //# 813: compile-time error
|
|
|
|
class IPointer implements ffi.Pointer {} //# 814: compile-time error
|
|
|
|
class IStruct implements ffi.Struct {} //# 815: compile-time error
|