100 lines
2.8 KiB
Go
100 lines
2.8 KiB
Go
package test
|
|
|
|
import (
|
|
"context"
|
|
_ "embed"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/docker/docker/api/types/container"
|
|
"github.com/docker/docker/api/types/network"
|
|
"github.com/go-errors/errors"
|
|
"github.com/jackc/pgconn"
|
|
"github.com/jackc/pgerrcode"
|
|
"github.com/jackc/pgx/v4"
|
|
"github.com/spf13/afero"
|
|
"github.com/spf13/viper"
|
|
"github.com/supabase/cli/internal/utils"
|
|
cliConfig "github.com/supabase/cli/pkg/config"
|
|
)
|
|
|
|
const (
|
|
ENABLE_PGTAP = "create extension if not exists pgtap with schema extensions"
|
|
DISABLE_PGTAP = "drop extension if exists pgtap"
|
|
)
|
|
|
|
func Run(ctx context.Context, testFiles []string, config pgconn.Config, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error {
|
|
// Build test command
|
|
cmd := []string{"pg_prove", "--ext", ".pg", "--ext", ".sql", "-r"}
|
|
for _, fp := range testFiles {
|
|
relPath, err := filepath.Rel(utils.DbTestsDir, fp)
|
|
if err != nil {
|
|
return errors.Errorf("failed to resolve relative path: %w", err)
|
|
}
|
|
cmd = append(cmd, relPath)
|
|
}
|
|
if viper.GetBool("DEBUG") {
|
|
cmd = append(cmd, "--verbose")
|
|
}
|
|
// Mount tests directory into container as working directory
|
|
srcPath, err := filepath.Abs(utils.DbTestsDir)
|
|
if err != nil {
|
|
return errors.Errorf("failed to resolve absolute path: %w", err)
|
|
}
|
|
dstPath := "/tmp"
|
|
binds := []string{fmt.Sprintf("%s:%s:ro", srcPath, dstPath)}
|
|
// Enable pgTAP if not already exists
|
|
alreadyExists := false
|
|
options = append(options, func(cc *pgx.ConnConfig) {
|
|
cc.OnNotice = func(pc *pgconn.PgConn, n *pgconn.Notice) {
|
|
alreadyExists = n.Code == pgerrcode.DuplicateObject
|
|
}
|
|
})
|
|
conn, err := utils.ConnectByConfig(ctx, config, options...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer conn.Close(context.Background())
|
|
if _, err := conn.Exec(ctx, ENABLE_PGTAP); err != nil {
|
|
return errors.Errorf("failed to enable pgTAP: %w", err)
|
|
}
|
|
if !alreadyExists {
|
|
defer func() {
|
|
if _, err := conn.Exec(ctx, DISABLE_PGTAP); err != nil {
|
|
fmt.Fprintln(os.Stderr, "failed to disable pgTAP:", err)
|
|
}
|
|
}()
|
|
}
|
|
// Use custom network when connecting to local database
|
|
// disable selinux via security-opt to allow pg-tap to work properly
|
|
hostConfig := container.HostConfig{Binds: binds, SecurityOpt: []string{"label:disable"}}
|
|
if utils.IsLocalDatabase(config) {
|
|
config.Host = utils.DbAliases[0]
|
|
config.Port = 5432
|
|
} else {
|
|
hostConfig.NetworkMode = network.NetworkHost
|
|
}
|
|
// Run pg_prove on volume mount
|
|
return utils.DockerRunOnceWithConfig(
|
|
ctx,
|
|
container.Config{
|
|
Image: cliConfig.Images.PgProve,
|
|
Env: []string{
|
|
"PGHOST=" + config.Host,
|
|
fmt.Sprintf("PGPORT=%d", config.Port),
|
|
"PGUSER=" + config.User,
|
|
"PGPASSWORD=" + config.Password,
|
|
"PGDATABASE=" + config.Database,
|
|
},
|
|
Cmd: cmd,
|
|
WorkingDir: dstPath,
|
|
},
|
|
hostConfig,
|
|
network.NetworkingConfig{},
|
|
"",
|
|
os.Stdout,
|
|
os.Stderr,
|
|
)
|
|
}
|