Skip to content

Commit

Permalink
Add test + doc for Signal/Callable::object_id() on dead objects
Browse files Browse the repository at this point in the history
  • Loading branch information
Bromeon committed Oct 9, 2024
1 parent 666355e commit adfe6eb
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 9 deletions.
6 changes: 4 additions & 2 deletions godot-core/src/builtin/callable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,8 @@ impl Callable {

/// Returns the object on which this callable is called.
///
/// Returns `None` when this callable doesn't have any target object to call a method on, regardless of
/// if the method exists for that target or not.
/// Returns `None` when this callable doesn't have any target object to call a method on (regardless of whether the method exists for that
/// target or not). Also returns `None` if the object is dead. You can differentiate these two cases using [`object_id()`][Self::object_id].
///
/// _Godot equivalent: `get_object`_
pub fn object(&self) -> Option<Gd<Object>> {
Expand All @@ -222,6 +222,8 @@ impl Callable {
///
/// Returns `None` when this callable doesn't have any target to call a method on.
///
/// If the pointed-to object is dead, the ID will still be returned. Use [`object()`][Self::object] to check for liveness.
///
/// _Godot equivalent: `get_object_id`_
pub fn object_id(&self) -> Option<InstanceId> {
let id = self.as_inner().get_object_id();
Expand Down
5 changes: 4 additions & 1 deletion godot-core/src/builtin/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ impl Signal {

/// Returns the object to which this signal belongs.
///
/// Returns [`None`] when this signal doesn't have any object.
/// Returns [`None`] when this signal doesn't have any object, or the object is dead. You can differentiate these two situations using
/// [`object_id()`][Self::object_id].
///
/// _Godot equivalent: `get_object`_
pub fn object(&self) -> Option<Gd<Object>> {
Expand All @@ -135,6 +136,8 @@ impl Signal {
///
/// Returns [`None`] when this signal doesn't have any object.
///
/// If the pointed-to object is dead, the ID will still be returned. Use [`object()`][Self::object] to check for liveness.
///
/// _Godot equivalent: `get_object_id`_
pub fn object_id(&self) -> Option<InstanceId> {
let id = self.as_inner().get_object_id();
Expand Down
14 changes: 10 additions & 4 deletions itest/rust/src/builtin_tests/containers/callable_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,19 @@ fn callable_hash() {

#[itest]
fn callable_object_method() {
let obj = CallableTestObj::new_gd();
let callable = obj.callable("foo");
let object = CallableTestObj::new_gd();
let object_id = object.instance_id();
let callable = object.callable("foo");

assert_eq!(callable.object(), Some(obj.clone().upcast::<Object>()));
assert_eq!(callable.object_id(), Some(obj.instance_id()));
assert_eq!(callable.object(), Some(object.clone().upcast::<Object>()));
assert_eq!(callable.object_id(), Some(object_id));
assert_eq!(callable.method_name(), Some("foo".into()));

// Invalidating the object still returns the old ID, however not the object.
drop(object);
assert_eq!(callable.object_id(), Some(object_id));
assert_eq!(callable.object(), None);

assert_eq!(Callable::invalid().object(), None);
assert_eq!(Callable::invalid().object_id(), None);
assert_eq!(Callable::invalid().method_name(), None);
Expand Down
10 changes: 8 additions & 2 deletions itest/rust/src/builtin_tests/containers/signal_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,21 @@ fn signals() {
#[itest]
fn instantiate_signal() {
let mut object = RefCounted::new_gd();
let object_id = object.instance_id();

object.add_user_signal("test_signal".into());

let signal = Signal::from_object_signal(&object, "test_signal");

assert!(!signal.is_null());
assert_eq!(signal.name(), StringName::from("test_signal"));
assert_eq!(signal.object().unwrap(), object.clone().upcast());
assert_eq!(signal.object_id().unwrap(), object.instance_id());
assert_eq!(signal.object(), Some(object.clone().upcast()));
assert_eq!(signal.object_id(), Some(object_id));

// Invalidating the object still returns the old ID, however not the object.
drop(object);
assert_eq!(signal.object_id(), Some(object_id));
assert_eq!(signal.object(), None);
}

#[itest]
Expand Down

0 comments on commit adfe6eb

Please sign in to comment.