Skip to content

Commit 71720fd

Browse files
committed
add reflect reference tests
1 parent 9a71df2 commit 71720fd

File tree

1 file changed

+284
-0
lines changed

1 file changed

+284
-0
lines changed

crates/bevy_mod_scripting_core/src/bindings/reference.rs

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ impl ReflectReference {
8080
})
8181
}
8282

83+
/// Create a new reference to a value by allocating it.
84+
///
85+
/// You can retrieve the allocator from the world using [`WorldGuard::allocator`].
86+
/// Make sure to drop the allocator write guard before doing anything with the reference to prevent deadlocks.
87+
///
8388
pub fn new_allocated<T: PartialReflect>(
8489
value: T,
8590
allocator: &mut ReflectAllocator,
@@ -547,3 +552,282 @@ impl Iterator for ReflectRefIter {
547552
Some(result)
548553
}
549554
}
555+
556+
#[cfg(test)]
557+
mod test {
558+
use bevy::prelude::{AppTypeRegistry, World};
559+
560+
use crate::bindings::{
561+
function::script_function::AppScriptFunctionRegistry, AppReflectAllocator, WorldAccessGuard,
562+
};
563+
564+
use super::*;
565+
566+
#[derive(Reflect, Component, Debug, Clone, PartialEq)]
567+
struct Component(Vec<String>);
568+
569+
#[derive(Reflect, Resource, Debug, Clone, PartialEq)]
570+
struct Resource(Vec<String>);
571+
572+
fn setup_world() -> World {
573+
let mut world = World::default();
574+
575+
let type_registry = AppTypeRegistry::default();
576+
{
577+
let mut guard_type_registry = type_registry.write();
578+
guard_type_registry.register::<Component>();
579+
guard_type_registry.register::<Resource>();
580+
}
581+
582+
world.insert_resource(type_registry);
583+
584+
let allocator = AppReflectAllocator::default();
585+
world.insert_resource(allocator);
586+
587+
let script_function_registry = AppScriptFunctionRegistry::default();
588+
world.insert_resource(script_function_registry);
589+
590+
world
591+
}
592+
593+
#[test]
594+
fn test_component_ref() {
595+
let mut world = setup_world();
596+
597+
let entity = world
598+
.spawn(Component(vec!["hello".to_owned(), "world".to_owned()]))
599+
.id();
600+
601+
let world_guard = WorldGuard::new(WorldAccessGuard::new(&mut world));
602+
603+
let mut component_ref =
604+
ReflectReference::new_component_ref::<Component>(entity, world_guard.clone())
605+
.expect("could not create component reference");
606+
607+
// index into component
608+
assert_eq!(
609+
component_ref
610+
.tail_type_id(world_guard.clone())
611+
.unwrap()
612+
.unwrap(),
613+
TypeId::of::<Component>()
614+
);
615+
616+
component_ref
617+
.with_reflect(world_guard.clone(), |s| {
618+
let s = s.try_downcast_ref::<Component>().unwrap();
619+
assert_eq!(s, &Component(vec!["hello".to_owned(), "world".to_owned()]));
620+
})
621+
.unwrap();
622+
623+
// index into vec field
624+
component_ref.index_path(ParsedPath::parse_static(".0").unwrap());
625+
assert_eq!(
626+
component_ref
627+
.tail_type_id(world_guard.clone())
628+
.unwrap()
629+
.unwrap(),
630+
TypeId::of::<Vec<String>>()
631+
);
632+
633+
assert_eq!(
634+
component_ref
635+
.element_type_id(world_guard.clone())
636+
.unwrap()
637+
.unwrap(),
638+
TypeId::of::<String>()
639+
);
640+
641+
assert_eq!(
642+
component_ref
643+
.key_type_id(world_guard.clone())
644+
.unwrap()
645+
.unwrap(),
646+
TypeId::of::<usize>()
647+
);
648+
649+
component_ref
650+
.with_reflect(world_guard.clone(), |s| {
651+
let s = s.try_downcast_ref::<Vec<String>>().unwrap();
652+
assert_eq!(s, &vec!["hello".to_owned(), "world".to_owned()]);
653+
})
654+
.unwrap();
655+
656+
// index into vec
657+
component_ref.index_path(ParsedPath::parse_static("[0]").unwrap());
658+
659+
component_ref
660+
.with_reflect(world_guard.clone(), |s| {
661+
let s = s.try_downcast_ref::<String>().unwrap();
662+
assert_eq!(s, "hello");
663+
})
664+
.unwrap();
665+
666+
assert_eq!(
667+
component_ref
668+
.tail_type_id(world_guard.clone())
669+
.unwrap()
670+
.unwrap(),
671+
TypeId::of::<String>()
672+
);
673+
}
674+
675+
#[test]
676+
fn test_resource_ref() {
677+
let mut world = setup_world();
678+
679+
world.insert_resource(Resource(vec!["hello".to_owned(), "world".to_owned()]));
680+
681+
let world_guard = WorldGuard::new(WorldAccessGuard::new(&mut world));
682+
683+
let mut resource_ref = ReflectReference::new_resource_ref::<Resource>(world_guard.clone())
684+
.expect("could not create resource reference");
685+
686+
// index into resource
687+
assert_eq!(
688+
resource_ref
689+
.tail_type_id(world_guard.clone())
690+
.unwrap()
691+
.unwrap(),
692+
TypeId::of::<Resource>()
693+
);
694+
695+
resource_ref
696+
.with_reflect(world_guard.clone(), |s| {
697+
let s = s.try_downcast_ref::<Resource>().unwrap();
698+
assert_eq!(s, &Resource(vec!["hello".to_owned(), "world".to_owned()]));
699+
})
700+
.unwrap();
701+
702+
// index into vec field
703+
resource_ref.index_path(ParsedPath::parse_static(".0").unwrap());
704+
assert_eq!(
705+
resource_ref
706+
.tail_type_id(world_guard.clone())
707+
.unwrap()
708+
.unwrap(),
709+
TypeId::of::<Vec<String>>()
710+
);
711+
712+
assert_eq!(
713+
resource_ref
714+
.element_type_id(world_guard.clone())
715+
.unwrap()
716+
.unwrap(),
717+
TypeId::of::<String>()
718+
);
719+
720+
assert_eq!(
721+
resource_ref
722+
.key_type_id(world_guard.clone())
723+
.unwrap()
724+
.unwrap(),
725+
TypeId::of::<usize>()
726+
);
727+
728+
resource_ref
729+
.with_reflect(world_guard.clone(), |s| {
730+
let s = s.try_downcast_ref::<Vec<String>>().unwrap();
731+
assert_eq!(s, &vec!["hello".to_owned(), "world".to_owned()]);
732+
})
733+
.unwrap();
734+
735+
// index into vec
736+
resource_ref.index_path(ParsedPath::parse_static("[0]").unwrap());
737+
738+
resource_ref
739+
.with_reflect(world_guard.clone(), |s| {
740+
let s = s.try_downcast_ref::<String>().unwrap();
741+
assert_eq!(s, "hello");
742+
})
743+
.unwrap();
744+
745+
assert_eq!(
746+
resource_ref
747+
.tail_type_id(world_guard.clone())
748+
.unwrap()
749+
.unwrap(),
750+
TypeId::of::<String>()
751+
);
752+
}
753+
754+
#[test]
755+
fn test_allocation_ref() {
756+
let mut world = setup_world();
757+
758+
let value = Component(vec!["hello".to_owned(), "world".to_owned()]);
759+
760+
let world_guard = WorldGuard::new(WorldAccessGuard::new(&mut world));
761+
let allocator = world_guard.allocator();
762+
let mut allocator_write = allocator.write();
763+
let mut allocation_ref = ReflectReference::new_allocated(value, &mut allocator_write);
764+
drop(allocator_write);
765+
766+
// index into component
767+
assert_eq!(
768+
allocation_ref
769+
.tail_type_id(world_guard.clone())
770+
.unwrap()
771+
.unwrap(),
772+
TypeId::of::<Component>()
773+
);
774+
775+
allocation_ref
776+
.with_reflect(world_guard.clone(), |s| {
777+
let s = s.try_downcast_ref::<Component>().unwrap();
778+
assert_eq!(s, &Component(vec!["hello".to_owned(), "world".to_owned()]));
779+
})
780+
.unwrap();
781+
782+
// index into vec field
783+
allocation_ref.index_path(ParsedPath::parse_static(".0").unwrap());
784+
assert_eq!(
785+
allocation_ref
786+
.tail_type_id(world_guard.clone())
787+
.unwrap()
788+
.unwrap(),
789+
TypeId::of::<Vec<String>>()
790+
);
791+
792+
assert_eq!(
793+
allocation_ref
794+
.element_type_id(world_guard.clone())
795+
.unwrap()
796+
.unwrap(),
797+
TypeId::of::<String>()
798+
);
799+
800+
assert_eq!(
801+
allocation_ref
802+
.key_type_id(world_guard.clone())
803+
.unwrap()
804+
.unwrap(),
805+
TypeId::of::<usize>()
806+
);
807+
808+
allocation_ref
809+
.with_reflect(world_guard.clone(), |s| {
810+
let s = s.try_downcast_ref::<Vec<String>>().unwrap();
811+
assert_eq!(s, &vec!["hello".to_owned(), "world".to_owned()]);
812+
})
813+
.unwrap();
814+
815+
// index into vec
816+
allocation_ref.index_path(ParsedPath::parse_static("[0]").unwrap());
817+
818+
allocation_ref
819+
.with_reflect(world_guard.clone(), |s| {
820+
let s = s.try_downcast_ref::<String>().unwrap();
821+
assert_eq!(s, "hello");
822+
})
823+
.unwrap();
824+
825+
assert_eq!(
826+
allocation_ref
827+
.tail_type_id(world_guard.clone())
828+
.unwrap()
829+
.unwrap(),
830+
TypeId::of::<String>()
831+
);
832+
}
833+
}

0 commit comments

Comments
 (0)