mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
* migratex api uses tx now instead of db we want to be able to do external queries outside of the migration itself inside of the same transaction for version checking. if we don't do this, we risk the case where we set the version to the latest but we don't run the table creates at all, so we have a db that thinks it's up to date but doesn't even have any tables, and on subsequent boots if a migration slides in then the migrations will run when there are no tables. it was unlikely, but now it's dead. * tx friendly table exists check the previous existence checker for dbs was relying on getting back errors about the db not existing. if we use this in a tx, it makes the whole tx invalid for postgres. so, now we have count the table queries which return a 1 or a 0 instead of a 1 or an error so that we can check existence inside of a transaction. voila.
131 lines
3.0 KiB
Go
131 lines
3.0 KiB
Go
package sql
|
|
|
|
import (
|
|
"context"
|
|
"net/url"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/fnproject/fn/api/datastore/internal/datastoretest"
|
|
"github.com/fnproject/fn/api/datastore/internal/datastoreutil"
|
|
"github.com/fnproject/fn/api/datastore/sql/migratex"
|
|
"github.com/fnproject/fn/api/datastore/sql/migrations"
|
|
logstoretest "github.com/fnproject/fn/api/logs/testing"
|
|
"github.com/fnproject/fn/api/models"
|
|
"github.com/jmoiron/sqlx"
|
|
)
|
|
|
|
// since New with fresh dbs skips all migrations:
|
|
// * open a fresh db on latest version
|
|
// * run all down migrations
|
|
// * run all up migrations
|
|
// [ then run tests against that db ]
|
|
func newWithMigrations(ctx context.Context, url *url.URL) (*sqlStore, error) {
|
|
ds, err := newDS(ctx, url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = ds.Tx(func(tx *sqlx.Tx) error {
|
|
return migratex.Down(ctx, tx, migrations.Migrations)
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// go through New, to ensure our Up logic works in there...
|
|
ds, err = newDS(ctx, url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return ds, nil
|
|
}
|
|
|
|
func TestDatastore(t *testing.T) {
|
|
ctx := context.Background()
|
|
defer os.RemoveAll("sqlite_test_dir")
|
|
u, err := url.Parse("sqlite3://sqlite_test_dir")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
f := func(t *testing.T) models.Datastore {
|
|
os.RemoveAll("sqlite_test_dir")
|
|
ds, err := newDS(ctx, u)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// we don't want to test the validator, really
|
|
return datastoreutil.NewValidator(ds)
|
|
}
|
|
datastoretest.Test(t, f)
|
|
|
|
// also logs
|
|
logstoretest.Test(t, f(t))
|
|
|
|
// NOTE: sqlite3 does not like ALTER TABLE DROP COLUMN so do not run
|
|
// migration tests against it, only pg and mysql -- should prove UP migrations
|
|
// will likely work for sqlite3, but may need separate testing by devs :(
|
|
|
|
// if being run from test script (CI) poke around for pg and mysql containers
|
|
// to run tests against them too. this runs with a fresh db first run, then
|
|
// will down migrate all migrations, up migrate, and run tests again.
|
|
|
|
both := func(u *url.URL) {
|
|
f := func(t *testing.T) models.Datastore {
|
|
ds, err := newDS(ctx, u)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ds.clear()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return datastoreutil.NewValidator(ds)
|
|
}
|
|
|
|
// test fresh w/o migrations
|
|
datastoretest.Test(t, f)
|
|
|
|
// also test sql implements logstore
|
|
logstoretest.Test(t, f(t))
|
|
|
|
f = func(t *testing.T) models.Datastore {
|
|
t.Log("with migrations now!")
|
|
ds, err := newWithMigrations(ctx, u)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ds.clear()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return datastoreutil.NewValidator(ds)
|
|
}
|
|
|
|
// test that migrations work & things work with them
|
|
datastoretest.Test(t, f)
|
|
|
|
// also test sql implements logstore
|
|
logstoretest.Test(t, f(t))
|
|
}
|
|
|
|
if pg := os.Getenv("POSTGRES_URL"); pg != "" {
|
|
u, err := url.Parse(pg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
both(u)
|
|
}
|
|
|
|
if mysql := os.Getenv("MYSQL_URL"); mysql != "" {
|
|
u, err := url.Parse(mysql)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
both(u)
|
|
}
|
|
}
|