From 2878b391ab2b7b979b02f00e0879a75045ddb493 Mon Sep 17 00:00:00 2001 From: Marcin Kulik Date: Tue, 24 Jun 2025 20:01:15 +0200 Subject: [PATCH] Add tests for alis module --- src/alis.rs | 251 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) diff --git a/src/alis.rs b/src/alis.rs index d173448..af9ab7c 100644 --- a/src/alis.rs +++ b/src/alis.rs @@ -158,3 +158,254 @@ impl EventSerializer { rel_time } } + +#[cfg(test)] +mod tests { + use rgb::RGB8; + + use super::*; + use crate::tty::{TtySize, TtyTheme}; + + #[test] + fn test_serialize_init_with_theme_and_seed() { + let mut serializer = EventSerializer(0); + + let theme = TtyTheme { + fg: rgb(255, 255, 255), + bg: rgb(0, 0, 0), + palette: vec![ + rgb(0, 0, 0), // Black + rgb(128, 0, 0), // Dark Red + rgb(0, 128, 0), // Dark Green + rgb(128, 128, 0), // Dark Yellow + rgb(0, 0, 128), // Dark Blue + rgb(128, 0, 128), // Dark Magenta + rgb(0, 128, 128), // Dark Cyan + rgb(192, 192, 192), // Light Gray + rgb(128, 128, 128), // Dark Gray + rgb(255, 0, 0), // Bright Red + rgb(0, 255, 0), // Bright Green + rgb(255, 255, 0), // Bright Yellow + rgb(0, 0, 255), // Bright Blue + rgb(255, 0, 255), // Bright Magenta + rgb(0, 255, 255), // Bright Cyan + rgb(255, 255, 255), // White + ], + }; + + let event = Event::Init( + 42, + 1000, + TtySize(180, 24), + Some(theme), + "terminal seed".to_string(), + ); + + let bytes = serializer.serialize_event(event); + + let mut expected = vec![ + 0x01, // Init event type + 0x2A, // id (42) in LEB128 + 0xE8, 0x07, // time (1000) in LEB128 + 0xB4, 0x01, // cols (180) in LEB128 + 0x18, // rows (24) in LEB128 + 16, // theme - 16 colors + 255, 255, 255, // foreground RGB + 0, 0, 0, // background RGB + ]; + + // Add palette colors (16 colors * 3 bytes each) + expected.extend_from_slice(&[ + 0, 0, 0, // Black + 128, 0, 0, // Dark Red + 0, 128, 0, // Dark Green + 128, 128, 0, // Dark Yellow + 0, 0, 128, // Dark Blue + 128, 0, 128, // Dark Magenta + 0, 128, 128, // Dark Cyan + 192, 192, 192, // Light Gray + 128, 128, 128, // Dark Gray + 255, 0, 0, // Bright Red + 0, 255, 0, // Bright Green + 255, 255, 0, // Bright Yellow + 0, 0, 255, // Bright Blue + 255, 0, 255, // Bright Magenta + 0, 255, 255, // Bright Cyan + 255, 255, 255, // White + ]); + + expected.push(0x0D); // init string length (13) + expected.extend_from_slice(b"terminal seed"); // init string + + assert_eq!(bytes, expected); + assert_eq!(serializer.0, 1000); + } + + #[test] + fn test_serialize_init_without_theme_nor_seed() { + let mut serializer = EventSerializer(0); + let event = Event::Init(1, 500, TtySize(120, 130), None, "".to_string()); + let bytes = serializer.serialize_event(event); + + let expected = vec![ + 0x01, // Init event type + 0x01, // id (1) in LEB128 + 0xF4, 0x03, // relative time (500) in LEB128 + 0x78, // cols (120) in LEB128 + 0x82, 0x01, // rows (130) in LEB128 + 0x00, // no theme flag + 0x00, // init string length (0) in LEB128 + ]; + + assert_eq!(bytes, expected); + assert_eq!(serializer.0, 500); + } + + #[test] + fn test_serialize_output() { + let mut serializer = EventSerializer(1000); + let event = Event::Output(5, 1200, "Hello δΈ–η•Œ 🌍".to_string()); + let bytes = serializer.serialize_event(event); + + let mut expected = vec![ + b'o', // Output event type + 0x05, // id (5) in LEB128 + 0xC8, 0x01, // relative time (200) in LEB128 + 0x11, // text length in bytes + ]; + + expected.extend_from_slice("Hello δΈ–η•Œ 🌍".as_bytes()); // text bytes + + assert_eq!(bytes, expected); + assert_eq!(serializer.0, 1200); // Time updated to 1200 + } + + #[test] + fn test_serialize_input() { + let mut serializer = EventSerializer(500); + let event = Event::Input(1000000, 750, "x".to_string()); + let bytes = serializer.serialize_event(event); + + let expected = vec![ + b'i', // Input event type + 0xC0, 0x84, 0x3D, // id (1000000) in LEB128 + 0xFA, 0x01, // relative time (250) in LEB128 + 0x01, // text length (1) in LEB128 + b'x', // text + ]; + + assert_eq!(bytes, expected); + assert_eq!(serializer.0, 750); + } + + #[test] + fn test_serialize_resize() { + let mut serializer = EventSerializer(2000); + let event = Event::Resize(15, 2100, TtySize(180, 50)); + let bytes = serializer.serialize_event(event); + + let expected = vec![ + b'r', // Resize event type + 0x0F, // id (15) in LEB128 + 0x64, // relative time (100) in LEB128 + 0xB4, 0x01, // cols (180) in LEB128 + 0x32, // rows (50) in LEB128 + ]; + + assert_eq!(bytes, expected); + assert_eq!(serializer.0, 2100); + } + + #[test] + fn test_serialize_marker_with_label() { + let mut serializer = EventSerializer(3000); + let event = Event::Marker(20, 3500, "checkpoint".to_string()); + let bytes = serializer.serialize_event(event); + + let expected = vec![ + b'm', // Marker event type + 0x14, // id (20) in LEB128 + 0xF4, 0x03, // relative time (500) in LEB128 + 0x0A, // label length (10) in LEB128 + ]; + let mut expected = expected; + expected.extend_from_slice(b"checkpoint"); // label bytes + + assert_eq!(bytes, expected); + assert_eq!(serializer.0, 3500); + } + + #[test] + fn test_serialize_marker_without_label() { + let mut serializer = EventSerializer(3000); + let event = Event::Marker(2, 3300, "".to_string()); + let bytes = serializer.serialize_event(event); + + let expected = vec![ + b'm', // Marker event type + 0x02, // id (2) in LEB128 + 0xAC, 0x02, // relative time (300) in LEB128 + 0x00, // label length (0) + ]; + + assert_eq!(bytes, expected); + } + + #[test] + fn test_serialize_exit_positive_status() { + let mut serializer = EventSerializer(4000); + let event = Event::Exit(25, 4200, 0); + let bytes = serializer.serialize_event(event); + + let expected = vec![ + b'x', // Exit event type + 0x19, // id (25) in LEB128 + 0xC8, 0x01, // relative time (200) in LEB128 + 0x00, // status (0) in LEB128 + ]; + + assert_eq!(bytes, expected); + assert_eq!(serializer.0, 4200); + } + + #[test] + fn test_serialize_exit_negative_status() { + let mut serializer = EventSerializer(5000); + let event = Event::Exit(30, 5300, -1); + let bytes = serializer.serialize_event(event); + + let expected = vec![ + b'x', // Exit event type + 0x1E, // id (30) in LEB128 + 0xAC, 0x02, // relative time (300) in LEB128 + 0x00, // status (clamped to 0) in LEB128 + ]; + + assert_eq!(bytes, expected); + assert_eq!(serializer.0, 5300); + } + + #[test] + fn test_subsequent_event_lower_time() { + let mut serializer = EventSerializer(1000); + + // First event at time 1000 + let event1 = Event::Output(1, 1000, "first".to_string()); + let bytes1 = serializer.serialize_event(event1); + + // Verify first event uses time 0 (1000 - 1000) + assert_eq!(bytes1[2], 0x00); // relative time should be 0 + assert_eq!(serializer.0, 1000); + + // Second event with lower timestamp (wraparound risk case) + let event2 = Event::Output(2, 500, "second".to_string()); + let bytes2 = serializer.serialize_event(event2); + + assert_eq!(bytes2[2], 0x00); // relative time should be 0 + assert_eq!(serializer.0, 1000); // Time should remain 1000 (not decrease) + } + + fn rgb(r: u8, g: u8, b: u8) -> RGB8 { + RGB8::new(r, g, b) + } +}