From eb3a30ec8a0916881e76621db908d0f986b9ca75 Mon Sep 17 00:00:00 2001 From: Bel LaPointe <153096461+breel-render@users.noreply.github.com> Date: Sun, 15 Dec 2024 10:19:04 -0700 Subject: [PATCH] test hangs due to fill inf looping --- cmd/server/games.go | 37 +++++---- cmd/server/games_test.go | 167 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 190 insertions(+), 14 deletions(-) diff --git a/cmd/server/games.go b/cmd/server/games.go index e1c1c8a..1ae2286 100644 --- a/cmd/server/games.go +++ b/cmd/server/games.go @@ -465,23 +465,40 @@ func (m AllKillWords) assigned() []string { return result } +//go:embed holiday.txt +var wordsHoliday string + func (m AllKillWords) FillKillWords() AllKillWords { + return m.fillKillWords( + strings.Fields(wordsHoliday), + strings.Fields(wordsHoliday), // TODO medium difficulty + strings.Fields(wordsHoliday), // TODO hard difficulty + ) +} + +func (m AllKillWords) fillKillWords( + poolGlobal, + poolPublic, + poolPrivate []string, +) AllKillWords { + result := maps.Clone(m) + m = result for k, v := range m { if v.Global.Word == "" { - v.Global = KillWord{Word: m.unusedGlobal(), Points: -1} + v.Global = KillWord{Word: m.unusedGlobal(poolGlobal), Points: -1} m[k] = v } if len(v.Assignment.Public) == 0 { v.Assignment.Public = []KillWord{} for i := 0; i < 2; i++ { - v.Assignment.Public = append(v.Assignment.Public, KillWord{Word: m.unusedPublic(), Points: 50}) + v.Assignment.Public = append(v.Assignment.Public, KillWord{Word: m.unusedPublic(poolPublic), Points: 50}) m[k] = v } } if len(v.Assignment.Private) == 0 { v.Assignment.Private = []KillWord{} for i := 0; i < 2; i++ { - v.Assignment.Private = append(v.Assignment.Private, KillWord{Word: m.unusedPrivate(), Points: 100}) + v.Assignment.Private = append(v.Assignment.Private, KillWord{Word: m.unusedPrivate(poolPrivate), Points: 100}) m[k] = v } } @@ -489,11 +506,7 @@ func (m AllKillWords) FillKillWords() AllKillWords { return m } -//go:embed holiday.txt -var wordsHoliday string - -func (m AllKillWords) unusedGlobal() string { - pool := strings.Fields(wordsHoliday) +func (m AllKillWords) unusedGlobal(pool []string) string { inUse := func() []string { result := []string{} for _, killWords := range m { @@ -509,9 +522,7 @@ func (m AllKillWords) unusedGlobal() string { } } -// TODO hard difficulty -func (m AllKillWords) unusedPrivate() string { - pool := strings.Fields(wordsHoliday) +func (m AllKillWords) unusedPrivate(pool []string) string { inUse := func() []string { result := []string{} for _, killWords := range m { @@ -529,9 +540,7 @@ func (m AllKillWords) unusedPrivate() string { } } -// TODO medium difficulty -func (m AllKillWords) unusedPublic() string { - pool := strings.Fields(wordsHoliday) +func (m AllKillWords) unusedPublic(pool []string) string { inUse := func() []string { result := []string{} for _, killWords := range m { diff --git a/cmd/server/games_test.go b/cmd/server/games_test.go index b39f4fa..7796f9d 100644 --- a/cmd/server/games_test.go +++ b/cmd/server/games_test.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "context" "encoding/json" "fmt" @@ -213,3 +214,169 @@ func TestParseEvent(t *testing.T) { }) } } + +func TestAllKillWordsFill(t *testing.T) { + kw := func(w string) KillWord { + return KillWord{Word: w} + } + kws := func(w string) []KillWord { + if w == "" { + return nil + } + return []KillWord{kw(w)} + } + ass := func(pub, pri string) Assignment { + return Assignment{ + Public: kws(pub), + Private: kws(pri), + } + } + + cases := map[string]struct { + given KillWords + expect KillWords + }{ + "full": { + given: KillWords{ + Global: kw("global"), + Assignment: ass("pub", "pri"), + }, + expect: KillWords{ + Global: kw("global"), + Assignment: ass("pub", "pri"), + }, + }, + "no ass": { + given: KillWords{ + Global: kw("global"), + Assignment: Assignment{}, + }, + expect: KillWords{ + Global: kw("global"), + Assignment: ass("filled-public", "filled-private"), + }, + }, + "no pub": { + given: KillWords{ + Global: kw("global"), + Assignment: ass("", "pri"), + }, + expect: KillWords{ + Global: kw("global"), + Assignment: ass("filled-public", "filled-private"), + }, + }, + "no pri": { + given: KillWords{ + Global: kw("global"), + Assignment: ass("pub", ""), + }, + expect: KillWords{ + Global: kw("global"), + Assignment: ass("pub", "filled-private"), + }, + }, + "empty": { + given: KillWords{}, + expect: KillWords{ + Global: kw("filled-global"), + Assignment: ass("filled-public", "filled-private"), + }, + }, + "no global": { + given: KillWords{ + Assignment: ass("pub", "pri"), + }, + expect: KillWords{ + Global: kw("filled-global"), + Assignment: ass("pub", "pri"), + }, + }, + } + + equal := func(a, b KillWords) bool { + ba, _ := json.Marshal(a) + bb, _ := json.Marshal(b) + return bytes.Equal(ba, bb) + } + + for name, d := range cases { + c := d + t.Run(name, func(t *testing.T) { + akw := make(AllKillWords) + akw[name] = c.given + akw = akw.fillKillWords( + []string{"filled-global"}, + []string{"filled-public"}, + []string{"filled-private"}, + ) + got := akw[name] + + if !equal(c.expect, got) { + t.Errorf("expected \n\t%+v but got \n\t%+v", c.expect, got) + } + }) + } +} + +func TestAllKillWordsUnused(t *testing.T) { + t.Run("empty", func(t *testing.T) { + akw := make(AllKillWords) + if got := akw.unusedPublic([]string{"x"}); got != "x" { + t.Error("empty playerbase didnt think only option was unused") + } + + if got := akw.unusedPrivate([]string{"x"}); got != "x" { + t.Error("empty playerbase didnt think only option was unused") + } + + if got := akw.unusedGlobal([]string{"x"}); got != "x" { + t.Error("empty playerbase didnt think only option was unused") + } + }) + + t.Run("dont return used", func(t *testing.T) { + t.Run("private", func(t *testing.T) { + akw := make(AllKillWords) + akw["k"] = KillWords{ + Global: KillWord{Word: "x"}, + Assignment: Assignment{ + Private: []KillWord{{}, {Word: "y"}}, + Public: []KillWord{{}, {Word: "x"}}, + }, + } + got := akw.unusedPrivate([]string{"x", "y"}) + if got != "x" { + t.Error("didnt return only unused option") + } + }) + t.Run("global", func(t *testing.T) { + akw := make(AllKillWords) + akw["k"] = KillWords{ + Global: KillWord{Word: "y"}, + Assignment: Assignment{ + Private: []KillWord{{}, {Word: "x"}}, + Public: []KillWord{{}, {Word: "x"}}, + }, + } + got := akw.unusedGlobal([]string{"x", "y"}) + if got != "x" { + t.Error("didnt return only unused option") + } + }) + t.Run("public", func(t *testing.T) { + akw := make(AllKillWords) + akw["k"] = KillWords{ + Global: KillWord{Word: "x"}, + Assignment: Assignment{ + Private: []KillWord{{}, {Word: "x"}}, + Public: []KillWord{{}, {Word: "y"}}, + }, + } + got := akw.unusedPublic([]string{"x", "y"}) + if got != "x" { + t.Error("didnt return only unused option") + } + }) + }) +}