use ponko::*;
use std::alloc::{GlobalAlloc, Layout, System};
use std::cell::Cell;
struct CountingAllocator;
thread_local! {
static TRACK: Cell<bool> = const { Cell::new(false) };
static ALLOCS: Cell<usize> = const { Cell::new(0) };
}
fn record_allocation() {
if TRACK.try_with(Cell::get).unwrap_or(false) {
let _ = ALLOCS.try_with(|n| n.set(n.get() + 1));
}
}
unsafe impl GlobalAlloc for CountingAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
record_allocation();
unsafe { System.alloc(layout) }
}
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
record_allocation();
unsafe { System.alloc_zeroed(layout) }
}
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, size: usize) -> *mut u8 {
record_allocation();
unsafe { System.realloc(ptr, layout, size) }
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
unsafe { System.dealloc(ptr, layout) }
}
}
#[global_allocator]
static ALLOCATOR: CountingAllocator = CountingAllocator;
#[test]
fn input_events_and_action_queries_allocate_nothing_after_installation() {
let mut frames = 0;
Game::new("allocations", 1, 1)
.system(move |ctx: &mut Ctx| {
if frames == 0 {
ALLOCS.set(0);
TRACK.set(true);
}
let pad = Gamepad::from_slot(0).unwrap();
for i in 0..128 {
ctx.feed_input(InputEvent::Key(Key::Space, i % 2 == 0));
ctx.feed_input(InputEvent::GamepadAxis(pad, GamepadAxis::LeftStickX, 0.6));
std::hint::black_box(ctx.action_down("jump"));
std::hint::black_box(ctx.action_pressed("jump"));
std::hint::black_box(ctx.action_released("jump"));
std::hint::black_box(ctx.action_axis("throttle"));
std::hint::black_box(ctx.action_axis2("move"));
}
frames += 1;
if frames == 3 {
TRACK.set(false);
assert_eq!(ALLOCS.get(), 0);
}
})
.run_headless(3, |ctx| {
let mut map = ActionMap::default();
let pad = Gamepad::from_slot(0).unwrap();
map.set("jump", Action::Button(vec![ButtonBinding::Key(Key::Space)]));
map.set(
"throttle",
Action::Axis(vec![AxisBinding::Gamepad {
pad,
axis: GamepadAxis::RightTrigger,
deadzone: 0.2,
}]),
);
map.set(
"move",
Action::Axis2(vec![Axis2Binding::Gamepad {
pad,
stick: GamepadStick::Left,
deadzone: 0.2,
}]),
);
ctx.set_actions(map);
});
}