mirror of
https://github.com/Stone-Red-Code/se-poker.git
synced 2026-09-04 00:56:18 +02:00
275 lines
10 KiB
Go
275 lines
10 KiB
Go
package main
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func TestNewHand(t *testing.T) {
|
|
tests := []struct {
|
|
input string
|
|
expected *Hand
|
|
expectedErr bool
|
|
}{
|
|
{
|
|
input: "H2 S3 C4 D5 H6",
|
|
expected: &Hand{Cards: []Card{
|
|
{Suit: "H", Value: 2},
|
|
{Suit: "S", Value: 3},
|
|
{Suit: "C", Value: 4},
|
|
{Suit: "D", Value: 5},
|
|
{Suit: "H", Value: 6},
|
|
}},
|
|
expectedErr: false,
|
|
},
|
|
{
|
|
input: "CT CJ CQ CK CA",
|
|
expected: &Hand{Cards: []Card{
|
|
{Suit: "C", Value: 10},
|
|
{Suit: "C", Value: 11},
|
|
{Suit: "C", Value: 12},
|
|
{Suit: "C", Value: 13},
|
|
{Suit: "C", Value: 14},
|
|
}},
|
|
expectedErr: false,
|
|
},
|
|
{
|
|
input: "Invalid Input",
|
|
expected: nil,
|
|
expectedErr: true,
|
|
},
|
|
{
|
|
input: "H2 S3 C4 D5", // Not 5 cards
|
|
expected: nil,
|
|
expectedErr: true,
|
|
},
|
|
{
|
|
input: "H2 S3 C4 D5 Hx", // Invalid card value
|
|
expected: nil,
|
|
expectedErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
hand, err := NewHand(tt.input)
|
|
if (err != nil) != tt.expectedErr {
|
|
t.Errorf("NewHand(%q) error = %v, expectedErr %v", tt.input, err, tt.expectedErr)
|
|
continue
|
|
}
|
|
if !tt.expectedErr && !reflect.DeepEqual(hand, tt.expected) {
|
|
t.Errorf("NewHand(%q) got = %v, want %v", tt.input, hand, tt.expected)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEvaluateHandValues(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expected HandCategory
|
|
}{
|
|
{"Royal Flush", "CT CJ CQ CK CA", RoyalFlush},
|
|
{"Straight Flush", "D8 D9 DT DJ DQ", StraightFlush},
|
|
{"Four of a Kind", "HT SA ST DT CT", FourOfAKind},
|
|
{"Full House", "H2 SQ C2 D2 CQ", FullHouse},
|
|
{"Flush", "HK HQ H2 H4 H5", Flush},
|
|
{"Straight", "H3 S7 H5 D6 C4", Straight},
|
|
{"Three of a Kind", "H2 SQ S2 D2 CK", ThreeOfAKind},
|
|
{"Two Pair", "H5 SQ C5 DT CT", TwoPair},
|
|
{"Pair", "H3 S8 H5 D8 CA", Pair},
|
|
{"High Card", "H3 S8 H5 D4 CA", HighCard},
|
|
{"Straight Wheel", "H4 S5 HA D3 C2", Straight},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
hand, err := NewHand(tt.input)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create hand for %s: %v", tt.input, err)
|
|
}
|
|
result := hand.Evaluate()
|
|
if result.Category != tt.expected {
|
|
t.Errorf("Hand: %s, Expected %s, got %s", tt.input, handNames[tt.expected], handNames[result.Category])
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCompareHands(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
hand1 string
|
|
hand2 string
|
|
expected int // 1 if hand1 wins, 2 if hand2 wins, 0 for tie
|
|
}{
|
|
{"Royal Flush vs Straight Flush", "CT CJ CQ CK CA", "D8 D9 DT DJ DQ", 1},
|
|
{"Straight Flush vs Four of a Kind", "D8 D9 DT DJ DQ", "HT SA ST DT CT", 1},
|
|
{"Four of a Kind vs Full House", "HT SA ST DT CT", "H2 SQ C2 D2 CQ", 1},
|
|
{"Full House vs Flush", "H2 SQ C2 D2 CQ", "HK HQ H2 H4 H5", 1},
|
|
{"Flush vs Straight", "HK HQ H2 H4 H5", "H3 S7 H5 D6 C4", 1},
|
|
{"Straight vs Three of a Kind", "H3 S7 H5 D6 C4", "H2 SQ S2 D2 CK", 1},
|
|
{"Three of a Kind vs Two Pair", "H2 SQ S2 D2 CK", "H5 SQ C5 DT CT", 1},
|
|
{"Two Pair vs Pair", "H5 SQ C5 DT CT", "H3 S8 H5 D8 CA", 1},
|
|
{"Pair vs High Card", "H3 S8 H5 D8 CA", "H3 S8 H5 D4 C2", 1},
|
|
{"Tie - Same Royal Flush", "CT CJ CQ CK CA", "CT CJ CQ CK CA", 0},
|
|
{"Tie - Same Straight Flush", "D8 D9 DT DJ DQ", "D8 D9 DT DJ DQ", 0},
|
|
{"Tie - Higher Straight Flush", "S8 S9 ST SJ SQ", "D8 D9 DT DJ DQ", 0},
|
|
{"Tie - Four of a Kind (higher value)", "HA SA DA CA H2", "HK SK DK CK H2", 1},
|
|
{"Tie - Four of a Kind (same value, higher kicker)", "HA SA DA CA H3", "HA SA DA CA H2", 1},
|
|
{"Tie - Full House (higher trips)", "HA SA DA H2 C2", "HK SK DK H2 C2", 1},
|
|
{"Tie - Full House (same trips, higher pair)", "HA SA DA H3 C3", "HA SA DA H2 C2", 1},
|
|
{"Tie - Flush (higher card)", "HA H9 H8 H7 H5", "HA H9 H8 H7 H4", 1},
|
|
{"Tie - Straight (higher card)", "S9 ST SJ SQ SK", "S8 S9 ST SJ SQ", 1},
|
|
{"Tie - Three of a Kind (higher trips)", "HA SA DA H3 C4", "HK SK DK H3 C4", 1},
|
|
{"Tie - Three of a Kind (same trips, higher kicker)", "HA SA DA H5 C4", "HA SA DA H3 C2", 1},
|
|
{"Tie - Two Pair (higher top pair)", "HA SA H2 C2 DK", "HK SK H2 C2 DA", 1},
|
|
{"Tie - Two Pair (same top pair, higher second pair)", "HA SA H3 C3 DK", "HA SA H2 C2 DK", 1},
|
|
{"Tie - Two Pair (same pairs, higher kicker)", "HA SA H2 C2 DQ", "HA SA H2 C2 DJ", 1},
|
|
{"Tie - Pair (higher pair)", "HA SA H2 C3 D4", "HK SK H2 C3 D4", 1},
|
|
{"Tie - Pair (same pair, higher kicker)", "HA SA H5 C3 D4", "HA SA H4 C2 D5", 1},
|
|
{"Tie - High Card (higher card)", "HA SK CJ D9 H7", "HQ SK CJ D9 H7", 1},
|
|
{"Tie - High Card (all equal)", "HA SK CJ D9 H7", "HA SK CJ D9 H7", 0},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
hand1, err1 := NewHand(tt.hand1)
|
|
hand2, err2 := NewHand(tt.hand2)
|
|
if err1 != nil || err2 != nil {
|
|
t.Fatalf("Failed to create hands: %v, %v", err1, err2)
|
|
}
|
|
|
|
result := hand1.Compare(hand2)
|
|
if result != tt.expected {
|
|
t.Errorf("CompareHands(%s, %s) Expected %d, got %d", tt.hand1, tt.hand2, tt.expected, result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFindBestHand(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
sevenCards []Card
|
|
expected *Hand
|
|
expectedErr bool
|
|
}{
|
|
{
|
|
name: "Royal Flush from 7 cards",
|
|
sevenCards: []Card{
|
|
{Suit: "C", Value: 2}, {Suit: "C", Value: 10}, {Suit: "C", Value: 11}, {Suit: "C", Value: 12},
|
|
{Suit: "C", Value: 13}, {Suit: "C", Value: 14}, {Suit: "H", Value: 7},
|
|
},
|
|
expected: &Hand{Cards: []Card{{Suit: "C", Value: 14}, {Suit: "C", Value: 13}, {Suit: "C", Value: 12}, {Suit: "C", Value: 11}, {Suit: "C", Value: 10}}},
|
|
expectedErr: false,
|
|
},
|
|
{
|
|
name: "Straight Flush from 7 cards",
|
|
sevenCards: []Card{
|
|
{Suit: "D", Value: 8}, {Suit: "D", Value: 9}, {Suit: "D", Value: 10}, {Suit: "D", Value: 11},
|
|
{Suit: "D", Value: 12}, {Suit: "S", Value: 5}, {Suit: "C", Value: 2},
|
|
},
|
|
expected: &Hand{Cards: []Card{{Suit: "D", Value: 12}, {Suit: "D", Value: 11}, {Suit: "D", Value: 10}, {Suit: "D", Value: 9}, {Suit: "D", Value: 8}}},
|
|
expectedErr: false,
|
|
},
|
|
{
|
|
name: "Four of a Kind from 7 cards",
|
|
sevenCards: []Card{
|
|
{Suit: "H", Value: 10}, {Suit: "S", Value: 10}, {Suit: "D", Value: 10}, {Suit: "C", Value: 10},
|
|
{Suit: "H", Value: 2}, {Suit: "S", Value: 3}, {Suit: "D", Value: 4},
|
|
},
|
|
expected: &Hand{Cards: []Card{{Suit: "H", Value: 10}, {Suit: "S", Value: 10}, {Suit: "D", Value: 10}, {Suit: "C", Value: 10}, {Suit: "D", Value: 4}}},
|
|
expectedErr: false,
|
|
},
|
|
{
|
|
name: "Full House from 7 cards",
|
|
sevenCards: []Card{
|
|
{Suit: "H", Value: 2}, {Suit: "S", Value: 2}, {Suit: "D", Value: 2}, {Suit: "C", Value: 3},
|
|
{Suit: "H", Value: 3}, {Suit: "S", Value: 7}, {Suit: "D", Value: 8},
|
|
},
|
|
expected: &Hand{Cards: []Card{{Suit: "H", Value: 3}, {Suit: "C", Value: 3}, {Suit: "H", Value: 2}, {Suit: "S", Value: 2}, {Suit: "D", Value: 2}}},
|
|
expectedErr: false,
|
|
},
|
|
{
|
|
name: "Flush from 7 cards",
|
|
sevenCards: []Card{
|
|
{Suit: "H", Value: 14}, {Suit: "H", Value: 12}, {Suit: "H", Value: 10}, {Suit: "H", Value: 8},
|
|
{Suit: "H", Value: 6}, {Suit: "S", Value: 5}, {Suit: "D", Value: 4},
|
|
},
|
|
expected: &Hand{Cards: []Card{{Suit: "H", Value: 14}, {Suit: "H", Value: 12}, {Suit: "H", Value: 10}, {Suit: "H", Value: 8}, {Suit: "H", Value: 6}}},
|
|
expectedErr: false,
|
|
},
|
|
{
|
|
name: "Straight from 7 cards",
|
|
sevenCards: []Card{
|
|
{Suit: "H", Value: 5}, {Suit: "S", Value: 6}, {Suit: "C", Value: 7}, {Suit: "D", Value: 8},
|
|
{Suit: "H", Value: 9}, {Suit: "S", Value: 2}, {Suit: "C", Value: 3},
|
|
},
|
|
expected: &Hand{Cards: []Card{{Suit: "H", Value: 9}, {Suit: "D", Value: 8}, {Suit: "C", Value: 7}, {Suit: "S", Value: 6}, {Suit: "H", Value: 5}}},
|
|
expectedErr: false,
|
|
},
|
|
{
|
|
name: "Three of a Kind from 7 cards",
|
|
sevenCards: []Card{
|
|
{Suit: "H", Value: 2}, {Suit: "S", Value: 2}, {Suit: "D", Value: 2}, {Suit: "C", Value: 7},
|
|
{Suit: "H", Value: 8}, {Suit: "S", Value: 9}, {Suit: "D", Value: 10},
|
|
},
|
|
expected: &Hand{Cards: []Card{{Suit: "D", Value: 10}, {Suit: "S", Value: 9}, {Suit: "H", Value: 8}, {Suit: "H", Value: 2}, {Suit: "S", Value: 2}, {Suit: "D", Value: 2}}},
|
|
expectedErr: false, // expected cards will be sorted by value inside Evaluate()
|
|
},
|
|
{
|
|
name: "High Card from 7 cards",
|
|
sevenCards: []Card{
|
|
{Suit: "H", Value: 2}, {Suit: "S", Value: 4}, {Suit: "C", Value: 6}, {Suit: "D", Value: 8},
|
|
{Suit: "H", Value: 10}, {Suit: "S", Value: 3}, {Suit: "C", Value: 5},
|
|
},
|
|
expected: &Hand{Cards: []Card{{Suit: "C", Value: 6}, {Suit: "C", Value: 5}, {Suit: "S", Value: 4}, {Suit: "S", Value: 3}, {Suit: "H", Value: 2}}},
|
|
expectedErr: false,
|
|
},
|
|
{
|
|
name: "Invalid number of cards (less than 7)",
|
|
sevenCards: []Card{
|
|
{Suit: "H", Value: 2}, {Suit: "S", Value: 4}, {Suit: "C", Value: 6}, {Suit: "D", Value: 8},
|
|
{Suit: "H", Value: 10}, {Suit: "S", Value: 3},
|
|
},
|
|
expected: nil,
|
|
expectedErr: true,
|
|
},
|
|
{
|
|
name: "Invalid number of cards (more than 7)",
|
|
sevenCards: []Card{
|
|
{Suit: "H", Value: 2}, {Suit: "S", Value: 4}, {Suit: "C", Value: 6}, {Suit: "D", Value: 8},
|
|
{Suit: "H", Value: 10}, {Suit: "S", Value: 3}, {Suit: "C", Value: 5}, {Suit: "D", Value: 7},
|
|
},
|
|
expected: nil,
|
|
expectedErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
hand, err := FindBestHand(tt.sevenCards)
|
|
if (err != nil) != tt.expectedErr {
|
|
t.Errorf("FindBestHand() error = %v, expectedErr %v", err, tt.expectedErr)
|
|
return
|
|
}
|
|
if !tt.expectedErr {
|
|
// The order of cards in the expected hand might not exactly match due to sorting,
|
|
// so we compare the evaluated categories and tie-breakers.
|
|
if hand == nil {
|
|
t.Fatalf("FindBestHand() returned nil hand for valid input")
|
|
}
|
|
expectedHandResult := (&Hand{Cards: tt.expected.Cards}).Evaluate()
|
|
actualHandResult := hand.Evaluate()
|
|
|
|
if expectedHandResult.Category != actualHandResult.Category {
|
|
t.Errorf("FindBestHand() for %s: expected category %s, got %s", tt.name, handNames[expectedHandResult.Category], handNames[actualHandResult.Category])
|
|
}
|
|
if !reflect.DeepEqual(expectedHandResult.TieBreakers, actualHandResult.TieBreakers) {
|
|
t.Errorf("FindBestHand() for %s: expected tie-breakers %v, got %v", tt.name, expectedHandResult.TieBreakers, actualHandResult.TieBreakers)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|