From 527c53bcb18a52d98822237413f7ec7dc09fe187 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 4 Dec 2024 11:39:11 +1100 Subject: [PATCH 1/2] event ordering test --- .../native_objc_test/event_order_config.yaml | 15 ++++++ .../native_objc_test/event_order_test.dart | 50 +++++++++++++++++++ .../test/native_objc_test/event_order_test.h | 35 +++++++++++++ .../test/native_objc_test/event_order_test.m | 36 +++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 pkgs/ffigen/test/native_objc_test/event_order_config.yaml create mode 100644 pkgs/ffigen/test/native_objc_test/event_order_test.dart create mode 100644 pkgs/ffigen/test/native_objc_test/event_order_test.h create mode 100644 pkgs/ffigen/test/native_objc_test/event_order_test.m diff --git a/pkgs/ffigen/test/native_objc_test/event_order_config.yaml b/pkgs/ffigen/test/native_objc_test/event_order_config.yaml new file mode 100644 index 000000000..6252217c2 --- /dev/null +++ b/pkgs/ffigen/test/native_objc_test/event_order_config.yaml @@ -0,0 +1,15 @@ +name: EventOrderTestObjCLibrary +description: 'Tests the ordering of listener callback events' +language: objc +output: + bindings: 'event_order_bindings.dart' + objc-bindings: 'event_order_bindings.m' +exclude-all-by-default: true +objc-interfaces: + include: + - EventOrderTest +headers: + entry-points: + - 'event_order_test.h' +preamble: | + // ignore_for_file: camel_case_types, non_constant_identifier_names, unnecessary_non_null_assertion, unused_element, unused_field diff --git a/pkgs/ffigen/test/native_objc_test/event_order_test.dart b/pkgs/ffigen/test/native_objc_test/event_order_test.dart new file mode 100644 index 000000000..f16f87478 --- /dev/null +++ b/pkgs/ffigen/test/native_objc_test/event_order_test.dart @@ -0,0 +1,50 @@ +// Copyright (c) 2024, 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. + +// Objective C support is only available on mac. +@TestOn('mac-os') + +import 'dart:ffi'; +import 'dart:io'; + +import 'package:ffi/ffi.dart'; +import 'package:test/test.dart'; +import '../test_utils.dart'; +import 'event_order_bindings.dart'; +import 'util.dart'; + +void main() { + group('event ordering', () { + setUpAll(() { + // TODO(https://github.com/dart-lang/native/issues/1068): Remove this. + DynamicLibrary.open('../objective_c/test/objective_c.dylib'); + final dylib = File('test/native_objc_test/objc_test.dylib'); + verifySetupFile(dylib); + DynamicLibrary.open(dylib.absolute.path); + generateBindingsForCoverage('event_order'); + }); + + test('Many listener calls with different signatures', () async { + final result = []; + + EventOrderTest.countTo1000OnNewThread___________________( + ObjCBlock_ffiVoid_Int32_Int8.listener((x, _) => result.add(x)), + ObjCBlock_ffiVoid_Int32_Int16.listener((x, _) => result.add(x)), + ObjCBlock_ffiVoid_Int32_Int32.listener((x, _) => result.add(x)), + ObjCBlock_ffiVoid_Int32_Int64.listener((x, _) => result.add(x)), + ObjCBlock_ffiVoid_Int32_Uint8.listener((x, _) => result.add(x)), + ObjCBlock_ffiVoid_Int32_Uint16.listener((x, _) => result.add(x)), + ObjCBlock_ffiVoid_Int32_Uint32.listener((x, _) => result.add(x)), + ObjCBlock_ffiVoid_Int32_Uint64.listener((x, _) => result.add(x)), + ObjCBlock_ffiVoid_Int32_ffiDouble.listener((x, _) => result.add(x)), + ObjCBlock_ffiVoid_Int32_ffiFloat.listener((x, _) => result.add(x)), + ); + + while (result.length < 1000) { + await Future.delayed(Duration(milliseconds: 10)); + } + expect(result, [ for (int i = 1; i <= 1000; ++i) i ]); + }); + }); +} diff --git a/pkgs/ffigen/test/native_objc_test/event_order_test.h b/pkgs/ffigen/test/native_objc_test/event_order_test.h new file mode 100644 index 000000000..2ac26a079 --- /dev/null +++ b/pkgs/ffigen/test/native_objc_test/event_order_test.h @@ -0,0 +1,35 @@ +// Copyright (c) 2024, 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 + +// 10 listeners with different signatures. Only the first arg is actually used +// in this test. +typedef void (^Listener1)(int32_t, int8_t); +typedef void (^Listener2)(int32_t, int16_t); +typedef void (^Listener3)(int32_t, int32_t); +typedef void (^Listener4)(int32_t, int64_t); +typedef void (^Listener5)(int32_t, uint8_t); +typedef void (^Listener6)(int32_t, uint16_t); +typedef void (^Listener7)(int32_t, uint32_t); +typedef void (^Listener8)(int32_t, uint64_t); +typedef void (^Listener9)(int32_t, double); +typedef void (^Listener10)(int32_t, float); + +@interface EventOrderTest { +} + ++(void)countTo1000OnNewThread: + (Listener1)listener1 + _: (Listener2)listener2 + _: (Listener3)listener3 + _: (Listener4)listener4 + _: (Listener5)listener5 + _: (Listener6)listener6 + _: (Listener7)listener7 + _: (Listener8)listener8 + _: (Listener9)listener9 + _: (Listener10)listener10; + +@end diff --git a/pkgs/ffigen/test/native_objc_test/event_order_test.m b/pkgs/ffigen/test/native_objc_test/event_order_test.m new file mode 100644 index 000000000..b54d40f69 --- /dev/null +++ b/pkgs/ffigen/test/native_objc_test/event_order_test.m @@ -0,0 +1,36 @@ +// Copyright (c) 2024, 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. + +#include "event_order_test.h" + +@implementation EventOrderTest + ++(void)countTo1000OnNewThread: + (Listener1)listener1 + _: (Listener2)listener2 + _: (Listener3)listener3 + _: (Listener4)listener4 + _: (Listener5)listener5 + _: (Listener6)listener6 + _: (Listener7)listener7 + _: (Listener8)listener8 + _: (Listener9)listener9 + _: (Listener10)listener10 { + return [[[NSThread alloc] initWithBlock:^{ + for (int32_t i = 0; i < 1000; i += 10) { + listener1(i + 1, 0); + listener2(i + 2, 0); + listener3(i + 3, 0); + listener4(i + 4, 0); + listener5(i + 5, 0); + listener6(i + 6, 0); + listener7(i + 7, 0); + listener8(i + 8, 0); + listener9(i + 9, 0); + listener10(i + 10, 0); + } + }] start]; +} + +@end From a592183d8fc1cd8ef4366dda203b8af1b2e35b5c Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 4 Dec 2024 11:53:39 +1100 Subject: [PATCH 2/2] Use a protocol --- .../native_objc_test/event_order_config.yaml | 3 ++ .../native_objc_test/event_order_test.dart | 24 ++++++------ .../test/native_objc_test/event_order_test.h | 37 +++++++------------ .../test/native_objc_test/event_order_test.m | 32 ++++++---------- 4 files changed, 41 insertions(+), 55 deletions(-) diff --git a/pkgs/ffigen/test/native_objc_test/event_order_config.yaml b/pkgs/ffigen/test/native_objc_test/event_order_config.yaml index 6252217c2..cfd4878d5 100644 --- a/pkgs/ffigen/test/native_objc_test/event_order_config.yaml +++ b/pkgs/ffigen/test/native_objc_test/event_order_config.yaml @@ -8,6 +8,9 @@ exclude-all-by-default: true objc-interfaces: include: - EventOrderTest +objc-protocols: + include: + - EventOrderProtocol headers: entry-points: - 'event_order_test.h' diff --git a/pkgs/ffigen/test/native_objc_test/event_order_test.dart b/pkgs/ffigen/test/native_objc_test/event_order_test.dart index f16f87478..d5a9f68ff 100644 --- a/pkgs/ffigen/test/native_objc_test/event_order_test.dart +++ b/pkgs/ffigen/test/native_objc_test/event_order_test.dart @@ -28,19 +28,21 @@ void main() { test('Many listener calls with different signatures', () async { final result = []; - EventOrderTest.countTo1000OnNewThread___________________( - ObjCBlock_ffiVoid_Int32_Int8.listener((x, _) => result.add(x)), - ObjCBlock_ffiVoid_Int32_Int16.listener((x, _) => result.add(x)), - ObjCBlock_ffiVoid_Int32_Int32.listener((x, _) => result.add(x)), - ObjCBlock_ffiVoid_Int32_Int64.listener((x, _) => result.add(x)), - ObjCBlock_ffiVoid_Int32_Uint8.listener((x, _) => result.add(x)), - ObjCBlock_ffiVoid_Int32_Uint16.listener((x, _) => result.add(x)), - ObjCBlock_ffiVoid_Int32_Uint32.listener((x, _) => result.add(x)), - ObjCBlock_ffiVoid_Int32_Uint64.listener((x, _) => result.add(x)), - ObjCBlock_ffiVoid_Int32_ffiDouble.listener((x, _) => result.add(x)), - ObjCBlock_ffiVoid_Int32_ffiFloat.listener((x, _) => result.add(x)), + final protocol = EventOrderProtocol.implementAsListener( + method1_y_: (x, _) => result.add(x), + method2_y_: (x, _) => result.add(x), + method3_y_: (x, _) => result.add(x), + method4_y_: (x, _) => result.add(x), + method5_y_: (x, _) => result.add(x), + method6_y_: (x, _) => result.add(x), + method7_y_: (x, _) => result.add(x), + method8_y_: (x, _) => result.add(x), + method9_y_: (x, _) => result.add(x), + method10_y_: (x, _) => result.add(x), ); + EventOrderTest.countTo1000OnNewThread_(protocol); + while (result.length < 1000) { await Future.delayed(Duration(milliseconds: 10)); } diff --git a/pkgs/ffigen/test/native_objc_test/event_order_test.h b/pkgs/ffigen/test/native_objc_test/event_order_test.h index 2ac26a079..91ab5b795 100644 --- a/pkgs/ffigen/test/native_objc_test/event_order_test.h +++ b/pkgs/ffigen/test/native_objc_test/event_order_test.h @@ -4,32 +4,23 @@ #import -// 10 listeners with different signatures. Only the first arg is actually used -// in this test. -typedef void (^Listener1)(int32_t, int8_t); -typedef void (^Listener2)(int32_t, int16_t); -typedef void (^Listener3)(int32_t, int32_t); -typedef void (^Listener4)(int32_t, int64_t); -typedef void (^Listener5)(int32_t, uint8_t); -typedef void (^Listener6)(int32_t, uint16_t); -typedef void (^Listener7)(int32_t, uint32_t); -typedef void (^Listener8)(int32_t, uint64_t); -typedef void (^Listener9)(int32_t, double); -typedef void (^Listener10)(int32_t, float); +@protocol EventOrderProtocol +@required +- (void) method1:(int32_t)x y:(int8_t)y; +- (void) method2:(int32_t)x y:(int16_t)y; +- (void) method3:(int32_t)x y:(int32_t)y; +- (void) method4:(int32_t)x y:(int64_t)y; +- (void) method5:(int32_t)x y:(uint8_t)y; +- (void) method6:(int32_t)x y:(uint16_t)y; +- (void) method7:(int32_t)x y:(uint32_t)y; +- (void) method8:(int32_t)x y:(uint64_t)y; +- (void) method9:(int32_t)x y:(double)y; +- (void) method10:(int32_t)x y:(float)y; +@end @interface EventOrderTest { } -+(void)countTo1000OnNewThread: - (Listener1)listener1 - _: (Listener2)listener2 - _: (Listener3)listener3 - _: (Listener4)listener4 - _: (Listener5)listener5 - _: (Listener6)listener6 - _: (Listener7)listener7 - _: (Listener8)listener8 - _: (Listener9)listener9 - _: (Listener10)listener10; ++(void)countTo1000OnNewThread: (id) protocol; @end diff --git a/pkgs/ffigen/test/native_objc_test/event_order_test.m b/pkgs/ffigen/test/native_objc_test/event_order_test.m index b54d40f69..c32ac6cf5 100644 --- a/pkgs/ffigen/test/native_objc_test/event_order_test.m +++ b/pkgs/ffigen/test/native_objc_test/event_order_test.m @@ -6,29 +6,19 @@ @implementation EventOrderTest -+(void)countTo1000OnNewThread: - (Listener1)listener1 - _: (Listener2)listener2 - _: (Listener3)listener3 - _: (Listener4)listener4 - _: (Listener5)listener5 - _: (Listener6)listener6 - _: (Listener7)listener7 - _: (Listener8)listener8 - _: (Listener9)listener9 - _: (Listener10)listener10 { ++(void)countTo1000OnNewThread: (id) protocol { return [[[NSThread alloc] initWithBlock:^{ for (int32_t i = 0; i < 1000; i += 10) { - listener1(i + 1, 0); - listener2(i + 2, 0); - listener3(i + 3, 0); - listener4(i + 4, 0); - listener5(i + 5, 0); - listener6(i + 6, 0); - listener7(i + 7, 0); - listener8(i + 8, 0); - listener9(i + 9, 0); - listener10(i + 10, 0); + [protocol method1: i + 1 y: 0]; + [protocol method2: i + 2 y: 0]; + [protocol method3: i + 3 y: 0]; + [protocol method4: i + 4 y: 0]; + [protocol method5: i + 5 y: 0]; + [protocol method6: i + 6 y: 0]; + [protocol method7: i + 7 y: 0]; + [protocol method8: i + 8 y: 0]; + [protocol method9: i + 9 y: 0]; + [protocol method10: i + 10 y: 0]; } }] start]; }