Files
hcie-rust-v3.05/hcie-history/tests/history_state.rs
T

171 lines
4.5 KiB
Rust
Raw Normal View History

2026-07-09 02:59:53 +03:00
use hcie_history::{HistoryManager, UndoableAction};
use hcie_protocol::Layer;
struct SetPixelAction {
layer_idx: usize,
old_color: [u8; 4],
new_color: [u8; 4],
}
impl UndoableAction<Vec<Layer>> for SetPixelAction {
fn undo(&mut self, layers: &mut Vec<Layer>) {
if let Some(layer) = layers.get_mut(self.layer_idx) {
layer.set_pixel(0, 0, self.old_color);
}
}
fn redo(&mut self, layers: &mut Vec<Layer>) {
if let Some(layer) = layers.get_mut(self.layer_idx) {
layer.set_pixel(0, 0, self.new_color);
}
}
fn description(&self) -> String {
"SetPixel".to_string()
}
}
fn make_layer() -> Layer {
Layer::new_transparent("test", 10, 10)
}
#[test]
fn test_history_new_is_empty() {
let hist = HistoryManager::<Vec<Layer>>::new(10);
assert_eq!(hist.len(), 0);
assert!(!hist.can_undo());
assert!(!hist.can_redo());
assert_eq!(hist.current_index(), -1);
}
#[test]
fn test_history_push_undo_redo() {
let mut layers = vec![make_layer()];
let mut hist = HistoryManager::<Vec<Layer>>::new(10);
hist.push(Box::new(SetPixelAction {
2026-07-21 04:25:23 +03:00
layer_idx: 0,
old_color: [0; 4],
new_color: [255, 0, 0, 255],
2026-07-09 02:59:53 +03:00
}));
hist.push(Box::new(SetPixelAction {
2026-07-21 04:25:23 +03:00
layer_idx: 0,
old_color: [255, 0, 0, 255],
new_color: [0, 255, 0, 255],
2026-07-09 02:59:53 +03:00
}));
assert!(hist.can_undo());
assert!(!hist.can_redo());
hist.undo(&mut layers);
assert_eq!(layers[0].get_pixel(0, 0), [255, 0, 0, 255]);
assert!(hist.can_redo());
hist.redo(&mut layers);
assert_eq!(layers[0].get_pixel(0, 0), [0, 255, 0, 255]);
}
#[test]
fn test_history_undo_twice_is_stable() {
let mut layers = vec![make_layer()];
let mut hist = HistoryManager::<Vec<Layer>>::new(10);
hist.push(Box::new(SetPixelAction {
2026-07-21 04:25:23 +03:00
layer_idx: 0,
old_color: [0; 4],
new_color: [255; 4],
2026-07-09 02:59:53 +03:00
}));
hist.undo(&mut layers);
hist.undo(&mut layers);
assert!(!hist.can_undo(), "should reach bottom");
}
#[test]
fn test_history_redo_twice_is_stable() {
let mut layers = vec![make_layer()];
let mut hist = HistoryManager::<Vec<Layer>>::new(10);
hist.push(Box::new(SetPixelAction {
2026-07-21 04:25:23 +03:00
layer_idx: 0,
old_color: [0; 4],
new_color: [255; 4],
2026-07-09 02:59:53 +03:00
}));
hist.undo(&mut layers);
hist.redo(&mut layers);
hist.redo(&mut layers);
assert!(!hist.can_redo(), "should reach top");
}
#[test]
fn test_history_max_steps() {
let _layers = vec![make_layer()];
let mut hist = HistoryManager::<Vec<Layer>>::new(3);
for i in 0..10 {
hist.push(Box::new(SetPixelAction {
layer_idx: 0,
old_color: [0; 4],
new_color: [i; 4],
}));
}
assert_eq!(hist.len(), 3, "should cap at max_steps=3");
}
#[test]
fn test_history_new_action_truncates_redo() {
let mut layers = vec![make_layer()];
let mut hist = HistoryManager::<Vec<Layer>>::new(10);
hist.push(Box::new(SetPixelAction {
2026-07-21 04:25:23 +03:00
layer_idx: 0,
old_color: [0; 4],
new_color: [1; 4],
2026-07-09 02:59:53 +03:00
}));
hist.push(Box::new(SetPixelAction {
2026-07-21 04:25:23 +03:00
layer_idx: 0,
old_color: [1; 4],
new_color: [2; 4],
2026-07-09 02:59:53 +03:00
}));
hist.undo(&mut layers);
assert!(hist.can_redo());
hist.push(Box::new(SetPixelAction {
2026-07-21 04:25:23 +03:00
layer_idx: 0,
old_color: [1; 4],
new_color: [3; 4],
2026-07-09 02:59:53 +03:00
}));
assert!(!hist.can_redo(), "new action should truncate redo stack");
}
#[test]
fn test_history_jump_to() {
let mut layers = vec![make_layer()];
let mut hist = HistoryManager::<Vec<Layer>>::new(10);
hist.push(Box::new(SetPixelAction {
2026-07-21 04:25:23 +03:00
layer_idx: 0,
old_color: [0; 4],
new_color: [1; 4],
2026-07-09 02:59:53 +03:00
}));
hist.push(Box::new(SetPixelAction {
2026-07-21 04:25:23 +03:00
layer_idx: 0,
old_color: [1; 4],
new_color: [2; 4],
2026-07-09 02:59:53 +03:00
}));
hist.push(Box::new(SetPixelAction {
2026-07-21 04:25:23 +03:00
layer_idx: 0,
old_color: [2; 4],
new_color: [3; 4],
2026-07-09 02:59:53 +03:00
}));
hist.jump_to(-1, &mut layers);
assert!(!hist.can_undo(), "jump to -1 should be at bottom");
2026-07-21 04:25:23 +03:00
assert!(
hist.can_redo(),
"jump to -1 should allow replaying the first entry"
);
2026-07-09 02:59:53 +03:00
assert_eq!(layers[0].get_pixel(0, 0), [0; 4]);
}
#[test]
fn test_entry_description() {
let mut hist = HistoryManager::<Vec<Layer>>::new(10);
hist.push(Box::new(SetPixelAction {
2026-07-21 04:25:23 +03:00
layer_idx: 0,
old_color: [0; 4],
new_color: [255; 4],
2026-07-09 02:59:53 +03:00
}));
assert_eq!(hist.entry_description(0), Some("SetPixel".to_string()));
assert_eq!(hist.entry_description(99), None);
}