add PlaceShips message
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"log/slog"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -14,6 +15,7 @@ import (
|
||||
|
||||
"github.com/ruby-sea-battle/game-server/internal/auth"
|
||||
"github.com/ruby-sea-battle/game-server/internal/game"
|
||||
"github.com/ruby-sea-battle/game-server/internal/protocol"
|
||||
"github.com/ruby-sea-battle/game-server/internal/ws"
|
||||
)
|
||||
|
||||
@@ -55,10 +57,16 @@ func userToken(t *testing.T, userID int64) string {
|
||||
func startServerWithManager(t *testing.T, joinTimeout time.Duration) (string, *game.Manager) {
|
||||
t.Helper()
|
||||
manager := game.NewManager(joinTimeout)
|
||||
log := slog.New(slog.NewTextHandler(testWriter{t}, nil))
|
||||
tw := &testWriter{t: t}
|
||||
log := slog.New(slog.NewTextHandler(tw, nil))
|
||||
handler := ws.NewHandler(manager, secret, publicAddr, []string{"*"}, log)
|
||||
srv := httptest.NewServer(handler)
|
||||
t.Cleanup(srv.Close)
|
||||
t.Cleanup(func() {
|
||||
srv.Close()
|
||||
tw.mu.Lock()
|
||||
tw.done = true
|
||||
tw.mu.Unlock()
|
||||
})
|
||||
return "ws" + strings.TrimPrefix(srv.URL, "http"), manager
|
||||
}
|
||||
|
||||
@@ -67,10 +75,18 @@ func startServer(t *testing.T, joinTimeout time.Duration) (url string) {
|
||||
return u
|
||||
}
|
||||
|
||||
type testWriter struct{ t *testing.T }
|
||||
type testWriter struct {
|
||||
mu sync.Mutex
|
||||
t *testing.T
|
||||
done bool
|
||||
}
|
||||
|
||||
func (w testWriter) Write(p []byte) (int, error) {
|
||||
w.t.Log(strings.TrimSpace(string(p)))
|
||||
func (w *testWriter) Write(p []byte) (int, error) {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
if !w.done {
|
||||
w.t.Log(strings.TrimSpace(string(p)))
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
@@ -317,3 +333,99 @@ func TestManagerShutdownClosesConnectionsGoingAway(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 TestPlaceShipsOverWebSocket(t *testing.T) {
|
||||
url, mgr := startServerWithManager(t, time.Minute)
|
||||
exp := time.Now().Add(time.Hour)
|
||||
gt := gameToken(t, "m-ws-placeships", 1, 2, publicAddr, exp)
|
||||
|
||||
c1, c2 := dial(t, url), dial(t, url)
|
||||
join(t, c1, gt, userToken(t, 1))
|
||||
join(t, c2, gt, userToken(t, 2))
|
||||
|
||||
// Both receive StatePlacingShips (seq 1)
|
||||
v1 := readMsg(t, c1)
|
||||
if v1[0] != float64(protocol.OpState) || v1[1] != float64(1) || v1[2] != float64(protocol.StatePlacingShips) {
|
||||
t.Fatalf("c1 unexpected initial state: %v", v1)
|
||||
}
|
||||
v2 := readMsg(t, c2)
|
||||
if v2[0] != float64(protocol.OpState) || v2[1] != float64(1) || v2[2] != float64(protocol.StatePlacingShips) {
|
||||
t.Fatalf("c2 unexpected initial state: %v", v2)
|
||||
}
|
||||
|
||||
// ACK seq 1
|
||||
_ = c1.Write(context.Background(), websocket.MessageText, protocol.BuildAck(1))
|
||||
_ = c2.Write(context.Background(), websocket.MessageText, protocol.BuildAck(1))
|
||||
|
||||
// Player 1 sends PlaceShips
|
||||
ships := validTestShips()
|
||||
placeMsg := protocol.BuildPlaceShips(ships)
|
||||
if err := c1.Write(context.Background(), websocket.MessageText, placeMsg); err != nil {
|
||||
t.Fatalf("write PlaceShips c1: %v", err)
|
||||
}
|
||||
|
||||
// c1 gets StateWaitOpponentReady (3), c2 gets StateOpponentReady (2)
|
||||
v1 = readMsg(t, c1)
|
||||
if v1[0] != float64(protocol.OpState) || v1[1] != float64(2) || v1[2] != float64(protocol.StateWaitOpponentReady) {
|
||||
t.Fatalf("c1 got %v, want StateWaitOpponentReady (3)", v1)
|
||||
}
|
||||
v2 = readMsg(t, c2)
|
||||
if v2[0] != float64(protocol.OpState) || v2[1] != float64(2) || v2[2] != float64(protocol.StateOpponentReady) {
|
||||
t.Fatalf("c2 got %v, want StateOpponentReady (2)", v2)
|
||||
}
|
||||
|
||||
_ = c1.Write(context.Background(), websocket.MessageText, protocol.BuildAck(2))
|
||||
_ = c2.Write(context.Background(), websocket.MessageText, protocol.BuildAck(2))
|
||||
|
||||
// Player 2 sends PlaceShips
|
||||
if err := c2.Write(context.Background(), websocket.MessageText, placeMsg); err != nil {
|
||||
t.Fatalf("write PlaceShips c2: %v", err)
|
||||
}
|
||||
|
||||
// Game starts: Player 1 was first, so c1 gets StateYourTurn (4), c2 gets StateWaitOpponentTurn (5)
|
||||
v1 = readMsg(t, c1)
|
||||
if v1[0] != float64(protocol.OpState) || v1[1] != float64(3) || v1[2] != float64(protocol.StateYourTurn) {
|
||||
t.Fatalf("c1 got %v, want StateYourTurn (4)", v1)
|
||||
}
|
||||
v2 = readMsg(t, c2)
|
||||
if v2[0] != float64(protocol.OpState) || v2[1] != float64(3) || v2[2] != float64(protocol.StateWaitOpponentTurn) {
|
||||
t.Fatalf("c2 got %v, want StateWaitOpponentTurn (5)", v2)
|
||||
}
|
||||
|
||||
_ = c1.Write(context.Background(), websocket.MessageText, protocol.BuildAck(3))
|
||||
_ = c2.Write(context.Background(), websocket.MessageText, protocol.BuildAck(3))
|
||||
|
||||
// Check that the match on the server has the placements stored
|
||||
match := mgr.GetMatch("m-ws-placeships")
|
||||
if match == nil {
|
||||
t.Fatal("match not found on manager")
|
||||
}
|
||||
if len(match.Ships(0)) != 10 || len(match.Ships(1)) != 10 {
|
||||
t.Fatalf("ships not stored on match: p1=%d, p2=%d", len(match.Ships(0)), len(match.Ships(1)))
|
||||
}
|
||||
if _, ok := match.Board(0); !ok {
|
||||
t.Fatal("p1 board not placed")
|
||||
}
|
||||
if _, ok := match.Board(1); !ok {
|
||||
t.Fatal("p2 board not placed")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user