mlp-server-tools/draftbot/draftbot_test.go

205 lines
4.6 KiB
Go

package main_test
import (
"testing"
"time"
"git.fromouter.space/mcg/draft/mlp"
"git.fromouter.space/mcg/cardgage/client/bot"
lobby "git.fromouter.space/mcg/cardgage/lobby/proto"
room "git.fromouter.space/mcg/cardgage/room/api"
draft "git.fromouter.space/mcg/mlp-server-tools/draftbot"
)
const TestBotName = "test-bot"
const TestRoomName = "test-room"
type MockServer struct {
in chan room.ServerMessage
out chan room.BotMessage
}
func makeMockServer() *MockServer {
in := make(chan room.ServerMessage)
out := make(chan room.BotMessage)
srv := &MockServer{
in: in,
out: out,
}
return srv
}
func (m *MockServer) Send(msg room.BotMessage) {
m.out <- msg
}
func (m *MockServer) Bind(fn bot.MessageHandler) {
for msg := range m.in {
fn(msg)
}
}
func TestDraftSession(t *testing.T) {
mock := makeMockServer()
draftbot := draft.NewDraftBot(mock, TestBotName)
go mock.Bind(draftbot.OnMessage)
// Create a new room
mock.in <- room.ServerMessage{
RoomID: TestRoomName,
Type: room.MsgEvent,
Event: &room.Event{
Type: room.EvtNewRoom,
Room: &lobby.Room{
Id: TestRoomName,
Name: "Test draft room",
Creator: "test-owner",
},
},
}
// Create new session with a fake message from owner
mock.message("test-owner", "create", draft.SessionOptions{
Players: 8, // Two players, six bots
Options: draft.DraftOptions{
Type: draft.DraftSet,
Positioning: draft.PosEven,
Set: mlp.SetAbsoluteDiscord,
PackCount: 4,
},
})
mock.expect(t, "session-open", 5)
// Join session as owner
mock.message("test-owner", "join", nil)
mock.expect(t, "player-joined-session", 5)
// .. and as second player
mock.message("test-guest", "join", nil)
mock.expect(t, "player-joined-session", 5)
// Try to start the session
mock.message("test-owner", "start", nil)
// These two can happen in any order, so they get their own special check
mock.multiexpect(t, 5, "session-start", "draft-order")
//TODO make players pick cards etc
// Close the room
mock.in <- room.ServerMessage{
RoomID: TestRoomName,
Type: room.MsgEvent,
Event: &room.Event{
Type: room.EvtRoomClosed,
},
}
}
func TestDraftSessionButEverythingGoesWrong(t *testing.T) {
mock := makeMockServer()
draftbot := draft.NewDraftBot(mock, TestBotName)
go mock.Bind(draftbot.OnMessage)
// Create a new room
mock.in <- room.ServerMessage{
Type: room.MsgEvent,
Event: &room.Event{
Type: room.EvtNewRoom,
Room: &lobby.Room{
Id: TestRoomName,
Name: "Test draft room",
Creator: "test-owner",
},
},
}
// Try creating a new session as NOT the owner
mock.message("test-guest", "create", draft.SessionOptions{
Players: 8, // Two players, six bots
Options: draft.DraftOptions{
Type: draft.DraftSet,
Positioning: draft.PosEven,
Set: mlp.SetAbsoluteDiscord,
PackCount: 4,
},
})
mock.expect(t, "must-be-owner", 5)
//TODO:
// Try to start session when session doesn't exist
// Try to create session twice
// Try to start session with no players
// Try to start session as not the owner
// Try to make too many players join a session
}
func (m *MockServer) expect(t *testing.T, typ string, timeout int) {
for {
select {
case msg := <-m.out:
// Skip all actions
if msg.Type != room.MsgMessage {
continue
}
// Check expected type
if msg.Message.Type != typ {
// Oh noes
t.Fatalf("Expected message \"%s\" but got \"%s\"", typ, msg.Message.Type)
}
return
case <-time.After(time.Duration(timeout) * time.Second):
t.Fatalf("Expected message \"%s\" but found nothing (timeout after %d seconds)!", typ, timeout)
}
}
}
func (m *MockServer) multiexpect(t *testing.T, timeout int, types ...string) {
for {
if len(types) < 1 {
return
}
select {
case msg := <-m.out:
// Skip all actions
if msg.Type != room.MsgMessage {
continue
}
// Check expected type
found := false
for i, typ := range types {
if typ == msg.Message.Type {
found = true
types[i] = types[len(types)-1]
types = types[:len(types)-1]
break
}
}
if !found {
// Oh noes
t.Fatalf("Expected one of %s but got \"%s\"", types, msg.Message.Type)
}
return
case <-time.After(time.Duration(timeout) * time.Second):
t.Fatalf("Expected one of %s but found nothing (timeout after %d seconds)!", types, timeout)
}
}
}
func (m *MockServer) message(from string, typ string, data interface{}) {
m.in <- room.ServerMessage{
RoomID: TestRoomName,
Type: room.MsgMessage,
Message: &room.Message{
From: from,
To: TestBotName,
Type: typ,
Data: data,
},
}
}