test: add primitive tests

This commit is contained in:
Kristofers Solo 2024-11-06 11:39:04 +02:00
parent 2e2d4525ec
commit a06ddaa740
4 changed files with 440 additions and 15 deletions

View File

View File

@ -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"
);
}
}
}

View File

@ -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"
);
}
}
}

View File

@ -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);
}
}