2020-02-13 14:45:02 +00:00
|
|
|
package migrations
|
|
|
|
|
|
|
|
import (
|
2021-06-04 14:56:49 +00:00
|
|
|
"context"
|
2020-08-11 11:23:41 +00:00
|
|
|
"errors"
|
2020-08-05 10:13:35 +00:00
|
|
|
"testing"
|
|
|
|
|
2021-07-29 11:53:13 +00:00
|
|
|
"github.com/ledgerwatch/erigon-lib/kv"
|
|
|
|
"github.com/ledgerwatch/erigon-lib/kv/memdb"
|
2021-05-20 18:25:53 +00:00
|
|
|
"github.com/ledgerwatch/erigon/eth/stagedsync/stages"
|
2020-09-05 16:07:27 +00:00
|
|
|
|
2020-08-05 10:13:35 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2020-02-13 14:45:02 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestApplyWithInit(t *testing.T) {
|
2021-07-28 02:47:38 +00:00
|
|
|
require, db := require.New(t), memdb.NewTestDB(t)
|
2021-06-04 14:56:49 +00:00
|
|
|
m := []Migration{
|
2020-02-13 14:45:02 +00:00
|
|
|
{
|
|
|
|
"one",
|
2021-07-28 02:47:38 +00:00
|
|
|
func(db kv.RwDB, tmpdir string, progress []byte, BeforeCommit Callback) (err error) {
|
2021-07-24 04:28:05 +00:00
|
|
|
tx, err := db.BeginRw(context.Background())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer tx.Rollback()
|
|
|
|
|
|
|
|
if err := BeforeCommit(tx, nil, true); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return tx.Commit()
|
2020-02-13 14:45:02 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"two",
|
2021-07-28 02:47:38 +00:00
|
|
|
func(db kv.RwDB, tmpdir string, progress []byte, BeforeCommit Callback) (err error) {
|
2021-07-24 04:28:05 +00:00
|
|
|
tx, err := db.BeginRw(context.Background())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer tx.Rollback()
|
|
|
|
|
|
|
|
if err := BeforeCommit(tx, nil, true); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return tx.Commit()
|
2020-02-13 14:45:02 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2021-07-28 02:47:38 +00:00
|
|
|
migrator := NewMigrator(kv.ChainDB)
|
2021-06-04 14:56:49 +00:00
|
|
|
migrator.Migrations = m
|
2021-06-16 10:57:58 +00:00
|
|
|
err := migrator.Apply(db, "")
|
2020-08-05 10:13:35 +00:00
|
|
|
require.NoError(err)
|
2021-06-04 14:56:49 +00:00
|
|
|
var applied map[string][]byte
|
2021-07-28 02:47:38 +00:00
|
|
|
err = db.View(context.Background(), func(tx kv.Tx) error {
|
2021-06-04 14:56:49 +00:00
|
|
|
applied, err = AppliedMigrations(tx, false)
|
|
|
|
require.NoError(err)
|
2020-08-05 10:13:35 +00:00
|
|
|
|
2021-06-04 14:56:49 +00:00
|
|
|
_, ok := applied[m[0].Name]
|
|
|
|
require.True(ok)
|
|
|
|
_, ok = applied[m[1].Name]
|
|
|
|
require.True(ok)
|
|
|
|
return nil
|
|
|
|
})
|
2020-08-05 10:13:35 +00:00
|
|
|
require.NoError(err)
|
|
|
|
|
|
|
|
// apply again
|
2021-06-16 10:57:58 +00:00
|
|
|
err = migrator.Apply(db, "")
|
2020-08-05 10:13:35 +00:00
|
|
|
require.NoError(err)
|
2021-07-28 02:47:38 +00:00
|
|
|
err = db.View(context.Background(), func(tx kv.Tx) error {
|
2021-06-04 14:56:49 +00:00
|
|
|
applied2, err := AppliedMigrations(tx, false)
|
|
|
|
require.NoError(err)
|
|
|
|
require.Equal(applied, applied2)
|
|
|
|
return nil
|
|
|
|
})
|
2020-08-05 10:13:35 +00:00
|
|
|
require.NoError(err)
|
2020-02-13 14:45:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestApplyWithoutInit(t *testing.T) {
|
2021-07-28 02:47:38 +00:00
|
|
|
require, db := require.New(t), memdb.NewTestDB(t)
|
2021-06-04 14:56:49 +00:00
|
|
|
m := []Migration{
|
2020-02-13 14:45:02 +00:00
|
|
|
{
|
|
|
|
"one",
|
2021-07-28 02:47:38 +00:00
|
|
|
func(db kv.RwDB, tmpdir string, progress []byte, BeforeCommit Callback) (err error) {
|
2020-02-13 14:45:02 +00:00
|
|
|
t.Fatal("shouldn't been executed")
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"two",
|
2021-07-28 02:47:38 +00:00
|
|
|
func(db kv.RwDB, tmpdir string, progress []byte, BeforeCommit Callback) (err error) {
|
2021-07-24 04:28:05 +00:00
|
|
|
tx, err := db.BeginRw(context.Background())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer tx.Rollback()
|
|
|
|
|
|
|
|
if err := BeforeCommit(tx, nil, true); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return tx.Commit()
|
2020-08-04 09:25:28 +00:00
|
|
|
},
|
|
|
|
},
|
2020-02-13 14:45:02 +00:00
|
|
|
}
|
2021-07-28 02:47:38 +00:00
|
|
|
err := db.Update(context.Background(), func(tx kv.RwTx) error {
|
|
|
|
return tx.Put(kv.Migrations, []byte(m[0].Name), []byte{1})
|
2021-07-04 07:50:32 +00:00
|
|
|
})
|
2020-08-05 10:13:35 +00:00
|
|
|
require.NoError(err)
|
2020-08-04 09:25:28 +00:00
|
|
|
|
2021-07-28 02:47:38 +00:00
|
|
|
migrator := NewMigrator(kv.ChainDB)
|
2021-06-04 14:56:49 +00:00
|
|
|
migrator.Migrations = m
|
2021-06-16 10:57:58 +00:00
|
|
|
err = migrator.Apply(db, "")
|
2020-08-05 10:13:35 +00:00
|
|
|
require.NoError(err)
|
|
|
|
|
2021-06-04 14:56:49 +00:00
|
|
|
var applied map[string][]byte
|
2021-07-28 02:47:38 +00:00
|
|
|
err = db.View(context.Background(), func(tx kv.Tx) error {
|
2021-06-04 14:56:49 +00:00
|
|
|
applied, err = AppliedMigrations(tx, false)
|
|
|
|
require.NoError(err)
|
2020-08-05 10:13:35 +00:00
|
|
|
|
2021-06-04 14:56:49 +00:00
|
|
|
require.Equal(2, len(applied))
|
|
|
|
_, ok := applied[m[1].Name]
|
|
|
|
require.True(ok)
|
|
|
|
_, ok = applied[m[0].Name]
|
|
|
|
require.True(ok)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
require.NoError(err)
|
2020-08-05 10:13:35 +00:00
|
|
|
|
|
|
|
// apply again
|
2021-06-16 10:57:58 +00:00
|
|
|
err = migrator.Apply(db, "")
|
2020-08-05 10:13:35 +00:00
|
|
|
require.NoError(err)
|
|
|
|
|
2021-07-28 02:47:38 +00:00
|
|
|
err = db.View(context.Background(), func(tx kv.Tx) error {
|
2021-06-04 14:56:49 +00:00
|
|
|
applied2, err := AppliedMigrations(tx, false)
|
|
|
|
require.NoError(err)
|
|
|
|
require.Equal(applied, applied2)
|
|
|
|
return nil
|
|
|
|
})
|
2020-08-05 10:13:35 +00:00
|
|
|
require.NoError(err)
|
2021-06-04 14:56:49 +00:00
|
|
|
|
2020-08-05 10:13:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestWhenNonFirstMigrationAlreadyApplied(t *testing.T) {
|
2021-07-28 02:47:38 +00:00
|
|
|
require, db := require.New(t), memdb.NewTestDB(t)
|
2021-06-04 14:56:49 +00:00
|
|
|
m := []Migration{
|
2020-08-05 10:13:35 +00:00
|
|
|
{
|
|
|
|
"one",
|
2021-07-28 02:47:38 +00:00
|
|
|
func(db kv.RwDB, tmpdir string, progress []byte, BeforeCommit Callback) (err error) {
|
2021-07-24 04:28:05 +00:00
|
|
|
tx, err := db.BeginRw(context.Background())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer tx.Rollback()
|
|
|
|
|
|
|
|
if err := BeforeCommit(tx, nil, true); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return tx.Commit()
|
2020-08-05 10:13:35 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"two",
|
2021-07-28 02:47:38 +00:00
|
|
|
func(db kv.RwDB, tmpdir string, progress []byte, BeforeCommit Callback) (err error) {
|
2020-08-05 10:13:35 +00:00
|
|
|
t.Fatal("shouldn't been executed")
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
},
|
2020-08-04 10:05:27 +00:00
|
|
|
}
|
2021-07-28 02:47:38 +00:00
|
|
|
err := db.Update(context.Background(), func(tx kv.RwTx) error {
|
|
|
|
return tx.Put(kv.Migrations, []byte(m[1].Name), []byte{1}) // apply non-first migration
|
2021-07-04 07:50:32 +00:00
|
|
|
})
|
2020-08-05 10:13:35 +00:00
|
|
|
require.NoError(err)
|
|
|
|
|
2021-07-28 02:47:38 +00:00
|
|
|
migrator := NewMigrator(kv.ChainDB)
|
2021-06-04 14:56:49 +00:00
|
|
|
migrator.Migrations = m
|
2021-06-16 10:57:58 +00:00
|
|
|
err = migrator.Apply(db, "")
|
2020-08-05 10:13:35 +00:00
|
|
|
require.NoError(err)
|
|
|
|
|
2021-06-04 14:56:49 +00:00
|
|
|
var applied map[string][]byte
|
2021-07-28 02:47:38 +00:00
|
|
|
err = db.View(context.Background(), func(tx kv.Tx) error {
|
2021-06-04 14:56:49 +00:00
|
|
|
applied, err = AppliedMigrations(tx, false)
|
|
|
|
require.NoError(err)
|
2020-08-05 10:13:35 +00:00
|
|
|
|
2021-06-04 14:56:49 +00:00
|
|
|
require.Equal(2, len(applied))
|
|
|
|
_, ok := applied[m[1].Name]
|
|
|
|
require.True(ok)
|
|
|
|
_, ok = applied[m[0].Name]
|
|
|
|
require.True(ok)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
require.NoError(err)
|
2020-08-05 10:13:35 +00:00
|
|
|
|
|
|
|
// apply again
|
2021-06-16 10:57:58 +00:00
|
|
|
err = migrator.Apply(db, "")
|
2020-08-05 10:13:35 +00:00
|
|
|
require.NoError(err)
|
2021-07-28 02:47:38 +00:00
|
|
|
err = db.View(context.Background(), func(tx kv.Tx) error {
|
2021-06-04 14:56:49 +00:00
|
|
|
applied2, err := AppliedMigrations(tx, false)
|
|
|
|
require.NoError(err)
|
|
|
|
require.Equal(applied, applied2)
|
|
|
|
return nil
|
|
|
|
})
|
2020-08-05 10:13:35 +00:00
|
|
|
require.NoError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMarshalStages(t *testing.T) {
|
2021-07-08 02:56:09 +00:00
|
|
|
require := require.New(t)
|
2021-07-28 02:47:38 +00:00
|
|
|
_, tx := memdb.NewTestTx(t)
|
2020-08-05 10:13:35 +00:00
|
|
|
|
2021-07-08 02:56:09 +00:00
|
|
|
err := stages.SaveStageProgress(tx, stages.Execution, 42)
|
2020-08-05 10:13:35 +00:00
|
|
|
require.NoError(err)
|
|
|
|
|
2021-07-08 02:56:09 +00:00
|
|
|
data, err := MarshalMigrationPayload(tx)
|
2020-08-05 10:13:35 +00:00
|
|
|
require.NoError(err)
|
|
|
|
|
|
|
|
res, err := UnmarshalMigrationPayload(data)
|
|
|
|
require.NoError(err)
|
|
|
|
|
|
|
|
require.Equal(1, len(res))
|
2020-09-05 16:07:27 +00:00
|
|
|
v, ok := res[string(stages.Execution)]
|
2020-08-05 10:13:35 +00:00
|
|
|
require.True(ok)
|
|
|
|
require.NotNil(v)
|
2020-02-13 14:45:02 +00:00
|
|
|
}
|
2020-08-11 11:23:41 +00:00
|
|
|
|
|
|
|
func TestValidation(t *testing.T) {
|
2021-07-28 02:47:38 +00:00
|
|
|
require, db := require.New(t), memdb.NewTestDB(t)
|
2021-06-04 14:56:49 +00:00
|
|
|
m := []Migration{
|
2020-08-11 11:23:41 +00:00
|
|
|
{
|
|
|
|
Name: "repeated_name",
|
2021-07-28 02:47:38 +00:00
|
|
|
Up: func(db kv.RwDB, tmpdir string, progress []byte, BeforeCommit Callback) (err error) {
|
2021-07-24 04:28:05 +00:00
|
|
|
tx, err := db.BeginRw(context.Background())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer tx.Rollback()
|
|
|
|
|
|
|
|
if err := BeforeCommit(tx, nil, true); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return tx.Commit()
|
2020-08-11 11:23:41 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "repeated_name",
|
2021-07-28 02:47:38 +00:00
|
|
|
Up: func(db kv.RwDB, tmpdir string, progress []byte, BeforeCommit Callback) (err error) {
|
2021-07-24 04:28:05 +00:00
|
|
|
tx, err := db.BeginRw(context.Background())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer tx.Rollback()
|
|
|
|
|
|
|
|
if err := BeforeCommit(tx, nil, true); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return tx.Commit()
|
2020-08-11 11:23:41 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2021-07-28 02:47:38 +00:00
|
|
|
migrator := NewMigrator(kv.ChainDB)
|
2021-06-04 14:56:49 +00:00
|
|
|
migrator.Migrations = m
|
2021-06-16 10:57:58 +00:00
|
|
|
err := migrator.Apply(db, "")
|
2020-08-11 11:23:41 +00:00
|
|
|
require.True(errors.Is(err, ErrMigrationNonUniqueName))
|
|
|
|
|
2021-06-04 14:56:49 +00:00
|
|
|
var applied map[string][]byte
|
2021-07-28 02:47:38 +00:00
|
|
|
err = db.View(context.Background(), func(tx kv.Tx) error {
|
2021-06-04 14:56:49 +00:00
|
|
|
applied, err = AppliedMigrations(tx, false)
|
|
|
|
require.NoError(err)
|
|
|
|
require.Equal(0, len(applied))
|
|
|
|
return nil
|
|
|
|
})
|
2020-08-11 11:23:41 +00:00
|
|
|
require.NoError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCommitCallRequired(t *testing.T) {
|
2021-07-28 02:47:38 +00:00
|
|
|
require, db := require.New(t), memdb.NewTestDB(t)
|
2021-06-04 14:56:49 +00:00
|
|
|
m := []Migration{
|
2020-08-11 11:23:41 +00:00
|
|
|
{
|
|
|
|
Name: "one",
|
2021-07-28 02:47:38 +00:00
|
|
|
Up: func(db kv.RwDB, tmpdir string, progress []byte, BeforeCommit Callback) (err error) {
|
2021-07-24 04:28:05 +00:00
|
|
|
//don't call BeforeCommit
|
|
|
|
return nil
|
2020-08-11 11:23:41 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2021-07-28 02:47:38 +00:00
|
|
|
migrator := NewMigrator(kv.ChainDB)
|
2021-06-04 14:56:49 +00:00
|
|
|
migrator.Migrations = m
|
2021-06-16 10:57:58 +00:00
|
|
|
err := migrator.Apply(db, "")
|
2020-08-11 11:23:41 +00:00
|
|
|
require.True(errors.Is(err, ErrMigrationCommitNotCalled))
|
|
|
|
|
2021-06-04 14:56:49 +00:00
|
|
|
var applied map[string][]byte
|
2021-07-28 02:47:38 +00:00
|
|
|
err = db.View(context.Background(), func(tx kv.Tx) error {
|
2021-06-04 14:56:49 +00:00
|
|
|
applied, err = AppliedMigrations(tx, false)
|
|
|
|
require.NoError(err)
|
|
|
|
require.Equal(0, len(applied))
|
|
|
|
return nil
|
|
|
|
})
|
2020-08-11 11:23:41 +00:00
|
|
|
require.NoError(err)
|
|
|
|
}
|