diff --git a/tests/error.rs b/tests/error.rs new file mode 100644 index 0000000..f2cd1d3 --- /dev/null +++ b/tests/error.rs @@ -0,0 +1,158 @@ +use pacman::error::{ + AnimatedTextureError, AssetError, EntityError, GameError, GameResult, IntoGameError, MapError, OptionExt, ParseError, + ResultExt, TextureError, +}; +use std::io; + +#[test] +fn test_game_error_from_asset_error() { + let asset_error = AssetError::NotFound("test.png".to_string()); + let game_error: GameError = asset_error.into(); + assert!(matches!(game_error, GameError::Asset(_))); +} + +#[test] +fn test_game_error_from_parse_error() { + let parse_error = ParseError::UnknownCharacter('Z'); + let game_error: GameError = parse_error.into(); + assert!(matches!(game_error, GameError::MapParse(_))); +} + +#[test] +fn test_game_error_from_map_error() { + let map_error = MapError::NodeNotFound(42); + let game_error: GameError = map_error.into(); + assert!(matches!(game_error, GameError::Map(_))); +} + +#[test] +fn test_game_error_from_texture_error() { + let texture_error = TextureError::LoadFailed("Failed to load".to_string()); + let game_error: GameError = texture_error.into(); + assert!(matches!(game_error, GameError::Texture(_))); +} + +#[test] +fn test_game_error_from_entity_error() { + let entity_error = EntityError::NodeNotFound(10); + let game_error: GameError = entity_error.into(); + assert!(matches!(game_error, GameError::Entity(_))); +} + +#[test] +fn test_game_error_from_io_error() { + let io_error = io::Error::new(io::ErrorKind::NotFound, "File not found"); + let game_error: GameError = io_error.into(); + assert!(matches!(game_error, GameError::Io(_))); +} + +#[test] +fn test_texture_error_from_animated_error() { + let animated_error = AnimatedTextureError::InvalidFrameDuration(-1.0); + let texture_error: TextureError = animated_error.into(); + assert!(matches!(texture_error, TextureError::Animated(_))); +} + +#[test] +fn test_asset_error_from_io_error() { + let io_error = io::Error::new(io::ErrorKind::PermissionDenied, "Permission denied"); + let asset_error: AssetError = io_error.into(); + assert!(matches!(asset_error, AssetError::Io(_))); +} + +#[test] +fn test_parse_error_display() { + let error = ParseError::UnknownCharacter('!'); + assert_eq!(error.to_string(), "Unknown character in board: !"); + + let error = ParseError::InvalidHouseDoorCount(3); + assert_eq!(error.to_string(), "House door must have exactly 2 positions, found 3"); +} + +#[test] +fn test_entity_error_display() { + let error = EntityError::NodeNotFound(42); + assert_eq!(error.to_string(), "Node not found in graph: 42"); + + let error = EntityError::EdgeNotFound { from: 1, to: 2 }; + assert_eq!(error.to_string(), "Edge not found: from 1 to 2"); +} + +#[test] +fn test_animated_texture_error_display() { + let error = AnimatedTextureError::InvalidFrameDuration(0.0); + assert_eq!(error.to_string(), "Frame duration must be positive, got 0"); +} + +#[test] +fn test_into_game_error_trait() { + let result: Result = Err(io::Error::new(io::ErrorKind::Other, "test error")); + let game_result: GameResult = result.into_game_error(); + + assert!(game_result.is_err()); + if let Err(GameError::InvalidState(msg)) = game_result { + assert!(msg.contains("test error")); + } else { + panic!("Expected InvalidState error"); + } +} + +#[test] +fn test_into_game_error_trait_success() { + let result: Result = Ok(42); + let game_result: GameResult = result.into_game_error(); + + assert_eq!(game_result.unwrap(), 42); +} + +#[test] +fn test_option_ext_some() { + let option: Option = Some(42); + let result: GameResult = option.ok_or_game_error(|| GameError::InvalidState("Not found".to_string())); + + assert_eq!(result.unwrap(), 42); +} + +#[test] +fn test_option_ext_none() { + let option: Option = None; + let result: GameResult = option.ok_or_game_error(|| GameError::InvalidState("Not found".to_string())); + + assert!(result.is_err()); + if let Err(GameError::InvalidState(msg)) = result { + assert_eq!(msg, "Not found"); + } else { + panic!("Expected InvalidState error"); + } +} + +#[test] +fn test_result_ext_success() { + let result: Result = Ok(42); + let game_result: GameResult = result.with_context(|_| GameError::InvalidState("Context".to_string())); + + assert_eq!(game_result.unwrap(), 42); +} + +#[test] +fn test_result_ext_error() { + let result: Result = Err(io::Error::new(io::ErrorKind::Other, "original error")); + let game_result: GameResult = result.with_context(|_| GameError::InvalidState("Context error".to_string())); + + assert!(game_result.is_err()); + if let Err(GameError::InvalidState(msg)) = game_result { + assert_eq!(msg, "Context error"); + } else { + panic!("Expected InvalidState error"); + } +} + +#[test] +fn test_error_chain_conversions() { + // Test that we can convert through multiple levels + let animated_error = AnimatedTextureError::InvalidFrameDuration(-5.0); + let texture_error: TextureError = animated_error.into(); + let game_error: GameError = texture_error.into(); + + assert!(matches!(game_error, GameError::Texture(TextureError::Animated(_)))); +} diff --git a/tests/events.rs b/tests/events.rs new file mode 100644 index 0000000..7039bf0 --- /dev/null +++ b/tests/events.rs @@ -0,0 +1,117 @@ +use pacman::events::{GameCommand, GameEvent}; +use pacman::map::direction::Direction; + +#[test] +fn test_game_command_variants() { + // Test that all GameCommand variants can be created + let commands = vec![ + GameCommand::Exit, + GameCommand::MovePlayer(Direction::Up), + GameCommand::MovePlayer(Direction::Down), + GameCommand::MovePlayer(Direction::Left), + GameCommand::MovePlayer(Direction::Right), + GameCommand::ToggleDebug, + GameCommand::MuteAudio, + GameCommand::ResetLevel, + GameCommand::TogglePause, + ]; + + // Just verify they can be created and compared + assert_eq!(commands.len(), 9); + assert_eq!(commands[0], GameCommand::Exit); + assert_eq!(commands[1], GameCommand::MovePlayer(Direction::Up)); +} + +#[test] +fn test_game_command_equality() { + assert_eq!(GameCommand::Exit, GameCommand::Exit); + assert_eq!(GameCommand::ToggleDebug, GameCommand::ToggleDebug); + assert_eq!( + GameCommand::MovePlayer(Direction::Left), + GameCommand::MovePlayer(Direction::Left) + ); + + assert_ne!(GameCommand::Exit, GameCommand::ToggleDebug); + assert_ne!( + GameCommand::MovePlayer(Direction::Left), + GameCommand::MovePlayer(Direction::Right) + ); +} + +#[test] +fn test_game_command_copy_clone() { + let original = GameCommand::MovePlayer(Direction::Up); + let copied = original; + let cloned = original.clone(); + + assert_eq!(original, copied); + assert_eq!(original, cloned); + assert_eq!(copied, cloned); +} + +#[test] +fn test_game_event_variants() { + let command_event = GameEvent::Command(GameCommand::Exit); + let collision_event = GameEvent::Collision(bevy_ecs::entity::Entity::from_raw(1), bevy_ecs::entity::Entity::from_raw(2)); + + // Test that events can be created and compared + assert_eq!(command_event, GameEvent::Command(GameCommand::Exit)); + assert_ne!(command_event, collision_event); +} + +#[test] +fn test_game_command_to_game_event_conversion() { + let command = GameCommand::ToggleDebug; + let event: GameEvent = command.into(); + + assert_eq!(event, GameEvent::Command(GameCommand::ToggleDebug)); +} + +#[test] +fn test_game_command_to_game_event_conversion_all_variants() { + let commands = vec![ + GameCommand::Exit, + GameCommand::MovePlayer(Direction::Up), + GameCommand::ToggleDebug, + GameCommand::MuteAudio, + GameCommand::ResetLevel, + GameCommand::TogglePause, + ]; + + for command in commands { + let event: GameEvent = command.into(); + assert_eq!(event, GameEvent::Command(command)); + } +} + +#[test] +fn test_move_player_all_directions() { + let directions = [Direction::Up, Direction::Down, Direction::Left, Direction::Right]; + + for direction in directions { + let command = GameCommand::MovePlayer(direction); + let event: GameEvent = command.into(); + + if let GameEvent::Command(GameCommand::MovePlayer(dir)) = event { + assert_eq!(dir, direction); + } else { + panic!("Expected MovePlayer command with direction {:?}", direction); + } + } +} + +#[test] +fn test_game_event_debug_format() { + let event = GameEvent::Command(GameCommand::Exit); + let debug_str = format!("{:?}", event); + assert!(debug_str.contains("Command")); + assert!(debug_str.contains("Exit")); +} + +#[test] +fn test_game_command_debug_format() { + let command = GameCommand::MovePlayer(Direction::Left); + let debug_str = format!("{:?}", command); + assert!(debug_str.contains("MovePlayer")); + assert!(debug_str.contains("Left")); +}