tictactoe_test.gno
3.08 Kb · 112 lines
1package tictactoe
2
3import (
4 "testing"
5
6 "gno.land/p/nt/testutils/v0"
7 "gno.land/p/nt/uassert/v0"
8)
9
10var (
11 alice = testutils.TestAddress("alice")
12 bob = testutils.TestAddress("bob")
13 carol = testutils.TestAddress("carol")
14)
15
16// TestXWins: alice (X) beats bob (O) on the top row.
17func TestXWins(cur realm, t *testing.T) {
18 testing.SetRealm(testing.NewUserRealm(alice))
19 id := NewGame(cross(cur), bob)
20 uassert.True(t, id >= 1, "expected a game id")
21
22 // alice X -> 0
23 testing.SetRealm(testing.NewUserRealm(alice))
24 Move(cross(cur), id, 0)
25 // bob O -> 3
26 testing.SetRealm(testing.NewUserRealm(bob))
27 Move(cross(cur), id, 3)
28 // alice X -> 1
29 testing.SetRealm(testing.NewUserRealm(alice))
30 Move(cross(cur), id, 1)
31 // bob O -> 4
32 testing.SetRealm(testing.NewUserRealm(bob))
33 Move(cross(cur), id, 4)
34 // alice X -> 2 wins top row
35 testing.SetRealm(testing.NewUserRealm(alice))
36 Move(cross(cur), id, 2)
37
38 g, err := GetGame(id)
39 uassert.NoError(t, err)
40 uassert.True(t, g.finished, "game should be finished")
41 uassert.Equal(t, markX, g.winner)
42 uassert.False(t, g.draw, "should not be a draw")
43}
44
45// TestTurnAndTakenGuards: rejects out-of-turn moves, taken cells, and non-players.
46func TestTurnAndTakenGuards(cur realm, t *testing.T) {
47 testing.SetRealm(testing.NewUserRealm(alice))
48 id := NewGame(cross(cur), bob)
49
50 // bob (O) cannot move first — it's X's turn.
51 testing.SetRealm(testing.NewUserRealm(bob))
52 uassert.AbortsWithMessage(t, cur, "not your turn", func() {
53 Move(cross(cur), id, 0)
54 })
55
56 // alice (X) plays 0.
57 testing.SetRealm(testing.NewUserRealm(alice))
58 Move(cross(cur), id, 0)
59
60 // alice cannot play twice in a row.
61 testing.SetRealm(testing.NewUserRealm(alice))
62 uassert.AbortsWithMessage(t, cur, "not your turn", func() {
63 Move(cross(cur), id, 1)
64 })
65
66 // bob cannot take an occupied cell.
67 testing.SetRealm(testing.NewUserRealm(bob))
68 uassert.AbortsWithMessage(t, cur, "cell already taken", func() {
69 Move(cross(cur), id, 0)
70 })
71
72 // carol is not a player.
73 testing.SetRealm(testing.NewUserRealm(carol))
74 uassert.AbortsWithMessage(t, cur, "caller is not a player in this game", func() {
75 Move(cross(cur), id, 5)
76 })
77}
78
79// TestDraw: fill the board with no winner.
80func TestDraw(cur realm, t *testing.T) {
81 testing.SetRealm(testing.NewUserRealm(alice))
82 id := NewGame(cross(cur), bob)
83
84 // Sequence yielding a full board with no three-in-a-row:
85 // X:0 O:1 X:2 O:4 X:3 O:5 X:7 O:6 X:8
86 seq := []struct {
87 who address
88 cell int
89 }{
90 {alice, 0}, {bob, 1}, {alice, 2},
91 {bob, 4}, {alice, 3}, {bob, 5},
92 {alice, 7}, {bob, 6}, {alice, 8},
93 }
94 for _, s := range seq {
95 testing.SetRealm(testing.NewUserRealm(s.who))
96 Move(cross(cur), id, s.cell)
97 }
98
99 g, err := GetGame(id)
100 uassert.NoError(t, err)
101 uassert.True(t, g.finished, "game should be finished")
102 uassert.True(t, g.draw, "should be a draw")
103 uassert.Equal(t, 0, g.winner)
104}
105
106// The store's labelled MustGet names the game v0's "game not found" left out.
107func TestMoveOnAMissingGameNamesIt(cur realm, t *testing.T) {
108 testing.SetRealm(testing.NewUserRealm(alice))
109 uassert.AbortsWithMessage(t, cur, "game #999999 not found", func() {
110 Move(cross(cur), 999999, 0)
111 })
112}