add PlaceShips message
This commit is contained in:
@@ -454,3 +454,193 @@ func mustMatch(t *testing.T, m *Manager, id string) *Match {
|
||||
}
|
||||
return match
|
||||
}
|
||||
|
||||
func validTestShips() []protocol.Ship {
|
||||
return []protocol.Ship{
|
||||
// 4 size 1
|
||||
{Orientation: protocol.OrientationHorizontal, X: 9, Y: 4, Size: 1},
|
||||
{Orientation: protocol.OrientationVertical, X: 7, Y: 4, Size: 1},
|
||||
{Orientation: protocol.OrientationHorizontal, X: 5, Y: 4, Size: 1},
|
||||
{Orientation: protocol.OrientationHorizontal, X: 3, Y: 4, Size: 1},
|
||||
// 3 size 2
|
||||
{Orientation: protocol.OrientationHorizontal, X: 0, Y: 4, Size: 2},
|
||||
{Orientation: protocol.OrientationHorizontal, X: 7, Y: 2, Size: 2},
|
||||
{Orientation: protocol.OrientationHorizontal, X: 4, Y: 2, Size: 2},
|
||||
// 2 size 3
|
||||
{Orientation: protocol.OrientationHorizontal, X: 0, Y: 2, Size: 3},
|
||||
{Orientation: protocol.OrientationHorizontal, X: 5, Y: 0, Size: 3},
|
||||
// 1 size 4
|
||||
{Orientation: protocol.OrientationHorizontal, X: 0, Y: 0, Size: 4},
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlaceShipsP1First(t *testing.T) {
|
||||
m := NewManager(time.Minute)
|
||||
gc := claims(time.Now().Add(time.Hour))
|
||||
c1, c2 := &fakeConn{}, &fakeConn{}
|
||||
|
||||
match, _, err := m.Join(context.Background(), c1, gc, gc.Player1ID)
|
||||
if err != nil {
|
||||
t.Fatalf("join p1: %v", err)
|
||||
}
|
||||
if _, _, err := m.Join(context.Background(), c2, gc, gc.Player2ID); err != nil {
|
||||
t.Fatalf("join p2: %v", err)
|
||||
}
|
||||
if match.State() != StatePlacingShips {
|
||||
t.Fatalf("state = %d, want StatePlacingShips", match.State())
|
||||
}
|
||||
|
||||
ships := validTestShips()
|
||||
|
||||
// Player 1 places ships first
|
||||
if err := m.PlaceShips(context.Background(), match, 0, ships); err != nil {
|
||||
t.Fatalf("p1 place ships: %v", err)
|
||||
}
|
||||
if match.State() != StatePlayer1Ready {
|
||||
t.Fatalf("state = %d, want StatePlayer1Ready (2)", match.State())
|
||||
}
|
||||
|
||||
// Verify stored ships and board for p1
|
||||
p1Ships := match.Ships(0)
|
||||
if len(p1Ships) != len(ships) {
|
||||
t.Fatalf("got %d ships, want %d", len(p1Ships), len(ships))
|
||||
}
|
||||
p1Board, placed := match.Board(0)
|
||||
if !placed {
|
||||
t.Fatal("expected p1 board placed to be true")
|
||||
}
|
||||
// Check that ship 9 (size 4 at 0,0 horizontal) is in p1 board with id 10
|
||||
for x := 0; x < 4; x++ {
|
||||
if p1Board[0][x] != 10 {
|
||||
t.Fatalf("p1Board[0][%d] = %d, want 10", x, p1Board[0][x])
|
||||
}
|
||||
}
|
||||
|
||||
// Verify states delivered to p1 and p2
|
||||
p1Msgs, p2Msgs := c1.messages(), c2.messages()
|
||||
if v := parseMsg(t, p1Msgs[len(p1Msgs)-1]); v[2] != float64(protocol.StateWaitOpponentReady) {
|
||||
t.Fatalf("p1 got state %v, want StateWaitOpponentReady (3)", v)
|
||||
}
|
||||
if v := parseMsg(t, p2Msgs[len(p2Msgs)-1]); v[2] != float64(protocol.StateOpponentReady) {
|
||||
t.Fatalf("p2 got state %v, want StateOpponentReady (2)", v)
|
||||
}
|
||||
|
||||
// Player 1 cannot place ships again
|
||||
if err := m.PlaceShips(context.Background(), match, 0, ships); err == nil {
|
||||
t.Fatal("expected error when player 1 places ships again")
|
||||
}
|
||||
|
||||
// Player 2 places ships
|
||||
if err := m.PlaceShips(context.Background(), match, 1, ships); err != nil {
|
||||
t.Fatalf("p2 place ships: %v", err)
|
||||
}
|
||||
if match.State() != StatePlayer1Turn {
|
||||
t.Fatalf("state = %d, want StatePlayer1Turn (4)", match.State())
|
||||
}
|
||||
|
||||
// Verify states delivered to p1 and p2 after game starts
|
||||
p1Msgs, p2Msgs = c1.messages(), c2.messages()
|
||||
if v := parseMsg(t, p1Msgs[len(p1Msgs)-1]); v[2] != float64(protocol.StateYourTurn) {
|
||||
t.Fatalf("p1 got state %v, want StateYourTurn (4)", v)
|
||||
}
|
||||
if v := parseMsg(t, p2Msgs[len(p2Msgs)-1]); v[2] != float64(protocol.StateWaitOpponentTurn) {
|
||||
t.Fatalf("p2 got state %v, want StateWaitOpponentTurn (5)", v)
|
||||
}
|
||||
|
||||
// Subsequent PlaceShips calls are rejected
|
||||
if err := m.PlaceShips(context.Background(), match, 1, ships); err == nil {
|
||||
t.Fatal("expected error when match is in turn phase")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlaceShipsP2First(t *testing.T) {
|
||||
m := NewManager(time.Minute)
|
||||
gc := claims(time.Now().Add(time.Hour))
|
||||
c1, c2 := &fakeConn{}, &fakeConn{}
|
||||
|
||||
match, _, err := m.Join(context.Background(), c1, gc, gc.Player1ID)
|
||||
if err != nil {
|
||||
t.Fatalf("join p1: %v", err)
|
||||
}
|
||||
if _, _, err := m.Join(context.Background(), c2, gc, gc.Player2ID); err != nil {
|
||||
t.Fatalf("join p2: %v", err)
|
||||
}
|
||||
|
||||
ships := validTestShips()
|
||||
|
||||
// Player 2 places ships first
|
||||
if err := m.PlaceShips(context.Background(), match, 1, ships); err != nil {
|
||||
t.Fatalf("p2 place ships: %v", err)
|
||||
}
|
||||
if match.State() != StatePlayer2Ready {
|
||||
t.Fatalf("state = %d, want StatePlayer2Ready (3)", match.State())
|
||||
}
|
||||
|
||||
// Verify states delivered to p1 and p2
|
||||
p1Msgs, p2Msgs := c1.messages(), c2.messages()
|
||||
if v := parseMsg(t, p1Msgs[len(p1Msgs)-1]); v[2] != float64(protocol.StateOpponentReady) {
|
||||
t.Fatalf("p1 got state %v, want StateOpponentReady (2)", v)
|
||||
}
|
||||
if v := parseMsg(t, p2Msgs[len(p2Msgs)-1]); v[2] != float64(protocol.StateWaitOpponentReady) {
|
||||
t.Fatalf("p2 got state %v, want StateWaitOpponentReady (3)", v)
|
||||
}
|
||||
|
||||
// Player 1 places ships
|
||||
if err := m.PlaceShips(context.Background(), match, 0, ships); err != nil {
|
||||
t.Fatalf("p1 place ships: %v", err)
|
||||
}
|
||||
if match.State() != StatePlayer2Turn {
|
||||
t.Fatalf("state = %d, want StatePlayer2Turn (5)", match.State())
|
||||
}
|
||||
|
||||
// Player 2 finished first, so Player 2 gets first turn!
|
||||
p1Msgs, p2Msgs = c1.messages(), c2.messages()
|
||||
if v := parseMsg(t, p1Msgs[len(p1Msgs)-1]); v[2] != float64(protocol.StateWaitOpponentTurn) {
|
||||
t.Fatalf("p1 got state %v, want StateWaitOpponentTurn (5)", v)
|
||||
}
|
||||
if v := parseMsg(t, p2Msgs[len(p2Msgs)-1]); v[2] != float64(protocol.StateYourTurn) {
|
||||
t.Fatalf("p2 got state %v, want StateYourTurn (4)", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlaceShipsValidationFailure(t *testing.T) {
|
||||
m := NewManager(time.Minute)
|
||||
gc := claims(time.Now().Add(time.Hour))
|
||||
c1, c2 := &fakeConn{}, &fakeConn{}
|
||||
|
||||
match, _, err := m.Join(context.Background(), c1, gc, gc.Player1ID)
|
||||
if err != nil {
|
||||
t.Fatalf("join p1: %v", err)
|
||||
}
|
||||
if _, _, err := m.Join(context.Background(), c2, gc, gc.Player2ID); err != nil {
|
||||
t.Fatalf("join p2: %v", err)
|
||||
}
|
||||
|
||||
invalidShips := validTestShips()
|
||||
invalidShips[0].X = invalidShips[1].X // overlapping ships
|
||||
|
||||
if err := m.PlaceShips(context.Background(), match, 0, invalidShips); err == nil {
|
||||
t.Fatal("expected validation error")
|
||||
}
|
||||
if match.State() != StatePlacingShips {
|
||||
t.Fatalf("state changed to %d on error, want StatePlacingShips", match.State())
|
||||
}
|
||||
if match.Ships(0) != nil {
|
||||
t.Fatal("expected nil ships for p1 after failed placement")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlaceShipsBeforeMatchStarts(t *testing.T) {
|
||||
m := NewManager(time.Minute)
|
||||
gc := claims(time.Now().Add(time.Hour))
|
||||
c1 := &fakeConn{}
|
||||
|
||||
match, _, err := m.Join(context.Background(), c1, gc, gc.Player1ID)
|
||||
if err != nil {
|
||||
t.Fatalf("join p1: %v", err)
|
||||
}
|
||||
|
||||
if err := m.PlaceShips(context.Background(), match, 0, validTestShips()); err != ErrMatchNotStarted {
|
||||
t.Fatalf("got err = %v, want ErrMatchNotStarted", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user