| // 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( |
| 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, |
| ), |
| ), |
| ), |
| ], |
| ); |
| |
| 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; |
| |
| class Bindings{ |
| /// Holds the Dynamic library. |
| final ffi.DynamicLibrary _dylib; |
| |
| /// The symbols are looked up in [dynamicLibrary]. |
| Bindings(ffi.DynamicLibrary dynamicLibrary): _dylib = dynamicLibrary; |
| |
| /// Just a test function |
| /// heres another line |
| int noParam( |
| ) { |
| return (_noParam ??= _dylib.lookupFunction<_c_noParam,_dart_noParam>('noParam'))( |
| ); |
| } |
| _dart_noParam? _noParam; |
| |
| int withPrimitiveParam( |
| int a, |
| int b, |
| ) { |
| return (_withPrimitiveParam ??= _dylib.lookupFunction<_c_withPrimitiveParam,_dart_withPrimitiveParam>('withPrimitiveParam'))( |
| a, |
| b, |
| ); |
| } |
| _dart_withPrimitiveParam? _withPrimitiveParam; |
| |
| ffi.Pointer<ffi.Double> withPointerParam( |
| ffi.Pointer<ffi.Int32> a, |
| ffi.Pointer<ffi.Pointer<ffi.Uint8>> b, |
| ) { |
| return (_withPointerParam ??= _dylib.lookupFunction<_c_withPointerParam,_dart_withPointerParam>('withPointerParam'))( |
| a, |
| b, |
| ); |
| } |
| _dart_withPointerParam? _withPointerParam; |
| |
| } |
| |
| typedef _c_noParam = ffi.Int32 Function( |
| ); |
| |
| typedef _dart_noParam = int Function( |
| ); |
| |
| typedef _c_withPrimitiveParam = ffi.Uint8 Function( |
| ffi.Int32 a, |
| ffi.Uint8 b, |
| ); |
| |
| typedef _dart_withPrimitiveParam = int Function( |
| int a, |
| int b, |
| ); |
| |
| 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( |
| 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, |
| ), |
| ), |
| ], |
| ), |
| ], |
| ); |
| |
| 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; |
| |
| /// Just a test struct |
| /// heres another line |
| class NoMember extends ffi.Struct{ |
| } |
| |
| class WithPrimitiveMember extends ffi.Struct{ |
| @ffi.Int32() |
| external int a; |
| |
| @ffi.Double() |
| external double b; |
| |
| @ffi.Uint8() |
| external int c; |
| |
| } |
| |
| class WithPointerMember extends ffi.Struct{ |
| external ffi.Pointer<ffi.Int32> a; |
| |
| external ffi.Pointer<ffi.Pointer<ffi.Double>> b; |
| |
| @ffi.Uint8() |
| external 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 struct_some = 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: [ |
| struct_some, |
| Func( |
| name: 'someFunc', |
| parameters: [ |
| Parameter( |
| name: 'some', |
| type: Type.pointer( |
| Type.pointer( |
| Type.struct( |
| struct_some, |
| ), |
| ), |
| ), |
| ), |
| ], |
| returnType: Type.pointer( |
| Type.struct( |
| struct_some, |
| ), |
| ), |
| ), |
| ], |
| ); |
| |
| 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; |
| |
| class Bindings{ |
| /// Holds the Dynamic library. |
| final ffi.DynamicLibrary _dylib; |
| |
| /// The symbols are looked up in [dynamicLibrary]. |
| Bindings(ffi.DynamicLibrary dynamicLibrary): _dylib = dynamicLibrary; |
| |
| ffi.Pointer<SomeStruc> someFunc( |
| ffi.Pointer<ffi.Pointer<SomeStruc>> some, |
| ) { |
| return (_someFunc ??= _dylib.lookupFunction<_c_someFunc,_dart_someFunc>('someFunc'))( |
| some, |
| ); |
| } |
| _dart_someFunc? _someFunc; |
| |
| } |
| |
| class SomeStruc extends ffi.Struct{ |
| @ffi.Int32() |
| external int a; |
| |
| @ffi.Double() |
| external double b; |
| |
| @ffi.Uint8() |
| external int c; |
| |
| } |
| |
| 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 struc_some = Struc( |
| name: 'Some', |
| ); |
| final library = Library( |
| name: 'Bindings', |
| bindings: [ |
| Global( |
| name: 'test1', |
| type: Type.nativeType( |
| SupportedNativeType.Int32, |
| ), |
| ), |
| Global( |
| name: 'test2', |
| type: Type.pointer( |
| Type.nativeType( |
| SupportedNativeType.Float, |
| ), |
| ), |
| ), |
| struc_some, |
| Global( |
| name: 'test5', |
| type: Type.pointer( |
| Type.struct( |
| struc_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; |
| |
| class Bindings{ |
| /// Holds the Dynamic library. |
| final ffi.DynamicLibrary _dylib; |
| |
| /// The symbols are looked up in [dynamicLibrary]. |
| Bindings(ffi.DynamicLibrary dynamicLibrary): _dylib = dynamicLibrary; |
| |
| late final ffi.Pointer<int> _test1 = _dylib.lookup<ffi.Int32>('test1'); |
| |
| int get test1 => _test1.value; |
| |
| set test1(int value) => _test1.value = value; |
| |
| late final ffi.Pointer<ffi.Pointer<ffi.Float>> _test2 = _dylib.lookup<ffi.Pointer<ffi.Float>>('test2'); |
| |
| ffi.Pointer<ffi.Float> get test2 => _test2.value; |
| |
| set test2(ffi.Pointer<ffi.Float> value) => _test2.value = value; |
| |
| late final ffi.Pointer<ffi.Pointer<Some>> _test5 = _dylib.lookup<ffi.Pointer<Some>>('test5'); |
| |
| ffi.Pointer<Some> get test5 => _test5.value; |
| |
| set test5(ffi.Pointer<Some> value) => _test5.value = value; |
| |
| } |
| |
| class Some extends ffi.Struct{ |
| } |
| |
| '''); |
| if (file.existsSync()) { |
| file.delete(); |
| } |
| } catch (e) { |
| file.writeAsStringSync(gen); |
| print('Failed test, Debug output: ${file.absolute.path}'); |
| rethrow; |
| } |
| }); |
| |
| test('constant', () { |
| final library = Library( |
| name: 'Bindings', |
| bindings: [ |
| Constant( |
| name: 'test1', |
| rawType: 'int', |
| rawValue: '20', |
| ), |
| Constant( |
| name: 'test2', |
| rawType: 'double', |
| 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; |
| |
| 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('enum_class', () { |
| final library = Library( |
| name: 'Bindings', |
| 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; |
| |
| /// test line 1 |
| /// test line 2 |
| abstract 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; |
| } |
| }); |
| test('Internal conflict resolution', () { |
| final library = Library( |
| name: 'init_dylib', |
| 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'), |
| ], |
| ); |
| |
| final gen = library.generate(); |
| |
| // Writing to file for debug purpose. |
| final file = File( |
| 'test/debug_generated/internal-conflict-resolution.dart', |
| ); |
| try { |
| expect(gen, r'''// AUTO GENERATED FILE, DO NOT EDIT. |
| // |
| // Generated by `package:ffigen`. |
| import 'dart:ffi' as ffi; |
| |
| class init_dylib_1{ |
| /// Holds the Dynamic library. |
| final ffi.DynamicLibrary _dylib; |
| |
| /// The symbols are looked up in [dynamicLibrary]. |
| init_dylib_1(ffi.DynamicLibrary dynamicLibrary): _dylib = dynamicLibrary; |
| |
| void test( |
| ) { |
| return (_test_1 ??= _dylib.lookupFunction<_c_test1,_dart_test1>('test'))( |
| ); |
| } |
| _dart_test1? _test_1; |
| |
| void _test( |
| ) { |
| return (__test ??= _dylib.lookupFunction<_c__test,_dart__test>('_test'))( |
| ); |
| } |
| _dart__test? __test; |
| |
| void _c_test( |
| ) { |
| return (__c_test ??= _dylib.lookupFunction<_c__c_test,_dart__c_test>('_c_test'))( |
| ); |
| } |
| _dart__c_test? __c_test; |
| |
| void _dart_test( |
| ) { |
| return (__dart_test ??= _dylib.lookupFunction<_c__dart_test,_dart__dart_test>('_dart_test'))( |
| ); |
| } |
| _dart__dart_test? __dart_test; |
| |
| void Test( |
| ) { |
| return (_Test ??= _dylib.lookupFunction<_c_Test1,_dart_Test>('Test'))( |
| ); |
| } |
| _dart_Test? _Test; |
| |
| } |
| |
| class _Test extends ffi.Struct{ |
| @ffi.Int8() |
| external int _unique_array_item_0; |
| @ffi.Int8() |
| external int _unique_array_item_1; |
| /// Helper for array `array`. |
| ArrayHelper1__Test_array_level0 get array => ArrayHelper1__Test_array_level0(this, [2], 0, 0); |
| } |
| |
| /// Helper for array `array` in struct `_Test`. |
| class ArrayHelper1__Test_array_level0{ |
| final _Test _struct; |
| final List<int> dimensions; |
| final int level; |
| final int _absoluteIndex; |
| int get length => dimensions[level]; |
| ArrayHelper1__Test_array_level0(this._struct, this.dimensions, this.level, this._absoluteIndex); |
| void _checkBounds(int index) { |
| if (index >= length || index < 0) { |
| throw RangeError('Dimension $level: index not in range 0..${length} exclusive.'); |
| } |
| } |
| int operator[](int index){ |
| _checkBounds(index); |
| switch(_absoluteIndex+index){ |
| case 0: |
| return _struct._unique_array_item_0; |
| case 1: |
| return _struct._unique_array_item_1; |
| default: |
| throw Exception('Invalid Array Helper generated.');} |
| } |
| void operator[]=(int index, int value){ |
| _checkBounds(index); |
| switch(_absoluteIndex+index){ |
| case 0: |
| _struct._unique_array_item_0 = value; |
| break; |
| case 1: |
| _struct._unique_array_item_1 = value; |
| break; |
| default: |
| throw Exception('Invalid Array Helper generated.'); |
| } |
| } |
| } |
| class ArrayHelperPrefixCollisionTest extends ffi.Struct{ |
| } |
| |
| abstract class _c_Test { |
| } |
| |
| abstract class init_dylib { |
| } |
| |
| typedef _c_test1 = ffi.Void Function( |
| ); |
| |
| typedef _dart_test1 = void Function( |
| ); |
| |
| typedef _c__test = ffi.Void Function( |
| ); |
| |
| typedef _dart__test = void Function( |
| ); |
| |
| typedef _c__c_test = ffi.Void Function( |
| ); |
| |
| typedef _dart__c_test = void Function( |
| ); |
| |
| typedef _c__dart_test = ffi.Void Function( |
| ); |
| |
| typedef _dart__dart_test = void Function( |
| ); |
| |
| typedef _c_Test1 = ffi.Void Function( |
| ); |
| |
| typedef _dart_Test = void Function( |
| ); |
| |
| '''); |
| if (file.existsSync()) { |
| file.delete(); |
| } |
| } catch (e) { |
| file.writeAsStringSync(gen); |
| print('Failed test, Debug output: ${file.absolute.path}'); |
| rethrow; |
| } |
| }); |
| }); |
| 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()), |
| ], |
| ), |
| ], |
| ); |
| |
| final gen = library.generate(); |
| |
| // Writing to file for debug purpose. |
| final file = File( |
| 'test/debug_generated/boolean-dartbool-output.dart', |
| ); |
| try { |
| expect(gen, '''// AUTO GENERATED FILE, DO NOT EDIT. |
| // |
| // Generated by `package:ffigen`. |
| import 'dart:ffi' as ffi; |
| |
| class Bindings{ |
| /// Holds the Dynamic library. |
| final ffi.DynamicLibrary _dylib; |
| |
| /// The symbols are looked up in [dynamicLibrary]. |
| Bindings(ffi.DynamicLibrary dynamicLibrary): _dylib = dynamicLibrary; |
| |
| bool test1( |
| bool a, |
| ffi.Pointer<ffi.Uint8> b, |
| ) { |
| return (_test1 ??= _dylib.lookupFunction<_c_test1,_dart_test1>('test1'))( |
| a?1:0, |
| b, |
| )!=0; |
| } |
| _dart_test1? _test1; |
| |
| } |
| |
| class test2 extends ffi.Struct{ |
| @ffi.Uint8() |
| external int a; |
| |
| } |
| |
| typedef _c_test1 = ffi.Uint8 Function( |
| ffi.Uint8 a, |
| ffi.Pointer<ffi.Uint8> b, |
| ); |
| |
| typedef _dart_test1 = int Function( |
| int a, |
| 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('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()), |
| ], |
| ), |
| ], |
| ); |
| |
| final gen = library.generate(); |
| |
| // Writing to file for debug purpose. |
| final file = File( |
| 'test/debug_generated/boolean-no-dartBool-output.dart', |
| ); |
| try { |
| expect(gen, '''// AUTO GENERATED FILE, DO NOT EDIT. |
| // |
| // Generated by `package:ffigen`. |
| import 'dart:ffi' as ffi; |
| |
| class Bindings{ |
| /// Holds the Dynamic library. |
| final ffi.DynamicLibrary _dylib; |
| |
| /// The symbols are looked up in [dynamicLibrary]. |
| Bindings(ffi.DynamicLibrary dynamicLibrary): _dylib = dynamicLibrary; |
| |
| int test1( |
| int a, |
| ffi.Pointer<ffi.Uint8> b, |
| ) { |
| return (_test1 ??= _dylib.lookupFunction<_c_test1,_dart_test1>('test1'))( |
| a, |
| b, |
| ); |
| } |
| _dart_test1? _test1; |
| |
| } |
| |
| class test2 extends ffi.Struct{ |
| @ffi.Uint8() |
| external int a; |
| |
| } |
| |
| typedef _c_test1 = ffi.Uint8 Function( |
| ffi.Uint8 a, |
| ffi.Pointer<ffi.Uint8> b, |
| ); |
| |
| typedef _dart_test1 = int Function( |
| int a, |
| ffi.Pointer<ffi.Uint8> b, |
| ); |
| |
| '''); |
| if (file.existsSync()) { |
| file.delete(); |
| } |
| } catch (e) { |
| file.writeAsStringSync(gen); |
| print('Failed test, Debug output: ${file.absolute.path}'); |
| rethrow; |
| } |
| }); |
| } |