lobby_test.gno
4.23 Kb ยท 185 lines
1package chess
2
3import (
4 "os"
5 "std"
6 "testing"
7 "time"
8
9 "gno.land/p/morgan/chess/glicko2"
10)
11
12func TestLobbyJoin(t *testing.T) {
13 cleanup()
14 testing.SetRealm(std.NewUserRealm(white))
15 LobbyJoin(cross, 10*60, 5)
16 os.Sleep(time.Second * 5)
17 testing.SetRealm(std.NewUserRealm(black))
18 LobbyJoin(cross, 10*60, 5)
19 res := LobbyGameFound(cross)
20 if res == "null" {
21 t.Errorf("LobbyGameFound is null")
22 }
23}
24
25func sublobbyToIDs(pl []lobbyPlayer) []string {
26 s := make([]string, len(pl))
27 for idx, p := range pl {
28 s[idx] = string(p.player.Address)
29 }
30 return s
31}
32
33func TestLobbyGameFound(t *testing.T) {
34 check := func(checker ...func(t *testing.T)) func(t *testing.T) {
35 return func(t *testing.T) {
36 for _, ck := range checker {
37 ck(t)
38 }
39 }
40 }
41 ids := func(ids ...std.Address) func(t *testing.T) {
42 return func(t *testing.T) {
43 if len(ids) != len(lobby[0]) {
44 t.Errorf("lobby doesn't match expected ids: lobby: %v, newIDs: %v", sublobbyToIDs(lobby[0]), ids)
45 return
46 }
47 for idx, i := range ids {
48 if pa := lobby[0][idx].player.Address; pa != i {
49 t.Errorf("check pos %d: player id doesnt match (got %q want %q)", idx, pa, i)
50 }
51 }
52 }
53 }
54 numGames := func(n int) func(t *testing.T) {
55 return func(t *testing.T) {
56 l := gameStore.Size()
57 if l != n {
58 t.Errorf("invalid gameStore size; want %d got %d", n, l)
59 }
60 }
61 }
62
63 type pl struct {
64 id std.Address
65 rating float64
66 // use negative values here to indicate how many seconds in the past;
67 // ie: joinedAt: -1, means player joined 1 second ago.
68 joinedAt int
69 seenAt int
70 }
71 tt := []struct {
72 name string
73 pre []pl
74 caller std.Address
75 check func(t *testing.T)
76 }{
77 {
78 "equalRating",
79 []pl{{"1", 1200, -1, -1}, {"2", 1200, 0, 0}},
80 "1",
81 check(ids(), numGames(1)),
82 },
83 {
84 "minimumApart", // delta <= 25
85 []pl{{"1", 1200, 0, 0}, {"2", 1225, 0, 0}},
86 "2",
87 check(ids(), numGames(1)),
88 },
89 {
90 "tooFarApart", // delta > 25
91 []pl{{"1", 1200, 0, 0}, {"2", 1230, 0, 0}},
92 "2",
93 check(ids("1", "2"), numGames(0)),
94 },
95 {
96 "oldHighPriority",
97 // kicked hasn't been seen in too long, so should not be considered.
98 // 1 is active and has been looking for 30s, so it gets priority, even if 2-3 is
99 // a closer match.
100 []pl{{"kicked", 1800, -60, -50}, {"1", 1900, -30, -10}, {"2", 1400, 0, 0}, {"3", 1420, 0, 0}},
101 "3",
102 check(ids("2"), numGames(1)),
103 },
104 {
105 "oldHighPriority2",
106 []pl{{"comeback", 1800, -60, -50}, {"1", 1900, -30, -10}, {"2", 1400, 0, 0}, {"3", 1420, 0, 0}},
107 // same as last one, except the player who was kicked last time, because
108 // he's the caller, has their seenAt set back to the current time, so they're matched with 1.
109 "comeback",
110 check(ids("2", "3"), numGames(1)),
111 },
112 {
113 "alone",
114 []pl{{"1", 1200, 0, 0}},
115 "1",
116 check(ids("1"), numGames(0)),
117 },
118 {
119 "brackFail",
120 []pl{{"1", 1200, -4, -4}, {"2", 1450, -5, -5}},
121 "1",
122 check(ids("1", "2"), numGames(0)),
123 },
124 {
125 "brackFail2",
126 []pl{{"1", 1200, -5, -5}, {"2", 1450, -4, -4}},
127 "1",
128 check(ids("1", "2"), numGames(0)),
129 },
130 {
131 "brackSuccess",
132 []pl{{"1", 1200, -5, -5}, {"2", 1450, -5, -5}},
133 "1",
134 check(ids(), numGames(1)),
135 },
136 }
137
138 for _, tc := range tt {
139 t.Run(tc.name, func(t *testing.T) {
140 cleanup()
141 now := time.Now()
142 for _, p := range tc.pre {
143 lobby[0] = append(lobby[0], lobbyPlayer{
144 joinedAt: now.Add(time.Duration(p.joinedAt) * time.Second),
145 seenAt: now.Add(time.Duration(p.seenAt) * time.Second),
146 player: &Player{
147 Address: p.id,
148 CategoryInfo: [CategoryMax]CategoryInfo{
149 Blitz: {PlayerRating: &glicko2.PlayerRating{Rating: p.rating}},
150 },
151 },
152 })
153 }
154
155 testing.SetRealm(std.NewUserRealm(tc.caller))
156 LobbyGameFound(cross)
157
158 if tc.check != nil {
159 tc.check(t)
160 }
161 })
162 }
163}
164
165func TestLobbyJoin_HasOpenGames(t *testing.T) {
166 cleanup()
167 g := &Game{
168 ID: "123",
169 White: white,
170 Black: black,
171 State: GameStateOpen,
172 }
173 gameStore.Set(g.ID, g)
174 addToUser2Games(white, g)
175 addToUser2Games(black, g)
176
177 testing.SetRealm(std.NewUserRealm(white))
178 LobbyJoin(cross, 10*60, 5)
179 if g.State != GameStateAborted {
180 t.Errorf("state wrong: want %d got %d", GameStateAborted, g.State)
181 }
182 if g.Winner != WinnerNone {
183 t.Errorf("winner wrong: want %q got %q", "none", g.Winner)
184 }
185}