feat: use postgres
This commit is contained in:
@@ -5,19 +5,25 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"galaxy/postgres"
|
||||
"galaxy/user/internal/app"
|
||||
"galaxy/user/internal/config"
|
||||
|
||||
"github.com/alicebob/miniredis/v2"
|
||||
"github.com/stretchr/testify/require"
|
||||
testcontainers "github.com/testcontainers/testcontainers-go"
|
||||
tcpostgres "github.com/testcontainers/testcontainers-go/modules/postgres"
|
||||
"github.com/testcontainers/testcontainers-go/wait"
|
||||
)
|
||||
|
||||
type runtimeContractHarness struct {
|
||||
@@ -34,9 +40,14 @@ func newRuntimeContractHarness(t *testing.T) *runtimeContractHarness {
|
||||
t.Helper()
|
||||
|
||||
redisServer := miniredis.RunT(t)
|
||||
redisServer.RequireAuth("integration")
|
||||
|
||||
pgDSN := startPostgresForContractTest(t)
|
||||
|
||||
cfg := config.DefaultConfig()
|
||||
cfg.Redis.Addr = redisServer.Addr()
|
||||
cfg.Redis.Conn.MasterAddr = redisServer.Addr()
|
||||
cfg.Redis.Conn.Password = "integration"
|
||||
cfg.Postgres.Conn.PrimaryDSN = pgDSN
|
||||
cfg.InternalHTTP.Addr = freeLoopbackAddress(t)
|
||||
cfg.AdminHTTP.Addr = ""
|
||||
cfg.ShutdownTimeout = 10 * time.Second
|
||||
@@ -841,3 +852,72 @@ func TestEligibilityUnknownMarkersZeroValueMatchesContract(t *testing.T) {
|
||||
require.Equal(t, eligibilityMarkers{}, eligibilityMarkers{})
|
||||
require.False(t, strings.HasPrefix("", "user-"))
|
||||
}
|
||||
|
||||
// startPostgresForContractTest boots one isolated PostgreSQL container,
|
||||
// provisions the user schema with the userservice role, and returns a DSN
|
||||
// pinned to search_path=user. The test is skipped (not failed) when a
|
||||
// container cannot be started — typically because Docker is unavailable in
|
||||
// the dev environment.
|
||||
func startPostgresForContractTest(t *testing.T) string {
|
||||
t.Helper()
|
||||
|
||||
ctx := context.Background()
|
||||
container, err := tcpostgres.Run(ctx,
|
||||
"postgres:16-alpine",
|
||||
tcpostgres.WithDatabase("galaxy_user"),
|
||||
tcpostgres.WithUsername("galaxy"),
|
||||
tcpostgres.WithPassword("galaxy"),
|
||||
testcontainers.WithWaitStrategy(
|
||||
wait.ForLog("database system is ready to accept connections").
|
||||
WithOccurrence(2).
|
||||
WithStartupTimeout(60*time.Second),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
t.Skipf("postgres container start failed (Docker likely unavailable): %v", err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if err := testcontainers.TerminateContainer(container); err != nil {
|
||||
t.Errorf("terminate postgres container: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
baseDSN, err := container.ConnectionString(ctx, "sslmode=disable")
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg := postgres.DefaultConfig()
|
||||
cfg.PrimaryDSN = baseDSN
|
||||
cfg.OperationTimeout = 5 * time.Second
|
||||
db, err := postgres.OpenPrimary(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
defer func() { _ = db.Close() }()
|
||||
|
||||
for _, statement := range []string{
|
||||
`CREATE ROLE userservice LOGIN PASSWORD 'userservice'`,
|
||||
`CREATE SCHEMA IF NOT EXISTS "user" AUTHORIZATION userservice`,
|
||||
`GRANT USAGE ON SCHEMA "user" TO userservice`,
|
||||
} {
|
||||
if _, err := db.ExecContext(ctx, statement); err != nil {
|
||||
require.NoError(t, err, "provision postgres role/schema: %s", statement)
|
||||
}
|
||||
}
|
||||
|
||||
parsed, err := url.Parse(baseDSN)
|
||||
require.NoError(t, err)
|
||||
|
||||
values := url.Values{}
|
||||
values.Set("search_path", "user")
|
||||
values.Set("sslmode", "disable")
|
||||
scoped := url.URL{
|
||||
Scheme: parsed.Scheme,
|
||||
User: url.UserPassword("userservice", "userservice"),
|
||||
Host: parsed.Host,
|
||||
Path: parsed.Path,
|
||||
RawQuery: values.Encode(),
|
||||
}
|
||||
return scoped.String()
|
||||
}
|
||||
|
||||
// errSentinel is a small unused alias kept to silence imports above when
|
||||
// non-default builds drop testcontainers references.
|
||||
var errSentinel = fmt.Errorf("contract test sentinel")
|
||||
|
||||
Reference in New Issue
Block a user