blob: 5d7f4c929ac38c1f3a5908a7a234cd695a68d95f [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.
import 'package:ffigen/src/code_generator.dart';
import 'package:test/test.dart';
import '../test_utils.dart';
void main() {
group('code_generator: ', () {
test('Function Binding (primitives, pointers)', () {
final library = Library(
name: 'Bindings',
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,
),
),
),
],
);
_matchLib(library, 'function');
});
test('Struct Binding (primitives, pointers)', () {
final library = Library(
name: 'Bindings',
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,
),
),
],
),
],
);
_matchLib(library, 'struct');
});
test('Function and Struct Binding (pointer to Struct)', () {
final structSome = 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,
),
),
],
);
final library = Library(
name: 'Bindings',
bindings: [
structSome,
Func(
name: 'someFunc',
parameters: [
Parameter(
name: 'some',
type: Type.pointer(
Type.pointer(
Type.struct(
structSome,
),
),
),
),
],
returnType: Type.pointer(
Type.struct(
structSome,
),
),
),
],
);
_matchLib(library, 'function_n_struct');
});
test('global (primitives, pointers, pointer to struct)', () {
final strucSome = Struc(
name: 'Some',
);
final emptyGlobalStruc = Struc(name: 'EmptyStruct');
final library = Library(
name: 'Bindings',
bindings: [
Global(
name: 'test1',
type: Type.nativeType(
SupportedNativeType.Int32,
),
),
Global(
name: 'test2',
type: Type.pointer(
Type.nativeType(
SupportedNativeType.Float,
),
),
),
strucSome,
Global(
name: 'test5',
type: Type.pointer(
Type.struct(
strucSome,
),
),
),
emptyGlobalStruc,
Global(name: 'globalStruct', type: Type.struct(emptyGlobalStruc)),
],
);
_matchLib(library, 'global');
});
test('constant', () {
final library = Library(
name: 'Bindings',
header: '// ignore_for_file: unused_import\n',
bindings: [
Constant(
name: 'test1',
rawType: 'int',
rawValue: '20',
),
Constant(
name: 'test2',
rawType: 'double',
rawValue: '20.0',
),
],
);
_matchLib(library, 'constant');
});
test('enum_class', () {
final library = Library(
name: 'Bindings',
header: '// ignore_for_file: unused_import\n',
bindings: [
EnumClass(
name: 'Constants',
dartDoc: 'test line 1\ntest line 2',
enumConstants: [
EnumConstant(
name: 'a',
value: 10,
),
EnumConstant(name: 'b', value: -1, dartDoc: 'negative'),
],
),
],
);
_matchLib(library, 'enumclass');
});
test('Internal conflict resolution', () {
final library = Library(
name: 'init_dylib',
header:
'// ignore_for_file: unused_element, camel_case_types, non_constant_identifier_names\n',
bindings: [
Func(
name: 'test',
returnType: Type.nativeType(SupportedNativeType.Void),
),
Func(
name: '_test',
returnType: Type.nativeType(SupportedNativeType.Void),
),
Func(
name: '_c_test',
returnType: Type.nativeType(SupportedNativeType.Void),
),
Func(
name: '_dart_test',
returnType: Type.nativeType(SupportedNativeType.Void),
),
Struc(
name: '_Test',
members: [
Member(
name: 'array',
type: Type.constantArray(
2,
Type.nativeType(
SupportedNativeType.Int8,
),
),
),
],
),
Struc(name: 'ArrayHelperPrefixCollisionTest'),
Func(
name: 'Test',
returnType: Type.nativeType(SupportedNativeType.Void),
),
EnumClass(name: '_c_Test'),
EnumClass(name: 'init_dylib'),
],
);
_matchLib(library, 'internal_conflict_resolution');
});
});
test('boolean_dartBool', () {
final library = Library(
name: 'Bindings',
dartBool: true,
bindings: [
Func(
name: 'test1',
returnType: Type.boolean(),
parameters: [
Parameter(name: 'a', type: Type.boolean()),
Parameter(name: 'b', type: Type.pointer(Type.boolean())),
],
),
Struc(
name: 'Test2',
members: [
Member(name: 'a', type: Type.boolean()),
],
),
],
);
_matchLib(library, 'boolean_dartbool');
});
test('boolean_no_dartBool', () {
final library = Library(
name: 'Bindings',
dartBool: false,
bindings: [
Func(
name: 'test1',
returnType: Type.boolean(),
parameters: [
Parameter(name: 'a', type: Type.boolean()),
Parameter(name: 'b', type: Type.pointer(Type.boolean())),
],
),
Struc(
name: 'Test2',
members: [
Member(name: 'a', type: Type.boolean()),
],
),
],
);
_matchLib(library, 'boolean_no_dartbool');
});
test('sort bindings', () {
final library = Library(
name: 'Bindings',
sort: true,
bindings: [
Func(name: 'b', returnType: Type.nativeType(SupportedNativeType.Void)),
Func(name: 'a', returnType: Type.nativeType(SupportedNativeType.Void)),
Struc(name: 'D'),
Struc(name: 'C'),
],
);
_matchLib(library, 'sort_bindings');
});
test('Pack Structs', () {
final library = Library(
name: 'Bindings',
bindings: [
Struc(name: 'NoPacking', pack: null, members: [
Member(name: 'a', type: Type.nativeType(SupportedNativeType.Char)),
]),
Struc(name: 'Pack1', pack: 1, members: [
Member(name: 'a', type: Type.nativeType(SupportedNativeType.Char)),
]),
Struc(name: 'Pack2', pack: 2, members: [
Member(name: 'a', type: Type.nativeType(SupportedNativeType.Char)),
]),
Struc(name: 'Pack2', pack: 4, members: [
Member(name: 'a', type: Type.nativeType(SupportedNativeType.Char)),
]),
Struc(name: 'Pack2', pack: 8, members: [
Member(name: 'a', type: Type.nativeType(SupportedNativeType.Char)),
]),
Struc(name: 'Pack16', pack: 16, members: [
Member(name: 'a', type: Type.nativeType(SupportedNativeType.Char)),
]),
],
);
_matchLib(library, 'packed_structs');
});
test('Union Bindings', () {
final struct1 = Struc(name: 'Struct1', members: [
Member(name: 'a', type: Type.nativeType(SupportedNativeType.Int8))
]);
final union1 = Union(name: 'Union1', members: [
Member(name: 'a', type: Type.nativeType(SupportedNativeType.Int8))
]);
final library = Library(
name: 'Bindings',
bindings: [
struct1,
union1,
Union(name: 'EmptyUnion'),
Union(name: 'Primitives', members: [
Member(name: 'a', type: Type.nativeType(SupportedNativeType.Int8)),
Member(name: 'b', type: Type.nativeType(SupportedNativeType.Int32)),
Member(name: 'c', type: Type.nativeType(SupportedNativeType.Float)),
Member(name: 'd', type: Type.nativeType(SupportedNativeType.Double)),
]),
Union(name: 'PrimitivesWithPointers', members: [
Member(name: 'a', type: Type.nativeType(SupportedNativeType.Int8)),
Member(name: 'b', type: Type.nativeType(SupportedNativeType.Float)),
Member(
name: 'c',
type: Type.pointer(Type.nativeType(SupportedNativeType.Double))),
Member(name: 'd', type: Type.pointer(Type.union(union1))),
Member(name: 'd', type: Type.pointer(Type.struct(struct1))),
]),
Union(name: 'WithArray', members: [
Member(
name: 'a',
type: Type.constantArray(
10, Type.nativeType(SupportedNativeType.Int8))),
Member(name: 'b', type: Type.constantArray(10, Type.union(union1))),
Member(name: 'b', type: Type.constantArray(10, Type.struct(struct1))),
Member(
name: 'c',
type: Type.constantArray(10, Type.pointer(Type.union(union1)))),
]),
],
);
_matchLib(library, 'unions');
});
test('Typealias Bindings', () {
final library = Library(
name: 'Bindings',
header: '// ignore_for_file: non_constant_identifier_names\n',
bindings: [
Typealias(
name: 'RawUnused', type: Type.compound(Struc(name: 'Struct1'))),
Struc(name: 'WithTypealiasStruc', members: [
Member(
name: 't',
type: Type.typealias(Typealias(
name: 'Struct2Typealias',
type: Type.struct(Struc(name: 'Struct2', members: [
Member(
name: 'a',
type: Type.nativeType(SupportedNativeType.Double))
])))))
]),
Func(
name: 'WithTypealiasStruc',
returnType: Type.pointer(Type.nativeFunc(
NativeFunc.fromFunctionType(FunctionType(
returnType: Type.nativeType(SupportedNativeType.Void),
parameters: [])))),
parameters: [
Parameter(
name: 't',
type: Type.typealias(Typealias(
name: 'Struct3Typealias',
type: Type.struct(Struc(name: 'Struct3')))))
]),
],
);
_matchLib(library, 'typealias');
});
}
/// Utility to match expected bindings to the generated bindings.
void _matchLib(Library lib, String testName) {
matchLibraryWithExpected(lib, [
'test',
'debug_generated',
'code_generator_test_${testName}_output.dart'
], [
'test',
'code_generator_tests',
'expected_bindings',
'_expected_${testName}_bindings.dart'
]);
}