- Rename `macros` crate to `libmarathon-macros` for better discoverability on crates.io - Update all imports from `macros::` to `libmarathon_macros::` - Add crates.io metadata (description, license, repository, homepage, etc.) - Bump version to 0.1.1 - Add version requirement for libmarathon-macros dependency
173 lines
5.0 KiB
Rust
173 lines
5.0 KiB
Rust
/// Basic tests for the #[synced] attribute macro
|
|
use bevy::prelude::*;
|
|
|
|
// Test 1: Basic struct with synced attribute compiles
|
|
#[libmarathon_macros::synced]
|
|
struct Health {
|
|
current: f32,
|
|
}
|
|
|
|
#[test]
|
|
fn test_health_compiles() {
|
|
let health = Health { current: 100.0 };
|
|
assert_eq!(health.current, 100.0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_health_has_component_trait() {
|
|
// The synced macro should automatically derive Component
|
|
let health = Health { current: 100.0 };
|
|
|
|
// Can insert into Bevy world
|
|
let mut world = World::new();
|
|
let entity = world.spawn(health).id();
|
|
|
|
// Can query it back
|
|
let health_ref = world.get::<Health>(entity).unwrap();
|
|
assert_eq!(health_ref.current, 100.0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_health_rkyv_serialization() {
|
|
let health = Health { current: 100.0 };
|
|
|
|
// Test rkyv serialization (which the synced macro adds)
|
|
let bytes = rkyv::to_bytes::<rkyv::rancor::Failure>(&health)
|
|
.expect("Should serialize with rkyv");
|
|
|
|
let deserialized: Health = rkyv::from_bytes::<Health, rkyv::rancor::Failure>(&bytes)
|
|
.expect("Should deserialize with rkyv");
|
|
|
|
assert_eq!(deserialized.current, health.current);
|
|
}
|
|
|
|
#[test]
|
|
fn test_health_is_clone_and_copy() {
|
|
let health = Health { current: 100.0 };
|
|
|
|
// Test Clone
|
|
let cloned = health.clone();
|
|
assert_eq!(cloned.current, health.current);
|
|
|
|
// Test Copy (implicit through assignment)
|
|
let copied = health;
|
|
assert_eq!(copied.current, health.current);
|
|
|
|
// Original still valid after copy
|
|
assert_eq!(health.current, 100.0);
|
|
}
|
|
|
|
// Test 2: Struct with multiple fields
|
|
#[libmarathon_macros::synced]
|
|
struct Position {
|
|
x: f32,
|
|
y: f32,
|
|
}
|
|
|
|
#[test]
|
|
fn test_position_compiles() {
|
|
let pos = Position { x: 10.0, y: 20.0 };
|
|
assert_eq!(pos.x, 10.0);
|
|
assert_eq!(pos.y, 20.0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_position_rkyv_serialization() {
|
|
let pos = Position { x: 10.0, y: 20.0 };
|
|
|
|
let bytes = rkyv::to_bytes::<rkyv::rancor::Failure>(&pos)
|
|
.expect("Should serialize with rkyv");
|
|
|
|
let deserialized: Position = rkyv::from_bytes::<Position, rkyv::rancor::Failure>(&bytes)
|
|
.expect("Should deserialize with rkyv");
|
|
|
|
assert_eq!(deserialized.x, pos.x);
|
|
assert_eq!(deserialized.y, pos.y);
|
|
}
|
|
|
|
#[test]
|
|
fn test_position_in_bevy_world() {
|
|
let pos = Position { x: 10.0, y: 20.0 };
|
|
|
|
let mut world = World::new();
|
|
let entity = world.spawn(pos).id();
|
|
|
|
let pos_ref = world.get::<Position>(entity).unwrap();
|
|
assert_eq!(pos_ref.x, 10.0);
|
|
assert_eq!(pos_ref.y, 20.0);
|
|
}
|
|
|
|
// Test 3: Component registration in type registry
|
|
// This test verifies that the inventory::submit! generated by the macro works
|
|
#[test]
|
|
fn test_component_registry_has_health() {
|
|
use libmarathon::persistence::ComponentTypeRegistry;
|
|
|
|
let registry = ComponentTypeRegistry::init();
|
|
|
|
// The macro should have registered Health
|
|
let type_id = std::any::TypeId::of::<Health>();
|
|
let discriminant = registry.get_discriminant(type_id);
|
|
|
|
assert!(discriminant.is_some(), "Health should be registered in ComponentTypeRegistry");
|
|
|
|
// Check the type name
|
|
let type_name = registry.get_type_name(discriminant.unwrap());
|
|
assert_eq!(type_name, Some("Health"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_component_registry_has_position() {
|
|
use libmarathon::persistence::ComponentTypeRegistry;
|
|
|
|
let registry = ComponentTypeRegistry::init();
|
|
|
|
let type_id = std::any::TypeId::of::<Position>();
|
|
let discriminant = registry.get_discriminant(type_id);
|
|
|
|
assert!(discriminant.is_some(), "Position should be registered in ComponentTypeRegistry");
|
|
|
|
// Check the type name
|
|
let type_name = registry.get_type_name(discriminant.unwrap());
|
|
assert_eq!(type_name, Some("Position"));
|
|
}
|
|
|
|
// Test 4: End-to-end serialization via ComponentTypeRegistry
|
|
#[test]
|
|
fn test_registry_serialization_roundtrip() {
|
|
use libmarathon::persistence::ComponentTypeRegistry;
|
|
|
|
let mut world = World::new();
|
|
let entity = world.spawn(Health { current: 75.0 }).id();
|
|
|
|
let registry = ComponentTypeRegistry::init();
|
|
let type_id = std::any::TypeId::of::<Health>();
|
|
let discriminant = registry.get_discriminant(type_id).unwrap();
|
|
|
|
// Serialize using the registry
|
|
let serialize_fn = registry.get_discriminant(type_id)
|
|
.and_then(|disc| {
|
|
// Get serializer from the registry internals
|
|
// We'll use the serialization method from the registry
|
|
let serializer = world.get::<Health>(entity).map(|component| {
|
|
rkyv::to_bytes::<rkyv::rancor::Failure>(component)
|
|
.expect("Should serialize")
|
|
.to_vec()
|
|
});
|
|
serializer
|
|
})
|
|
.expect("Should serialize Health component");
|
|
|
|
// Deserialize using the registry
|
|
let deserialize_fn = registry.get_deserialize_fn(discriminant)
|
|
.expect("Should have deserialize function");
|
|
|
|
let boxed = deserialize_fn(&serialize_fn)
|
|
.expect("Should deserialize Health component");
|
|
|
|
let health = boxed.downcast::<Health>()
|
|
.expect("Should downcast to Health");
|
|
|
|
assert_eq!(health.current, 75.0);
|
|
}
|