mirror of
https://github.com/nkanaev/yarr.git
synced 2026-06-24 09:05:16 +00:00
storage: postgres per-test isolation
This commit is contained in:
@@ -1,16 +1,32 @@
|
|||||||
package tests
|
package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"database/sql"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
_ "github.com/lib/pq"
|
||||||
"github.com/nkanaev/yarr/src/storage"
|
"github.com/nkanaev/yarr/src/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
func dbtest(t *testing.T, testcase func(t *testing.T, db storage.Storage)) {
|
func dbtest(t *testing.T, testcase func(t *testing.T, db storage.Storage)) {
|
||||||
testurls := map[string]string{
|
testurls := map[string]string{
|
||||||
"sqlite": ":memory:",
|
"sqlite": ":memory:",
|
||||||
// "postgres": "postgres://postgres:postgres@localhost:5432/yarr_test?sslmode=disable",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pgUrl := os.Getenv("YARR_POSTGRES_TEST_URL"); pgUrl != "" {
|
||||||
|
dburl, cleanup, err := createPostgresDB(pgUrl)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create postgres test database: %v", err)
|
||||||
|
}
|
||||||
|
t.Cleanup(cleanup)
|
||||||
|
testurls["postgres"] = dburl
|
||||||
|
}
|
||||||
|
|
||||||
for testname, url := range testurls {
|
for testname, url := range testurls {
|
||||||
db, err := storage.New(url)
|
db, err := storage.New(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -21,3 +37,50 @@ func dbtest(t *testing.T, testcase func(t *testing.T, db storage.Storage)) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createPostgresDB(pgUrl string) (string, func(), error) {
|
||||||
|
u, err := url.Parse(pgUrl)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
u.Path = "/postgres"
|
||||||
|
adminConnStr := u.String()
|
||||||
|
|
||||||
|
adminDB, err := sql.Open("postgres", adminConnStr)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, fmt.Errorf("admin connect: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b := make([]byte, 4)
|
||||||
|
if _, err := rand.Read(b); err != nil {
|
||||||
|
adminDB.Close()
|
||||||
|
return "", nil, fmt.Errorf("generate suffix: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
testDBName := "yarr_test_" + hex.EncodeToString(b)
|
||||||
|
|
||||||
|
if _, err := adminDB.Exec(fmt.Sprintf(`CREATE DATABASE "%s"`, testDBName)); err != nil {
|
||||||
|
adminDB.Close()
|
||||||
|
return "", nil, fmt.Errorf("create database: %w", err)
|
||||||
|
}
|
||||||
|
adminDB.Close()
|
||||||
|
|
||||||
|
u.Path = "/" + testDBName
|
||||||
|
testURL := u.String()
|
||||||
|
|
||||||
|
cleanup := func() {
|
||||||
|
dropDB, err := sql.Open("postgres", adminConnStr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer dropDB.Close()
|
||||||
|
dropDB.Exec(fmt.Sprintf(
|
||||||
|
`SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '%s' AND pid <> pg_backend_pid()`,
|
||||||
|
testDBName,
|
||||||
|
))
|
||||||
|
dropDB.Exec(fmt.Sprintf(`DROP DATABASE IF EXISTS "%s"`, testDBName))
|
||||||
|
}
|
||||||
|
|
||||||
|
return testURL, cleanup, nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user