Files
hi-server/tests/acceptance/fixtures.go
T

133 lines
3.0 KiB
Go

package acceptance
import (
"context"
"database/sql"
"fmt"
"os"
"strings"
"testing"
"time"
_ "github.com/go-sql-driver/mysql"
"github.com/redis/go-redis/v9"
)
type FixtureLoader struct {
cfg Config
}
func newFixtureLoader(c Config) *FixtureLoader {
return &FixtureLoader{cfg: c}
}
func (l *FixtureLoader) SeedIfConfigured(t *testing.T, ctx context.Context) {
t.Helper()
if !l.hasDBConfig() {
t.Log("staging DB config not provided; skipping seed loader")
return
}
sqlBytes, err := os.ReadFile(l.cfg.SeedSQLPath)
if err != nil {
t.Fatalf("read seed SQL %q: %v", l.cfg.SeedSQLPath, err)
}
db, err := sql.Open("mysql", l.dsn(true))
if err != nil {
t.Fatalf("open staging DB: %v", err)
}
defer func() {
_ = db.Close()
}()
if err := db.PingContext(ctx); err != nil {
t.Fatalf("ping staging DB: %v", err)
}
statements := splitSQL(string(sqlBytes))
for _, statement := range statements {
statement = strings.ReplaceAll(statement, "{{RUN_ID}}", l.cfg.RunID)
if _, err := db.ExecContext(ctx, statement); err != nil {
t.Fatalf("execute seed SQL: %v; statement=%s", err, statement)
}
}
}
func (l *FixtureLoader) NodeSecret(ctx context.Context) (string, error) {
if l.cfg.NodeSecret != "" {
return l.cfg.NodeSecret, nil
}
if !l.hasDBConfig() {
return "", nil
}
db, err := sql.Open("mysql", l.dsn(false))
if err != nil {
return "", fmt.Errorf("open staging DB: %w", err)
}
defer func() {
_ = db.Close()
}()
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
var secret string
err = db.QueryRowContext(ctx, "SELECT value FROM system WHERE category = 'server' AND `key` = 'NodeSecret' LIMIT 1").Scan(&secret)
if err != nil {
return "", fmt.Errorf("read NodeSecret from staging DB: %w", err)
}
return secret, nil
}
func (l *FixtureLoader) RedisClient() *redis.Client {
if l.cfg.Redis.Addr == "" {
return nil
}
return redis.NewClient(&redis.Options{
Addr: l.cfg.Redis.Addr,
Password: l.cfg.Redis.Password,
DB: l.cfg.Redis.DB,
})
}
func (l *FixtureLoader) hasDBConfig() bool {
return l.cfg.DB.Host != "" && l.cfg.DB.User != "" && l.cfg.DB.Name != ""
}
func (l *FixtureLoader) dsn(multiStatements bool) string {
params := "parseTime=true&timeout=5s&readTimeout=10s&writeTimeout=10s"
if multiStatements {
params += "&multiStatements=true"
}
return fmt.Sprintf("%s:%s@tcp(%s)/%s?%s",
l.cfg.DB.User,
l.cfg.DB.Password,
l.cfg.DB.Host,
l.cfg.DB.Name,
params,
)
}
func splitSQL(script string) []string {
parts := strings.Split(script, ";")
statements := make([]string, 0, len(parts))
for _, part := range parts {
lines := strings.Split(part, "\n")
kept := make([]string, 0, len(lines))
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "--") {
continue
}
kept = append(kept, line)
}
statement := strings.Join(kept, "\n")
if statement == "" || strings.HasPrefix(statement, "--") {
continue
}
statements = append(statements, statement)
}
return statements
}