Search Apps Documentation Source Content File Folder Download Copy Actions Download

lobby_test.gno

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