diff --git a/frb_example/pure_dart/dart/lib/main.dart b/frb_example/pure_dart/dart/lib/main.dart index 5070d22cd3..8d0870f675 100644 --- a/frb_example/pure_dart/dart/lib/main.dart +++ b/frb_example/pure_dart/dart/lib/main.dart @@ -24,7 +24,12 @@ void main(List args) async { print('dart call primitiveTypes'); { - expect(await api.primitiveTypes(myI32: 123, myI64: 10000000000000, myF64: 12345678901234567890.123, myBool: true), + expect( + await api.primitiveTypes( + myI32: 123, + myI64: 10000000000000, + myF64: 12345678901234567890.123, + myBool: true), 42); } @@ -40,13 +45,15 @@ void main(List args) async { print('dart call handleString'); { - expect(await api.handleString(s: "Hello, world!"), "Hello, world!Hello, world!"); + expect(await api.handleString(s: "Hello, world!"), + "Hello, world!Hello, world!"); } print('dart call handleVecU8'); { final len = 100000; - expect(await api.handleVecU8(v: Uint8List.fromList(List.filled(len, 127))), + expect( + await api.handleVecU8(v: Uint8List.fromList(List.filled(len, 127))), Uint8List.fromList(List.filled(len * 2, 127))); } @@ -84,8 +91,9 @@ void main(List args) async { print('dart call handleStruct'); { - final structResp = - await api.handleStruct(arg: MySize(width: 42, height: 100), boxed: MySize(width: 1000, height: 10000)); + final structResp = await api.handleStruct( + arg: MySize(width: 42, height: 100), + boxed: MySize(width: 1000, height: 10000)); expect(structResp.width, 42 + 1000); expect(structResp.height, 100 + 10000); } @@ -98,8 +106,10 @@ void main(List args) async { print('dart call handleListOfStruct'); { - final listOfStructResp = - await api.handleListOfStruct(l: [MySize(width: 42, height: 100), MySize(width: 420, height: 1000)]); + final listOfStructResp = await api.handleListOfStruct(l: [ + MySize(width: 42, height: 100), + MySize(width: 420, height: 1000) + ]); expect(listOfStructResp.length, 4); expect(listOfStructResp[0].width, 42); expect(listOfStructResp[1].width, 420); @@ -116,12 +126,16 @@ void main(List args) async { print('dart call handleComplexStruct'); { final arrLen = 5; - final complexStructResp = await api.handleComplexStruct(s: _createMyTreeNode(arrLen: arrLen)); + final complexStructResp = + await api.handleComplexStruct(s: _createMyTreeNode(arrLen: arrLen)); expect(complexStructResp.valueI32, 100); expect(complexStructResp.valueVecU8, List.filled(arrLen, 100)); - expect(complexStructResp.children[0].valueVecU8, List.filled(arrLen, 110)); - expect(complexStructResp.children[0].children[0].valueVecU8, List.filled(arrLen, 111)); - expect(complexStructResp.children[1].valueVecU8, List.filled(arrLen, 120)); + expect( + complexStructResp.children[0].valueVecU8, List.filled(arrLen, 110)); + expect(complexStructResp.children[0].children[0].valueVecU8, + List.filled(arrLen, 111)); + expect( + complexStructResp.children[1].valueVecU8, List.filled(arrLen, 120)); } print('dart call handle_sync_return'); @@ -187,7 +201,8 @@ void main(List args) async { { final message = 'Hello there.'; final ret = await api.handleOptionalStruct(document: message); - if (ret == null) fail('handleOptionalStruct returned null for non-null document'); + if (ret == null) + fail('handleOptionalStruct returned null for non-null document'); expect(ret.tag, 'div'); expect(ret.text, null); expect(ret.attributes?[0].key, 'id'); @@ -204,7 +219,8 @@ void main(List args) async { { expect(await api.handleOptionalIncrement(), null); - var ret = await api.handleOptionalIncrement(opt: ExoticOptionals(attributesNullable: [])); + var ret = await api.handleOptionalIncrement( + opt: ExoticOptionals(attributesNullable: [])); if (ret == null) fail('increment returned null for non-null params'); final loopFor = 20; for (var i = 1; i < loopFor; i++) { @@ -246,7 +262,8 @@ void main(List args) async { { final optional10 = await api.handleOptionBoxArguments( boolbox: true, - structbox: await api.handleOptionalIncrement(opt: ExoticOptionals(attributesNullable: [])), + structbox: await api.handleOptionalIncrement( + opt: ExoticOptionals(attributesNullable: [])), ); print(optional10); } @@ -260,7 +277,8 @@ void main(List args) async { print('dart call handleEnumParameter'); { - expect(await api.handleEnumParameter(weekday: Weekdays.Saturday), Weekdays.Saturday); + expect(await api.handleEnumParameter(weekday: Weekdays.Saturday), + Weekdays.Saturday); } print('dart call handleEnumStruct'); @@ -330,7 +348,9 @@ void main(List args) async { name: "from dart", version: "XX", mode: ApplicationMode.Embedded, - env: ApplicationEnv(vars: [ApplicationEnvVar(field0: "sendback", field1: true)]))), + env: ApplicationEnv(vars: [ + ApplicationEnvVar(field0: "sendback", field1: true) + ]))), true); } diff --git a/frb_example/with_flutter/integration_test/main.dart b/frb_example/with_flutter/integration_test/main.dart index d37a8c8987..3b678eb359 100644 --- a/frb_example/with_flutter/integration_test/main.dart +++ b/frb_example/with_flutter/integration_test/main.dart @@ -5,7 +5,7 @@ import 'dart:io'; import 'dart:isolate'; import 'dart:typed_data'; -import 'package:flutter/material.dart'; +import 'package:flutter/material.dart' hide Size; import 'package:flutter_rust_bridge_example/bridge_generated.dart'; import 'package:flutter_rust_bridge_example/main.dart' as app; import 'package:flutter_test/flutter_test.dart'; @@ -18,14 +18,16 @@ void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); group('end-to-end test', () { - testWidgets('run and wait to see if there is memory problem', (WidgetTester tester) async { + testWidgets('run and wait to see if there is memory problem', + (WidgetTester tester) async { app.main(); await tester.pumpAndSettle(); // run many times to see memory leaks or other problems for (var i = 0; i < 20; ++i) { await tester.pumpAndSettle(); - expect(find.textContaining('Hi this string is from Rust'), findsOneWidget); + expect( + find.textContaining('Hi this string is from Rust'), findsOneWidget); Future.delayed(const Duration(milliseconds: 50)); @@ -35,7 +37,8 @@ void main() { } }); - testWidgets('test Rust deliberately have error', (WidgetTester tester) async { + testWidgets('test Rust deliberately have error', + (WidgetTester tester) async { app.main(); await tester.pumpAndSettle(); @@ -64,49 +67,80 @@ void main() { } }); - testWidgets('repeat call to offTopicMemoryTestInputComplexStruct', (WidgetTester tester) async { + testWidgets('repeat call to offTopicMemoryTestInputComplexStruct', + (WidgetTester tester) async { await _testMemoryProblemForSingleTypeOfMethod( tester, () async => expect( await app.api.offTopicMemoryTestInputComplexStruct( - input: TreeNode( - name: 'root', children: [for (var i = 0; i < 2000; ++i) TreeNode(name: 'child', children: [])])), + input: TreeNode(name: 'root', children: [ + for (var i = 0; i < 2000; ++i) + TreeNode(name: 'child', children: []) + ])), 2000)); }); - testWidgets('repeat call to offTopicMemoryTestOutputComplexStruct', (WidgetTester tester) async { - await _testMemoryProblemForSingleTypeOfMethod(tester, - () async => expect((await app.api.offTopicMemoryTestOutputComplexStruct(len: 2000)).children.length, 2000)); + testWidgets('repeat call to offTopicMemoryTestOutputComplexStruct', + (WidgetTester tester) async { + await _testMemoryProblemForSingleTypeOfMethod( + tester, + () async => expect( + (await app.api.offTopicMemoryTestOutputComplexStruct(len: 2000)) + .children + .length, + 2000)); }); - testWidgets('repeat call to offTopicMemoryTestInputVecOfObject', (WidgetTester tester) async { + testWidgets('repeat call to offTopicMemoryTestInputVecOfObject', + (WidgetTester tester) async { await _testMemoryProblemForSingleTypeOfMethod( tester, () async => expect( - await app.api - .offTopicMemoryTestInputVecOfObject(input: List.filled(100000, Size(width: 42, height: 100))), + await app.api.offTopicMemoryTestInputVecOfObject( + input: List.filled(100000, Size(width: 42, height: 100))), 100000)); }); - testWidgets('repeat call to offTopicMemoryTestOutputVecOfObject', (WidgetTester tester) async { + testWidgets('repeat call to offTopicMemoryTestOutputVecOfObject', + (WidgetTester tester) async { await _testMemoryProblemForSingleTypeOfMethod( - tester, () async => expect((await app.api.offTopicMemoryTestOutputVecOfObject(len: 100000)).length, 100000)); + tester, + () async => expect( + (await app.api.offTopicMemoryTestOutputVecOfObject(len: 100000)) + .length, + 100000)); }); - testWidgets('repeat call to offTopicMemoryTestInputArray', (WidgetTester tester) async { + testWidgets('repeat call to offTopicMemoryTestInputArray', + (WidgetTester tester) async { await _testMemoryProblemForSingleTypeOfMethod( - tester, () async => expect(await app.api.offTopicMemoryTestInputArray(input: Uint8List(1000000)), 1000000)); + tester, + () async => expect( + await app.api + .offTopicMemoryTestInputArray(input: Uint8List(1000000)), + 1000000)); }); - testWidgets('repeat call to offTopicMemoryTestOutputZeroCopyBuffer', (WidgetTester tester) async { - await _testMemoryProblemForSingleTypeOfMethod(tester, - () async => expect((await app.api.offTopicMemoryTestOutputZeroCopyBuffer(len: 1000000)).length, 1000000)); + testWidgets('repeat call to offTopicMemoryTestOutputZeroCopyBuffer', + (WidgetTester tester) async { + await _testMemoryProblemForSingleTypeOfMethod( + tester, + () async => expect( + (await app.api + .offTopicMemoryTestOutputZeroCopyBuffer(len: 1000000)) + .length, + 1000000)); }); - testWidgets('repeat call to offTopicMemoryTestOutputVecU8', (WidgetTester tester) async { + testWidgets('repeat call to offTopicMemoryTestOutputVecU8', + (WidgetTester tester) async { await _testMemoryProblemForSingleTypeOfMethod( - tester, () async => expect((await app.api.offTopicMemoryTestOutputVecU8(len: 200000)).length, 200000)); + tester, + () async => expect( + (await app.api.offTopicMemoryTestOutputVecU8(len: 200000)).length, + 200000)); }); }); } -Future _testMemoryProblemForSingleTypeOfMethod(WidgetTester tester, Future Function() callFfi) async { +Future _testMemoryProblemForSingleTypeOfMethod( + WidgetTester tester, Future Function() callFfi) async { print('testMemoryProblemForSingleTypeOfMethod start'); app.main(); @@ -163,7 +197,8 @@ Future _maybeGC([String hint = '']) async { final vmService = await vmServiceConnectUri(_toWebSocket(serverUri)); // notice this variable is also large and can consume megabytes of memory... - final profileAfterMaybeGc = await vmService.getAllocationProfile(isolateId, reset: true, gc: true); + final profileAfterMaybeGc = + await vmService.getAllocationProfile(isolateId, reset: true, gc: true); print('Memory usage after maybe GC $hint: ${profileAfterMaybeGc.memoryUsage} ' 'dateLastServiceGC=${profileAfterMaybeGc.dateLastServiceGC} now=${DateTime.now().millisecondsSinceEpoch}'); } diff --git a/frb_example/with_flutter/lib/main.dart b/frb_example/with_flutter/lib/main.dart index 53f9beb941..68ca3de426 100644 --- a/frb_example/with_flutter/lib/main.dart +++ b/frb_example/with_flutter/lib/main.dart @@ -47,12 +47,16 @@ class _MyAppState extends State { Future _callExampleFfiOne() async { final receivedImage = await api.drawMandelbrot( - imageSize: Size(width: 50, height: 50), zoomPoint: examplePoint, scale: generateScale(), numThreads: 4); + imageSize: Size(width: 50, height: 50), + zoomPoint: examplePoint, + scale: generateScale(), + numThreads: 4); if (mounted) setState(() => exampleImage = receivedImage); } Future _callExampleFfiTwo() async { - final receivedText = await api.passingComplexStructs(root: createExampleTree()); + final receivedText = + await api.passingComplexStructs(root: createExampleTree()); if (mounted) setState(() => exampleText = receivedText); } } diff --git a/frb_example/with_flutter/lib/off_topic_code.dart b/frb_example/with_flutter/lib/off_topic_code.dart index 064ded6ed8..be673f80fe 100644 --- a/frb_example/with_flutter/lib/off_topic_code.dart +++ b/frb_example/with_flutter/lib/off_topic_code.dart @@ -19,21 +19,28 @@ Widget buildPageUi(Uint8List? exampleImage, String? exampleText) { padding: const EdgeInsets.symmetric(horizontal: 24), child: Card( child: Container( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + padding: + const EdgeInsets.symmetric(horizontal: 24, vertical: 16), child: Column( children: [ - const Text('Example 1', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), + const Text('Example 1', + style: TextStyle( + fontSize: 18, fontWeight: FontWeight.bold)), Container(height: 8), - const Text('Image generated (periodically) by Rust and displayed by Flutter/Dart'), + const Text( + 'Image generated (periodically) by Rust and displayed by Flutter/Dart'), Container(height: 24), (exampleImage != null ? SizedBox( width: 50, height: 50, - child: Center(child: AnimatedReplaceableImage(image: MemoryImage(exampleImage)))) + child: Center( + child: AnimatedReplaceableImage( + image: MemoryImage(exampleImage)))) : Container()), Container(height: 4), - const Text('Mandelbrot Set', style: TextStyle(fontSize: 11, color: Colors.grey)), + const Text('Mandelbrot Set', + style: TextStyle(fontSize: 11, color: Colors.grey)), const Text('classical image requiring lots of computing', style: TextStyle(fontSize: 11, color: Colors.grey)), Container(height: 8), @@ -47,14 +54,20 @@ Widget buildPageUi(Uint8List? exampleImage, String? exampleText) { padding: const EdgeInsets.symmetric(horizontal: 24), child: Card( child: Container( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + padding: + const EdgeInsets.symmetric(horizontal: 24, vertical: 16), child: Column( children: [ - const Text('Example 2', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), + const Text('Example 2', + style: TextStyle( + fontSize: 18, fontWeight: FontWeight.bold)), Container(height: 8), - const Text('Complex struct/class is passed smoothly through FFI'), + const Text( + 'Complex struct/class is passed smoothly through FFI'), Container(height: 24), - Text(exampleText ?? '', style: const TextStyle(fontSize: 11, color: Colors.grey)), + Text(exampleText ?? '', + style: + const TextStyle(fontSize: 11, color: Colors.grey)), Container(height: 8), ], ), @@ -70,7 +83,8 @@ Widget buildPageUi(Uint8List? exampleImage, String? exampleText) { TreeNode createExampleTree() => TreeNode(name: 'root', children: [ for (var i = 0; i < 1 + Random().nextInt(2); ++i) TreeNode(name: 'child_$i', children: [ - for (var j = 0; j < 1 + Random().nextInt(2); ++j) TreeNode(name: 'grandchild_$j', children: []) + for (var j = 0; j < 1 + Random().nextInt(2); ++j) + TreeNode(name: 'grandchild_$j', children: []) ]), ]); @@ -81,10 +95,12 @@ final examplePoint = Point( class AnimatedReplaceableImage extends StatefulWidget { final ImageProvider image; - const AnimatedReplaceableImage({Key? key, required this.image}) : super(key: key); + const AnimatedReplaceableImage({Key? key, required this.image}) + : super(key: key); @override - _AnimatedReplaceableImageState createState() => _AnimatedReplaceableImageState(); + _AnimatedReplaceableImageState createState() => + _AnimatedReplaceableImageState(); } class _AnimatedReplaceableImageState extends State { @@ -99,7 +115,8 @@ class _AnimatedReplaceableImageState extends State { @override void didUpdateWidget(AnimatedReplaceableImage oldWidget) { super.didUpdateWidget(oldWidget); - if (oldWidget.image.obtainKey(const ImageConfiguration()) != widget.image.obtainKey(const ImageConfiguration())) { + if (oldWidget.image.obtainKey(const ImageConfiguration()) != + widget.image.obtainKey(const ImageConfiguration())) { previousImage = oldWidget.image; } } @@ -108,8 +125,11 @@ class _AnimatedReplaceableImageState extends State { Widget build(BuildContext context) { return Image( image: widget.image, - frameBuilder: (BuildContext context, Widget child, int? frame, bool wasSynchronouslyLoaded) => - (frame == null && previousImage != null) ? Stack(children: [Image(image: previousImage!), child]) : child, + frameBuilder: (BuildContext context, Widget child, int? frame, + bool wasSynchronouslyLoaded) => + (frame == null && previousImage != null) + ? Stack(children: [Image(image: previousImage!), child]) + : child, ); } }