2019-04-02 08:54:09 +01:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package storagenodedb_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"path/filepath"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
2019-07-12 20:29:09 +01:00
|
|
|
"github.com/zeebo/errs"
|
2019-04-02 08:54:09 +01:00
|
|
|
"go.uber.org/zap/zaptest"
|
|
|
|
|
|
|
|
"storj.io/storj/internal/dbutil/dbschema"
|
|
|
|
"storj.io/storj/internal/dbutil/sqliteutil"
|
2019-08-21 15:32:25 +01:00
|
|
|
"storj.io/storj/internal/testcontext"
|
2019-04-02 08:54:09 +01:00
|
|
|
"storj.io/storj/storagenode/storagenodedb"
|
|
|
|
)
|
|
|
|
|
|
|
|
// loadSnapshots loads all the dbschemas from testdata/db.* caching the result
|
|
|
|
func loadSnapshots() (*dbschema.Snapshots, error) {
|
|
|
|
snapshots := &dbschema.Snapshots{}
|
|
|
|
|
|
|
|
// snapshot represents clean DB state
|
|
|
|
snapshots.Add(&dbschema.Snapshot{
|
|
|
|
Version: -1,
|
|
|
|
Schema: &dbschema.Schema{},
|
|
|
|
Script: "",
|
|
|
|
})
|
|
|
|
|
|
|
|
// find all sql files
|
|
|
|
matches, err := filepath.Glob("testdata/sqlite.*")
|
|
|
|
if err != nil {
|
2019-07-12 20:29:09 +01:00
|
|
|
return nil, errs.Wrap(err)
|
2019-04-02 08:54:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, match := range matches {
|
|
|
|
versionStr := match[17 : len(match)-4] // hack to avoid trim issues with path differences in windows/linux
|
|
|
|
version, err := strconv.Atoi(versionStr)
|
|
|
|
if err != nil {
|
2019-07-12 20:29:09 +01:00
|
|
|
return nil, errs.Wrap(err)
|
2019-04-02 08:54:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
scriptData, err := ioutil.ReadFile(match)
|
|
|
|
if err != nil {
|
2019-07-12 20:29:09 +01:00
|
|
|
return nil, errs.Wrap(err)
|
2019-04-02 08:54:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
snapshot, err := sqliteutil.LoadSnapshotFromSQL(string(scriptData))
|
|
|
|
if err != nil {
|
2019-07-12 20:29:09 +01:00
|
|
|
return nil, errs.Wrap(err)
|
2019-04-02 08:54:09 +01:00
|
|
|
}
|
|
|
|
snapshot.Version = version
|
|
|
|
|
|
|
|
snapshots.Add(snapshot)
|
|
|
|
}
|
|
|
|
|
|
|
|
snapshots.Sort()
|
|
|
|
|
|
|
|
return snapshots, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
const newDataSeparator = `-- NEW DATA --`
|
|
|
|
|
|
|
|
func newData(snap *dbschema.Snapshot) string {
|
|
|
|
tokens := strings.SplitN(snap.Script, newDataSeparator, 2)
|
|
|
|
if len(tokens) != 2 {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return tokens[1]
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMigrate(t *testing.T) {
|
2019-08-21 15:32:25 +01:00
|
|
|
ctx := testcontext.New(t)
|
2019-04-02 08:54:09 +01:00
|
|
|
snapshots, err := loadSnapshots()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
log := zaptest.NewLogger(t)
|
|
|
|
|
2019-08-21 15:32:25 +01:00
|
|
|
cfg := storagenodedb.Config{
|
|
|
|
Pieces: ctx.Dir("storage"),
|
|
|
|
Info2: ctx.Dir("storage") + "/info.db",
|
|
|
|
Kademlia: ctx.Dir("storage") + "/kademlia",
|
|
|
|
}
|
|
|
|
|
2019-04-02 08:54:09 +01:00
|
|
|
// create a new satellitedb connection
|
2019-08-21 15:32:25 +01:00
|
|
|
db, err := storagenodedb.New(log, cfg)
|
2019-04-02 08:54:09 +01:00
|
|
|
require.NoError(t, err)
|
|
|
|
defer func() { require.NoError(t, db.Close()) }()
|
|
|
|
|
|
|
|
// get migration for this database
|
|
|
|
migrations := db.Migration()
|
|
|
|
for i, step := range migrations.Steps {
|
|
|
|
// the schema is different when migration step is before the step, cannot test the layout
|
|
|
|
tag := fmt.Sprintf("#%d - v%d", i, step.Version)
|
|
|
|
|
|
|
|
// run migration up to a specific version
|
2019-08-21 15:32:25 +01:00
|
|
|
err := migrations.TargetVersion(step.Version).Run(log.Named("migrate"), db.VersionsMigration())
|
2019-04-02 08:54:09 +01:00
|
|
|
require.NoError(t, err, tag)
|
|
|
|
|
|
|
|
// find the matching expected version
|
|
|
|
expected, ok := snapshots.FindVersion(step.Version)
|
|
|
|
require.True(t, ok)
|
|
|
|
|
|
|
|
// insert data for new tables
|
|
|
|
if newdata := newData(expected); newdata != "" {
|
2019-08-21 15:32:25 +01:00
|
|
|
_, err = db.Versions().Exec(newdata)
|
2019-04-02 08:54:09 +01:00
|
|
|
require.NoError(t, err, tag)
|
|
|
|
}
|
|
|
|
|
|
|
|
// load schema from database
|
2019-08-21 15:32:25 +01:00
|
|
|
currentSchema, err := sqliteutil.QuerySchema(db.Versions())
|
2019-04-02 08:54:09 +01:00
|
|
|
require.NoError(t, err, tag)
|
|
|
|
|
|
|
|
// we don't care changes in versions table
|
|
|
|
currentSchema.DropTable("versions")
|
|
|
|
|
|
|
|
// load data from database
|
2019-08-21 15:32:25 +01:00
|
|
|
currentData, err := sqliteutil.QueryData(db.Versions(), currentSchema)
|
2019-04-02 08:54:09 +01:00
|
|
|
require.NoError(t, err, tag)
|
|
|
|
|
|
|
|
// verify schema and data
|
|
|
|
require.Equal(t, expected.Schema, currentSchema, tag)
|
|
|
|
require.Equal(t, expected.Data, currentData, tag)
|
|
|
|
}
|
|
|
|
}
|