blob: 431283724ecd159dc7456d61d6ac901961d6ef52 [file] [log] [blame]
// Copyright (c) 2020, 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:io';
import 'package:ffigen/src/code_generator.dart';
import 'package:test/test.dart';
void main() {
group('code_generator: ', () {
test('Function Binding (primitives, pointers)', () {
final library = Library(
bindings: [
Func(
name: 'noParam',
dartDoc: 'Just a test function\nheres another line',
returnType: Type.nativeType(
SupportedNativeType.Int32,
),
),
Func(
name: 'withPrimitiveParam',
parameters: [
Parameter(
name: 'a',
type: Type.nativeType(
SupportedNativeType.Int32,
),
),
Parameter(
name: 'b',
type: Type.nativeType(
SupportedNativeType.Uint8,
),
),
],
returnType: Type.nativeType(
SupportedNativeType.Char,
),
),
Func(
name: 'withPointerParam',
parameters: [
Parameter(
name: 'a',
type: Type.pointer(
Type.nativeType(
SupportedNativeType.Int32,
),
),
),
Parameter(
name: 'b',
type: Type.pointer(
Type.pointer(
Type.nativeType(
SupportedNativeType.Uint8,
),
),
),
),
],
returnType: Type.pointer(
Type.nativeType(
SupportedNativeType.Double,
),
),
),
],
);
final gen = library.generate();
// Writing to file for debug purpose.
final file = File(
'test/debug_generated/Function-Binding-test-output.dart',
);
try {
expect(gen, '''/// AUTO GENERATED FILE, DO NOT EDIT.
///
/// Generated by `package:ffigen`.
import 'dart:ffi' as ffi;
/// Holds the Dynamic library.
ffi.DynamicLibrary _dylib;
/// Initialises the Dynamic library.
void init(ffi.DynamicLibrary dylib){
_dylib = dylib;
}
/// Just a test function
/// heres another line
int noParam(
) {
return _noParam(
);
}
final _dart_noParam _noParam = _dylib.lookupFunction<_c_noParam,_dart_noParam>('noParam');
typedef _c_noParam = ffi.Int32 Function(
);
typedef _dart_noParam = int Function(
);
int withPrimitiveParam(
int a,
int b,
) {
return _withPrimitiveParam(
a,
b,
);
}
final _dart_withPrimitiveParam _withPrimitiveParam = _dylib.lookupFunction<_c_withPrimitiveParam,_dart_withPrimitiveParam>('withPrimitiveParam');
typedef _c_withPrimitiveParam = ffi.Uint8 Function(
ffi.Int32 a,
ffi.Uint8 b,
);
typedef _dart_withPrimitiveParam = int Function(
int a,
int b,
);
ffi.Pointer<ffi.Double> withPointerParam(
ffi.Pointer<ffi.Int32> a,
ffi.Pointer<ffi.Pointer<ffi.Uint8>> b,
) {
return _withPointerParam(
a,
b,
);
}
final _dart_withPointerParam _withPointerParam = _dylib.lookupFunction<_c_withPointerParam,_dart_withPointerParam>('withPointerParam');
typedef _c_withPointerParam = ffi.Pointer<ffi.Double> Function(
ffi.Pointer<ffi.Int32> a,
ffi.Pointer<ffi.Pointer<ffi.Uint8>> b,
);
typedef _dart_withPointerParam = ffi.Pointer<ffi.Double> Function(
ffi.Pointer<ffi.Int32> a,
ffi.Pointer<ffi.Pointer<ffi.Uint8>> b,
);
''');
if (file.existsSync()) {
file.delete();
}
} catch (e) {
file.writeAsStringSync(gen);
print('Failed test, Debug output: ${file.absolute?.path}');
rethrow;
}
});
test('Struct Binding (primitives, pointers)', () {
final library = Library(
bindings: [
Struc(
name: 'NoMember',
dartDoc: 'Just a test struct\nheres another line',
),
Struc(
name: 'WithPrimitiveMember',
members: [
Member(
name: 'a',
type: Type.nativeType(
SupportedNativeType.Int32,
),
),
Member(
name: 'b',
type: Type.nativeType(
SupportedNativeType.Double,
),
),
Member(
name: 'c',
type: Type.nativeType(
SupportedNativeType.Char,
),
),
],
),
Struc(
name: 'WithPointerMember',
members: [
Member(
name: 'a',
type: Type.pointer(
Type.nativeType(
SupportedNativeType.Int32,
),
),
),
Member(
name: 'b',
type: Type.pointer(
Type.pointer(
Type.nativeType(
SupportedNativeType.Double,
),
),
),
),
Member(
name: 'c',
type: Type.nativeType(
SupportedNativeType.Char,
),
),
],
),
],
);
final gen = library.generate();
// Writing to file for debug purpose.
final file = File('test/debug_generated/Struct-Binding-test-output.dart');
try {
expect(gen, '''/// AUTO GENERATED FILE, DO NOT EDIT.
///
/// Generated by `package:ffigen`.
import 'dart:ffi' as ffi;
/// Holds the Dynamic library.
ffi.DynamicLibrary _dylib;
/// Initialises the Dynamic library.
void init(ffi.DynamicLibrary dylib){
_dylib = dylib;
}
/// Just a test struct
/// heres another line
class NoMember extends ffi.Struct{
}
class WithPrimitiveMember extends ffi.Struct{
@ffi.Int32()
int a;
@ffi.Double()
double b;
@ffi.Uint8()
int c;
}
class WithPointerMember extends ffi.Struct{
ffi.Pointer<ffi.Int32> a;
ffi.Pointer<ffi.Pointer<ffi.Double>> b;
@ffi.Uint8()
int c;
}
''');
if (file.existsSync()) {
file.delete();
}
} catch (e) {
file.writeAsStringSync(gen);
print('Failed test, Debug output: ${file.absolute?.path}');
rethrow;
}
});
test('Function and Struct Binding (pointer to Struct)', () {
final library = Library(
bindings: [
Struc(
name: 'SomeStruc',
members: [
Member(
name: 'a',
type: Type.nativeType(
SupportedNativeType.Int32,
),
),
Member(
name: 'b',
type: Type.nativeType(
SupportedNativeType.Double,
),
),
Member(
name: 'c',
type: Type.nativeType(
SupportedNativeType.Char,
),
),
],
),
Func(
name: 'someFunc',
parameters: [
Parameter(
name: 'some',
type: Type.pointer(
Type.pointer(
Type.struct(
'SomeStruc',
),
),
),
),
],
returnType: Type.pointer(
Type.struct(
'SomeStruc',
),
),
),
],
);
final gen = library.generate();
// Writing to file for debug purpose.
final file =
File('test/debug_generated/Func-n-Struct-Binding-test-output.dart');
try {
//expect
expect(gen, '''/// AUTO GENERATED FILE, DO NOT EDIT.
///
/// Generated by `package:ffigen`.
import 'dart:ffi' as ffi;
/// Holds the Dynamic library.
ffi.DynamicLibrary _dylib;
/// Initialises the Dynamic library.
void init(ffi.DynamicLibrary dylib){
_dylib = dylib;
}
class SomeStruc extends ffi.Struct{
@ffi.Int32()
int a;
@ffi.Double()
double b;
@ffi.Uint8()
int c;
}
ffi.Pointer<SomeStruc> someFunc(
ffi.Pointer<ffi.Pointer<SomeStruc>> some,
) {
return _someFunc(
some,
);
}
final _dart_someFunc _someFunc = _dylib.lookupFunction<_c_someFunc,_dart_someFunc>('someFunc');
typedef _c_someFunc = ffi.Pointer<SomeStruc> Function(
ffi.Pointer<ffi.Pointer<SomeStruc>> some,
);
typedef _dart_someFunc = ffi.Pointer<SomeStruc> Function(
ffi.Pointer<ffi.Pointer<SomeStruc>> some,
);
''');
if (file.existsSync()) {
file.delete();
}
} catch (e) {
file.writeAsStringSync(gen);
print('Failed test, Debug output: ${file.absolute?.path}');
rethrow;
}
});
test('global (primitives, pointers, pointer to struct)', () {
final library = Library(
bindings: [
Global(
name: 'test1',
type: Type.nativeType(
SupportedNativeType.Int32,
),
),
Global(
name: 'test2',
type: Type.pointer(
Type.nativeType(
SupportedNativeType.Float,
),
),
),
Struc(
name: 'Some',
),
Global(
name: 'test5',
type: Type.pointer(
Type.struct(
'Some',
),
),
),
],
);
final gen = library.generate();
// Writing to file for debug purpose.
final file = File(
'test/debug_generated/Global-Binding-test-output.dart',
);
try {
expect(gen, '''/// AUTO GENERATED FILE, DO NOT EDIT.
///
/// Generated by `package:ffigen`.
import 'dart:ffi' as ffi;
/// Holds the Dynamic library.
ffi.DynamicLibrary _dylib;
/// Initialises the Dynamic library.
void init(ffi.DynamicLibrary dylib){
_dylib = dylib;
}
final int test1 = _dylib.lookup<ffi.Int32>('test1').value;
final ffi.Pointer<ffi.Float> test2 = _dylib.lookup<ffi.Pointer<ffi.Float>>('test2').value;
class Some extends ffi.Struct{
}
final ffi.Pointer<Some> test5 = _dylib.lookup<ffi.Pointer<Some>>('test5').value;
''');
if (file.existsSync()) {
file.delete();
}
} catch (e) {
file.writeAsStringSync(gen);
print('Failed test, Debug output: ${file.absolute?.path}');
rethrow;
}
});
test('constant', () {
final library = Library(
bindings: [
Constant(
name: 'test1',
type: Type.nativeType(
SupportedNativeType.Int32,
),
rawValue: '20',
),
Constant(
name: 'test2',
type: Type.nativeType(
SupportedNativeType.Float,
),
rawValue: '20.0',
),
],
);
final gen = library.generate();
// Writing to file for debug purpose.
final file = File(
'test/debug_generated/Constant-test-output.dart',
);
try {
expect(gen, '''/// AUTO GENERATED FILE, DO NOT EDIT.
///
/// Generated by `package:ffigen`.
import 'dart:ffi' as ffi;
/// Holds the Dynamic library.
ffi.DynamicLibrary _dylib;
/// Initialises the Dynamic library.
void init(ffi.DynamicLibrary dylib){
_dylib = dylib;
}
const int test1 = 20;
const double test2 = 20.0;
''');
if (file.existsSync()) {
file.delete();
}
} catch (e) {
file.writeAsStringSync(gen);
print('Failed test, Debug output: ${file.absolute?.path}');
rethrow;
}
});
test('TypedefC (primitive, pointers, pointer to struct)', () {
final library = Library(
bindings: [
TypedefC(
dartDoc: 'just a test',
name: 'test1',
returnType: Type.nativeType(
SupportedNativeType.Int32,
),
),
Struc(name: 'SomeStruct'),
TypedefC(
name: 'test2',
returnType: Type.pointer(
Type.nativeType(
SupportedNativeType.Int32,
),
),
parameters: [
Parameter(
name: 'param1',
type: Type.pointer(
Type.struct('SomeStruct'),
),
),
Parameter(
name: 'param2',
type: Type.nativeType(
SupportedNativeType.Char,
),
),
],
),
],
);
final gen = library.generate();
// Writing to file for debug purpose.
final file =
File('test/debug_generated/typedef-Binding-test-output.dart');
try {
expect(gen, '''/// AUTO GENERATED FILE, DO NOT EDIT.
///
/// Generated by `package:ffigen`.
import 'dart:ffi' as ffi;
/// Holds the Dynamic library.
ffi.DynamicLibrary _dylib;
/// Initialises the Dynamic library.
void init(ffi.DynamicLibrary dylib){
_dylib = dylib;
}
/// just a test
typedef test1 = ffi.Int32 Function(
);
class SomeStruct extends ffi.Struct{
}
typedef test2 = ffi.Pointer<ffi.Int32> Function(
ffi.Pointer<SomeStruct> param1,
ffi.Uint8 param2,
);
''');
if (file.existsSync()) {
file.delete();
}
} catch (e) {
file.writeAsStringSync(gen);
print('Failed test, Debug output: ${file.absolute?.path}');
rethrow;
}
});
test('enum_class', () {
final library = Library(
bindings: [
EnumClass(
name: 'Constants',
dartDoc: 'test line 1\ntest line 2',
enumConstants: [
EnumConstant(
name: 'a',
value: 10,
),
EnumConstant(name: 'b', value: -1, dartDoc: 'negative'),
],
),
],
);
final gen = library.generate();
// Writing to file for debug purpose.
final file = File(
'test/debug_generated/enum-class-test-output.dart',
);
try {
expect(gen, '''/// AUTO GENERATED FILE, DO NOT EDIT.
///
/// Generated by `package:ffigen`.
import 'dart:ffi' as ffi;
/// Holds the Dynamic library.
ffi.DynamicLibrary _dylib;
/// Initialises the Dynamic library.
void init(ffi.DynamicLibrary dylib){
_dylib = dylib;
}
/// test line 1
/// test line 2
class Constants {
static const int a = 10;
/// negative
static const int b = -1;
}
''');
if (file.existsSync()) {
file.delete();
}
} catch (e) {
file.writeAsStringSync(gen);
print('Failed test, Debug output: ${file.absolute?.path}');
rethrow;
}
});
});
}