| // 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:ffi'; | |
| import 'dart:math'; | |
| import 'package:ffigen/src/header_parser.dart' show parse; | |
| import 'package:path/path.dart' as path; | |
| import 'package:test/test.dart'; | |
| import '../test_utils.dart'; | |
| import '_expected_native_test_bindings.dart'; | |
| import 'native_test_config.dart' as native_test_config; | |
| void main() { | |
| group('native_test', () { | |
| test('generate_bindings', () async { | |
| final config = native_test_config.getConfig( | |
| Uri.file(path.join(packagePathForTests, '')), | |
| ); | |
| final context = testContext(config); | |
| await matchLibraryWithExpected( | |
| context, | |
| parse(context), | |
| 'native_test_bindings.dart', | |
| ['test', 'native_test', '_expected_native_test_bindings.dart'], | |
| ); | |
| }); | |
| test('bool', () { | |
| expect(Function1Bool(true), false); | |
| expect(Function1Bool(false), true); | |
| }); | |
| test('uint8_t', () { | |
| expect(Function1Uint8(pow(2, 8).toInt()), 42); | |
| }); | |
| test('uint16_t', () { | |
| expect(Function1Uint16(pow(2, 16).toInt()), 42); | |
| }); | |
| test('uint32_t', () { | |
| expect(Function1Uint32(pow(2, 32).toInt()), 42); | |
| }); | |
| test('uint64_t', () { | |
| expect(Function1Uint64(pow(2, 64).toInt()), 42); | |
| }); | |
| test('int8_t', () { | |
| expect(Function1Int8(pow(2, 7).toInt()), -pow(2, 7).toInt() + 42); | |
| }); | |
| test('int16_t', () { | |
| expect(Function1Int16(pow(2, 15).toInt()), -pow(2, 15).toInt() + 42); | |
| }); | |
| test('int32_t', () { | |
| expect(Function1Int32(pow(2, 31).toInt()), -pow(2, 31).toInt() + 42); | |
| }); | |
| test('int64_t', () { | |
| expect(Function1Int64(pow(2, 63).toInt()), -pow(2, 63).toInt() + 42); | |
| }); | |
| test('intptr_t', () { | |
| expect(Function1IntPtr(0), 42); | |
| }); | |
| test('float', () { | |
| expect(Function1Float(0), 42.0); | |
| }); | |
| test('double', () { | |
| expect(Function1Double(0), 42.0); | |
| }); | |
| test('array global', () { | |
| globalArray[0] = 1; | |
| globalArray[1] = 2; | |
| expect(globalArray[0], 1); | |
| expect(globalArray[1], 2); | |
| globalArray[1] = 3; | |
| expect(globalArray[1], 3); | |
| }); | |
| test('Array Test: Order of access', () { | |
| final struct1 = getStruct1(); | |
| var expectedValue = 1; | |
| final dimensions = [3, 1, 2]; | |
| for (var i = 0; i < dimensions[0]; i++) { | |
| for (var j = 0; j < dimensions[1]; j++) { | |
| for (var k = 0; k < dimensions[2]; k++) { | |
| expect(struct1.ref.data[i][j][k], expectedValue); | |
| expectedValue++; | |
| } | |
| } | |
| } | |
| }); | |
| test('Array Workaround: Range Errors', () { | |
| final struct1 = getStruct1(); | |
| // Index (get) above range. | |
| expect( | |
| () => struct1.ref.data[4][0][0], | |
| throwsA(const TypeMatcher<RangeError>()), | |
| ); | |
| expect( | |
| () => struct1.ref.data[0][2][0], | |
| throwsA(const TypeMatcher<RangeError>()), | |
| ); | |
| expect( | |
| () => struct1.ref.data[0][0][3], | |
| throwsA(const TypeMatcher<RangeError>()), | |
| ); | |
| // Index (get) below range. | |
| expect( | |
| () => struct1.ref.data[-1][0][0], | |
| throwsA(const TypeMatcher<RangeError>()), | |
| ); | |
| expect( | |
| () => struct1.ref.data[-1][0][0], | |
| throwsA(const TypeMatcher<RangeError>()), | |
| ); | |
| expect( | |
| () => struct1.ref.data[0][0][-1], | |
| throwsA(const TypeMatcher<RangeError>()), | |
| ); | |
| // Index (set) above range. | |
| expect( | |
| () => struct1.ref.data[4][0][0] = 0, | |
| throwsA(const TypeMatcher<RangeError>()), | |
| ); | |
| expect( | |
| () => struct1.ref.data[0][2][0] = 0, | |
| throwsA(const TypeMatcher<RangeError>()), | |
| ); | |
| expect( | |
| () => struct1.ref.data[0][0][3] = 0, | |
| throwsA(const TypeMatcher<RangeError>()), | |
| ); | |
| // Index (get) below range. | |
| expect( | |
| () => struct1.ref.data[-1][0][0] = 0, | |
| throwsA(const TypeMatcher<RangeError>()), | |
| ); | |
| expect( | |
| () => struct1.ref.data[-1][0][0] = 0, | |
| throwsA(const TypeMatcher<RangeError>()), | |
| ); | |
| expect( | |
| () => struct1.ref.data[0][0][-1] = 0, | |
| throwsA(const TypeMatcher<RangeError>()), | |
| ); | |
| }); | |
| test('Struct By Value', () { | |
| final r = Random(); | |
| final a = r.nextInt(100), b = r.nextInt(100), c = r.nextInt(100); | |
| final s = Function1StructReturnByValue(a, b, c); | |
| expect(Function1StructPassByValue(s), a + b + c); | |
| }); | |
| test('Enum1 is a Dart enum', () { | |
| final enum1 = Enum1.enum1Value1; | |
| final result = funcWithEnum1(enum1); | |
| expect(enum1, isA<Enum1>()); | |
| expect(enum1.value, isA<int>()); | |
| expect(result, enum1); | |
| }); | |
| test('Enum2 is a Dart integer', () { | |
| final enum2 = Enum2.enum2Value1; | |
| final result = funcWithEnum2(enum2); | |
| expect(enum2, isA<int>()); | |
| expect(result, enum2); | |
| }); | |
| test('Enum in a struct', () { | |
| final struct1 = getStructWithEnums(); | |
| Enum1 enum1; | |
| enum1 = struct1.enum1; | |
| expect(enum1, Enum1.enum1Value1); | |
| expect(enum1, isA<Enum1>()); | |
| expect(enum1.value, isA<int>()); | |
| enum1 = Enum1.fromValue(struct1.enum1Pointer.value); | |
| expect(struct1.enum1Pointer, isA<Pointer<UnsignedInt>>()); | |
| expect(enum1, Enum1.enum1Value2); | |
| for (var i = 0; i < 5; i++) { | |
| enum1 = Enum1.fromValue(struct1.enum1Array[i]); | |
| expect(enum1, Enum1.enum1Value3); | |
| } | |
| int enum2; | |
| enum2 = struct1.enum2; | |
| expect(enum2, Enum2.enum2Value1); | |
| expect(enum2, isA<int>()); | |
| enum2 = struct1.enum2Pointer.value; | |
| expect(struct1.enum2Pointer, isA<Pointer<UnsignedInt>>()); | |
| expect(enum2, Enum2.enum2Value2); | |
| for (var i = 0; i < 5; i++) { | |
| enum2 = struct1.enum2Array[i]; | |
| expect(enum2, Enum2.enum2Value3); | |
| } | |
| }); | |
| }); | |
| } |