2020-08-19 18:01:21 -06:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io/ioutil"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/spf13/afero"
|
|
|
|
)
|
|
|
|
|
|
|
|
const TestMaintenanceInterval = time.Millisecond * 1
|
|
|
|
const TestTeamID = "teamID"
|
|
|
|
|
|
|
|
func NewTestServer() *MothServer {
|
|
|
|
puzzles := NewTestMothballs()
|
|
|
|
go puzzles.Maintain(TestMaintenanceInterval)
|
|
|
|
|
|
|
|
state := NewTestState()
|
|
|
|
afero.WriteFile(state, "teamids.txt", []byte("teamID\n"), 0644)
|
2022-01-28 16:26:27 -07:00
|
|
|
afero.WriteFile(state, "participantids.txt", []byte("participantID\n"), 0644)
|
2020-08-19 18:01:21 -06:00
|
|
|
afero.WriteFile(state, "messages.html", []byte("messages.html"), 0644)
|
|
|
|
go state.Maintain(TestMaintenanceInterval)
|
|
|
|
|
|
|
|
theme := NewTestTheme()
|
2020-08-21 17:02:38 -06:00
|
|
|
afero.WriteFile(theme.Fs, "/index.html", []byte("index.html"), 0644)
|
2020-08-19 18:01:21 -06:00
|
|
|
go theme.Maintain(TestMaintenanceInterval)
|
|
|
|
|
2020-09-11 20:16:58 -06:00
|
|
|
return NewMothServer(Configuration{}, theme, state, puzzles)
|
2020-08-19 18:01:21 -06:00
|
|
|
}
|
|
|
|
|
2020-10-16 14:18:44 -06:00
|
|
|
func TestDevelServer(t *testing.T) {
|
|
|
|
server := NewTestServer()
|
|
|
|
server.Config.Devel = true
|
|
|
|
anonHandler := server.NewHandler("badParticipantId", "badTeamId")
|
|
|
|
|
|
|
|
{
|
|
|
|
es := anonHandler.ExportState()
|
|
|
|
if !es.Config.Devel {
|
|
|
|
t.Error("Not marked as development server")
|
|
|
|
}
|
|
|
|
if len(es.Puzzles) != 1 {
|
|
|
|
t.Error("Wrong puzzles for anonymous state on devel server:", es.Puzzles)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestProdServer(t *testing.T) {
|
2020-08-19 18:01:21 -06:00
|
|
|
teamName := "OurTeam"
|
|
|
|
participantID := "participantID"
|
|
|
|
teamID := TestTeamID
|
|
|
|
|
|
|
|
server := NewTestServer()
|
|
|
|
handler := server.NewHandler(participantID, teamID)
|
2020-10-13 18:33:12 -06:00
|
|
|
anonHandler := server.NewHandler("badParticipantId", "badTeamId")
|
2020-10-13 16:41:50 -06:00
|
|
|
|
|
|
|
{
|
|
|
|
es := handler.ExportState()
|
|
|
|
if es.Config.Devel {
|
|
|
|
t.Error("Marked as development server", es.Config)
|
|
|
|
}
|
|
|
|
if len(es.Puzzles) != 0 {
|
|
|
|
t.Log("State", es)
|
|
|
|
t.Error("Unauthenticated state has non-empty puzzles list")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-19 18:01:21 -06:00
|
|
|
if err := handler.Register(teamName); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
2020-10-13 18:33:12 -06:00
|
|
|
if err := handler.Register(teamName); err == nil {
|
|
|
|
t.Error("Registering twice should have raised an error")
|
|
|
|
} else if err != ErrAlreadyRegistered {
|
|
|
|
t.Error("Wrong error for duplicate registration:", err)
|
|
|
|
}
|
|
|
|
|
2022-01-28 17:03:34 -07:00
|
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
|
2022-01-28 16:26:27 -07:00
|
|
|
if err := handler.AssignParticipant(); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
if err := handler.AssignParticipant(); err == nil {
|
|
|
|
t.Error("Assigning a participant twice should have raised an error")
|
|
|
|
} else if err != ErrAlreadyRegistered {
|
|
|
|
t.Error("Wrong error for duplicate registration:", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-21 17:02:38 -06:00
|
|
|
if r, _, err := handler.ThemeOpen("/index.html"); err != nil {
|
2020-08-19 18:01:21 -06:00
|
|
|
t.Error(err)
|
|
|
|
} else if contents, err := ioutil.ReadAll(r); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
} else if string(contents) != "index.html" {
|
|
|
|
t.Error("index.html wrong contents", contents)
|
|
|
|
}
|
|
|
|
|
2021-10-26 12:48:23 -06:00
|
|
|
// Wait for refresh to pick everything up
|
|
|
|
time.Sleep(TestMaintenanceInterval)
|
|
|
|
|
2020-10-14 10:04:13 -06:00
|
|
|
{
|
|
|
|
es := handler.ExportState()
|
|
|
|
if es.Config.Devel {
|
|
|
|
t.Error("Marked as development server", es.Config)
|
|
|
|
}
|
|
|
|
if len(es.Puzzles) != 1 {
|
2021-10-26 12:48:23 -06:00
|
|
|
t.Error("Puzzle categories wrong length", len(es.Puzzles))
|
2020-10-14 10:04:13 -06:00
|
|
|
}
|
|
|
|
if es.Messages != "messages.html" {
|
|
|
|
t.Error("Messages has wrong contents")
|
|
|
|
}
|
|
|
|
if len(es.PointsLog) != 0 {
|
|
|
|
t.Error("Points log not empty")
|
|
|
|
}
|
|
|
|
if len(es.TeamNames) != 1 {
|
|
|
|
t.Error("Wrong number of team names")
|
|
|
|
}
|
|
|
|
if es.TeamNames["self"] != teamName {
|
|
|
|
t.Error("TeamNames['self'] wrong")
|
|
|
|
}
|
2020-08-19 18:01:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if r, _, err := handler.PuzzlesOpen("pategory", 1, "moo.txt"); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
} else if contents, err := ioutil.ReadAll(r); err != nil {
|
2020-08-21 17:02:38 -06:00
|
|
|
r.Close()
|
2020-08-19 18:01:21 -06:00
|
|
|
t.Error(err)
|
|
|
|
} else if string(contents) != "moo" {
|
2020-08-21 17:02:38 -06:00
|
|
|
r.Close()
|
2020-08-19 18:01:21 -06:00
|
|
|
t.Error("moo.txt has wrong contents", contents)
|
2020-08-21 17:02:38 -06:00
|
|
|
} else {
|
|
|
|
r.Close()
|
|
|
|
}
|
|
|
|
|
2020-10-13 18:33:12 -06:00
|
|
|
if r, _, err := handler.PuzzlesOpen("pategory", 2, "puzzle.json"); err == nil {
|
2020-08-21 17:02:38 -06:00
|
|
|
t.Error("Opening locked puzzle shouldn't work")
|
|
|
|
r.Close()
|
|
|
|
}
|
|
|
|
|
2020-10-13 18:33:12 -06:00
|
|
|
if r, _, err := handler.PuzzlesOpen("pategory", 20, "puzzle.json"); err == nil {
|
2020-08-21 17:02:38 -06:00
|
|
|
t.Error("Opening non-existent puzzle shouldn't work")
|
|
|
|
r.Close()
|
2020-08-19 18:01:21 -06:00
|
|
|
}
|
|
|
|
|
2020-12-02 19:31:34 -07:00
|
|
|
if err := anonHandler.CheckAnswer("pategory", 1, "answer123"); err == nil {
|
2022-01-28 16:26:27 -07:00
|
|
|
t.Error("Invalid participant ID was able to get points with correct answer")
|
2020-12-02 19:31:34 -07:00
|
|
|
}
|
2020-08-19 18:01:21 -06:00
|
|
|
if err := handler.CheckAnswer("pategory", 1, "answer123"); err != nil {
|
|
|
|
t.Error("Right answer marked wrong", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
time.Sleep(TestMaintenanceInterval)
|
|
|
|
|
2020-10-14 10:04:13 -06:00
|
|
|
{
|
|
|
|
es := handler.ExportState()
|
|
|
|
if len(es.PointsLog) != 1 {
|
|
|
|
t.Error("I didn't get my points!")
|
|
|
|
}
|
|
|
|
if len(es.Puzzles["pategory"]) != 2 {
|
|
|
|
t.Error("The next puzzle didn't unlock!")
|
|
|
|
} else if es.Puzzles["pategory"][1] != 2 {
|
|
|
|
t.Error("The 2-point puzzle should have unlocked!")
|
|
|
|
}
|
2020-10-13 18:33:12 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if r, _, err := handler.PuzzlesOpen("pategory", 2, "puzzle.json"); err != nil {
|
|
|
|
t.Error("Opening unlocked puzzle should work")
|
|
|
|
} else {
|
|
|
|
r.Close()
|
|
|
|
}
|
|
|
|
if r, _, err := anonHandler.PuzzlesOpen("pategory", 2, "puzzle.json"); err != nil {
|
|
|
|
t.Error("Opening unlocked puzzle anonymously should work")
|
|
|
|
} else {
|
|
|
|
r.Close()
|
|
|
|
}
|
2020-08-21 17:02:38 -06:00
|
|
|
|
2020-10-14 09:46:51 -06:00
|
|
|
if err := handler.CheckAnswer("pategory", 2, "wat"); err != nil {
|
|
|
|
t.Error("Right answer marked wrong:", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
time.Sleep(TestMaintenanceInterval)
|
2020-10-14 10:04:13 -06:00
|
|
|
|
|
|
|
{
|
|
|
|
es := anonHandler.ExportState()
|
|
|
|
if len(es.TeamNames) != 1 {
|
|
|
|
t.Error("Anonymous TeamNames is wrong:", es.TeamNames)
|
|
|
|
}
|
|
|
|
if len(es.PointsLog) != 2 {
|
2021-10-18 18:30:11 -06:00
|
|
|
t.Errorf("Points log wrong length: got %d, wanted 2", len(es.PointsLog))
|
|
|
|
} else if es.PointsLog[1].TeamID != "0" {
|
2020-10-14 10:04:13 -06:00
|
|
|
t.Error("Second point log didn't anonymize team ID correctly:", es.PointsLog[1])
|
|
|
|
}
|
2020-10-14 09:52:19 -06:00
|
|
|
}
|
2020-10-14 09:46:51 -06:00
|
|
|
|
2020-10-14 10:04:13 -06:00
|
|
|
{
|
|
|
|
es := handler.ExportState()
|
|
|
|
if len(es.TeamNames) != 1 {
|
|
|
|
t.Error("TeamNames is wrong:", es.TeamNames)
|
|
|
|
}
|
2020-10-14 09:46:51 -06:00
|
|
|
}
|
|
|
|
|
2020-08-21 17:02:38 -06:00
|
|
|
// BUG(neale): We aren't currently testing the various ways to disable the server
|
2020-08-19 18:01:21 -06:00
|
|
|
}
|