//! Integration Tests for BSP dungeon generation #[cfg(test)] mod tests { use dungeon::*; use pos::Pos; use rand::{Rng, SeedableRng}; /// Generate a set of test seeds for reproducibility with a seeded RNG fn generate_test_seeds(seed: u64) -> Vec { let mut rng = rand::rngs::StdRng::seed_from_u64(seed); // Generate 100 random u64 seeds (0..100).map(|_| rng.random_range(0..u64::MAX)).collect() } /// Basic integration test for BSP generation #[test] fn test_bsp_integration() { let test_seeds = generate_test_seeds(123456); for seed in test_seeds { let (tiles, player_start) = bsp::generate(seed); // Basic integration test: ensure we get valid data assert!(!tiles.is_empty()); assert!(player_start.x() < map::MAP_SIZE); assert!(player_start.y() < map::MAP_SIZE); } } /// Test that BSP-generated floors have a valid player start #[test] fn test_bsp_player_start() { let test_seeds = generate_test_seeds(654321); for seed in test_seeds { let (tiles, player_start) = bsp::generate(seed); // Ensure player start is within bounds assert!(player_start.x() < map::MAP_SIZE); assert!(player_start.y() < map::MAP_SIZE); // Ensure player start is a room tile let idx = player_start.idx(); assert_eq!(tiles[idx], map::Tile::Room); } } /// Test that BSP-generated floors have at least one room tile #[test] fn test_bsp_2_or_more_rooms() { let test_seeds = generate_test_seeds(111222); for seed in test_seeds { let (tiles, _player_start) = bsp::generate(seed); // Ensure we have at least one room tile let room_count = tiles .iter() .filter(|&&tile| tile == map::Tile::Room) .count(); assert!( room_count >= 1, "Expected at least one room tile, found {room_count}" ); } } /// Test that BSP-generated floors have walls on the borders #[test] fn test_bsp_walls_on_borders() { let test_seeds = generate_test_seeds(777888); for seed in test_seeds { let (tiles, _player_start) = bsp::generate(seed); // Go through all tiles, and ensure border tiles are walls for x in 0..map::MAP_SIZE { for y in 0..map::MAP_SIZE { let pos = Pos::new(x, y).unwrap_or(const_pos!(1, 1)); if pos.is_border() { let idx = pos.idx(); assert_eq!( tiles[idx], map::Tile::Wall, "Expected wall at border position {pos:?}" ); } } } } } // Test that BSP-generated floors are reproducible with the same seed #[test] fn test_bsp_reproducibility() { let test_seeds = generate_test_seeds(111111); for seed in test_seeds { let (tiles1, player_start1) = bsp::generate(seed); let (tiles2, player_start2) = bsp::generate(seed); assert_eq!(tiles1, tiles2, "Tiles differ for same seed {seed}"); assert_eq!( player_start1, player_start2, "Player starts differ for same seed {seed}" ); } } // Test that all `air` tiles (`Tile::Room` and `Tile::Hallway`) are reachable from the player start #[test] fn test_bsp_all_air_tiles_reachable() { let test_seeds = generate_test_seeds(333444); for seed in test_seeds { check_air_tiles_reachable(seed); } } // Helper function to check that all air tiles are reachable from player start fn check_air_tiles_reachable(seed: u64) { let (tiles, player_start) = bsp::generate(seed); // BFS to find all reachable air tiles let mut visited = vec![false; tiles.len()]; let mut queue = vec![player_start]; visited[player_start.idx()] = true; while let Some(pos) = queue.pop() { for neighbor in pos.neighbors() { let idx = neighbor.idx(); if !visited[idx] && tiles[idx] != map::Tile::Wall { visited[idx] = true; queue.push(neighbor); } } } for (i, &tile) in tiles.iter().enumerate() { if tile == map::Tile::Room || tile == map::Tile::Hallway { assert!(visited[i], "Unreachable air tile at index {i}"); } } } }