Files
sm-user-plugin/updates/postgres_test.go
Jakub Zych 8d1248c328 feat(05-03): add user-plugin organisations table (structure only)
- create_organisations folds PHP v3.2.0; no users-table ALTER this phase
- Organisation model is an FK target; app.key placeholder in config
2026-09-18 19:37:41 +02:00

140 lines
2.9 KiB
Go

package updates
import (
"context"
"database/sql"
"fmt"
"net/url"
"os"
"strings"
"testing"
"time"
_ "github.com/jackc/pgx/v5/stdlib"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/modules/postgres"
)
var (
userPG *postgres.PostgresContainer
userSQL *sql.DB
userDSN string
userPGErr error
)
func TestMain(m *testing.M) {
code := 1
if !testShort() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
userPGErr = startUserPostgres(ctx)
cancel()
if userPGErr != nil {
fmt.Fprintf(os.Stderr, "golem15.user: testcontainers postgres: %v\n", userPGErr)
stopUserPostgres()
os.Exit(1)
}
}
code = m.Run()
stopUserPostgres()
os.Exit(code)
}
func testShort() bool {
for _, a := range os.Args {
if a == "-test.short" {
return true
}
}
return false
}
func startUserPostgres(ctx context.Context) error {
ctr, err := postgres.Run(ctx,
"postgres:16-alpine",
postgres.WithDatabase("golem15_user"),
postgres.WithUsername("golem15_user"),
postgres.WithPassword("golem15_user"),
postgres.BasicWaitStrategies(),
testcontainers.WithEnv(map[string]string{
"POSTGRES_INITDB_ARGS": "--locale-provider=icu --icu-locale=pl-PL --encoding=UTF8",
}),
)
if err != nil {
return err
}
userPG = ctr
dsn, err := ctr.ConnectionString(ctx, "sslmode=disable")
if err != nil {
return err
}
db, err := sql.Open("pgx", dsn)
if err != nil {
return err
}
if err := db.PingContext(ctx); err != nil {
_ = db.Close()
return err
}
userSQL = db
userDSN = dsn
return nil
}
func stopUserPostgres() {
if userSQL != nil {
_ = userSQL.Close()
}
if userPG != nil {
_ = testcontainers.TerminateContainer(userPG)
}
}
func userAdminDB(t *testing.T) *sql.DB {
t.Helper()
if testing.Short() {
t.Skip("requires testcontainers postgres")
}
if userPGErr != nil {
t.Fatalf("postgres unavailable: %v", userPGErr)
}
if userSQL == nil {
t.Fatal("postgres unavailable: container was not started")
}
return userSQL
}
func dedicatedDB(t *testing.T, name string) *sql.DB {
t.Helper()
admin := userAdminDB(t)
ctx := t.Context()
quoted := `"` + strings.ReplaceAll(name, `"`, `""`) + `"`
if _, err := admin.ExecContext(ctx, `CREATE DATABASE `+quoted+` TEMPLATE template0 ENCODING 'UTF8' LOCALE_PROVIDER icu ICU_LOCALE 'pl-PL'`); err != nil && !strings.Contains(err.Error(), "already exists") {
t.Fatalf("create %s: %v", name, err)
}
dsn, err := dsnWithDB(userDSN, name)
if err != nil {
t.Fatal(err)
}
db, err := sql.Open("pgx", dsn)
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
_ = db.Close()
_, _ = admin.ExecContext(context.Background(), `DROP DATABASE IF EXISTS `+quoted+` WITH (FORCE)`)
})
if err := db.PingContext(ctx); err != nil {
t.Fatal(err)
}
return db
}
func dsnWithDB(dsn, name string) (string, error) {
u, err := url.Parse(dsn)
if err != nil {
return "", err
}
u.Path = "/" + name
return u.String(), nil
}