diff --git a/pkgs/objective_c/hook/build.dart b/pkgs/objective_c/hook/build.dart index 94c2b6331..4ab0bee7d 100644 --- a/pkgs/objective_c/hook/build.dart +++ b/pkgs/objective_c/hook/build.dart @@ -15,7 +15,6 @@ const assetName = 'objective_c.dylib'; // TODO(https://github.com/dart-lang/native/issues/2272): Remove this from the // main build. -const testFiles = ['test/util.c']; final logger = Logger('') ..level = Level.INFO @@ -59,14 +58,6 @@ void main(List args) async { } } - // Only include the test utils on mac OS. They use memory functions that - // aren't supported on iOS, like mach_vm_region. We don't need them on iOS - // anyway since we only run memory tests on mac. - if (os == OS.macOS) { - cFiles.addAll( - testFiles.map((f) => input.packageRoot.resolve(f).toFilePath()), - ); - } final sysroot = sdkPath(codeConfig); final minVersion = minOSVersion(codeConfig); diff --git a/pkgs/objective_c/pubspec.yaml b/pkgs/objective_c/pubspec.yaml index ca4a7fd60..f3e8bca10 100644 --- a/pkgs/objective_c/pubspec.yaml +++ b/pkgs/objective_c/pubspec.yaml @@ -45,3 +45,5 @@ dependency_overrides: path: ../hooks native_toolchain_c: path: ../native_toolchain_c + objective_c_helper: + path: ../objective_c_helper diff --git a/pkgs/objective_c/test/autorelease_test.dart b/pkgs/objective_c/test/autorelease_test.dart index 12f64ce6e..3130fcb36 100644 --- a/pkgs/objective_c/test/autorelease_test.dart +++ b/pkgs/objective_c/test/autorelease_test.dart @@ -10,7 +10,6 @@ import 'dart:ffi'; import 'package:objective_c/objective_c.dart'; import 'package:test/test.dart'; - import 'util.dart'; void main() { diff --git a/pkgs/objective_c/test/interface_lists_test.dart b/pkgs/objective_c/test/interface_lists_test.dart index 19837be51..a76402e6b 100644 --- a/pkgs/objective_c/test/interface_lists_test.dart +++ b/pkgs/objective_c/test/interface_lists_test.dart @@ -11,7 +11,6 @@ import 'dart:io'; import 'package:ffigen/src/code_generator/objc_built_in_types.dart'; import 'package:path/path.dart' as p; import 'package:test/test.dart'; - import 'util.dart'; // The default expect error message for sets isn't very useful. In the common diff --git a/pkgs/objective_c/test/nsdictionary_test.dart b/pkgs/objective_c/test/nsdictionary_test.dart index e7afb6d2e..852adab47 100644 --- a/pkgs/objective_c/test/nsdictionary_test.dart +++ b/pkgs/objective_c/test/nsdictionary_test.dart @@ -10,7 +10,6 @@ import 'dart:ffi'; import 'package:objective_c/objective_c.dart'; import 'package:test/test.dart'; - import 'util.dart'; void main() { diff --git a/pkgs/objective_c/test/observer_test.dart b/pkgs/objective_c/test/observer_test.dart index c5e17a676..59b2c4f75 100644 --- a/pkgs/objective_c/test/observer_test.dart +++ b/pkgs/objective_c/test/observer_test.dart @@ -10,7 +10,6 @@ import 'dart:ffi'; import 'package:objective_c/objective_c.dart'; import 'package:test/test.dart'; - import 'util.dart'; void main() { diff --git a/pkgs/objective_c/test/util.dart b/pkgs/objective_c/test/util.dart index d0300e8eb..0ec8e32bb 100644 --- a/pkgs/objective_c/test/util.dart +++ b/pkgs/objective_c/test/util.dart @@ -32,37 +32,4 @@ void doGC() { calloc.free(gcNow); } -@Native)>(isLeaf: true, symbol: 'isReadableMemory') -external int _isReadableMemory(Pointer ptr); - -@Native)>( - isLeaf: true, - symbol: 'getObjectRetainCount', -) -external int _getObjectRetainCount(Pointer object); - -int objectRetainCount(Pointer object) { - if (_isReadableMemory(object.cast()) == 0) return 0; - final header = object.cast().value; - - // package:objective_c's isValidObject function internally calls - // object_getClass then isValidClass. But object_getClass can occasionally - // crash for invalid objects. This masking logic is a simplified version of - // what object_getClass does internally. This is less likely to crash, but - // more likely to break due to ObjC runtime updates, which is a reasonable - // trade off to make in tests where we're explicitly calling it many times - // on invalid objects. In package:objective_c's case, it doesn't matter so - // much if isValidObject crashes, since it's a best effort attempt to give a - // nice stack trace before the real crash, but it would be a problem if - // isValidObject broke due to a runtime update. - // These constants are the ISA_MASK macro defined in runtime/objc-private.h. - const maskX64 = 0x00007ffffffffff8; - const maskArm = 0x0000000ffffffff8; - final mask = Abi.current() == Abi.macosX64 ? maskX64 : maskArm; - final clazz = Pointer.fromAddress(header & mask); - - if (!internal_for_testing.isValidClass(clazz)) return 0; - return _getObjectRetainCount(object.cast()); -} - String pkgDir = findPackageRoot('objective_c').toFilePath(); diff --git a/pkgs/objective_c/test/util.c b/pkgs/objective_c_helper/lib/src/util.c similarity index 100% rename from pkgs/objective_c/test/util.c rename to pkgs/objective_c_helper/lib/src/util.c diff --git a/pkgs/objective_c_helper/lib/src/util.dart b/pkgs/objective_c_helper/lib/src/util.dart new file mode 100644 index 000000000..66db4c12a --- /dev/null +++ b/pkgs/objective_c_helper/lib/src/util.dart @@ -0,0 +1,37 @@ +import 'dart:ffi'; +import 'package:objective_c/objective_c.dart'; +import 'package:objective_c/src/internal.dart' as internal_for_testing show isValidClass; + +@Native)>(isLeaf: true, symbol: 'isReadableMemory') +external int _isReadableMemory(Pointer ptr); + +@Native)>( + isLeaf: true, + symbol: 'getObjectRetainCount', +) +external int _getObjectRetainCount(Pointer object); + +int objectRetainCount(Pointer object) { + if (_isReadableMemory(object.cast()) == 0) return 0; + final header = object.cast().value; + + // package:objective_c's isValidObject function internally calls + // object_getClass then isValidClass. But object_getClass can occasionally + // crash for invalid objects. This masking logic is a simplified version of + // what object_getClass does internally. This is less likely to crash, but + // more likely to break due to ObjC runtime updates, which is a reasonable + // trade off to make in tests where we're explicitly calling it many times + // on invalid objects. In package:objective_c's case, it doesn't matter so + // much if isValidObject crashes, since it's a best effort attempt to give a + // nice stack trace before the real crash, but it would be a problem if + // isValidObject broke due to a runtime update. + // These constants are the ISA_MASK macro defined in runtime/objc-private.h. + const maskX64 = 0x00007ffffffffff8; + const maskArm = 0x0000000ffffffff8; + final mask = Abi.current() == Abi.macosX64 ? maskX64 : maskArm; + final clazz = Pointer.fromAddress(header & mask); + + if (!internal_for_testing.isValidClass(clazz)) return 0; + return _getObjectRetainCount(object.cast()); +} + diff --git a/pkgs/objective_c_helper/pubspec.yaml b/pkgs/objective_c_helper/pubspec.yaml new file mode 100644 index 000000000..21dbe4165 --- /dev/null +++ b/pkgs/objective_c_helper/pubspec.yaml @@ -0,0 +1,7 @@ +name: objective_c_helper +description: Helper package for objective_c tests +version: 0.0.1 +environment: + sdk: ">=2.19.0 <3.0.0" +dependencies: {} +dev_dependencies: {}