use std::{thread::sleep, time::Duration};
use anyhow::{bail, ensure};
use hecs::{Query, World};
use hecs_schedule::*;
#[test]
fn has() {
let mut world = World::default();
world.spawn((67_i32, 7.0_f32));
let subworld = SubWorldRef::<(&i32, &mut f32)>::new(&world);
assert!(subworld.has::<&i32>());
assert!(!subworld.has::<&mut i32>());
assert!(subworld.has::<&f32>());
assert!(subworld.has::<&mut f32>());
assert!(subworld.has_all::<(&i32, &f32)>());
assert!(!subworld.has_all::<(&mut i32, &f32)>());
assert!(subworld.has_all::<(&mut f32, &i32)>());
assert!(!subworld.has_all::<(&mut f32, &i32, &u32)>());
}
#[test]
fn query() {
let mut world = World::default();
world.spawn((67_i32, 7.0_f32));
let entity = world.spawn((42_i32, 3.1415_f32));
let subworld = SubWorldRef::<(&i32, &mut f32)>::new(&world);
let mut query = subworld.query::<(&i32, &mut f32)>();
query
.iter()
.for_each(|(e, val)| eprintln!("Entity {:?}: {:?}", e, val));
assert!(subworld.try_query::<(&mut i32, &f32)>().is_err());
let val = subworld.try_get::<i32>(entity).unwrap();
assert_eq!(*val, 42);
}
#[test]
fn custom_query() {
let mut world = World::default();
#[derive(Query, Debug)]
struct Foo<'a> {
_a: &'a i32,
_b: &'a mut f32,
}
world.spawn((67_i32, 7.0_f32));
let entity = world.spawn((42_i32, 3.1415_f32));
let subworld = SubWorldRef::<(Foo, &&'static str)>::new(&world);
assert!(subworld.has_all::<(&i32, &f32)>());
assert!(!subworld.has_all::<(&mut i32, &f32)>());
assert!(subworld.has_all::<(&mut f32, &i32)>());
assert!(subworld.has_all::<(&&'static str, &i32)>());
assert!(!subworld.has_all::<(&mut &'static str, &i32)>());
assert!(!subworld.has_all::<(&mut f32, &i32, &u32)>());
let mut query = subworld.try_query_one::<&i32>(entity).unwrap();
let val = query.get().unwrap();
assert_eq!(*val, 42);
let mut query = subworld.query::<Foo>();
query
.iter()
.for_each(|(e, val)| eprintln!("Entity {:?}: {:?}", e, val));
assert!(subworld.try_query::<(&mut i32, &f32)>().is_err());
let val = subworld.try_get::<i32>(entity).unwrap();
assert_eq!(*val, 42);
}
#[test]
#[should_panic]
fn fail_query() {
let mut world = World::default();
let entity = world.spawn((42_i32, 3.1415_f32));
let subworld = SubWorldRef::<(&i32, &f32)>::new(&world);
let val = subworld.try_get::<u64>(entity).unwrap();
assert_eq!(*val, 42);
}
#[test]
fn commandbuffer() {
let mut world = World::default();
let e = world.reserve_entity();
let mut cmds = CommandBuffer::default();
cmds.spawn((42_i32, 7.0_f32));
cmds.insert(e, (89_usize, 42_i32, String::from("Foo")));
cmds.remove_one::<usize>(e);
cmds.execute(&mut world);
assert!(world
.query::<(&i32, &f32)>()
.iter()
.map(|(_, val)| val)
.eq([(&42, &7.0)]))
}
#[test]
fn test_schedule() {
let mut world = World::default();
let a = world.spawn((789,));
let b = world.reserve_entity();
let mut schedule = Schedule::builder();
#[derive(Default, Debug, Clone, Copy, PartialEq)]
struct Foo {
val: i32,
}
let mut foo = Foo { val: 42 };
let system = move |w: SubWorld<&i32>| -> anyhow::Result<()> {
ensure!(*w.try_get::<i32>(a)? == 789, "Entity did not match");
Ok(())
};
let spawn_system = move |mut cmd: Write<CommandBuffer>| {
cmd.insert(b, ("b", 8));
};
schedule.add_system(spawn_system);
schedule.add_system(system);
schedule.flush();
schedule.add_system(|mut val: Write<Foo>| {
val.val = 56;
});
schedule.add_system(move |mut cmd: Write<CommandBuffer>| {
cmd.insert_one(a, "Hello, World!");
});
schedule.add_system(
move |w: SubWorld<(&&'static str, &i32)>| -> anyhow::Result<()> {
let mut query = w.try_query_one::<(&&'static str, &i32)>(b)?;
let (name, val) = query.get()?;
ensure!(*name == "b" && *val == 8, "Entity does not match");
Ok(())
},
);
let mut schedule = schedule.build();
schedule.execute_seq((&mut world, &mut foo)).unwrap();
assert_eq!(foo, Foo { val: 56 });
}
#[test]
#[should_panic]
fn schedule_fail() {
let mut schedule = Schedule::builder()
.add_system(|| -> anyhow::Result<()> { bail!("Dummy Error") })
.build();
schedule.execute_seq(()).unwrap();
}
#[test]
fn execute_par() {
let mut val = 3;
let mut other_val = 3.0;
let observe_before = |val: Read<i32>| {
sleep(Duration::from_millis(100));
assert_eq!(*val, 3)
};
let observe_other = |val: Read<f64>| {
sleep(Duration::from_millis(100));
assert_eq!(*val, 3.0);
};
let mutate = |mut val: Write<i32>| {
sleep(Duration::from_millis(20));
*val = 5;
};
let observe_after = |val: Read<i32>| {
assert_eq!(*val, 5);
};
let mut other_schedule = Schedule::builder();
other_schedule.add_system(observe_other).add_system(mutate);
let mut schedule = Schedule::builder()
.add_system(observe_before)
.append(&mut other_schedule)
.add_system(observe_after)
.build();
eprintln!("{}", schedule.batch_info());
schedule
.execute((&mut val, &mut other_val))
.map_err(|e| eprintln!("Error {}", e))
.expect("Failed to execute schedule");
}