a test!
parent
659bf0f559
commit
39b1a6a1e8
|
|
@ -3,7 +3,6 @@ package main
|
|||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
|
@ -107,7 +106,3 @@ func (db DB) dial(ctx context.Context) (*sql.DB, error) {
|
|||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (db DB) GetParty(id string) (string, error) {
|
||||
return "", io.EOF
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"path"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func newTestDB(t *testing.T) DB {
|
||||
ctx, can := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer can()
|
||||
conn := path.Join(t.TempDir(), "db")
|
||||
|
||||
db, err := NewDB(ctx, "sqlite", conn)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func TestDB(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
db := newTestDB(t)
|
||||
|
||||
t.Run("with lock", func(t *testing.T) {
|
||||
var called [2]bool
|
||||
if err := db.WithLock(func() error {
|
||||
for i := range called {
|
||||
if err := db.Query(ctx, func(rows *sql.Rows) error {
|
||||
return rows.Scan(&called[i])
|
||||
}, `SELECT true`); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !called[0] {
|
||||
t.Error(0)
|
||||
}
|
||||
if !called[1] {
|
||||
t.Error(1)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("exec, query", func(t *testing.T) {
|
||||
if err := db.Exec(ctx, `
|
||||
CREATE TABLE IF NOT EXISTS my_table (
|
||||
text TEXT,
|
||||
datetime DATETIME,
|
||||
number NUMBER
|
||||
)
|
||||
`); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := db.Exec(ctx, `
|
||||
INSERT INTO my_table (
|
||||
text,
|
||||
datetime,
|
||||
number
|
||||
) VALUES (?, ?, ?)
|
||||
`, "text", time.Now(), 1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var text string
|
||||
var datetime time.Time
|
||||
var number int
|
||||
if err := db.Query(ctx, func(rows *sql.Rows) error {
|
||||
return rows.Scan(&text, &datetime, &number)
|
||||
}, `
|
||||
SELECT
|
||||
text,
|
||||
datetime,
|
||||
number
|
||||
FROM my_table
|
||||
`); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if text != "text" {
|
||||
t.Error(text)
|
||||
}
|
||||
if datetime.IsZero() {
|
||||
t.Error(datetime)
|
||||
}
|
||||
if number != 1 {
|
||||
t.Error(number)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -8,6 +8,8 @@ import (
|
|||
"io"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Games struct {
|
||||
|
|
@ -61,15 +63,15 @@ func (games Games) GameByName(ctx context.Context, uid, name string) (string, er
|
|||
err := games.db.Query(ctx, func(rows *sql.Rows) error {
|
||||
return rows.Scan(&result)
|
||||
}, `
|
||||
SELECT
|
||||
players.games_uuid
|
||||
FROM
|
||||
players
|
||||
JOIN games ON players.game_uuid=games.game_uuid
|
||||
WHERE players.user_uuid=? AND games.name=?
|
||||
ORDER BY games.timestamp DESC
|
||||
LIMIT 1
|
||||
`, uid, name)
|
||||
SELECT
|
||||
players.game_uuid
|
||||
FROM
|
||||
players
|
||||
JOIN games ON players.game_uuid=games.uuid
|
||||
WHERE players.user_uuid=? AND games.name=?
|
||||
ORDER BY games.updated DESC
|
||||
LIMIT 1
|
||||
`, uid, name)
|
||||
return result, err
|
||||
}
|
||||
|
||||
|
|
@ -209,6 +211,32 @@ func (games Games) GameState(ctx context.Context, id string) (GameState, error)
|
|||
return result, err
|
||||
}
|
||||
|
||||
func (games Games) CreateGame(ctx context.Context, name string) (string, error) {
|
||||
var exists string
|
||||
if err := games.db.Query(ctx,
|
||||
func(rows *sql.Rows) error {
|
||||
return rows.Scan(&exists)
|
||||
},
|
||||
`
|
||||
SELECT uuid
|
||||
FROM games
|
||||
WHERE name=? AND completed IS NULL
|
||||
`, name); err != nil {
|
||||
return "", err
|
||||
} else if exists != "" {
|
||||
return exists, nil
|
||||
}
|
||||
|
||||
id := uuid.New().String()
|
||||
return id, games.db.Exec(ctx, `
|
||||
INSERT INTO games (
|
||||
uuid,
|
||||
updated,
|
||||
name
|
||||
) VALUES (?, ?, ?)
|
||||
`, id, time.Now(), name)
|
||||
}
|
||||
|
||||
func (games Games) CreateEventPlayerJoin(ctx context.Context, id string, player string) error {
|
||||
return games.createEvent(ctx, id, EventPlayerJoin{ID: player})
|
||||
}
|
||||
|
|
@ -217,10 +245,6 @@ func (games Games) CreateEventPlayerLeave(ctx context.Context, id string, player
|
|||
return games.createEvent(ctx, id, EventPlayerLeave{ID: player})
|
||||
}
|
||||
|
||||
func (games Games) CreateEventGameComplete(ctx context.Context, id string) error {
|
||||
return games.createEvent(ctx, id, EventGameComplete{})
|
||||
}
|
||||
|
||||
func (games Games) CreateEventAssignmentRotation(ctx context.Context, id string, killer, killed, killWord string) error {
|
||||
// TODO gather current assignees
|
||||
// TODO get victim's target
|
||||
|
|
@ -230,6 +254,10 @@ func (games Games) CreateEventAssignmentRotation(ctx context.Context, id string,
|
|||
//return games.createEvent(ctx, id, v)
|
||||
}
|
||||
|
||||
func (games Games) CreateEventGameComplete(ctx context.Context, id string) error {
|
||||
return games.createEvent(ctx, id, EventGameComplete{})
|
||||
}
|
||||
|
||||
func (games Games) createEvent(ctx context.Context, id string, v any) error {
|
||||
payload, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func newTestGames(t *testing.T) Games {
|
||||
db := newTestDB(t)
|
||||
|
||||
games, err := NewGames(context.Background(), db)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return games
|
||||
}
|
||||
|
||||
func TestGames(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
games := newTestGames(t)
|
||||
|
||||
if v, err := games.GamesForUser(ctx, ""); err != nil {
|
||||
t.Error("err getting games for empty user:", err)
|
||||
} else if len(v) > 0 {
|
||||
t.Error(v)
|
||||
}
|
||||
|
||||
if v, err := games.GameByName(ctx, "", ""); err != nil {
|
||||
t.Error("err getting game by empty name for empty user:", err)
|
||||
} else if len(v) > 0 {
|
||||
t.Error(v)
|
||||
}
|
||||
|
||||
if v, err := games.GameState(ctx, ""); err != nil {
|
||||
t.Error("err getting game state for empty:", err)
|
||||
} else if len(v.Players) > 0 || !v.Completed.IsZero() {
|
||||
t.Error(v)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("mvp", func(t *testing.T) {
|
||||
games := newTestGames(t)
|
||||
|
||||
id, err := games.CreateGame(ctx, "g1")
|
||||
if err != nil {
|
||||
t.Fatal("err creating game:", err)
|
||||
} else if id2, err := games.CreateGame(ctx, "g1"); err != nil {
|
||||
t.Fatal("err creating game redundantly:", err)
|
||||
} else if id != id2 {
|
||||
t.Fatal("redundant create game didnt return same id:", id2)
|
||||
}
|
||||
|
||||
if err := games.CreateEventPlayerJoin(ctx, id, "p0"); err != nil {
|
||||
t.Fatal("err creating event player join:", err)
|
||||
} else if err := games.CreateEventPlayerLeave(ctx, id, "p0"); err != nil {
|
||||
t.Fatal("err creating event player leave:", err)
|
||||
}
|
||||
|
||||
for i := 0; i < 4; i++ {
|
||||
p := fmt.Sprintf("p%d", i+1)
|
||||
if err := games.CreateEventPlayerJoin(ctx, id, p); err != nil {
|
||||
t.Fatal(p, "err creating event player join", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := games.CreateEventAssignmentRotation(ctx, id, "", "", ""); err != nil {
|
||||
t.Fatal("err creating rotation:", err)
|
||||
}
|
||||
|
||||
if v, err := games.GamesForUser(ctx, "p1"); err != nil {
|
||||
t.Error("err getting games for user:", err)
|
||||
} else if len(v) < 1 {
|
||||
t.Error("no games found for user:", v)
|
||||
} else if v[0] != id {
|
||||
t.Error("wrong game found for user:", v)
|
||||
}
|
||||
|
||||
if v, err := games.GameByName(ctx, "p1", "g1"); err != nil {
|
||||
t.Error("err getting game by name for user:", err)
|
||||
} else if v != id {
|
||||
t.Error("wrong game by name for user:", v)
|
||||
}
|
||||
|
||||
if v, err := games.GameState(ctx, id); err != nil {
|
||||
t.Error("err getting game state:", err)
|
||||
} else if len(v.Players) != 4 || !v.Completed.IsZero() {
|
||||
t.Error("wrong game state:", v)
|
||||
} else {
|
||||
for i := 0; i < 4; i++ {
|
||||
p := fmt.Sprintf("p%d", i+1)
|
||||
if v.Players[p].KillWords.Global == "" {
|
||||
t.Error(p, "no killwords.global")
|
||||
} else if v.Players[p].KillWords.Assigned.IsZero() {
|
||||
t.Error(p, "no killwords.assigned")
|
||||
} else if v.Players[p].KillWords.Assignee == "" {
|
||||
t.Error(p, "no killwords.assignee")
|
||||
} else if len(v.Players[p].KillWords.Assignment.Public) == 0 {
|
||||
t.Error(p, "no killwords.assigment.public")
|
||||
} else if len(v.Players[p].KillWords.Assignment.Private) == 0 {
|
||||
t.Error(p, "no killwords.assigment.private")
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
2
go.mod
2
go.mod
|
|
@ -9,7 +9,7 @@ require (
|
|||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
||||
github.com/glebarez/sqlite v1.11.0 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -8,6 +8,8 @@ github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GM
|
|||
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
|
|
|
|||
Loading…
Reference in New Issue