CI / ci (push) Successful in 49s
Co-authored-by: dev_agent <dev_agent@cubecraftlabs.com> Co-committed-by: dev_agent <dev_agent@cubecraftlabs.com>
117 lines
2.9 KiB
Go
117 lines
2.9 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func openTestStore(t *testing.T) *Store {
|
|
t.Helper()
|
|
s, err := Open(context.Background(), t.TempDir())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(func() {
|
|
if err := s.Close(); err != nil {
|
|
t.Error(err)
|
|
}
|
|
})
|
|
return s
|
|
}
|
|
|
|
func TestOpenCreatesDatabaseFile(t *testing.T) {
|
|
dir := t.TempDir()
|
|
s, err := Open(context.Background(), dir)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer s.Close()
|
|
if _, err := os.Stat(filepath.Join(dir, FileName)); err != nil {
|
|
t.Fatalf("database file: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestOpenMissingDirFails(t *testing.T) {
|
|
_, err := Open(context.Background(), filepath.Join(t.TempDir(), "missing"))
|
|
if err == nil {
|
|
t.Fatal("Open succeeded on a missing data directory")
|
|
}
|
|
}
|
|
|
|
func TestPoolSizes(t *testing.T) {
|
|
s := openTestStore(t)
|
|
if got := s.Writer.Stats().MaxOpenConnections; got != 1 {
|
|
t.Errorf("writer max open connections = %d, want 1", got)
|
|
}
|
|
if got := s.Reader.Stats().MaxOpenConnections; got != readPoolSize {
|
|
t.Errorf("reader max open connections = %d, want %d", got, readPoolSize)
|
|
}
|
|
}
|
|
|
|
// TestPragmasOnEveryConnection holds every reader connection open at once so
|
|
// each one is a distinct connection, then checks the pragmas on each and on
|
|
// the writer.
|
|
func TestPragmasOnEveryConnection(t *testing.T) {
|
|
ctx := context.Background()
|
|
s := openTestStore(t)
|
|
|
|
conns := []*sql.Conn{}
|
|
for range readPoolSize {
|
|
c, err := s.Reader.Conn(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer c.Close()
|
|
conns = append(conns, c)
|
|
}
|
|
w, err := s.Writer.Conn(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer w.Close()
|
|
conns = append(conns, w)
|
|
|
|
for i, c := range conns {
|
|
var fk, busy int
|
|
var journal string
|
|
if err := c.QueryRowContext(ctx, "PRAGMA foreign_keys").Scan(&fk); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := c.QueryRowContext(ctx, "PRAGMA busy_timeout").Scan(&busy); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := c.QueryRowContext(ctx, "PRAGMA journal_mode").Scan(&journal); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if fk != 1 || busy != 5000 || journal != "wal" {
|
|
t.Errorf("connection %d: foreign_keys=%d busy_timeout=%d journal_mode=%q, want 1, 5000, wal", i, fk, busy, journal)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestReaderIsReadOnly(t *testing.T) {
|
|
s := openTestStore(t)
|
|
if _, err := s.Reader.Exec("CREATE TABLE t (id INTEGER)"); err == nil {
|
|
t.Fatal("write through the reader succeeded")
|
|
}
|
|
if _, err := s.Writer.Exec("CREATE TABLE t (id INTEGER)"); err != nil {
|
|
t.Fatalf("write through the writer: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestForeignKeysEnforced(t *testing.T) {
|
|
s := openTestStore(t)
|
|
if _, err := s.Writer.Exec(`
|
|
CREATE TABLE parent (id INTEGER PRIMARY KEY);
|
|
CREATE TABLE child (parent_id INTEGER NOT NULL REFERENCES parent(id));
|
|
`); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := s.Writer.Exec("INSERT INTO child (parent_id) VALUES (42)"); err == nil {
|
|
t.Fatal("insert violating a foreign key succeeded")
|
|
}
|
|
}
|