Server tests

This commit is contained in:
Neale Pickett 2020-08-19 18:01:21 -06:00
parent f8556dd2e5
commit f49d1c3801
9 changed files with 137 additions and 33 deletions

View File

@ -38,7 +38,9 @@ func (h *HTTPServer) HandleMothFunc(
mothHandler func(MothRequestHandler, http.ResponseWriter, *http.Request),
) {
handler := func(w http.ResponseWriter, req *http.Request) {
mh := h.server.NewHandler(req.FormValue("id"))
participantID := req.FormValue("pid")
teamID := req.FormValue("id")
mh := h.server.NewHandler(participantID, teamID)
mothHandler(mh, w, req)
}
h.HandleFunc(h.base+pattern, handler)

10
cmd/mothd/httpd_test.go Normal file
View File

@ -0,0 +1,10 @@
package main
import (
"testing"
)
func TestHttpd(t *testing.T) {
//emptyBody := bytes.NewReader([]byte{})
//request := httptest.NewRequest("GET", "/", emptyBody)
}

View File

@ -2,7 +2,6 @@ package main
import (
"flag"
"log"
"mime"
"time"
@ -10,8 +9,6 @@ import (
)
func main() {
log.Print("Started")
themePath := flag.String(
"theme",
"theme",
@ -59,5 +56,6 @@ func main() {
server := NewMothServer(puzzles, theme, state)
httpd := NewHTTPServer(*base, server)
httpd.Run(*bindStr)
}

View File

@ -1,12 +0,0 @@
package main
import (
"testing"
)
func TestEverything(t *testing.T) {
state := NewTestState()
t.Error("No test")
state.refresh()
}

View File

@ -12,8 +12,9 @@ var testFiles = []struct {
Name, Body string
}{
{"puzzles.txt", "1"},
{"answers.txt", "1 answer123\n1 answer456\n"},
{"content/1/puzzle.json", `{"name": "moo"}`},
{"content/1/moo.txt", `My cow goes "moo"`},
{"content/1/moo.txt", `moo`},
}
func (m *Mothballs) createMothball(cat string) {
@ -29,11 +30,16 @@ func (m *Mothballs) createMothball(cat string) {
}
}
func TestMothballs(t *testing.T) {
func NewTestMothballs() *Mothballs {
m := NewMothballs(new(afero.MemMapFs))
m.createMothball("test1")
m.createMothball("pategory")
m.refresh()
if _, ok := m.categories["test1"]; !ok {
return m
}
func TestMothballs(t *testing.T) {
m := NewTestMothballs()
if _, ok := m.categories["pategory"]; !ok {
t.Error("Didn't create a new category")
}
@ -52,11 +58,22 @@ func TestMothballs(t *testing.T) {
}
}
if err := m.CheckAnswer("pategory", 1, "answer"); err == nil {
t.Error("Wrong answer marked right")
}
if err := m.CheckAnswer("pategory", 1, "answer123"); err != nil {
t.Error("Right answer marked wrong", err)
}
if err := m.CheckAnswer("pategory", 1, "answer456"); err != nil {
t.Error("Right answer marked wrong", err)
}
m.createMothball("test2")
m.Fs.Remove("test1.mb")
m.Fs.Remove("pategory.mb")
m.refresh()
inv = m.Inventory()
if len(inv) != 1 {
t.Error("Deleted mothball is still around", inv)
}
}

View File

@ -54,6 +54,7 @@ type StateProvider interface {
TeamName(teamID string) (string, error)
SetTeamName(teamID, teamName string) error
AwardPoints(teamID string, cat string, points int) error
LogEvent(msg string)
Maintainer
}
@ -82,17 +83,19 @@ func NewMothServer(puzzles PuzzleProvider, theme ThemeProvider, state StateProvi
}
// NewHandler returns a new http.RequestHandler for the provided teamID.
func (s *MothServer) NewHandler(teamID string) MothRequestHandler {
func (s *MothServer) NewHandler(participantID, teamID string) MothRequestHandler {
return MothRequestHandler{
MothServer: s,
teamID: teamID,
MothServer: s,
participantID: participantID,
teamID: teamID,
}
}
// MothRequestHandler provides http.RequestHandler for a MothServer.
type MothRequestHandler struct {
*MothServer
teamID string
participantID string
teamID string
}
// PuzzlesOpen opens a file associated with a puzzle.
@ -126,10 +129,14 @@ func (mh *MothRequestHandler) Register(teamName string) error {
// CheckAnswer returns an error if answer is not a correct answer for puzzle points in category cat
func (mh *MothRequestHandler) CheckAnswer(cat string, points int, answer string) error {
if err := mh.Puzzles.CheckAnswer(cat, points, answer); err != nil {
msg := fmt.Sprintf("BAD %s %s %s %d %s", mh.participantID, mh.teamID, cat, points, err.Error())
mh.State.LogEvent(msg)
return err
}
if err := mh.State.AwardPoints(mh.teamID, cat, points); err != nil {
msg := fmt.Sprintf("GOOD %s %s %s %d", mh.participantID, mh.teamID, cat, points)
mh.State.LogEvent(msg)
return err
}

86
cmd/mothd/server_test.go Normal file
View File

@ -0,0 +1,86 @@
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)
afero.WriteFile(state, "messages.html", []byte("messages.html"), 0644)
go state.Maintain(TestMaintenanceInterval)
theme := NewTestTheme()
afero.WriteFile(theme.Fs, "index.html", []byte("index.html"), 0644)
go theme.Maintain(TestMaintenanceInterval)
return NewMothServer(puzzles, theme, state)
}
func TestServer(t *testing.T) {
teamName := "OurTeam"
participantID := "participantID"
teamID := TestTeamID
server := NewTestServer()
handler := server.NewHandler(participantID, teamID)
if err := handler.Register(teamName); err != nil {
t.Error(err)
}
if r, _, err := handler.ThemeOpen("index.html"); err != nil {
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)
}
es := handler.ExportState()
if es.Config.Devel {
t.Error("Marked as development server")
}
if len(es.Puzzles) != 1 {
t.Error("Puzzle categories wrong length")
}
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")
}
if r, _, err := handler.PuzzlesOpen("pategory", 1, "moo.txt"); err != nil {
t.Error(err)
} else if contents, err := ioutil.ReadAll(r); err != nil {
t.Error(err)
} else if string(contents) != "moo" {
t.Error("moo.txt has wrong contents", contents)
}
if err := handler.CheckAnswer("pategory", 1, "answer123"); err != nil {
t.Error("Right answer marked wrong", err)
}
time.Sleep(TestMaintenanceInterval)
es = handler.ExportState()
if len(es.PointsLog) != 1 {
t.Error("I didn't get my points!")
}
}

View File

@ -204,7 +204,9 @@ func (s *State) AwardPoints(teamID, category string, points int) error {
return err
}
// BUG(neale): When points are awarded, state should be updated immediately
// State should be updated immediately
s.refreshNow <- true
return nil
}
@ -342,12 +344,6 @@ func (s *State) LogEvent(msg string) {
s.eventStream <- msg
}
// LogEventf writes a formatted message to the event log
func (s *State) LogEventf(format string, a ...interface{}) {
msg := fmt.Sprintf(format, a...)
s.LogEvent(msg)
}
func (s *State) reopenEventLog() error {
if s.eventWriter != nil {
if err := s.eventWriter.Close(); err != nil {

View File

@ -78,7 +78,7 @@ func TestState(t *testing.T) {
func TestStateEvents(t *testing.T) {
s := NewTestState()
s.LogEvent("moo")
s.LogEventf("moo %d", 2)
s.LogEvent("moo 2")
if msg := <-s.eventStream; msg != "moo" {
t.Error("Wrong message from event stream", msg)