diff --git a/objc2/src/__macro_helpers.rs b/objc2/src/__macro_helpers.rs index 106f9a9c7..7511c9b56 100644 --- a/objc2/src/__macro_helpers.rs +++ b/objc2/src/__macro_helpers.rs @@ -151,59 +151,107 @@ mod tests { use core::ptr; - use crate::rc::{Owned, Shared}; + use crate::rc::{Owned, RcTestObject, Shared, ThreadTestData}; use crate::runtime::Object; use crate::{Encoding, RefEncode}; - #[repr(C)] - struct _NSZone { - _inner: [u8; 0], - } + #[test] + fn test_macro_alloc() { + let mut expected = ThreadTestData::current(); + let cls = RcTestObject::class(); + + let obj: Id = unsafe { msg_send_id![cls, alloc].unwrap() }; + expected.alloc += 1; + expected.assert_current(); - unsafe impl RefEncode for _NSZone { - const ENCODING_REF: Encoding<'static> = - Encoding::Pointer(&Encoding::Struct("_NSZone", &[])); + drop(obj); + expected.release += 1; + expected.dealloc += 1; + expected.assert_current(); } #[test] - fn test_macro_alloc() { - let cls = class!(NSObject); + #[cfg_attr( + all(feature = "gnustep-1-7", feature = "verify_message"), + ignore = "NSZone's encoding is quite complex on GNUStep" + )] + fn test_alloc_with_zone() { + #[repr(C)] + struct _NSZone { + _inner: [u8; 0], + } - let _obj: Option> = unsafe { msg_send_id![cls, alloc] }; + unsafe impl RefEncode for _NSZone { + const ENCODING_REF: Encoding<'static> = + Encoding::Pointer(&Encoding::Struct("_NSZone", &[])); + } + + let expected = ThreadTestData::current(); + let cls = RcTestObject::class(); let zone: *const _NSZone = ptr::null(); - let _obj: Option> = unsafe { msg_send_id![cls, allocWithZone: zone] }; + let _obj: Id = + unsafe { msg_send_id![cls, allocWithZone: zone].unwrap() }; + // `+[NSObject alloc]` delegates to `+[NSObject allocWithZone:]`, but + // `RcTestObject` only catches `alloc`. + // expected.alloc += 1; + expected.assert_current(); } #[test] fn test_macro_init() { - let cls = class!(NSObject); + let mut expected = ThreadTestData::current(); + let cls = RcTestObject::class(); - let obj: Option> = unsafe { msg_send_id![cls, alloc] }; + let obj: Option> = unsafe { msg_send_id![cls, alloc] }; + expected.alloc += 1; // Don't check allocation error - let _obj: Id = unsafe { msg_send_id![obj, init].unwrap() }; + let _obj: Id = unsafe { msg_send_id![obj, init].unwrap() }; + expected.init += 1; + expected.assert_current(); - let obj: Option> = unsafe { msg_send_id![cls, alloc] }; + let obj: Option> = unsafe { msg_send_id![cls, alloc] }; + expected.alloc += 1; // Check allocation error before init let obj = obj.unwrap(); - let _obj: Id = unsafe { msg_send_id![obj, init].unwrap() }; + let _obj: Id = unsafe { msg_send_id![obj, init].unwrap() }; + expected.init += 1; + expected.assert_current(); } #[test] fn test_macro() { - let cls = class!(NSObject); - - let _obj: Id = unsafe { msg_send_id![cls, new].unwrap() }; - - let obj = unsafe { msg_send_id![cls, alloc] }; - - let obj: Id = unsafe { msg_send_id![obj, init].unwrap() }; - - // TODO: - // let copy: Id = unsafe { msg_send_id![&obj, copy].unwrap() }; - // let mutable_copy: Id = unsafe { msg_send_id![&obj, mutableCopy].unwrap() }; - - let _desc: Option> = unsafe { msg_send_id![&obj, description] }; + let mut expected = ThreadTestData::current(); + let cls = RcTestObject::class(); + crate::rc::autoreleasepool(|_| { + let _obj: Id = unsafe { msg_send_id![cls, new].unwrap() }; + expected.alloc += 1; + expected.init += 1; + expected.assert_current(); + + let obj = unsafe { msg_send_id![cls, alloc] }; + expected.alloc += 1; + expected.assert_current(); + + let obj: Id = unsafe { msg_send_id![obj, init].unwrap() }; + expected.init += 1; + expected.assert_current(); + + // TODO: + // let copy: Id = unsafe { msg_send_id![&obj, copy].unwrap() }; + // let mutable_copy: Id = unsafe { msg_send_id![&obj, mutableCopy].unwrap() }; + + let _self: Id = unsafe { msg_send_id![&obj, self].unwrap() }; + expected.retain += 1; + expected.assert_current(); + + let _desc: Option> = + unsafe { msg_send_id![&obj, description] }; + expected.assert_current(); + }); + expected.release += 3; + expected.dealloc += 2; + expected.assert_current(); } #[test] diff --git a/objc2/src/rc/test_object.rs b/objc2/src/rc/test_object.rs index f062688b3..90d66540e 100644 --- a/objc2/src/rc/test_object.rs +++ b/objc2/src/rc/test_object.rs @@ -5,7 +5,7 @@ use std::sync::Once; use super::{Id, Owned}; use crate::declare::ClassBuilder; use crate::runtime::{Bool, Class, Object, Sel}; -use crate::{msg_send, msg_send_bool, msg_send_id}; +use crate::{msg_send, msg_send_bool}; use crate::{Encoding, Message, RefEncode}; #[derive(Debug, Clone, Default, PartialEq)] @@ -77,7 +77,7 @@ impl DerefMut for RcTestObject { } impl RcTestObject { - fn class() -> &'static Class { + pub(crate) fn class() -> &'static Class { static REGISTER_CLASS: Once = Once::new(); REGISTER_CLASS.call_once(|| { @@ -152,6 +152,7 @@ impl RcTestObject { } pub(crate) fn new() -> Id { - unsafe { msg_send_id![Self::class(), new] }.unwrap() + // Use msg_send! to test that; msg_send_id! is tested elsewhere! + unsafe { Id::new(msg_send![Self::class(), new]) }.unwrap() } }