Files
Levyraati26_go/main_test.go
T
Esa Kataja 1fe5211ae6 Replace Postgres with SQLite
Ten members and a handful of songs a week never needed a database server,
and the server was the last thing making this a two-container deployment.
modernc.org/sqlite is pure Go, so CGO_ENABLED=0 survives and the dependency
count is unchanged: pgx out, sqlite in.

The port stayed small because the driver matches $1-style placeholders
against argument ordinals exactly as pgx does, so no query needed rewriting
for parameters. What did change:

- timestamptz becomes timestamp holding UTC 'YYYY-MM-DD HH:MM:SS'. The
  declared type is what makes the driver return time.Time, and the
  fixed-width UTC string is what makes ordering and comparison against
  datetime('now') mean what they say.
- interval has no equivalent: sessions.idle_ttl is seconds, and the review
  edit window travels as a SQLite date modifier string.
- No stddev_pop, so the divisive and unified boards spell the population
  formula out, guarded with max(0.0, ...) because cancellation returns a
  tiny negative when every score is identical.
- foreign_keys is off by default, so the cascades only exist because the
  pragma is set on every connection.

Drops the postgres service, its healthcheck, the depends_on gate, the
startup retry loop and POSTGRES_PASSWORD. ./storage is now the whole
backup. Tests get a fresh database file per test and run everywhere
instead of skipping without TEST_DATABASE_URL.
2026-08-02 20:47:41 +03:00

59 lines
1.5 KiB
Go

package main
import (
"context"
"net/http"
"net/http/httptest"
"testing"
)
func TestRequireAdmin(t *testing.T) {
a := &app{cfg: config{adminUser: "admin", adminPass: "s3cret"}}
h := a.requireAdmin(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusTeapot)
}))
for _, tc := range []struct {
name, user, pass string
auth bool
want int
}{
{name: "no credentials", want: http.StatusUnauthorized},
{name: "wrong password", user: "admin", pass: "hunter2", auth: true, want: http.StatusUnauthorized},
{name: "wrong user", user: "root", pass: "s3cret", auth: true, want: http.StatusUnauthorized},
{name: "correct", user: "admin", pass: "s3cret", auth: true, want: http.StatusTeapot},
} {
t.Run(tc.name, func(t *testing.T) {
r := httptest.NewRequest("GET", "/admin", nil)
if tc.auth {
r.SetBasicAuth(tc.user, tc.pass)
}
w := httptest.NewRecorder()
h.ServeHTTP(w, r)
if w.Code != tc.want {
t.Fatalf("status = %d, want %d", w.Code, tc.want)
}
})
}
}
func TestMigrateIsIdempotent(t *testing.T) {
ctx := context.Background()
a := testApp(t) // already migrated once
if err := migrate(ctx, a.db); err != nil {
t.Fatalf("second migrate: %v", err)
}
if err := sweep(ctx, a.db); err != nil {
t.Fatalf("sweep: %v", err)
}
var n int
if err := a.db.QueryRowContext(ctx, `select count(*) from schema_migrations`).Scan(&n); err != nil {
t.Fatal(err)
}
if n != 1 {
t.Fatalf("applied migrations = %d, want 1", n)
}
}