modes:pair:tests: refactor for more functional style tests
Nested iteration in the form presented before was quite bad - while it's a bit more efficient to iterate once and do all the tests in that one go, it can be kinda hard to preserve the context in ones head. This style makes it easier to see the flow of data and what is being tested.
This commit is contained in:
@@ -101,68 +101,105 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
card::{make_decks, Rank},
|
||||
modes::tests::test_non_reflexivity,
|
||||
modes::tests::test_footstool_non_reflexivity,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn new() {
|
||||
// Two jokers can never be a pair.
|
||||
/*
|
||||
There are 3 cases for generating a pair:
|
||||
1) Not a pair
|
||||
2) An improper pair made up of one joker
|
||||
3) A proper pair made up of two playing cards.
|
||||
*/
|
||||
|
||||
// TEST: Two jokers can never be a pair.
|
||||
assert_eq!(Pair::new(Card::make_joker(), Card::make_joker()), None);
|
||||
|
||||
// Iterate over all ranks
|
||||
for r1 in Rank::iter_all() {
|
||||
// Iterate over all cards in a rank
|
||||
for c1 in r1.cards() {
|
||||
// Iterate over all ranks that aren't r1
|
||||
for r2 in Rank::iter_all().filter(|&r2| r2 != r1) {
|
||||
// TEST: Cannot compose a pair made from two different
|
||||
// ranked cards.
|
||||
let all_cards = r2.cards();
|
||||
let all_pairs =
|
||||
all_cards.filter_map(|c2| Pair::new(c1, c2));
|
||||
|
||||
assert_eq!(all_pairs.count(), 0);
|
||||
}
|
||||
|
||||
// Iterate over all cards that are of the same rank as r1.
|
||||
for c2 in r1.cards() {
|
||||
// TEST: Pairs are composed of two similar rank cards.
|
||||
let pair = {
|
||||
// TEST: Non pair tests.
|
||||
Rank::iter_all()
|
||||
// Generate a mapping (r1, r2) where r1, r2 are ranks and r1 != r2
|
||||
.flat_map(|r1| {
|
||||
Rank::iter_all()
|
||||
.filter(move |&r2| r2 != r1)
|
||||
.map(move |r2| (r1, r2))
|
||||
})
|
||||
// Flat Map for combinations of (cards of rank r1, cards of rank r2)
|
||||
.flat_map(|(r1, r2)| {
|
||||
r1.cards()
|
||||
.flat_map(move |c1| r2.cards().map(move |c2| (c1, c2)))
|
||||
})
|
||||
.for_each(|(c1, c2)| {
|
||||
// TEST: Two cards of differing rank cannot be a pair
|
||||
let pair = Pair::new(c1, c2);
|
||||
assert_ne!(pair, None);
|
||||
assert!(
|
||||
pair.is_none(),
|
||||
"Expected cards {c1} and {c2} to never form a pair."
|
||||
)
|
||||
});
|
||||
|
||||
// TEST: Improper pair tests.
|
||||
PlayingCard::iter_deck(1)
|
||||
.map(Card::PlayingCard)
|
||||
.map(|c1| {
|
||||
// TEST: Any card with one joker can be made into a valid pair.
|
||||
let c2 = Card::make_joker();
|
||||
let pair = Pair::new(c1, c2);
|
||||
assert!(
|
||||
pair.is_some(),
|
||||
"Expected ({c1}, {c2}) to be a valid pair",
|
||||
);
|
||||
pair.unwrap()
|
||||
};
|
||||
|
||||
// Test: Pairs of two playing cards are proper
|
||||
assert!(pair.is_proper());
|
||||
|
||||
// TEST: Pairs always sort their cards in strength.
|
||||
let (b1, b2) = ordered(c1, c2);
|
||||
assert_eq!(pair.0, b1);
|
||||
assert_eq!(pair.1, b2);
|
||||
}
|
||||
|
||||
// TEST: Pairs may have one joker.
|
||||
let pair = {
|
||||
let p = Pair::new(c1, Card::make_joker());
|
||||
assert_ne!(p, None);
|
||||
p.unwrap()
|
||||
};
|
||||
|
||||
})
|
||||
.for_each(|pair| {
|
||||
// TEST: Pairs with a joker are improper.
|
||||
assert!(pair.is_improper());
|
||||
assert!(pair.is_improper(), "Expected {pair} to be improper");
|
||||
|
||||
// TEST: Improper pairs have a Joker in Pair::0.
|
||||
assert!(matches!(pair.0, Card::Joker(_)));
|
||||
assert!(matches!(pair.1, Card::PlayingCard(_)));
|
||||
}
|
||||
}
|
||||
assert!(
|
||||
matches!(pair.0, Card::Joker(_)),
|
||||
"Expected {} to be a joker",
|
||||
pair.0
|
||||
);
|
||||
|
||||
// TEST: Improper pairs have a playing card in Pair::1.
|
||||
assert!(
|
||||
matches!(pair.1, Card::PlayingCard(_)),
|
||||
"Expected {} to be a playing card",
|
||||
pair.1
|
||||
);
|
||||
});
|
||||
|
||||
// TEST: Proper pair tests
|
||||
PlayingCard::iter_deck(1)
|
||||
.map(Card::PlayingCard)
|
||||
// Flat Map every card (c1) into combinations (c1, card of same rank as c1)
|
||||
.flat_map(|c1| c1.rank().unwrap().cards().map(move |c2| (c1, c2)))
|
||||
// Map every (c1, c2) into a pair
|
||||
.map(|(c1, c2)| {
|
||||
// TEST: Two cards of similar rank make a valid pair.
|
||||
let pair = {
|
||||
let pair = Pair::new(c1, c2);
|
||||
assert!(
|
||||
pair.is_some(),
|
||||
"Expected {c1} and {c2} to form a valid pair."
|
||||
);
|
||||
pair.unwrap()
|
||||
};
|
||||
// TEST: Pairs of two playing cards are proper
|
||||
assert!(pair.is_proper(), "Expected {pair} to be proper.");
|
||||
(c1, c2, pair)
|
||||
})
|
||||
.for_each(|(c1, c2, pair)| {
|
||||
// TEST: Pairs always sort their cards in strength.
|
||||
let (b1, b2) = ordered(c1, c2);
|
||||
assert_eq!(pair.0, b1, "Expected {} to be {b1}", pair.0);
|
||||
assert_eq!(pair.1, b2, "Expected {} to be {b2}", pair.1);
|
||||
});
|
||||
}
|
||||
|
||||
/** Create an exhaustive set of pairs for one deck. */
|
||||
fn exhaustive_pairs_deck() -> impl Iterator<Item = Pair> {
|
||||
// A rank has 4 cards. There are a total of 10 proper pairs that can be
|
||||
// made out of 4 cards. With n jokers, add 4n improper pairs to the
|
||||
// total count of pairs for a single rank.
|
||||
make_decks(1).flat_map(|c1| {
|
||||
make_decks(1).filter_map(move |c2| Pair::new(c1, c2))
|
||||
})
|
||||
@@ -171,10 +208,7 @@ mod tests {
|
||||
#[test]
|
||||
fn ordering() {
|
||||
fn expected_ordering_relation(p1: &Pair, p2: &Pair) -> bool {
|
||||
let pair_ordering = p1.cmp(p2);
|
||||
let high_card_ordering = p1.1.cmp(&p2.1);
|
||||
|
||||
match (pair_ordering, high_card_ordering) {
|
||||
match (p1.cmp(p2), p1.1.cmp(&p2.1)) {
|
||||
// For any two pairs, we expect the high cards to dictate the
|
||||
// ordering of the pairs - the lower card should be irrelevant.
|
||||
(x, y) if x == y => true,
|
||||
@@ -184,44 +218,43 @@ mod tests {
|
||||
// exclusively one of the pairs is improper - pairs that are
|
||||
// improper should be sorted less than the proper one.
|
||||
(Ordering::Less, Ordering::Equal) => {
|
||||
// p1 has a joker, p2 doesn't => p1 < p2
|
||||
// p1 is improper, p2 is proper => p1 < p2
|
||||
p1.is_improper() && p2.is_proper()
|
||||
}
|
||||
(Ordering::Greater, Ordering::Equal) => {
|
||||
// p2 has a joker, p1 doesn't => p1 > p2
|
||||
// p2 is improper, p1 is proper => p1 > p2
|
||||
p2.is_improper() && p1.is_proper()
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
for p1 in exhaustive_pairs_deck() {
|
||||
for p2 in exhaustive_pairs_deck() {
|
||||
// TEST: For any two pair we expect them to have the
|
||||
exhaustive_pairs_deck()
|
||||
// Create a flat map of all combinations of two valid pairs.
|
||||
.flat_map(|p1| exhaustive_pairs_deck().map(move |p2| (p1, p2)))
|
||||
.for_each(|(p1, p2)| {
|
||||
// TEST: For any two valid pairs we expect them to have the
|
||||
// `expected_ordering_relation`.
|
||||
assert!(expected_ordering_relation(&p1, &p2));
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn footstool() {
|
||||
for p1 in exhaustive_pairs_deck() {
|
||||
for p2 in exhaustive_pairs_deck() {
|
||||
let (p1_on_p2, p2_on_p1) = test_non_reflexivity(&p1, &p2);
|
||||
exhaustive_pairs_deck()
|
||||
.flat_map(|p1| exhaustive_pairs_deck().map(move |p2| (p1, p2)))
|
||||
.for_each(|(p1, p2)| {
|
||||
let (p1_on_p2, p2_on_p1) =
|
||||
test_footstool_non_reflexivity(&p1, &p2);
|
||||
let (hc1_on_hc2, hc2_on_hc1) = {
|
||||
let [high_card_1, high_card_2] =
|
||||
[p1.1, p2.1].map(Single::new).map(|x| {
|
||||
assert!(x.is_some());
|
||||
x.unwrap()
|
||||
});
|
||||
test_non_reflexivity(&high_card_1, &high_card_2)
|
||||
let high_card_1 = Single::new(p1.1).unwrap();
|
||||
let high_card_2 = Single::new(p2.1).unwrap();
|
||||
test_footstool_non_reflexivity(&high_card_1, &high_card_2)
|
||||
};
|
||||
|
||||
// TEST: We expect pair footstools to mirror footstool rules of
|
||||
// Singles on the high card.
|
||||
assert!(p1_on_p2 == hc1_on_hc2 && p2_on_p1 == hc2_on_hc1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user