snapshot of https://github.com/ory/keto.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
CI / Run lints and checks (push) Failing after 47s
CI / Run tests (push) Failing after 1s
CI / Run race tests (push) Failing after 5s
CI / Build CLI docs (push) Has been skipped
CI / Run buf actions (push) Failing after 5s
CodeQL / Analyze (go) (push) Failing after 3s
CodeQL / Analyze (javascript) (push) Failing after 2s
Docker Image Scanners / scanners (push) Failing after 3s
Format / format (push) Failing after 3s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Draft newsletter (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
Some checks failed
CI / Run lints and checks (push) Failing after 47s
CI / Run tests (push) Failing after 1s
CI / Run race tests (push) Failing after 5s
CI / Build CLI docs (push) Has been skipped
CI / Run buf actions (push) Failing after 5s
CodeQL / Analyze (go) (push) Failing after 3s
CodeQL / Analyze (javascript) (push) Failing after 2s
Docker Image Scanners / scanners (push) Failing after 3s
Format / format (push) Failing after 3s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Draft newsletter (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
This commit is contained in:
188
internal/x/dbx/dsn_testutils.go
Normal file
188
internal/x/dbx/dsn_testutils.go
Normal file
@@ -0,0 +1,188 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package dbx
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-sql-driver/mysql"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tidwall/sjson"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/ory/pop/v6"
|
||||
)
|
||||
|
||||
type DsnT struct {
|
||||
Name string
|
||||
Conn string
|
||||
MigrateUp, MigrateDown bool
|
||||
}
|
||||
|
||||
const mySQLSchema = "mysql://"
|
||||
|
||||
func mySQLWithDbName(dsn string, db string) string {
|
||||
cfg, err := mysql.ParseDSN(strings.TrimPrefix(dsn, mySQLSchema))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
cfg.DBName = db
|
||||
return mySQLSchema + cfg.FormatDSN()
|
||||
}
|
||||
|
||||
func withDbName(dsn string, db string) string {
|
||||
// Special case for mysql, because their URLs are not parsable.
|
||||
if strings.HasPrefix(dsn, mySQLSchema) {
|
||||
return mySQLWithDbName(dsn, db)
|
||||
}
|
||||
|
||||
u, err := url.Parse(dsn)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
u.Path = db
|
||||
|
||||
return u.String()
|
||||
}
|
||||
|
||||
func dbName() string {
|
||||
var buf [20]byte
|
||||
_, _ = rand.Read(buf[:])
|
||||
return fmt.Sprintf("testdb_%x", buf)
|
||||
}
|
||||
|
||||
func openAndPing(url string) (*pop.Connection, error) {
|
||||
conn, err := pop.NewConnection(&pop.ConnectionDetails{URL: url})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to connect to %q: %w", url, err)
|
||||
}
|
||||
for range 120 {
|
||||
fmt.Println("trying to open connection to", url)
|
||||
if err := conn.Open(); err != nil {
|
||||
// return nil, fmt.Errorf("failed to open connection: %w", err)
|
||||
time.Sleep(1 * time.Second)
|
||||
continue
|
||||
}
|
||||
if err := Ping(conn); err == nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
if err := Ping(conn); err != nil {
|
||||
_ = conn.Close()
|
||||
return nil, fmt.Errorf("failed to ping: %w", err)
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func createDB(t testing.TB, url string, dbName string) (err error) {
|
||||
var conn *pop.Connection
|
||||
|
||||
if conn, err = openAndPing(url); err != nil {
|
||||
return fmt.Errorf("failed to connect to %q: %w", url, err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if err := conn.Close(); err != nil {
|
||||
t.Logf("could not close connection for %q in %q: %v", dbName, url, err)
|
||||
}
|
||||
})
|
||||
|
||||
if err := conn.RawQuery("CREATE DATABASE " + dbName).Exec(); err != nil {
|
||||
return fmt.Errorf("failed to create db %q in %q: %w", dbName, url, err)
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
if err := conn.RawQuery("DROP DATABASE " + dbName).Exec(); err != nil {
|
||||
t.Logf("could not drop database %q in %q: %v", dbName, url, err)
|
||||
}
|
||||
})
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func GetDSNs(t testing.TB) []*DsnT {
|
||||
dsns := []*DsnT{GetSqlite(t)}
|
||||
|
||||
if !testing.Short() {
|
||||
var mysql, postgres, cockroach string
|
||||
testDB := dbName()
|
||||
|
||||
var eg errgroup.Group
|
||||
eg.Go(func() (err error) {
|
||||
postgres, err = RunPostgres(t, testDB)
|
||||
return
|
||||
})
|
||||
eg.Go(func() (err error) {
|
||||
mysql, err = RunMySQL(t, testDB)
|
||||
return
|
||||
})
|
||||
eg.Go(func() (err error) {
|
||||
cockroach, err = RunCockroach(t, testDB)
|
||||
return
|
||||
})
|
||||
require.NoError(t, eg.Wait())
|
||||
|
||||
if mysql != "" {
|
||||
dsns = append(dsns, &DsnT{
|
||||
Name: "mysql",
|
||||
Conn: mysql,
|
||||
MigrateUp: true,
|
||||
MigrateDown: true,
|
||||
})
|
||||
}
|
||||
if postgres != "" {
|
||||
dsns = append(dsns, &DsnT{
|
||||
Name: "postgres",
|
||||
Conn: postgres,
|
||||
MigrateUp: true,
|
||||
MigrateDown: true,
|
||||
})
|
||||
}
|
||||
if cockroach != "" {
|
||||
dsns = append(dsns, &DsnT{
|
||||
Name: "cockroach",
|
||||
Conn: cockroach,
|
||||
MigrateUp: true,
|
||||
MigrateDown: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
require.NotZero(t, len(dsns), "expected to run against at least one database")
|
||||
return dsns
|
||||
}
|
||||
|
||||
func ConfigFile(t testing.TB, values map[string]interface{}) string {
|
||||
dir := t.TempDir()
|
||||
fn := filepath.Join(dir, "keto.json")
|
||||
|
||||
c := []byte("{}")
|
||||
for key, val := range values {
|
||||
var err error
|
||||
c, err = sjson.SetBytes(c, key, val)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
require.NoError(t, os.WriteFile(fn, c, 0600))
|
||||
|
||||
return fn
|
||||
}
|
||||
|
||||
type pinger interface{ Ping() error }
|
||||
|
||||
func Ping(conn *pop.Connection) error {
|
||||
p, ok := conn.Store.(pinger)
|
||||
if !ok {
|
||||
return fmt.Errorf("connection not opened: Store is %T", conn.Store)
|
||||
}
|
||||
return p.Ping()
|
||||
}
|
||||
Reference in New Issue
Block a user