Skip to content

Commit 9bbbd37

Browse files
committed
Add support for assoc items
- Refactor tests - remove checking for second trait (since we do it wit associated type one), reduce number of test cases, don't double-test methods that check for godot-related DynGd interactions if it is not absolutely necessary.
1 parent 3781254 commit 9bbbd37

File tree

1 file changed

+15
-140
lines changed

1 file changed

+15
-140
lines changed

itest/rust/src/object_tests/dyn_gd_test.rs

Lines changed: 15 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -76,34 +76,14 @@ fn deal_20_damage(h: &mut dyn Health) {
7676
h.deal_damage(20);
7777
}
7878

79-
#[itest]
80-
fn dyn_gd_with_assoc_trait_creation_deref() {
81-
let node = foreign::NodeHealth::new_alloc();
82-
let original_id = node.instance_id();
83-
84-
let mut node = node.into_dyn::<dyn HealthWithAssociatedType<HealthType = u8>>();
85-
86-
let dyn_id = node.instance_id();
87-
assert_eq!(dyn_id, original_id);
88-
89-
set_health_report_to_62(&mut *node.dyn_bind_mut());
90-
assert_eq!(node.dyn_bind().get_report(), 62);
91-
92-
node.free();
93-
}
94-
95-
fn set_health_report_to_62(h: &mut dyn HealthWithAssociatedType<HealthType = u8>) {
96-
h.set_report(62);
97-
}
98-
9979
#[itest]
10080
fn dyn_gd_upcast() {
10181
let original = foreign::NodeHealth::new_alloc();
10282
let original_copy = original.clone();
10383

10484
let concrete = original.clone().into_dyn::<dyn Health>();
10585
let concrete_with_associated_type =
106-
original.into_dyn::<dyn HealthWithAssociatedType<HealthType = u8>>();
86+
original.into_dyn::<dyn HealthWithAssociatedType<HealthType = f32>>();
10787

10888
let mut node = concrete.clone().upcast::<Node>();
10989
let object = concrete.upcast::<Object>();
@@ -115,12 +95,16 @@ fn dyn_gd_upcast() {
11595

11696
// Ensure applied to the object polymorphically. Concrete object can access bind(), no dyn_bind().
11797
assert_eq!(original_copy.bind().get_hitpoints(), 75);
118-
assert_eq!(original_copy.bind().get_report(), 75);
98+
assert_eq!(original_copy.bind().get_report(), 42.0);
11999

120100
// Check also another angle (via Object). Here dyn_bind().
121101
assert_eq!(object.dyn_bind().get_hitpoints(), 75);
102+
103+
let object = concrete_with_associated_type.clone().upcast::<Object>();
104+
assert_eq!(object.dyn_bind().get_report(), 42.0);
105+
122106
// via DynGd with associated type
123-
assert_eq!(concrete_with_associated_type.dyn_bind().get_report(), 75);
107+
assert_eq!(concrete_with_associated_type.dyn_bind().get_report(), 42.0);
124108

125109
node.free();
126110
}
@@ -173,14 +157,9 @@ fn dyn_gd_debug() {
173157
let expected = format!(".:DynGd {{ id: {id}, class: RefcHealth, trait: dyn Health }}:.");
174158

175159
assert_eq!(actual, expected);
176-
}
177160

178-
#[itest]
179-
fn dyn_gd_with_associated_type_debug() {
180161
let obj: DynGd<RefcHealth, dyn HealthWithAssociatedType<HealthType = u8>> =
181-
Gd::from_object(RefcHealth { hp: 20 }).into_dyn();
182-
let id = obj.instance_id();
183-
162+
obj.into_gd().into_dyn();
184163
let actual = format!(".:{obj:?}:.");
185164
let expected = format!(".:DynGd {{ id: {id}, class: RefcHealth, trait: dyn HealthWithAssociatedType<HealthType = u8> }}:.");
186165

@@ -210,7 +189,6 @@ fn dyn_gd_with_associated_type_display() {
210189

211190
#[itest]
212191
fn dyn_gd_eq() {
213-
// Eq checks for DynGds inner objects, therefore it works the same for DynGd with associated type.
214192
let gd = Gd::from_object(RefcHealth { hp: 55 });
215193
let a: DynGd<RefcHealth, dyn Health> = gd.clone().into_dyn();
216194
let b: DynGd<RefcHealth, dyn Health> = gd.into_dyn();
@@ -227,7 +205,6 @@ fn dyn_gd_eq() {
227205

228206
#[itest]
229207
fn dyn_gd_hash() {
230-
// Hash uses DynGds inner objects therefore it works the same for DynGd with associated type.
231208
use godot::sys::hash_value;
232209

233210
let gd = Gd::from_object(RefcHealth { hp: 55 });
@@ -334,19 +311,6 @@ fn dyn_gd_pass_to_godot_api() {
334311
parent.free();
335312
}
336313

337-
#[itest]
338-
fn dyn_gd_with_associated_type_pass_to_godot_api() {
339-
let child = foreign::NodeHealth::new_alloc()
340-
.into_dyn::<dyn HealthWithAssociatedType<HealthType = u8>>();
341-
342-
let mut parent = Node::new_alloc();
343-
parent.add_child(&child);
344-
345-
assert_eq!(child.get_parent().as_ref(), Some(&parent));
346-
347-
parent.free();
348-
}
349-
350314
#[itest]
351315
fn dyn_gd_variant_conversions() {
352316
let original = Gd::from_object(RefcHealth { hp: 11 }).into_dyn::<dyn Health>();
@@ -388,48 +352,6 @@ fn dyn_gd_variant_conversions() {
388352
assert_eq!(back.instance_id(), original_id);
389353
}
390354

391-
#[itest]
392-
fn dyn_gd_with_associated_type_variant_conversions() {
393-
let original = Gd::from_object(RefcHealth { hp: 11 })
394-
.into_dyn::<dyn HealthWithAssociatedType<HealthType = u8>>();
395-
let original_id = original.instance_id();
396-
let refc = original.into_gd().upcast::<RefCounted>();
397-
398-
let variant = refc.to_variant();
399-
400-
// Convert to different levels of DynGd:
401-
402-
let back: DynGd<RefcHealth, dyn HealthWithAssociatedType<HealthType = u8>> = variant.to();
403-
assert_eq!(back.bind().get_report(), 11);
404-
assert_eq!(back.instance_id(), original_id);
405-
406-
let back: DynGd<RefCounted, dyn HealthWithAssociatedType<HealthType = u8>> = variant.to();
407-
assert_eq!(back.dyn_bind().get_report(), 11);
408-
assert_eq!(back.instance_id(), original_id);
409-
410-
let back: DynGd<Object, dyn HealthWithAssociatedType<HealthType = u8>> = variant.to();
411-
assert_eq!(back.dyn_bind().get_report(), 11);
412-
assert_eq!(back.instance_id(), original_id);
413-
414-
// convert to different DynGd
415-
416-
let other: DynGd<RefcHealth, dyn Health> = variant.to();
417-
assert_eq!(other.dyn_bind().get_hitpoints(), 11);
418-
assert_eq!(other.instance_id(), original_id);
419-
420-
// Convert to different levels of Gd:
421-
422-
let back: Gd<RefcHealth> = variant.to();
423-
assert_eq!(back.bind().get_report(), 11);
424-
assert_eq!(back.instance_id(), original_id);
425-
426-
let back: Gd<RefcHealth> = variant.to();
427-
assert_eq!(back.instance_id(), original_id);
428-
429-
let back: Gd<Object> = variant.to();
430-
assert_eq!(back.instance_id(), original_id);
431-
}
432-
433355
#[itest]
434356
fn dyn_gd_store_in_godot_array() {
435357
let a = Gd::from_object(RefcHealth { hp: 33 }).into_dyn::<dyn Health>();
@@ -447,14 +369,9 @@ fn dyn_gd_store_in_godot_array() {
447369
fn dyn_gd_with_associated_type_store_in_godot_array() {
448370
let a: DynGd<RefcHealth, dyn HealthWithAssociatedType<HealthType = u8>> =
449371
Gd::from_object(RefcHealth { hp: 33 }).into_dyn();
450-
let b = foreign::NodeHealth::new_alloc().into_dyn();
451-
452-
let array: Array<DynGd<Object, _>> = array![&a.upcast(), &b.upcast()];
453372

373+
let array: Array<DynGd<Object, _>> = array![&a.upcast()];
454374
assert_eq!(array.at(0).dyn_bind().get_report(), 33);
455-
assert_eq!(array.at(1).dyn_bind().get_report(), 42);
456-
457-
array.at(1).free();
458375
}
459376

460377
#[itest]
@@ -478,6 +395,7 @@ fn dyn_gd_error_unregistered_trait() {
478395

479396
let back =
480397
variant.try_to::<DynGd<RefcHealth, dyn HealthWithAssociatedType<HealthType = i64>>>();
398+
481399
let err = back.expect_err("DynGd::try_to() should have failed");
482400
let expected_err = {
483401
format!("trait `dyn HealthWithAssociatedType<HealthType = i64>` has not been registered with #[godot_dyn]: {gd:?}")
@@ -559,18 +477,6 @@ fn dyn_gd_free_while_dyn_bound() {
559477
obj.free();
560478
}
561479

562-
#[itest]
563-
fn dyn_gd_multiple_traits() {
564-
let obj = foreign::NodeHealth::new_alloc();
565-
let original_id = obj.instance_id();
566-
567-
let obj = obj.into_dyn::<dyn InstanceIdProvider>().upcast::<Node>();
568-
let id = obj.dyn_bind().get_id_dynamic();
569-
assert_eq!(id, original_id);
570-
571-
obj.free();
572-
}
573-
574480
// ----------------------------------------------------------------------------------------------------------------------------------------------
575481
// Example symbols
576482

@@ -657,36 +563,16 @@ impl Health for foreign::NodeHealth {
657563
}
658564
}
659565

566+
// Implementation created only to register the DynGd `HealthWithAssociatedType<HealthType=f32>` trait.
660567
#[godot_dyn]
661568
impl HealthWithAssociatedType for foreign::NodeHealth {
662-
type HealthType = u8;
569+
type HealthType = f32;
663570

664571
fn get_report(&self) -> Self::HealthType {
665-
if self.base().has_meta("hp") {
666-
self.base().get_meta("hp").to::<u8>()
667-
} else {
668-
42 // initial value, if nothing set.
669-
}
572+
42.0
670573
}
671574

672-
fn set_report(&mut self, new: Self::HealthType) {
673-
self.base_mut().set_meta("hp", &new.to_variant());
674-
}
675-
}
676-
677-
// ----------------------------------------------------------------------------------------------------------------------------------------------
678-
// Check that one class can implement two or more traits.
679-
680-
// Pointless trait, but tests access to object.
681-
trait InstanceIdProvider {
682-
fn get_id_dynamic(&self) -> InstanceId;
683-
}
684-
685-
#[godot_dyn]
686-
impl InstanceIdProvider for foreign::NodeHealth {
687-
fn get_id_dynamic(&self) -> InstanceId {
688-
self.base().instance_id()
689-
}
575+
fn set_report(&mut self, _new: Self::HealthType) {}
690576
}
691577

692578
// ----------------------------------------------------------------------------------------------------------------------------------------------
@@ -698,16 +584,5 @@ struct RefcDynGdExporter {
698584
#[var]
699585
first: Option<DynGd<Object, dyn Health>>,
700586
#[export]
701-
second: Option<DynGd<foreign::NodeHealth, dyn InstanceIdProvider>>,
702-
}
703-
704-
#[godot_dyn]
705-
impl HealthWithAssociatedType for RefcDynGdExporter {
706-
type HealthType = f32;
707-
708-
fn get_report(&self) -> Self::HealthType {
709-
1.
710-
}
711-
712-
fn set_report(&mut self, _new: Self::HealthType) {}
587+
second: Option<DynGd<foreign::NodeHealth, dyn HealthWithAssociatedType<HealthType = f32>>>,
713588
}

0 commit comments

Comments
 (0)