mg-transport-core/core/migrate_test.go

372 lines
10 KiB
Go

package core
import (
"database/sql"
"regexp"
"testing"
"github.com/DATA-DOG/go-sqlmock"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/postgres"
"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() {
require.NotEmpty(m.T(), (MigrationInfo{}).TableName())
m.RefreshMigrate()
}
func (m *MigrateTest) RefreshMigrate() {
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{},
}
}
func (m *MigrateTest) Migration_TestModelFirst() *gormigrate.Migration {
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
},
}
}
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
},
}
}
func (m *MigrateTest) Test_Add() {
m.RefreshMigrate()
m.Migrate.Add(nil)
m.Migrate.Add(m.Migration_TestModelFirst())
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)
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
}
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())
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
}
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)
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
}
func (m *MigrateTest) Test_prepareMigrations_OK() {
m.RefreshMigrate()
m.Migrate.Add(m.Migration_TestModelFirst())
err := m.Migrate.prepareMigrations()
require.NoError(m.T(), err)
assert.True(m.T(), m.Migrate.prepared)
assert.NotNil(m.T(), m.Migrate.GORMigrate)
assert.NoError(m.T(), m.mock.ExpectationsWereMet())
}
func (m *MigrateTest) Test_Migrate_Fail_NilDB() {
m.RefreshMigrate()
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())
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)
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())
}
func TestMigrate_Migrate(t *testing.T) {
assert.NotNil(t, Migrations())
}
func TestMigrate_Suite(t *testing.T) {
suite.Run(t, new(MigrateTest))
}