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
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct HexMaze {
|
||||
tiles: HashMap<Hex, HexTile>,
|
||||
layout: HexLayout,
|
||||
@ -77,19 +77,181 @@ impl HexMaze {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn maze() {
|
||||
let layout = HexLayout::default();
|
||||
let mut maze = HexMaze::new(layout);
|
||||
fn new_maze() {
|
||||
let maze = HexMaze::default();
|
||||
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;
|
||||
|
||||
maze.add_tile(coord);
|
||||
assert!(maze.get_tile(&coord).is_some());
|
||||
// Operations on non-existent tile
|
||||
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);
|
||||
assert!(maze
|
||||
.get_walls(&coord)
|
||||
.unwrap()
|
||||
.has(EdgeDirection::FLAT_TOP_LEFT));
|
||||
// Adding wall to non-existent tile should not panic
|
||||
maze.add_wall(coord, EdgeDirection::FLAT_TOP);
|
||||
}
|
||||
|
||||
/* #[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
|
||||
}
|
||||
}
|
||||
|
||||
#[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)]
|
||||
mod tests {
|
||||
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);
|
||||
assert!(!walls.has(EdgeDirection::FLAT_TOP));
|
||||
|
||||
// Add back and verify
|
||||
walls.add(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