Fix picks being broadcasted, finish up main test
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Hamcha 2019-06-28 18:19:02 +02:00
parent fcb265c490
commit 21c257a0b1
2 changed files with 93 additions and 61 deletions

View File

@ -4,28 +4,33 @@ import (
"testing" "testing"
"time" "time"
"git.fromouter.space/mcg/draft"
"git.fromouter.space/mcg/draft/mlp" "git.fromouter.space/mcg/draft/mlp"
"git.fromouter.space/mcg/cardgage/client/bot" "git.fromouter.space/mcg/cardgage/client/bot"
lobby "git.fromouter.space/mcg/cardgage/lobby/proto" lobby "git.fromouter.space/mcg/cardgage/lobby/proto"
room "git.fromouter.space/mcg/cardgage/room/api" room "git.fromouter.space/mcg/cardgage/room/api"
draft "git.fromouter.space/mcg/mlp-server-tools/draftbot" draftbot "git.fromouter.space/mcg/mlp-server-tools/draftbot"
) )
const TestBotName = "test-bot" const TestBotName = "test-bot"
const TestRoomName = "test-room" const TestRoomName = "test-room"
type MockServer struct { type MockServer struct {
in chan room.ServerMessage in chan room.ServerMessage
out chan room.BotMessage out chan room.BotMessage
t *testing.T
timeout time.Duration
} }
func makeMockServer() *MockServer { func makeMockServer(t *testing.T, timeout int) *MockServer {
in := make(chan room.ServerMessage, 99) in := make(chan room.ServerMessage, 99)
out := make(chan room.BotMessage, 99) out := make(chan room.BotMessage, 99)
srv := &MockServer{ srv := &MockServer{
in: in, in: in,
out: out, out: out,
t: t,
timeout: time.Duration(timeout) * time.Second,
} }
return srv return srv
} }
@ -41,9 +46,9 @@ func (m *MockServer) Bind(fn bot.MessageHandler) {
} }
func TestDraftSession(t *testing.T) { func TestDraftSession(t *testing.T) {
mock := makeMockServer() mock := makeMockServer(t, 5)
draftbot := draft.NewDraftBot(mock, TestBotName) drafter := draftbot.NewDraftBot(mock, TestBotName)
go mock.Bind(draftbot.OnMessage) go mock.Bind(drafter.OnMessage)
// Create a new room // Create a new room
mock.in <- room.ServerMessage{ mock.in <- room.ServerMessage{
@ -60,33 +65,49 @@ func TestDraftSession(t *testing.T) {
} }
// Create new session with a fake message from owner // Create new session with a fake message from owner
mock.message("test-owner", "create", draft.SessionOptions{ mock.message("test-owner", "create", draftbot.SessionOptions{
Players: 8, // Two players, six bots Players: 8, // Two players, six bots
Options: draft.DraftOptions{ Options: draftbot.DraftOptions{
Type: draft.DraftSet, Type: draftbot.DraftSet,
Positioning: draft.PosEven, Positioning: draftbot.PosEven,
Set: mlp.SetAbsoluteDiscord, Set: mlp.SetAbsoluteDiscord,
PackCount: 4, PackCount: 4,
}, },
}) })
mock.expect(t, "session-open", 5) mock.expect("session-open")
// Join session as owner // Join session as owner
mock.message("test-owner", "join", nil) mock.message("test-owner", "join", nil)
mock.expect(t, "player-joined-session", 5) mock.expect("player-joined-session")
// .. and as second player // .. and as second player
mock.message("test-guest", "join", nil) mock.message("test-guest", "join", nil)
mock.expect(t, "player-joined-session", 5) mock.expect("player-joined-session")
// Try to start the session // Try to start the session
mock.message("test-owner", "start", nil) mock.message("test-owner", "start", nil)
// These two can happen in any order, so they get their own special check // These two can happen in any order, so they get their own special check
mock.multiexpect(t, 5, "session-start", "draft-order") mock.multiexpect("session-start", "draft-order")
//TODO make players pick cards etc // Pick card for each player
for packi := 0; packi < 4; packi++ {
mock.expect("draft-newpack")
for cardi := 0; cardi < 12; cardi++ {
// Get packs
msg1 := mock.expect("draft-newpick")
pack1 := msg1.Data.(draft.Pack)
msg2 := mock.expect("draft-newpick")
pack2 := msg2.Data.(draft.Pack)
// Pick first card in each pack
mock.message(msg1.To, "pick", pack1[0].ID)
mock.message(msg2.To, "pick", pack2[0].ID)
// Intercept picked events
mock.multiexpect("card-picked", "card-picked")
}
}
mock.expect("draft-finish")
// Close the room // Close the room
mock.in <- room.ServerMessage{ mock.in <- room.ServerMessage{
@ -99,9 +120,9 @@ func TestDraftSession(t *testing.T) {
} }
func TestDraftSessionButEverythingGoesWrong(t *testing.T) { func TestDraftSessionButEverythingGoesWrong(t *testing.T) {
mock := makeMockServer() mock := makeMockServer(t, 5)
draftbot := draft.NewDraftBot(mock, TestBotName) drafter := draftbot.NewDraftBot(mock, TestBotName)
go mock.Bind(draftbot.OnMessage) go mock.Bind(drafter.OnMessage)
// Create a new room // Create a new room
mock.in <- room.ServerMessage{ mock.in <- room.ServerMessage{
@ -117,80 +138,80 @@ func TestDraftSessionButEverythingGoesWrong(t *testing.T) {
} }
// Try creating a new session as NOT the owner // Try creating a new session as NOT the owner
mock.message("test-guest", "create", draft.SessionOptions{ mock.message("test-guest", "create", draftbot.SessionOptions{
Players: 8, Players: 8,
Options: draft.DraftOptions{ Options: draftbot.DraftOptions{
Type: draft.DraftSet, Type: draftbot.DraftSet,
Positioning: draft.PosEven, Positioning: draftbot.PosEven,
Set: mlp.SetAbsoluteDiscord, Set: mlp.SetAbsoluteDiscord,
PackCount: 4, PackCount: 4,
}, },
}) })
mock.expect(t, "must-be-owner", 5) mock.expect("must-be-owner")
// Try creating a session with an invalid type // Try creating a session with an invalid type
mock.message("test-owner", "create", draft.SessionOptions{ mock.message("test-owner", "create", draftbot.SessionOptions{
Players: 8, Players: 8,
Options: draft.DraftOptions{ Options: draftbot.DraftOptions{
Type: "lolwhat", Type: "lolwhat",
}, },
}) })
mock.expect(t, "session-create-error", 5) mock.expect("session-create-error")
// Try creating a session with invalid data // Try creating a session with invalid data
mock.message("test-owner", "create", 42) mock.message("test-owner", "create", 42)
mock.expect(t, "invalid-data", 5) mock.expect("invalid-data")
// Try starting a session that doesn't exist // Try starting a session that doesn't exist
mock.message("test-owner", "start", nil) mock.message("test-owner", "start", nil)
mock.expect(t, "command-unavailable", 5) mock.expect("command-unavailable")
// Try creating the session twice // Try creating the session twice
mock.message("test-owner", "create", draft.SessionOptions{ mock.message("test-owner", "create", draftbot.SessionOptions{
Players: 2, Players: 2,
Options: draft.DraftOptions{ Options: draftbot.DraftOptions{
Type: draft.DraftSet, Type: draftbot.DraftSet,
Positioning: draft.PosEven, Positioning: draftbot.PosEven,
Set: mlp.SetAbsoluteDiscord, Set: mlp.SetAbsoluteDiscord,
PackCount: 4, PackCount: 4,
}, },
}) })
mock.expect(t, "session-open", 5) mock.expect("session-open")
mock.message("test-owner", "create", draft.SessionOptions{ mock.message("test-owner", "create", draftbot.SessionOptions{
Players: 2, Players: 2,
Options: draft.DraftOptions{ Options: draftbot.DraftOptions{
Type: draft.DraftSet, Type: draftbot.DraftSet,
Positioning: draft.PosEven, Positioning: draftbot.PosEven,
Set: mlp.SetAbsoluteDiscord, Set: mlp.SetAbsoluteDiscord,
PackCount: 4, PackCount: 4,
}, },
}) })
mock.expect(t, "command-unavailable", 5) mock.expect("command-unavailable")
// Try to start session when no-one has joined // Try to start session when no-one has joined
mock.message("test-owner", "start", nil) mock.message("test-owner", "start", nil)
mock.expect(t, "session-start-error", 5) mock.expect("session-start-error")
// Try to make too many players join // Try to make too many players join
mock.message("a", "join", nil) mock.message("a", "join", nil)
mock.expect(t, "player-joined-session", 5) mock.expect("player-joined-session")
mock.message("b", "join", nil) mock.message("b", "join", nil)
mock.expect(t, "player-joined-session", 5) mock.expect("player-joined-session")
mock.message("c", "join", nil) mock.message("c", "join", nil)
mock.expect(t, "session-full", 5) mock.expect("session-full")
// Try to make someone join a session that already started // Try to make someone join a session that already started
mock.message("test-owner", "start", nil) mock.message("test-owner", "start", nil)
mock.multiexpect(t, 5, "session-start", "draft-order") mock.multiexpect("session-start", "draft-order", "draft-newpack", "draft-newpick", "draft-newpick")
mock.message("c", "join", nil) mock.message("c", "join", nil)
mock.expect(t, "session-already-started", 5) mock.expect("session-already-started")
//TODO More picking, etc shenanigans //TODO More picking, etc shenanigans
} }
func (m *MockServer) expect(t *testing.T, typ string, timeout int) { func (m *MockServer) expect(typ string) *room.Message {
for { for {
select { select {
case msg := <-m.out: case msg := <-m.out:
@ -202,27 +223,31 @@ func (m *MockServer) expect(t *testing.T, typ string, timeout int) {
// Check expected type // Check expected type
if msg.Message.Type != typ { if msg.Message.Type != typ {
// Oh noes // Oh noes
t.Fatalf("Expected message \"%s\" but got \"%s\"", typ, msg.Message.Type) m.t.Fatalf("Expected message \"%s\" but got \"%s\"", typ, msg.Message.Type)
} }
return return msg.Message
case <-time.After(time.Duration(timeout) * time.Second): case <-time.After(m.timeout):
t.Fatalf("Expected message \"%s\" but found nothing (timeout after %d seconds)!", typ, timeout) m.t.Fatalf("Expected message \"%s\" but found nothing (timeout)!", typ)
return nil
} }
} }
} }
func (m *MockServer) multiexpect(t *testing.T, timeout int, types ...string) { func (m *MockServer) multiexpect(types ...string) {
for { for {
if len(types) < 1 { if len(types) < 1 {
return return
} }
select { select {
case msg := <-m.out: case msg := <-m.out:
// Skip all actions // Skip all actions
if msg.Type != room.MsgMessage { if msg.Type != room.MsgMessage {
continue continue
} }
m.t.Logf("-> [%s] %s", msg.Message.Type, msg.Message.Message)
// Check expected type // Check expected type
found := false found := false
for i, typ := range types { for i, typ := range types {
@ -235,15 +260,16 @@ func (m *MockServer) multiexpect(t *testing.T, timeout int, types ...string) {
} }
if !found { if !found {
// Oh noes // Oh noes
t.Fatalf("Expected one of %s but got \"%s\"", types, msg.Message.Type) m.t.Fatalf("Expected one of %s but got \"%s\"", types, msg.Message.Type)
} }
case <-time.After(time.Duration(timeout) * time.Second): case <-time.After(m.timeout):
t.Fatalf("Expected one of %s but found nothing (timeout after %d seconds)!", types, timeout) m.t.Fatalf("Expected one of %s but found nothing (timeout)!", types)
} }
} }
} }
func (m *MockServer) message(from string, typ string, data interface{}) { func (m *MockServer) message(from string, typ string, data interface{}) {
m.t.Logf("<- <%s> %s (%v)", from, typ, data)
m.in <- room.ServerMessage{ m.in <- room.ServerMessage{
RoomID: TestRoomName, RoomID: TestRoomName,
Type: room.MsgMessage, Type: room.MsgMessage,

View File

@ -231,15 +231,20 @@ func (s *session) handlePicks() {
bot.PickNext() bot.PickNext()
} }
// Tell every players their new cards // Tell every players their new cards
for _, player := range s.Players { for pname, player := range s.Players {
s.messages <- room.Message{ s.messages <- room.Message{
Channel: "draft", To: pname,
Type: "draft-newpick", Type: "draft-newpick",
Data: player.CurrentPack, Data: player.CurrentPack,
Message: fmt.Sprintf("You got these cards: %s", player.CurrentPack), Message: fmt.Sprintf("You got these cards: %s", player.CurrentPack),
} }
} }
nextPack := false
select { select {
case <-s.Pod.ReadyNextPack:
// Break of pick loop, get next packs
nextPack = true
case <-s.Pod.ReadyNextPick: case <-s.Pod.ReadyNextPick:
// Pass packs around // Pass packs around
err := s.Pod.NextPacks() err := s.Pod.NextPacks()
@ -253,15 +258,16 @@ func (s *session) handlePicks() {
return return
} }
} }
case <-s.Pod.ReadyNextPack:
// Break of pick loop, get next packs
break
case <-s.exit: case <-s.exit:
// Room closed, exit early // Room closed, exit early
close(s.messages) close(s.messages)
close(s.exit) close(s.exit)
return return
} }
if nextPack {
break
}
} }
} }
} }