2019-09-18 18:02:40 +03:00
|
|
|
package core
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
|
|
|
"regexp"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/DATA-DOG/go-sqlmock"
|
|
|
|
"github.com/jinzhu/gorm"
|
2019-09-19 14:16:52 +03:00
|
|
|
_ "github.com/jinzhu/gorm/dialects/postgres"
|
2019-09-18 18:02:40 +03:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
"gopkg.in/gormigrate.v1"
|
|
|
|
)
|
|
|
|
|
|
|
|
type TestModel struct {
|
|
|
|
Name string `gorm:"column:name; type:varchar(70)"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (TestModel) TableName() string {
|
|
|
|
return "test_model"
|
|
|
|
}
|
|
|
|
|
|
|
|
type MigrateTest struct {
|
|
|
|
suite.Suite
|
|
|
|
DB *gorm.DB
|
|
|
|
Migrate *Migrate
|
|
|
|
mock sqlmock.Sqlmock
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) SetupSuite() {
|
2019-09-19 14:16:52 +03:00
|
|
|
require.NotEmpty(m.T(), (MigrationInfo{}).TableName())
|
|
|
|
m.RefreshMigrate()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) RefreshMigrate() {
|
2019-09-18 18:02:40 +03:00
|
|
|
var (
|
|
|
|
db *sql.DB
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
|
|
|
|
db, m.mock, err = sqlmock.New()
|
|
|
|
require.NoError(m.T(), err)
|
|
|
|
|
|
|
|
m.DB, err = gorm.Open("postgres", db)
|
|
|
|
require.NoError(m.T(), err)
|
|
|
|
|
|
|
|
m.DB.LogMode(true)
|
|
|
|
m.Migrate = &Migrate{
|
|
|
|
db: m.DB,
|
|
|
|
prepared: false,
|
|
|
|
migrations: map[string]*gormigrate.Migration{},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-19 14:16:52 +03:00
|
|
|
func (m *MigrateTest) Migration_TestModelFirst() *gormigrate.Migration {
|
2019-09-18 18:02:40 +03:00
|
|
|
return &gormigrate.Migration{
|
|
|
|
ID: "1",
|
|
|
|
Migrate: func(db *gorm.DB) error {
|
|
|
|
return db.AutoMigrate(TestModel{}).Error
|
|
|
|
},
|
|
|
|
Rollback: func(db *gorm.DB) error {
|
|
|
|
return db.DropTable(TestModel{}).Error
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-19 14:16:52 +03:00
|
|
|
func (m *MigrateTest) Migration_TestModelSecond() *gormigrate.Migration {
|
|
|
|
return &gormigrate.Migration{
|
|
|
|
ID: "2",
|
|
|
|
Migrate: func(db *gorm.DB) error {
|
|
|
|
return db.Model(TestModel{}).ModifyColumn("name", "varchar(100)").Error
|
|
|
|
},
|
|
|
|
Rollback: func(db *gorm.DB) error {
|
|
|
|
return db.Model(TestModel{}).ModifyColumn("name", "varchar(70)").Error
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-18 18:02:40 +03:00
|
|
|
func (m *MigrateTest) Test_Add() {
|
|
|
|
m.RefreshMigrate()
|
|
|
|
m.Migrate.Add(nil)
|
2019-09-19 14:16:52 +03:00
|
|
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
2019-09-18 18:02:40 +03:00
|
|
|
|
|
|
|
assert.Equal(m.T(), 1, len(m.Migrate.migrations))
|
|
|
|
i, ok := m.Migrate.migrations["1"]
|
|
|
|
require.True(m.T(), ok)
|
|
|
|
assert.Equal(m.T(), "1", i.ID)
|
2019-09-19 14:16:52 +03:00
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
2019-09-18 18:02:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) Test_prepareMigrations_NilDB() {
|
|
|
|
m.RefreshMigrate()
|
|
|
|
m.Migrate.db = nil
|
|
|
|
err := m.Migrate.prepareMigrations()
|
|
|
|
|
|
|
|
require.Error(m.T(), err)
|
|
|
|
assert.Equal(m.T(), "db must not be nil", err.Error())
|
2019-09-19 14:16:52 +03:00
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
2019-09-18 18:02:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) Test_prepareMigrations_AlreadyPrepared() {
|
|
|
|
m.RefreshMigrate()
|
|
|
|
m.Migrate.prepared = true
|
|
|
|
err := m.Migrate.prepareMigrations()
|
|
|
|
|
|
|
|
require.NoError(m.T(), err)
|
|
|
|
assert.Nil(m.T(), m.Migrate.GORMigrate)
|
2019-09-19 14:16:52 +03:00
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
2019-09-18 18:02:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) Test_prepareMigrations_OK() {
|
|
|
|
m.RefreshMigrate()
|
2019-09-19 14:16:52 +03:00
|
|
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
2019-09-18 18:02:40 +03:00
|
|
|
err := m.Migrate.prepareMigrations()
|
|
|
|
|
|
|
|
require.NoError(m.T(), err)
|
|
|
|
assert.True(m.T(), m.Migrate.prepared)
|
|
|
|
assert.NotNil(m.T(), m.Migrate.GORMigrate)
|
2019-09-19 14:16:52 +03:00
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
2019-09-18 18:02:40 +03:00
|
|
|
}
|
|
|
|
|
2019-09-19 14:16:52 +03:00
|
|
|
func (m *MigrateTest) Test_Migrate_Fail_NilDB() {
|
2019-09-18 18:02:40 +03:00
|
|
|
m.RefreshMigrate()
|
2019-09-19 14:16:52 +03:00
|
|
|
m.Migrate.SetDB(nil)
|
|
|
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
|
|
|
|
|
|
|
err := m.Migrate.Migrate()
|
|
|
|
|
|
|
|
assert.Error(m.T(), err)
|
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) Test_Migrate_Success_NoMigrations() {
|
|
|
|
m.RefreshMigrate()
|
|
|
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
|
|
|
|
|
|
|
m.mock.ExpectBegin()
|
|
|
|
m.mock.
|
|
|
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE migrations (id VARCHAR(255) PRIMARY KEY)`)).
|
|
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
m.mock.
|
|
|
|
ExpectQuery(regexp.QuoteMeta(`SELECT id FROM migrations`)).
|
|
|
|
WillReturnRows(sqlmock.NewRows([]string{"1"}))
|
|
|
|
m.mock.
|
|
|
|
ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "migrations" WHERE (id = $1)`)).
|
|
|
|
WithArgs("1").
|
|
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
|
|
|
m.mock.ExpectCommit()
|
|
|
|
|
|
|
|
err := m.Migrate.Migrate()
|
|
|
|
|
|
|
|
assert.NoError(m.T(), err)
|
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) Test_Migrate_Success() {
|
|
|
|
m.RefreshMigrate()
|
|
|
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
2019-09-18 18:02:40 +03:00
|
|
|
|
|
|
|
m.mock.ExpectBegin()
|
|
|
|
m.mock.
|
|
|
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE migrations (id VARCHAR(255) PRIMARY KEY)`)).
|
|
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
m.mock.
|
|
|
|
ExpectQuery(regexp.QuoteMeta(`SELECT id FROM migrations`)).
|
|
|
|
WillReturnRows(sqlmock.NewRows([]string{"1"}))
|
|
|
|
m.mock.
|
|
|
|
ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "migrations" WHERE (id = $1)`)).
|
|
|
|
WithArgs("1").
|
|
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))
|
|
|
|
m.mock.
|
|
|
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE "test_model" ("name" varchar(70) )`)).
|
|
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
m.mock.
|
|
|
|
ExpectExec(regexp.QuoteMeta(`INSERT INTO migrations (id) VALUES ($1)`)).
|
|
|
|
WithArgs("1").
|
|
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
m.mock.ExpectCommit()
|
|
|
|
|
|
|
|
err := m.Migrate.Migrate()
|
|
|
|
|
|
|
|
assert.NoError(m.T(), err)
|
2019-09-19 14:16:52 +03:00
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) Test_Rollback_Fail_NilDB() {
|
|
|
|
m.RefreshMigrate()
|
|
|
|
m.Migrate.SetDB(nil)
|
|
|
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
|
|
|
|
|
|
|
err := m.Migrate.Rollback()
|
|
|
|
|
|
|
|
assert.Error(m.T(), err)
|
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) Test_Rollback_Fail_NoMigrations() {
|
|
|
|
m.RefreshMigrate()
|
|
|
|
m.Migrate.first = m.Migration_TestModelFirst()
|
|
|
|
|
|
|
|
err := m.Migrate.Rollback()
|
|
|
|
|
|
|
|
assert.Error(m.T(), err)
|
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) Test_Rollback_Fail_NoFirstMigration() {
|
|
|
|
m.RefreshMigrate()
|
|
|
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
|
|
|
m.Migrate.first = nil
|
|
|
|
|
|
|
|
err := m.Migrate.Rollback()
|
|
|
|
|
|
|
|
assert.Error(m.T(), err)
|
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) Test_MigrateTo_Fail_NilDB() {
|
|
|
|
m.RefreshMigrate()
|
|
|
|
m.Migrate.SetDB(nil)
|
|
|
|
|
|
|
|
err := m.Migrate.MigrateTo("version")
|
|
|
|
|
|
|
|
assert.Error(m.T(), err)
|
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) Test_MigrateTo_DoNothing() {
|
|
|
|
m.RefreshMigrate()
|
|
|
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
|
|
|
|
|
|
|
m.mock.
|
|
|
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE "migrations" ("id" varchar(255) , PRIMARY KEY ("id"))`)).
|
|
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
m.mock.ExpectBegin()
|
|
|
|
m.mock.
|
|
|
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE migrations (id VARCHAR(255) PRIMARY KEY)`)).
|
|
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
m.mock.
|
|
|
|
ExpectQuery(regexp.QuoteMeta(`SELECT id FROM migrations`)).
|
|
|
|
WillReturnRows(sqlmock.NewRows([]string{"1"}))
|
|
|
|
m.mock.
|
|
|
|
ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "migrations" WHERE (id = $1)`)).
|
|
|
|
WithArgs("1").
|
|
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
|
|
|
m.mock.ExpectCommit()
|
|
|
|
|
|
|
|
err := m.Migrate.MigrateTo(m.Migration_TestModelFirst().ID)
|
|
|
|
|
|
|
|
assert.NoError(m.T(), err)
|
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) Test_MigrateTo() {
|
|
|
|
m.RefreshMigrate()
|
|
|
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
|
|
|
|
|
|
|
m.mock.
|
|
|
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE "migrations" ("id" varchar(255) , PRIMARY KEY ("id"))`)).
|
|
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
m.mock.ExpectBegin()
|
|
|
|
m.mock.
|
|
|
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE migrations (id VARCHAR(255) PRIMARY KEY)`)).
|
|
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
m.mock.
|
|
|
|
ExpectQuery(regexp.QuoteMeta(`SELECT id FROM migrations`)).
|
|
|
|
WillReturnRows(sqlmock.NewRows([]string{"1"}))
|
|
|
|
m.mock.
|
|
|
|
ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "migrations" WHERE (id = $1)`)).
|
|
|
|
WithArgs("1").
|
|
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))
|
|
|
|
m.mock.
|
|
|
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE "test_model" ("name" varchar(70) )`)).
|
|
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
m.mock.
|
|
|
|
ExpectExec(regexp.QuoteMeta(`INSERT INTO migrations (id) VALUES ($1)`)).
|
|
|
|
WithArgs("1").
|
|
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
m.mock.ExpectCommit()
|
|
|
|
|
|
|
|
err := m.Migrate.MigrateTo(m.Migration_TestModelFirst().ID)
|
|
|
|
|
|
|
|
assert.NoError(m.T(), err)
|
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) Test_RollbackTo() {
|
|
|
|
m.RefreshMigrate()
|
|
|
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
|
|
|
m.Migrate.Add(m.Migration_TestModelSecond())
|
|
|
|
|
|
|
|
m.mock.ExpectBegin()
|
|
|
|
m.mock.ExpectCommit()
|
|
|
|
|
|
|
|
err := m.Migrate.RollbackTo(m.Migration_TestModelSecond().ID)
|
|
|
|
|
|
|
|
assert.NoError(m.T(), err)
|
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) Test_MigrateNextTo() {
|
|
|
|
m.RefreshMigrate()
|
|
|
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
|
|
|
m.Migrate.Add(m.Migration_TestModelSecond())
|
|
|
|
|
|
|
|
m.mock.
|
|
|
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE "migrations" ("id" varchar(255) , PRIMARY KEY ("id"))`)).
|
|
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
m.mock.ExpectBegin()
|
|
|
|
m.mock.
|
|
|
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE migrations (id VARCHAR(255) PRIMARY KEY)`)).
|
|
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
m.mock.
|
|
|
|
ExpectQuery(regexp.QuoteMeta(`SELECT id FROM migrations`)).
|
|
|
|
WillReturnRows(sqlmock.NewRows([]string{"1"}))
|
|
|
|
m.mock.
|
|
|
|
ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "migrations" WHERE (id = $1)`)).
|
|
|
|
WithArgs("1").
|
|
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
|
|
|
m.mock.
|
|
|
|
ExpectQuery(regexp.QuoteMeta(`SELECT count(*) FROM "migrations" WHERE (id = $1)`)).
|
|
|
|
WithArgs("2").
|
|
|
|
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))
|
|
|
|
m.mock.
|
|
|
|
ExpectExec(regexp.QuoteMeta(`ALTER TABLE "test_model" ALTER COLUMN "name" TYPE varchar(100)`)).
|
|
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
m.mock.
|
|
|
|
ExpectExec(regexp.QuoteMeta(`INSERT INTO migrations (id) VALUES ($1)`)).
|
|
|
|
WithArgs("2").
|
|
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
m.mock.ExpectCommit()
|
|
|
|
|
|
|
|
err := m.Migrate.MigrateNextTo(m.Migration_TestModelFirst().ID)
|
|
|
|
|
|
|
|
assert.NoError(m.T(), err)
|
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) Test_MigratePreviousTo() {
|
|
|
|
m.RefreshMigrate()
|
|
|
|
m.Migrate.Add(m.Migration_TestModelFirst())
|
|
|
|
m.Migrate.Add(m.Migration_TestModelSecond())
|
|
|
|
|
|
|
|
m.mock.
|
|
|
|
ExpectExec(regexp.QuoteMeta(`CREATE TABLE "migrations" ("id" varchar(255) , PRIMARY KEY ("id"))`)).
|
|
|
|
WillReturnResult(sqlmock.NewResult(1, 1))
|
|
|
|
|
|
|
|
err := m.Migrate.MigratePreviousTo(m.Migration_TestModelSecond().ID)
|
|
|
|
|
|
|
|
assert.Error(m.T(), err)
|
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *MigrateTest) Test_Close() {
|
|
|
|
m.RefreshMigrate()
|
|
|
|
m.mock.ExpectClose()
|
|
|
|
err := m.Migrate.Close()
|
|
|
|
|
|
|
|
assert.NoError(m.T(), err)
|
|
|
|
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
|
2019-09-18 18:02:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestMigrate_Migrate(t *testing.T) {
|
|
|
|
assert.NotNil(t, Migrations())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMigrate_Suite(t *testing.T) {
|
|
|
|
suite.Run(t, new(MigrateTest))
|
|
|
|
}
|