package faq_test import ( "context" "database/sql" "flag" "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 ( pgContainer *postgres.PostgresContainer pgAdmin *sql.DB pgDSN string pgErr error ) // TestMain starts one Postgres container for the smoke tests unless the run // is -short. go test passes -test.short=true, so the flag is parsed and read // through testing.Short, never by scanning os.Args. func TestMain(m *testing.M) { flag.Parse() if !testing.Short() { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) pgErr = startPostgres(ctx) cancel() if pgErr != nil { fmt.Fprintf(os.Stderr, "golem15.faq: testcontainers postgres: %v\n", pgErr) } } code := m.Run() stopPostgres() os.Exit(code) } func startPostgres(ctx context.Context) error { ctr, err := postgres.Run(ctx, "postgres:16-alpine", postgres.WithDatabase("golem15_faq"), postgres.WithUsername("golem15_faq"), postgres.WithPassword("golem15_faq"), postgres.BasicWaitStrategies(), ) if err != nil { return err } pgContainer = 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 } pgAdmin, pgDSN = db, dsn return nil } func stopPostgres() { if pgAdmin != nil { _ = pgAdmin.Close() } if pgContainer != nil { _ = testcontainers.TerminateContainer(pgContainer) } } // freshDB creates a database of its own for one test and drops it after. func freshDB(t *testing.T) *sql.DB { t.Helper() if testing.Short() { t.Skip("requires testcontainers postgres") } if pgErr != nil { t.Fatalf("postgres unavailable: %v", pgErr) } if pgAdmin == nil { t.Fatal("postgres unavailable: container was not started") } name := fmt.Sprintf("faq_%d", time.Now().UnixNano()) quoted := `"` + strings.ReplaceAll(name, `"`, `""`) + `"` if _, err := pgAdmin.ExecContext(t.Context(), `CREATE DATABASE `+quoted+` TEMPLATE template0 ENCODING 'UTF8'`); err != nil { t.Fatalf("create %s: %v", name, err) } u, err := url.Parse(pgDSN) if err != nil { t.Fatal(err) } u.Path = "/" + name db, err := sql.Open("pgx", u.String()) if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = db.Close() _, _ = pgAdmin.ExecContext(context.Background(), `DROP DATABASE IF EXISTS `+quoted+` WITH (FORCE)`) }) if err := db.PingContext(t.Context()); err != nil { t.Fatal(err) } return db }