package main import ( "context" "fmt" "testing" ) func TestUserGameServer(t *testing.T) { ctx := context.Background() games := newTestGames(t) gid, err := games.CreateGame(ctx, "g1") if err != nil { t.Fatal(err) } pids := []string{} for i := 0; i < 4; i++ { pid := fmt.Sprintf("p%d", i+1) if err := games.CreateEventPlayerJoin(ctx, gid, pid); err != nil { t.Fatal(err) } pids = append(pids, pid) } ugs, err := NewUserGameServer(ctx, Session{ID: pids[0]}, games) if err != nil { t.Fatal(err) } t.Run("unstarted", func(t *testing.T) { state, err := ugs.State(ctx) if err != nil { t.Fatal(err) } if state.Started { t.Error("started after player joins only") } if !state.Completed.IsZero() { t.Error("completed after player joins only") } for _, pid := range pids { if p, ok := state.Players[pid]; !ok { t.Error(pid, "not in players") } else if !p.Empty() { t.Error(pid, p) } } }) if err := games.CreateEventAssignmentRotation(ctx, gid, "", "", "", 0); err != nil { t.Fatal(err) } t.Run("just started", func(t *testing.T) { state, err := ugs.State(ctx) if err != nil { t.Fatal(err) } if !state.Started { t.Error("not started after assignment rotation") } if !state.Completed.IsZero() { t.Error("completed after assignment rotation") } for _, pid := range pids { p, ok := state.Players[pid] if !ok { t.Error(pid, "not in players") } else if p.Empty() { t.Error(pid, p) } else if len(p.Kills) > 0 { t.Error(pid, "has a kill") } else if p.KillWords.Assigned.IsZero() { t.Error("assigned is zero") } if isSelf := pid == ugs.Session.ID; isSelf { if p.KillWords.Codename.KillWord.Word == "" || p.KillWords.Codename.KillWord.Points == 0 { t.Error("self codename missing field") } if p.KillWords.Assignee == "" { t.Error("assignee is empty") } if len(p.KillWords.Assignment.Public) > 0 { t.Error("self knows its own public") } if len(p.KillWords.Assignment.Private) > 0 { t.Error("self knows its own private") } } else { if !p.KillWords.Codename.KillWord.Empty() { t.Error("can see not self Codename") } if p.KillWords.Assignee != "" { t.Error("can see other player's assignee") } if len(p.KillWords.Assignment.Public) == 0 { t.Error("cannot see other player's public") } if state.Players[ugs.Session.ID].KillWords.Assignee == pid && len(p.KillWords.Assignment.Private) == 0 { t.Error("cannot see assignee's private") } else if state.Players[ugs.Session.ID].KillWords.Assignee != pid && len(p.KillWords.Assignment.Private) > 0 { t.Error("can see not assignee's private") } } } }) for i := 0; i < 3; i++ { state, err := games.GameState(ctx, ugs.ID) if err != nil { t.Fatal(err) } killer := ugs.Session.ID if i > 0 { killer = state.Players[killer].KillWords.Assignee } victim := state.Players[killer].KillWords.Assignee word := state.Players[victim].KillWords.Assignment.Public[0].Word points := state.Players[victim].KillWords.Assignment.Public[0].Points if err := games.CreateEventAssignmentRotation(ctx, gid, killer, victim, word, points); err != nil { t.Fatal(err) } } t.Run("after kills", func(t *testing.T) { state, err := ugs.State(ctx) if err != nil { t.Fatal(err) } if !state.Started { t.Error("not started after kills") } if !state.Completed.IsZero() { t.Error("completed after kills") } for _, pid := range pids { p, ok := state.Players[pid] if !ok { t.Error(pid, "not in players") } else if p.Empty() { t.Error(pid, p) } else if p.KillWords.Assigned.IsZero() { t.Error("assigned is zero") } if isSelf := pid == ugs.Session.ID; isSelf { if len(p.Kills) == 0 { t.Error("self never got a kill") } else if kill := p.Kills[0]; kill.Timestamp.IsZero() { t.Errorf("kill has no timestamp") } else if kill.Victim == "" { t.Errorf("kill has no victim") } else if kill.KillWord.Points != 0 { t.Errorf("know points of own kill") } else if kill.KillWord.Word == "" { t.Errorf("dont know own kill word") } if p.KillWords.Codename.KillWord.Word == "" || p.KillWords.Codename.KillWord.Points == 0 { t.Error("self Codename missing field") } if p.KillWords.Assignee == "" { t.Error("assignee is empty") } if len(p.KillWords.Assignment.Public) > 0 { t.Error("self knows its own public") } if len(p.KillWords.Assignment.Private) > 0 { t.Error("self knows its own private") } } else { if len(p.Kills) == 0 { } else if kill := p.Kills[0]; kill.Timestamp.IsZero() { t.Errorf("kill has no timestamp") } else if kill.Victim != "" { t.Errorf("know other's victim") } else if kill.KillWord.Points == 0 { t.Errorf("other's kill has no points") } else if kill.KillWord.Word != "" { t.Errorf("know other's kill word") } if !p.KillWords.Codename.KillWord.Empty() { t.Error("can see not self Codename") } if p.KillWords.Assignee != "" { t.Error("can see other player's assignee") } if len(p.KillWords.Assignment.Public) == 0 { t.Error("cannot see other player's public") } if state.Players[ugs.Session.ID].KillWords.Assignee == pid && len(p.KillWords.Assignment.Private) == 0 { t.Error("cannot see assignee's private") } else if state.Players[ugs.Session.ID].KillWords.Assignee != pid && len(p.KillWords.Assignment.Private) > 0 { t.Error("can see not assignee's private") } } } }) if err := games.CreateEventGameComplete(ctx, gid); err != nil { t.Fatal(err) } t.Run("completed", func(t *testing.T) { state, err := ugs.State(ctx) if err != nil { t.Fatal(err) } if !state.Started { t.Error("not started after complete") } if state.Completed.IsZero() { t.Error("not complete after complete") } for _, pid := range pids { p, ok := state.Players[pid] if !ok { t.Error(pid, "not in players") } else if p.Empty() { t.Error(pid, p) } else if p.KillWords.Assigned.IsZero() { t.Error("assigned is zero") } if isSelf := pid == ugs.Session.ID; isSelf { if len(p.Kills) == 0 { t.Error("self never got a kill") } else if kill := p.Kills[0]; kill.Timestamp.IsZero() { t.Errorf("kill has no timestamp") } else if kill.Victim == "" { t.Errorf("kill has no victim") } else if kill.KillWord.Points == 0 { t.Errorf("dont know points of own kill at game review") } else if kill.KillWord.Word == "" { t.Errorf("dont know own kill word") } if p.KillWords.Codename.KillWord.Word == "" || p.KillWords.Codename.KillWord.Points == 0 { t.Error("self Codename missing field") } if p.KillWords.Assignee == "" { t.Error("assignee is empty") } if len(p.KillWords.Assignment.Public) == 0 { t.Error("self doesnt know its own public after game") } if len(p.KillWords.Assignment.Private) == 0 { t.Error("self doesnt know its own private after game") } } else { if len(p.Kills) == 0 { } else if kill := p.Kills[0]; kill.Timestamp.IsZero() { t.Errorf("kill has no timestamp") } else if kill.Victim == "" { t.Errorf("cannot know other's victim") } else if kill.KillWord.Points == 0 { t.Errorf("other's kill has no points") } else if kill.KillWord.Word == "" { t.Errorf("dont know other's kill word") } if p.KillWords.Codename.KillWord.Empty() { t.Error("cannot see not self Codename") } if p.KillWords.Assignee == "" { t.Error("cannot see other player's assignee") } if len(p.KillWords.Assignment.Public) == 0 { t.Error("cannot see other player's public") } if state.Players[ugs.Session.ID].KillWords.Assignee == pid && len(p.KillWords.Assignment.Private) == 0 { t.Error("cannot see assignee's private") } else if state.Players[ugs.Session.ID].KillWords.Assignee != pid && len(p.KillWords.Assignment.Private) == 0 { t.Error("cannot see not assignee's private after game") } } } }) }