mirror of
https://github.com/kristoferssolo/hexlab.git
synced 2025-10-21 19:40:34 +00:00
test: add primitive tests
This commit is contained in:
parent
2e2d4525ec
commit
a06ddaa740
184
src/maze.rs
184
src/maze.rs
@ -6,7 +6,7 @@ use super::{HexTile, Walls};
|
|||||||
|
|
||||||
/// Represents a hexagonal maze with tiles and walls
|
/// Represents a hexagonal maze with tiles and walls
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct HexMaze {
|
pub struct HexMaze {
|
||||||
tiles: HashMap<Hex, HexTile>,
|
tiles: HashMap<Hex, HexTile>,
|
||||||
layout: HexLayout,
|
layout: HexLayout,
|
||||||
@ -77,19 +77,181 @@ impl HexMaze {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn maze() {
|
fn new_maze() {
|
||||||
let layout = HexLayout::default();
|
let maze = HexMaze::default();
|
||||||
let mut maze = HexMaze::new(layout);
|
assert!(maze.is_empty(), "New maze should be empty");
|
||||||
|
assert_eq!(maze.len(), 0, "New maze should have zero tiles");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn add_tile() {
|
||||||
|
let mut maze = HexMaze::default();
|
||||||
|
let coords = [Hex::ZERO, Hex::new(1, -1), Hex::new(-1, 1)];
|
||||||
|
|
||||||
|
// Add tiles
|
||||||
|
for &coord in &coords {
|
||||||
|
maze.add_tile(coord);
|
||||||
|
assert!(
|
||||||
|
maze.get_tile(&coord).is_some(),
|
||||||
|
"Tile should exist after adding"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
maze.len(),
|
||||||
|
coords.len(),
|
||||||
|
"Maze should contain all added tiles"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn wall_operations() {
|
||||||
|
let mut maze = HexMaze::default();
|
||||||
|
let coord = Hex::ZERO;
|
||||||
|
maze.add_tile(coord);
|
||||||
|
|
||||||
|
// Test adding walls
|
||||||
|
let directions = [
|
||||||
|
EdgeDirection::FLAT_TOP,
|
||||||
|
EdgeDirection::FLAT_BOTTOM,
|
||||||
|
EdgeDirection::POINTY_TOP_RIGHT,
|
||||||
|
];
|
||||||
|
|
||||||
|
for &direction in &directions {
|
||||||
|
maze.add_wall(coord, direction);
|
||||||
|
assert!(
|
||||||
|
maze.get_walls(&coord).unwrap().has(direction),
|
||||||
|
"Wall should exist after adding"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tile_iteration() {
|
||||||
|
let mut maze = HexMaze::default();
|
||||||
|
let coords = [Hex::ZERO, Hex::new(1, 0), Hex::new(0, 1)];
|
||||||
|
|
||||||
|
// Add tiles
|
||||||
|
for &coord in &coords {
|
||||||
|
maze.add_tile(coord);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test iterator
|
||||||
|
let collected = maze.tiles().map(|(_, tile)| tile).collect::<Vec<_>>();
|
||||||
|
assert_eq!(
|
||||||
|
collected.len(),
|
||||||
|
coords.len(),
|
||||||
|
"Iterator should yield all tiles"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn maze_clone() {
|
||||||
|
let mut maze = HexMaze::default();
|
||||||
|
let coord = Hex::ZERO;
|
||||||
|
maze.add_tile(coord);
|
||||||
|
maze.add_wall(coord, EdgeDirection::FLAT_TOP);
|
||||||
|
|
||||||
|
// Test cloning
|
||||||
|
let cloned_maze = maze.clone();
|
||||||
|
assert_eq!(
|
||||||
|
maze.len(),
|
||||||
|
cloned_maze.len(),
|
||||||
|
"Cloned maze should have same size"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
cloned_maze
|
||||||
|
.get_walls(&coord)
|
||||||
|
.unwrap()
|
||||||
|
.has(EdgeDirection::FLAT_TOP),
|
||||||
|
"Cloned maze should preserve wall state"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty_tile_operations() {
|
||||||
|
let mut maze = HexMaze::default();
|
||||||
let coord = Hex::ZERO;
|
let coord = Hex::ZERO;
|
||||||
|
|
||||||
maze.add_tile(coord);
|
// Operations on non-existent tile
|
||||||
assert!(maze.get_tile(&coord).is_some());
|
assert!(
|
||||||
|
maze.get_tile(&coord).is_none(),
|
||||||
|
"Should return None for non-existent tile"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
maze.get_walls(&coord).is_none(),
|
||||||
|
"Should return None for non-existent walls"
|
||||||
|
);
|
||||||
|
|
||||||
maze.add_wall(coord, EdgeDirection::FLAT_TOP_LEFT);
|
// Adding wall to non-existent tile should not panic
|
||||||
assert!(maze
|
maze.add_wall(coord, EdgeDirection::FLAT_TOP);
|
||||||
.get_walls(&coord)
|
}
|
||||||
.unwrap()
|
|
||||||
.has(EdgeDirection::FLAT_TOP_LEFT));
|
/* #[test]
|
||||||
|
fn multiple_tile_operations() {
|
||||||
|
let mut maze = HexMaze::default();
|
||||||
|
let coord = Hex::ZERO;
|
||||||
|
|
||||||
|
// Add same tile multiple times
|
||||||
|
maze.add_tile(coord);
|
||||||
|
let first_tile = maze.get_tile(&coord).unwrap();
|
||||||
|
maze.add_tile(coord);
|
||||||
|
let second_tile = maze.get_tile(&coord).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
first_tile, second_tile,
|
||||||
|
"Repeated add_tile should update existing tile"
|
||||||
|
);
|
||||||
|
assert_eq!(maze.len(), 1, "Repeated add_tile should not increase size");
|
||||||
|
} */
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn maze_boundaries() {
|
||||||
|
let mut maze = HexMaze::default();
|
||||||
|
let extreme_coords = [
|
||||||
|
Hex::new(i32::MAX, i32::MIN),
|
||||||
|
Hex::new(i32::MIN, i32::MAX),
|
||||||
|
Hex::new(0, i32::MAX),
|
||||||
|
Hex::new(0, i32::MIN),
|
||||||
|
Hex::new(i32::MAX, 0),
|
||||||
|
Hex::new(i32::MIN, 0),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Test with extreme coordinates
|
||||||
|
for &coord in &extreme_coords {
|
||||||
|
maze.add_tile(coord);
|
||||||
|
assert!(
|
||||||
|
maze.get_tile(&coord).is_some(),
|
||||||
|
"Should handle extreme coordinates"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn iterator_consistency() {
|
||||||
|
let mut maze = HexMaze::default();
|
||||||
|
let coords = [Hex::ZERO, Hex::new(1, -1), Hex::new(-1, 1)];
|
||||||
|
|
||||||
|
// Add tiles
|
||||||
|
for &coord in &coords {
|
||||||
|
maze.add_tile(coord);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify iterator
|
||||||
|
let iter_coords = maze.tiles().map(|(coord, _)| *coord).collect::<Vec<_>>();
|
||||||
|
assert_eq!(
|
||||||
|
iter_coords.len(),
|
||||||
|
coords.len(),
|
||||||
|
"Iterator should yield all coordinates"
|
||||||
|
);
|
||||||
|
|
||||||
|
for coord in coords {
|
||||||
|
assert!(
|
||||||
|
iter_coords.contains(&coord),
|
||||||
|
"Iterator should contain all added coordinates"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
158
src/tile.rs
158
src/tile.rs
@ -26,3 +26,161 @@ impl HexTile {
|
|||||||
&self.walls
|
&self.walls
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use hexx::EdgeDirection;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_tile() {
|
||||||
|
let pos = Hex::ZERO;
|
||||||
|
let tile = HexTile::new(pos);
|
||||||
|
|
||||||
|
assert_eq!(tile.pos, pos, "Position should match constructor argument");
|
||||||
|
assert_eq!(
|
||||||
|
tile.walls,
|
||||||
|
Walls::default(),
|
||||||
|
"Walls should be initialized to default"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tile_walls_accessor() {
|
||||||
|
let pos = Hex::new(1, -1);
|
||||||
|
let tile = HexTile::new(pos);
|
||||||
|
|
||||||
|
// Test walls accessor method
|
||||||
|
let walls_ref = tile.walls();
|
||||||
|
assert_eq!(
|
||||||
|
walls_ref, &tile.walls,
|
||||||
|
"Walls accessor should return reference to walls"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tile_modification() {
|
||||||
|
let pos = Hex::new(2, 3);
|
||||||
|
let mut tile = HexTile::new(pos);
|
||||||
|
|
||||||
|
// Modify walls
|
||||||
|
tile.walls.remove(EdgeDirection::FLAT_TOP);
|
||||||
|
assert!(
|
||||||
|
!tile.walls.has(EdgeDirection::FLAT_TOP),
|
||||||
|
"Wall should be removed"
|
||||||
|
);
|
||||||
|
|
||||||
|
tile.walls.add(EdgeDirection::FLAT_TOP);
|
||||||
|
assert!(
|
||||||
|
tile.walls.has(EdgeDirection::FLAT_TOP),
|
||||||
|
"Wall should be added back"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tile_copy() {
|
||||||
|
let pos = Hex::new(-1, 2);
|
||||||
|
let tile = HexTile::new(pos);
|
||||||
|
|
||||||
|
// Test Copy trait
|
||||||
|
let copied_tile = tile;
|
||||||
|
assert_eq!(tile, copied_tile, "Copied tile should equal original");
|
||||||
|
|
||||||
|
// Verify both tiles are still usable
|
||||||
|
assert_eq!(
|
||||||
|
tile.pos, copied_tile.pos,
|
||||||
|
"Positions should match after copy"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
tile.walls, copied_tile.walls,
|
||||||
|
"Walls should match after copy"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tile_clone() {
|
||||||
|
let pos = Hex::new(0, -2);
|
||||||
|
let tile = HexTile::new(pos);
|
||||||
|
|
||||||
|
// Test Clone trait
|
||||||
|
let cloned_tile = tile.clone();
|
||||||
|
assert_eq!(tile, cloned_tile, "Cloned tile should equal original");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tile_debug() {
|
||||||
|
let pos = Hex::ZERO;
|
||||||
|
let tile = HexTile::new(pos);
|
||||||
|
|
||||||
|
// Test Debug trait
|
||||||
|
let debug_string = format!("{:?}", tile);
|
||||||
|
assert!(
|
||||||
|
debug_string.contains("HexTile"),
|
||||||
|
"Debug output should contain struct name"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn different_positions() {
|
||||||
|
let positions = [Hex::ZERO, Hex::new(1, 0), Hex::new(-1, 1), Hex::new(2, -2)];
|
||||||
|
|
||||||
|
// Create tiles at different positions
|
||||||
|
let tiles = positions
|
||||||
|
.iter()
|
||||||
|
.map(|&pos| HexTile::new(pos))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// Verify each tile has correct position
|
||||||
|
for (tile, &pos) in tiles.iter().zip(positions.iter()) {
|
||||||
|
assert_eq!(
|
||||||
|
tile.pos, pos,
|
||||||
|
"Tile position should match constructor argument"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tile_equality() {
|
||||||
|
let pos1 = Hex::new(1, 1);
|
||||||
|
let pos2 = Hex::new(1, 1);
|
||||||
|
let pos3 = Hex::new(2, 1);
|
||||||
|
|
||||||
|
let tile1 = HexTile::new(pos1);
|
||||||
|
let tile2 = HexTile::new(pos2);
|
||||||
|
let tile3 = HexTile::new(pos3);
|
||||||
|
|
||||||
|
assert_eq!(tile1, tile2, "Tiles with same position should be equal");
|
||||||
|
assert_ne!(
|
||||||
|
tile1, tile3,
|
||||||
|
"Tiles with different positions should not be equal"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test with modified walls
|
||||||
|
let mut tile4 = HexTile::new(pos1);
|
||||||
|
tile4.walls.remove(EdgeDirection::FLAT_TOP);
|
||||||
|
assert_ne!(
|
||||||
|
tile1, tile4,
|
||||||
|
"Tiles with different walls should not be equal"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hex_boundaries() {
|
||||||
|
// Test with extreme coordinate values
|
||||||
|
let extreme_positions = [
|
||||||
|
Hex::new(i32::MAX, i32::MIN),
|
||||||
|
Hex::new(i32::MIN, i32::MAX),
|
||||||
|
Hex::new(0, i32::MAX),
|
||||||
|
Hex::new(i32::MIN, 0),
|
||||||
|
];
|
||||||
|
|
||||||
|
for pos in extreme_positions {
|
||||||
|
let tile = HexTile::new(pos);
|
||||||
|
assert_eq!(
|
||||||
|
tile.pos, pos,
|
||||||
|
"Tile should handle extreme coordinate values"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
113
src/walls.rs
113
src/walls.rs
@ -69,15 +69,120 @@ impl Default for Walls {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
|
||||||
fn walls() {
|
|
||||||
let mut walls = Walls::new();
|
|
||||||
assert!(walls.has(EdgeDirection::FLAT_TOP));
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_walls() {
|
||||||
|
let walls = Walls::new();
|
||||||
|
// All walls should be present by default
|
||||||
|
for direction in EdgeDirection::iter() {
|
||||||
|
assert!(
|
||||||
|
walls.has(direction),
|
||||||
|
"Wall should exist in direction {:?}",
|
||||||
|
direction
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn add_remove_single_wall() {
|
||||||
|
let mut walls = Walls::new();
|
||||||
|
|
||||||
|
// Remove and verify each wall
|
||||||
walls.remove(EdgeDirection::FLAT_TOP);
|
walls.remove(EdgeDirection::FLAT_TOP);
|
||||||
assert!(!walls.has(EdgeDirection::FLAT_TOP));
|
assert!(!walls.has(EdgeDirection::FLAT_TOP));
|
||||||
|
|
||||||
|
// Add back and verify
|
||||||
walls.add(EdgeDirection::FLAT_TOP);
|
walls.add(EdgeDirection::FLAT_TOP);
|
||||||
assert!(walls.has(EdgeDirection::FLAT_TOP));
|
assert!(walls.has(EdgeDirection::FLAT_TOP));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multiple_operations() {
|
||||||
|
let mut walls = Walls::new();
|
||||||
|
|
||||||
|
// Remove multiple walls
|
||||||
|
walls.remove(EdgeDirection::FLAT_TOP);
|
||||||
|
walls.remove(EdgeDirection::FLAT_BOTTOM);
|
||||||
|
|
||||||
|
// Verify removed walls
|
||||||
|
assert!(!walls.has(EdgeDirection::FLAT_TOP));
|
||||||
|
assert!(!walls.has(EdgeDirection::FLAT_BOTTOM));
|
||||||
|
|
||||||
|
// Verify other walls still exist
|
||||||
|
assert!(walls.has(EdgeDirection::FLAT_TOP_RIGHT));
|
||||||
|
assert!(walls.has(EdgeDirection::FLAT_TOP_LEFT));
|
||||||
|
|
||||||
|
// Add back one wall
|
||||||
|
walls.add(EdgeDirection::FLAT_TOP);
|
||||||
|
assert!(walls.has(EdgeDirection::FLAT_TOP));
|
||||||
|
assert!(!walls.has(EdgeDirection::FLAT_BOTTOM));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bit_patterns() {
|
||||||
|
let mut walls = Walls::new();
|
||||||
|
assert_eq!(
|
||||||
|
walls.as_bits(),
|
||||||
|
0b111111,
|
||||||
|
"Initial state should have all walls"
|
||||||
|
);
|
||||||
|
|
||||||
|
walls.remove(EdgeDirection::FLAT_BOTTOM_RIGHT);
|
||||||
|
assert_eq!(walls.as_bits() & 0b000001, 0, "First bit should be cleared");
|
||||||
|
|
||||||
|
walls.add(EdgeDirection::FLAT_BOTTOM_RIGHT);
|
||||||
|
assert_eq!(walls.as_bits() & 0b000001, 1, "First bit should be set");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn remove_all_walls() {
|
||||||
|
let mut walls = Walls::new();
|
||||||
|
|
||||||
|
// Remove all walls
|
||||||
|
for direction in EdgeDirection::iter() {
|
||||||
|
walls.remove(direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify all walls are removed
|
||||||
|
assert_eq!(walls.as_bits(), 0, "All walls should be removed");
|
||||||
|
|
||||||
|
// Verify each direction
|
||||||
|
for direction in EdgeDirection::iter() {
|
||||||
|
assert!(
|
||||||
|
!walls.has(direction),
|
||||||
|
"No wall should exist in direction {:?}",
|
||||||
|
direction
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deref_operations() {
|
||||||
|
let mut walls = Walls::new();
|
||||||
|
|
||||||
|
// Test Deref
|
||||||
|
let bits: &u8 = walls.deref();
|
||||||
|
assert_eq!(*bits, 0b111111);
|
||||||
|
|
||||||
|
// Test DerefMut
|
||||||
|
*walls.deref_mut() = 0;
|
||||||
|
assert_eq!(walls.as_bits(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn idempotent_operations() {
|
||||||
|
let mut walls = Walls::new();
|
||||||
|
|
||||||
|
// Adding twice shouldn't change the result
|
||||||
|
walls.add(EdgeDirection::FLAT_TOP);
|
||||||
|
let first_add = walls.as_bits();
|
||||||
|
walls.add(EdgeDirection::FLAT_TOP);
|
||||||
|
assert_eq!(walls.as_bits(), first_add);
|
||||||
|
|
||||||
|
// Removing twice shouldn't change the result
|
||||||
|
walls.remove(EdgeDirection::FLAT_TOP);
|
||||||
|
let first_remove = walls.as_bits();
|
||||||
|
walls.remove(EdgeDirection::FLAT_TOP);
|
||||||
|
assert_eq!(walls.as_bits(), first_remove);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user