summaryrefslogtreecommitdiff
path: root/model
diff options
context:
space:
mode:
authorMike White <botahamec@outlook.com>2021-09-06 08:03:54 -0400
committerMike White <botahamec@outlook.com>2021-09-06 08:03:54 -0400
commit21db0e1056d961b83ccf6d7e2feb06eded25174e (patch)
tree1e3021ba1a99c171c17dedf1546f591a40ce24f8 /model
parent744050c4b4747ac4645480e2f4a935a027b8350f (diff)
Unit tests
Diffstat (limited to 'model')
-rw-r--r--model/src/board.rs3
-rw-r--r--model/src/board/tests.rs33
-rw-r--r--model/src/moves.rs109
-rw-r--r--model/src/possible_moves.rs312
4 files changed, 416 insertions, 41 deletions
diff --git a/model/src/board.rs b/model/src/board.rs
index b67c13c..f95d837 100644
--- a/model/src/board.rs
+++ b/model/src/board.rs
@@ -137,6 +137,7 @@ impl CheckersBitBoard {
/// * `row` - The row. The a file is row 0
/// * `col` - The column. The first rank is column 0
#[must_use]
+ // TODO test
pub fn get_at_row_col(self, row: usize, col: usize) -> Option<Piece> {
if row > 32 || col > 32 {
None
@@ -319,6 +320,7 @@ impl CheckersBitBoard {
/// Change whose turn it is, without modifying the board
#[must_use]
+ // TODO test
pub const fn flip_turn(self) -> Self {
CheckersBitBoard::new(self.pieces, self.color, self.kings, self.turn.flip())
}
@@ -525,6 +527,7 @@ impl CheckersBitBoard {
/// Moving from the left side of the board results in undefined behavior.
/// Moving from the top of the board results in undefined behavior
#[must_use]
+ // TODO test the edge cases of the below if statement
pub const unsafe fn jump_piece_forward_left_unchecked(self, value: usize) -> Self {
let is_king = self.king_at_unchecked(value);
let board = self
diff --git a/model/src/board/tests.rs b/model/src/board/tests.rs
index e4d1f62..c3ea2cd 100644
--- a/model/src/board/tests.rs
+++ b/model/src/board/tests.rs
@@ -64,7 +64,9 @@ proptest! {
kings: k,
turn: PieceColor::Dark
};
- board.piece_at(v);
+
+ // just test for no crash
+ let _ = board.piece_at(v);
}
#[test]
@@ -75,7 +77,9 @@ proptest! {
kings: k,
turn: PieceColor::Dark
};
- unsafe {board.color_at_unchecked(v);}
+
+ // just test for no crash
+ unsafe {let _ = board.color_at_unchecked(v);}
}
#[test]
@@ -86,7 +90,7 @@ proptest! {
kings: k,
turn: PieceColor::Dark
};
- unsafe {board.king_at_unchecked(v);}
+ unsafe {let _ = board.king_at_unchecked(v);}
}
#[test]
@@ -97,7 +101,9 @@ proptest! {
kings: k,
turn: PieceColor::Dark
};
- board.color_at(v);
+
+ // just testing for no crash
+ let _ = board.color_at(v);
}
#[test]
@@ -108,7 +114,9 @@ proptest! {
kings: k,
turn: PieceColor::Dark
};
- board.king_at(v);
+
+ // just testing for no crash
+ let _ = board.king_at(v);
}
#[test]
@@ -555,12 +563,11 @@ fn test_move_piece_forward_standard() {
#[test]
fn test_move_piece_forward_wrap() {
let board = CheckersBitBoard::default();
- let board = unsafe { board.move_piece_forward_unchecked(31, 10) }; // go to 9
- assert!(!board.piece_at(31));
- assert!(board.piece_at(9));
- // TODO always move a dark squared piece
- assert_eq!(board.color_at(9).unwrap(), PieceColor::Light);
- assert!(!board.king_at(9).unwrap());
+ let board = unsafe { board.move_piece_forward_unchecked(26, 8) }; // go to 9
+ assert!(!board.piece_at(26));
+ assert!(board.piece_at(2));
+ assert_eq!(board.color_at(2).unwrap(), PieceColor::Dark);
+ assert!(!board.king_at(2).unwrap());
assert_eq!(board.turn, PieceColor::Light);
}
@@ -582,13 +589,13 @@ fn test_move_piece_backward_left_to_king() {
#[test]
fn test_move_piece_backward_standard() {
- let board = CheckersBitBoard::default();
+ let board = CheckersBitBoard::default().flip_turn();
let board = unsafe { board.move_piece_backward_unchecked(29, 14) }; // go to 15
assert!(!board.piece_at(29));
assert!(board.piece_at(15));
assert_eq!(board.color_at(15).unwrap(), PieceColor::Light);
assert!(!board.king_at(15).unwrap());
- assert_eq!(board.turn, PieceColor::Light);
+ assert_eq!(board.turn, PieceColor::Dark);
}
#[test]
diff --git a/model/src/moves.rs b/model/src/moves.rs
index 12a26db..720e11a 100644
--- a/model/src/moves.rs
+++ b/model/src/moves.rs
@@ -30,7 +30,6 @@ impl Move {
/// * `direction` - The direction the piece should move in
/// * `jump` - Whether or not the piece should jump
pub const fn new(start: usize, direction: MoveDirection, jump: bool) -> Self {
- // TODO what are the semantics of usize as u32?
Self {
start: start as u32,
direction,
@@ -38,10 +37,21 @@ impl Move {
}
}
+ /// The stating position of the move
pub const fn start(self) -> u32 {
self.start
}
+ /// The direction the move goes in
+ pub const fn direction(self) -> MoveDirection {
+ self.direction
+ }
+
+ /// Returns `true` if the move is a jump
+ pub const fn is_jump(self) -> bool {
+ self.jump
+ }
+
/// Calculates the value of the end position of the move
pub const fn end_position(self) -> usize {
let dest = match self.jump {
@@ -145,5 +155,102 @@ mod tests {
assert_eq!(move_test.direction, direction);
assert_eq!(move_test.jump, jump);
}
+
+ #[test]
+ fn start(start in 0usize..32, jump in proptest::bool::ANY) {
+ let direction = MoveDirection::ForwardLeft;
+ let move_test = Move::new(start, direction, jump);
+ assert_eq!(move_test.start(), start as u32);
+ }
+
+ #[test]
+ fn direction(start in 0usize..32, jump in proptest::bool::ANY) {
+ let direction = MoveDirection::ForwardLeft;
+ let move_test = Move::new(start, direction, jump);
+ assert_eq!(move_test.direction(), direction);
+
+ let direction = MoveDirection::ForwardRight;
+ let move_test = Move::new(start, direction, jump);
+ assert_eq!(move_test.direction(), direction);
+
+ let direction = MoveDirection::BackwardLeft;
+ let move_test = Move::new(start, direction, jump);
+ assert_eq!(move_test.direction(), direction);
+
+ let direction = MoveDirection::BackwardRight;
+ let move_test = Move::new(start, direction, jump);
+ assert_eq!(move_test.direction(), direction);
+ }
+
+ #[test]
+ fn is_jump(start in 0usize..32, jump in proptest::bool::ANY) {
+ let direction = MoveDirection::ForwardLeft;
+ let move_test = Move::new(start, direction, jump);
+ assert_eq!(move_test.is_jump(), jump);
+ }
+ }
+
+ #[test]
+ fn end_position_forward_left_slide() {
+ let direction = MoveDirection::ForwardLeft;
+ let start = 8;
+ let move_test = Move::new(start, direction, false);
+ assert_eq!(move_test.end_position(), 15);
+ }
+
+ #[test]
+ fn end_position_forward_right_slide() {
+ let direction = MoveDirection::ForwardRight;
+ let start = 26;
+ let move_test = Move::new(start, direction, false);
+ assert_eq!(move_test.end_position(), 27);
+ }
+
+ #[test]
+ fn end_position_backward_right_slide() {
+ let direction = MoveDirection::BackwardRight;
+ let start = 2;
+ let move_test = Move::new(start, direction, false);
+ assert_eq!(move_test.end_position(), 27);
+ }
+
+ #[test]
+ fn end_position_backward_left_slide() {
+ let direction = MoveDirection::BackwardLeft;
+ let start = 16;
+ let move_test = Move::new(start, direction, false);
+ assert_eq!(move_test.end_position(), 15);
+ }
+
+ #[test]
+ fn end_position_forward_left_jump() {
+ let direction = MoveDirection::ForwardLeft;
+ let start = 8;
+ let move_test = Move::new(start, direction, true);
+ assert_eq!(move_test.end_position(), 22);
+ }
+
+ #[test]
+ fn end_position_forward_right_jump() {
+ let direction = MoveDirection::ForwardRight;
+ let start = 26;
+ let move_test = Move::new(start, direction, true);
+ assert_eq!(move_test.end_position(), 28);
+ }
+
+ #[test]
+ fn end_position_backward_right_jump() {
+ let direction = MoveDirection::BackwardRight;
+ let start = 2;
+ let move_test = Move::new(start, direction, true);
+ assert_eq!(move_test.end_position(), 20);
+ }
+
+ #[test]
+ fn end_position_backward_left_jump() {
+ let direction = MoveDirection::BackwardLeft;
+ let start = 16;
+ let move_test = Move::new(start, direction, true);
+ assert_eq!(move_test.end_position(), 14);
}
}
diff --git a/model/src/possible_moves.rs b/model/src/possible_moves.rs
index f50c03e..50ad774 100644
--- a/model/src/possible_moves.rs
+++ b/model/src/possible_moves.rs
@@ -4,6 +4,7 @@ use std::alloc::{alloc, dealloc, handle_alloc_error, Layout};
use std::mem::MaybeUninit;
use std::ptr::NonNull;
+// The maximum number of available moves in any given position
const POSSIBLE_MOVES_ITER_SIZE: usize = 42;
/// A struct containing the possible moves in a particular checkers position
@@ -118,6 +119,7 @@ impl IntoIterator for PossibleMoves {
type Item = Move;
type IntoIter = PossibleMovesIter;
+ // TODO test
fn into_iter(self) -> Self::IntoIter {
let layout = Layout::array::<MaybeUninit<Move>>(POSSIBLE_MOVES_ITER_SIZE).unwrap();
let allocated_mem = unsafe { alloc(layout) };
@@ -318,7 +320,9 @@ impl IntoIterator for PossibleMoves {
}
impl PossibleMoves {
+ // TODO test
const fn slides_dark(board: CheckersBitBoard) -> Self {
+ // TODO maybe remove these?
const FORWARD_LEFT_MASK: u32 = 0b01111001111110111111001111011011;
const FORWARD_RIGHT_MASK: u32 = 0b01111101111111011111010111011101;
const BACKWARD_LEFT_MASK: u32 = 0b11111011111110111110101110111010;
@@ -582,39 +586,54 @@ impl PossibleMoves {
pub const fn can_jump(self) -> bool {
(self.backward_right_movers & 2) != 0
}
-
- /// Returns the pieces who can move forward left,
- /// with undefined behavior for bits where a forward left move is impossible
- ///
- /// # Safety
- ///
- /// This function is inherently unsafe because some bits are undefined
- // TODO make this unsafe
- pub const fn forward_left_bits(self) -> u32 {
- self.forward_left_movers
- }
-
- /// Gets the bits for a certain direction,
- /// with undefined behavior for bits where the given move is impossible
- ///
- /// # Safety
- ///
- /// This function is inherently unsafe because some bits are undefined
- // TODO make this unsafe
- pub const fn get_direction_bits(self, direction: MoveDirection) -> u32 {
- match direction {
- MoveDirection::ForwardLeft => self.forward_left_movers,
- MoveDirection::ForwardRight => self.forward_right_movers,
- MoveDirection::BackwardLeft => self.backward_left_movers,
- MoveDirection::BackwardRight => self.backward_right_movers,
- }
- }
}
#[cfg(test)]
mod tests {
use super::*;
+ fn setup_empty_iter() -> PossibleMovesIter {
+ let layout = Layout::array::<MaybeUninit<Move>>(POSSIBLE_MOVES_ITER_SIZE).unwrap();
+ let allocated_mem = unsafe { alloc(layout) };
+ let ptr =
+ match NonNull::new(allocated_mem as *mut [MaybeUninit<Move>; POSSIBLE_MOVES_ITER_SIZE])
+ {
+ Some(p) => p,
+ None => handle_alloc_error(layout),
+ };
+ let iter = PossibleMovesIter {
+ moves: ptr,
+ index: 0,
+ length: 0,
+ };
+
+ iter
+ }
+
+ fn setup_add_move_to_iter_invalid() -> (PossibleMovesIter, PossibleMoves) {
+ let moves = PossibleMoves {
+ forward_left_movers: 0,
+ forward_right_movers: 0,
+ backward_left_movers: 0,
+ backward_right_movers: 0,
+ };
+ let iter = setup_empty_iter();
+
+ (iter, moves)
+ }
+
+ fn setup_add_move_to_iter_valid() -> (PossibleMovesIter, PossibleMoves) {
+ let moves = PossibleMoves {
+ forward_left_movers: u32::MAX,
+ forward_right_movers: u32::MAX,
+ backward_left_movers: u32::MAX,
+ backward_right_movers: u32::MAX,
+ };
+ let iter = setup_empty_iter();
+
+ (iter, moves)
+ }
+
#[test]
fn same() {
let start = CheckersBitBoard::new(
@@ -635,4 +654,243 @@ mod tests {
PossibleMoves::has_jumps(flip)
)
}
+
+ #[test]
+ fn iter_next() {
+ let test_move1 = Move::new(8, MoveDirection::ForwardLeft, false);
+ let test_move2 = Move::new(26, MoveDirection::ForwardRight, true);
+ let mut iter = setup_empty_iter();
+ iter.length = 2;
+
+ let ptr = unsafe { iter.moves.as_mut() }.get_mut(0).unwrap();
+ *ptr = MaybeUninit::new(test_move1);
+
+ let ptr = unsafe { iter.moves.as_mut() }.get_mut(1).unwrap();
+ *ptr = MaybeUninit::new(test_move2);
+
+ let recieved_move = iter.next();
+ assert!(recieved_move.is_some());
+ assert_eq!(recieved_move.unwrap(), test_move1);
+
+ let recieved_move = iter.next();
+ assert!(recieved_move.is_some());
+ assert_eq!(recieved_move.unwrap(), test_move2);
+
+ let recieved_move = iter.next();
+ assert!(recieved_move.is_none());
+ }
+
+ #[test]
+ fn add_slide_forward_left_to_iter_invalid() {
+ const START: usize = 8;
+ let (mut iter, moves) = setup_add_move_to_iter_invalid();
+ iter.add_slide_forward_left::<START>(moves);
+
+ assert_eq!(iter.index, 0);
+ assert_eq!(iter.length, 0);
+ }
+
+ #[test]
+ fn add_slide_forward_left_to_iter_valid() {
+ const START: usize = 8;
+ let (mut iter, moves) = setup_add_move_to_iter_valid();
+ iter.add_slide_forward_left::<START>(moves);
+
+ assert_eq!(iter.index, 0);
+ assert_eq!(iter.length, 1);
+
+ let new_move = iter.next().unwrap();
+ assert_eq!(new_move.start(), START as u32);
+ assert_eq!(new_move.direction(), MoveDirection::ForwardLeft);
+ assert!(!new_move.is_jump());
+ }
+
+ #[test]
+ fn add_slide_forward_right_to_iter_invalid() {
+ const START: usize = 26;
+ let (mut iter, moves) = setup_add_move_to_iter_invalid();
+ iter.add_slide_forward_right::<START>(moves);
+
+ assert_eq!(iter.index, 0);
+ assert_eq!(iter.length, 0);
+ }
+
+ #[test]
+ fn add_slide_forward_right_to_iter_valid() {
+ const START: usize = 26;
+ let (mut iter, moves) = setup_add_move_to_iter_valid();
+ iter.add_slide_forward_right::<START>(moves);
+
+ assert_eq!(iter.index, 0);
+ assert_eq!(iter.length, 1);
+
+ let new_move = iter.next().unwrap();
+ assert_eq!(new_move.start(), START as u32);
+ assert_eq!(new_move.direction(), MoveDirection::ForwardRight);
+ assert!(!new_move.is_jump());
+ }
+
+ #[test]
+ fn add_slide_backward_left_to_iter_invalid() {
+ const START: usize = 17;
+ let (mut iter, moves) = setup_add_move_to_iter_invalid();
+ iter.add_slide_backward_left::<START>(moves);
+
+ assert_eq!(iter.index, 0);
+ assert_eq!(iter.length, 0);
+ }
+
+ #[test]
+ fn add_slide_backward_left_to_iter_valid() {
+ const START: usize = 17;
+ let (mut iter, moves) = setup_add_move_to_iter_valid();
+ iter.add_slide_backward_left::<START>(moves);
+
+ assert_eq!(iter.index, 0);
+ assert_eq!(iter.length, 1);
+
+ let new_move = iter.next().unwrap();
+ assert_eq!(new_move.start(), START as u32);
+ assert_eq!(new_move.direction(), MoveDirection::BackwardLeft);
+ assert!(!new_move.is_jump());
+ }
+
+ #[test]
+ fn add_slide_backward_right_to_iter_invalid() {
+ const START: usize = 3;
+ let (mut iter, moves) = setup_add_move_to_iter_invalid();
+ iter.add_slide_backward_right::<START>(moves);
+
+ assert_eq!(iter.index, 0);
+ assert_eq!(iter.length, 0);
+ }
+
+ #[test]
+ fn add_slide_backward_right_to_iter_valid() {
+ const START: usize = 3;
+ let (mut iter, moves) = setup_add_move_to_iter_valid();
+ iter.add_slide_backward_right::<START>(moves);
+
+ assert_eq!(iter.index, 0);
+ assert_eq!(iter.length, 1);
+
+ let new_move = iter.next().unwrap();
+ assert_eq!(new_move.start(), START as u32);
+ assert_eq!(new_move.direction(), MoveDirection::BackwardRight);
+ assert!(!new_move.is_jump());
+ }
+
+ #[test]
+ fn add_jump_forward_left_to_iter_invalid() {
+ const START: usize = 8;
+ let (mut iter, moves) = setup_add_move_to_iter_invalid();
+ iter.add_jump_forward_left::<START>(moves);
+
+ assert_eq!(iter.index, 0);
+ assert_eq!(iter.length, 0);
+ }
+
+ #[test]
+ fn add_jump_forward_left_to_iter_valid() {
+ const START: usize = 8;
+ let (mut iter, moves) = setup_add_move_to_iter_valid();
+ iter.add_jump_forward_left::<START>(moves);
+
+ assert_eq!(iter.index, 0);
+ assert_eq!(iter.length, 1);
+
+ let new_move = iter.next().unwrap();
+ assert_eq!(new_move.start(), START as u32);
+ assert_eq!(new_move.direction(), MoveDirection::ForwardLeft);
+ assert!(new_move.is_jump());
+ }
+
+ #[test]
+ fn add_jump_forward_right_to_iter_invalid() {
+ const START: usize = 26;
+ let (mut iter, moves) = setup_add_move_to_iter_invalid();
+ iter.add_jump_forward_right::<START>(moves);
+
+ assert_eq!(iter.index, 0);
+ assert_eq!(iter.length, 0);
+ }
+
+ #[test]
+ fn add_jump_forward_right_to_iter_valid() {
+ const START: usize = 26;
+ let (mut iter, moves) = setup_add_move_to_iter_valid();
+ iter.add_jump_forward_right::<START>(moves);
+
+ assert_eq!(iter.index, 0);
+ assert_eq!(iter.length, 1);
+
+ let new_move = iter.next().unwrap();
+ assert_eq!(new_move.start(), START as u32);
+ assert_eq!(new_move.direction(), MoveDirection::ForwardRight);
+ assert!(new_move.is_jump());
+ }
+
+ #[test]
+ fn add_jump_backward_left_to_iter_invalid() {
+ const START: usize = 17;
+ let (mut iter, moves) = setup_add_move_to_iter_invalid();
+ iter.add_jump_backward_left::<START>(moves);
+
+ assert_eq!(iter.index, 0);
+ assert_eq!(iter.length, 0);
+ }
+
+ #[test]
+ fn add_jump_backward_left_to_iter_valid() {
+ const START: usize = 17;
+ let (mut iter, moves) = setup_add_move_to_iter_valid();
+ iter.add_jump_backward_left::<START>(moves);
+
+ assert_eq!(iter.index, 0);
+ assert_eq!(iter.length, 1);
+
+ let new_move = iter.next().unwrap();
+ assert_eq!(new_move.start(), START as u32);
+ assert_eq!(new_move.direction(), MoveDirection::BackwardLeft);
+ assert!(new_move.is_jump());
+ }
+
+ #[test]
+ fn add_jump_backward_right_to_iter_invalid() {
+ const START: usize = 3;
+ let (mut iter, moves) = setup_add_move_to_iter_invalid();
+ iter.add_jump_backward_right::<START>(moves);
+
+ assert_eq!(iter.index, 0);
+ assert_eq!(iter.length, 0);
+ }
+
+ #[test]
+ fn add_jump_backward_right_to_iter_valid() {
+ const START: usize = 3;
+ let (mut iter, moves) = setup_add_move_to_iter_valid();
+ iter.add_jump_backward_right::<START>(moves);
+
+ assert_eq!(iter.index, 0);
+ assert_eq!(iter.length, 1);
+
+ let new_move = iter.next().unwrap();
+ assert_eq!(new_move.start(), START as u32);
+ assert_eq!(new_move.direction(), MoveDirection::BackwardRight);
+ assert!(new_move.is_jump());
+ }
+
+ #[test]
+ fn test_send() {
+ fn assert_send<T: Send>() {}
+ assert_send::<PossibleMoves>();
+ // TODO iterator
+ }
+
+ #[test]
+ fn test_sync() {
+ fn assert_sync<T: Sync>() {}
+ assert_sync::<PossibleMoves>();
+ // TODO iterator
+ }
}