Skip to content

Commit f1ca00a

Browse files
committed
Test reference-counting properties of msg_send_id!
1 parent aed5cdd commit f1ca00a

File tree

2 files changed

+82
-33
lines changed

2 files changed

+82
-33
lines changed

objc2/src/__macro_helpers.rs

Lines changed: 78 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -151,59 +151,107 @@ mod tests {
151151

152152
use core::ptr;
153153

154-
use crate::rc::{Owned, Shared};
154+
use crate::rc::{Owned, RcTestObject, Shared, ThreadTestData};
155155
use crate::runtime::Object;
156156
use crate::{Encoding, RefEncode};
157157

158-
#[repr(C)]
159-
struct _NSZone {
160-
_inner: [u8; 0],
161-
}
158+
#[test]
159+
fn test_macro_alloc() {
160+
let mut expected = ThreadTestData::current();
161+
let cls = RcTestObject::class();
162+
163+
let obj: Id<RcTestObject, Shared> = unsafe { msg_send_id![cls, alloc].unwrap() };
164+
expected.alloc += 1;
165+
expected.assert_current();
162166

163-
unsafe impl RefEncode for _NSZone {
164-
const ENCODING_REF: Encoding<'static> =
165-
Encoding::Pointer(&Encoding::Struct("_NSZone", &[]));
167+
drop(obj);
168+
expected.release += 1;
169+
expected.dealloc += 1;
170+
expected.assert_current();
166171
}
167172

168173
#[test]
169-
fn test_macro_alloc() {
170-
let cls = class!(NSObject);
174+
#[cfg_attr(
175+
all(feature = "gnustep-1-7", feature = "verify_message"),
176+
ignore = "NSZone's encoding is quite complex on GNUStep"
177+
)]
178+
fn test_alloc_with_zone() {
179+
#[repr(C)]
180+
struct _NSZone {
181+
_inner: [u8; 0],
182+
}
171183

172-
let _obj: Option<Id<Object, Shared>> = unsafe { msg_send_id![cls, alloc] };
184+
unsafe impl RefEncode for _NSZone {
185+
const ENCODING_REF: Encoding<'static> =
186+
Encoding::Pointer(&Encoding::Struct("_NSZone", &[]));
187+
}
188+
189+
let expected = ThreadTestData::current();
190+
let cls = RcTestObject::class();
173191

174192
let zone: *const _NSZone = ptr::null();
175-
let _obj: Option<Id<Object, Owned>> = unsafe { msg_send_id![cls, allocWithZone: zone] };
193+
let _obj: Id<RcTestObject, Owned> =
194+
unsafe { msg_send_id![cls, allocWithZone: zone].unwrap() };
195+
// `+[NSObject alloc]` delegates to `+[NSObject allocWithZone:]`, but
196+
// `RcTestObject` only catches `alloc`.
197+
// expected.alloc += 1;
198+
expected.assert_current();
176199
}
177200

178201
#[test]
179202
fn test_macro_init() {
180-
let cls = class!(NSObject);
203+
let mut expected = ThreadTestData::current();
204+
let cls = RcTestObject::class();
181205

182-
let obj: Option<Id<Object, Shared>> = unsafe { msg_send_id![cls, alloc] };
206+
let obj: Option<Id<RcTestObject, Shared>> = unsafe { msg_send_id![cls, alloc] };
207+
expected.alloc += 1;
183208
// Don't check allocation error
184-
let _obj: Id<Object, Shared> = unsafe { msg_send_id![obj, init].unwrap() };
209+
let _obj: Id<RcTestObject, Shared> = unsafe { msg_send_id![obj, init].unwrap() };
210+
expected.init += 1;
211+
expected.assert_current();
185212

186-
let obj: Option<Id<Object, Shared>> = unsafe { msg_send_id![cls, alloc] };
213+
let obj: Option<Id<RcTestObject, Shared>> = unsafe { msg_send_id![cls, alloc] };
214+
expected.alloc += 1;
187215
// Check allocation error before init
188216
let obj = obj.unwrap();
189-
let _obj: Id<Object, Shared> = unsafe { msg_send_id![obj, init].unwrap() };
217+
let _obj: Id<RcTestObject, Shared> = unsafe { msg_send_id![obj, init].unwrap() };
218+
expected.init += 1;
219+
expected.assert_current();
190220
}
191221

192222
#[test]
193223
fn test_macro() {
194-
let cls = class!(NSObject);
195-
196-
let _obj: Id<Object, Owned> = unsafe { msg_send_id![cls, new].unwrap() };
197-
198-
let obj = unsafe { msg_send_id![cls, alloc] };
199-
200-
let obj: Id<Object, Owned> = unsafe { msg_send_id![obj, init].unwrap() };
201-
202-
// TODO:
203-
// let copy: Id<Object, Shared> = unsafe { msg_send_id![&obj, copy].unwrap() };
204-
// let mutable_copy: Id<Object, Shared> = unsafe { msg_send_id![&obj, mutableCopy].unwrap() };
205-
206-
let _desc: Option<Id<Object, Shared>> = unsafe { msg_send_id![&obj, description] };
224+
let mut expected = ThreadTestData::current();
225+
let cls = RcTestObject::class();
226+
crate::rc::autoreleasepool(|_| {
227+
let _obj: Id<RcTestObject, Owned> = unsafe { msg_send_id![cls, new].unwrap() };
228+
expected.alloc += 1;
229+
expected.init += 1;
230+
expected.assert_current();
231+
232+
let obj = unsafe { msg_send_id![cls, alloc] };
233+
expected.alloc += 1;
234+
expected.assert_current();
235+
236+
let obj: Id<RcTestObject, Owned> = unsafe { msg_send_id![obj, init].unwrap() };
237+
expected.init += 1;
238+
expected.assert_current();
239+
240+
// TODO:
241+
// let copy: Id<RcTestObject, Shared> = unsafe { msg_send_id![&obj, copy].unwrap() };
242+
// let mutable_copy: Id<RcTestObject, Shared> = unsafe { msg_send_id![&obj, mutableCopy].unwrap() };
243+
244+
let _self: Id<RcTestObject, Shared> = unsafe { msg_send_id![&obj, self].unwrap() };
245+
expected.retain += 1;
246+
expected.assert_current();
247+
248+
let _desc: Option<Id<RcTestObject, Shared>> =
249+
unsafe { msg_send_id![&obj, description] };
250+
expected.assert_current();
251+
});
252+
expected.release += 3;
253+
expected.dealloc += 2;
254+
expected.assert_current();
207255
}
208256

209257
#[test]

objc2/src/rc/test_object.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::sync::Once;
55
use super::{Id, Owned};
66
use crate::declare::ClassBuilder;
77
use crate::runtime::{Bool, Class, Object, Sel};
8-
use crate::{msg_send, msg_send_bool, msg_send_id};
8+
use crate::{msg_send, msg_send_bool};
99
use crate::{Encoding, Message, RefEncode};
1010

1111
#[derive(Debug, Clone, Default, PartialEq)]
@@ -77,7 +77,7 @@ impl DerefMut for RcTestObject {
7777
}
7878

7979
impl RcTestObject {
80-
fn class() -> &'static Class {
80+
pub(crate) fn class() -> &'static Class {
8181
static REGISTER_CLASS: Once = Once::new();
8282

8383
REGISTER_CLASS.call_once(|| {
@@ -152,6 +152,7 @@ impl RcTestObject {
152152
}
153153

154154
pub(crate) fn new() -> Id<Self, Owned> {
155-
unsafe { msg_send_id![Self::class(), new] }.unwrap()
155+
// Use msg_send! to test that; msg_send_id! is tested elsewhere!
156+
unsafe { Id::new(msg_send![Self::class(), new]) }.unwrap()
156157
}
157158
}

0 commit comments

Comments
 (0)