Add basic tests for applier (#1165)

* Add basic tests for applier

* Add header
This commit is contained in:
Tim Vaillancourt 2022-09-06 15:06:14 +02:00 committed by GitHub
parent 3c946e97d7
commit 1fa3d4f75a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 181 additions and 9 deletions

View File

@ -8,6 +8,7 @@ package logic
import ( import (
gosql "database/sql" gosql "database/sql"
"fmt" "fmt"
"strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -122,17 +123,16 @@ func (this *Applier) validateAndReadTimeZone() error {
// - User may skip strict mode // - User may skip strict mode
// - User may allow zero dats or zero in dates // - User may allow zero dats or zero in dates
func (this *Applier) generateSqlModeQuery() string { func (this *Applier) generateSqlModeQuery() string {
sqlModeAddendum := `,NO_AUTO_VALUE_ON_ZERO` sqlModeAddendum := []string{`NO_AUTO_VALUE_ON_ZERO`}
if !this.migrationContext.SkipStrictMode { if !this.migrationContext.SkipStrictMode {
sqlModeAddendum = fmt.Sprintf("%s,STRICT_ALL_TABLES", sqlModeAddendum) sqlModeAddendum = append(sqlModeAddendum, `STRICT_ALL_TABLES`)
} }
sqlModeQuery := fmt.Sprintf("CONCAT(@@session.sql_mode, ',%s')", sqlModeAddendum) sqlModeQuery := fmt.Sprintf("CONCAT(@@session.sql_mode, ',%s')", strings.Join(sqlModeAddendum, ","))
if this.migrationContext.AllowZeroInDate { if this.migrationContext.AllowZeroInDate {
sqlModeQuery = fmt.Sprintf("REPLACE(REPLACE(%s, 'NO_ZERO_IN_DATE', ''), 'NO_ZERO_DATE', '')", sqlModeQuery) sqlModeQuery = fmt.Sprintf("REPLACE(REPLACE(%s, 'NO_ZERO_IN_DATE', ''), 'NO_ZERO_DATE', '')", sqlModeQuery)
} }
sqlModeQuery = fmt.Sprintf("sql_mode = %s", sqlModeQuery)
return sqlModeQuery return fmt.Sprintf("sql_mode = %s", sqlModeQuery)
} }
// readTableColumns reads table columns on applier // readTableColumns reads table columns on applier

172
go/logic/applier_test.go Normal file
View File

@ -0,0 +1,172 @@
/*
Copyright 2022 GitHub Inc.
See https://github.com/github/gh-ost/blob/master/LICENSE
*/
package logic
import (
"strings"
"testing"
test "github.com/openark/golib/tests"
"github.com/github/gh-ost/go/base"
"github.com/github/gh-ost/go/binlog"
"github.com/github/gh-ost/go/sql"
)
func TestApplierGenerateSqlModeQuery(t *testing.T) {
migrationContext := base.NewMigrationContext()
applier := NewApplier(migrationContext)
{
test.S(t).ExpectEquals(
applier.generateSqlModeQuery(),
`sql_mode = CONCAT(@@session.sql_mode, ',NO_AUTO_VALUE_ON_ZERO,STRICT_ALL_TABLES')`,
)
}
{
migrationContext.SkipStrictMode = true
migrationContext.AllowZeroInDate = false
test.S(t).ExpectEquals(
applier.generateSqlModeQuery(),
`sql_mode = CONCAT(@@session.sql_mode, ',NO_AUTO_VALUE_ON_ZERO')`,
)
}
{
migrationContext.SkipStrictMode = false
migrationContext.AllowZeroInDate = true
test.S(t).ExpectEquals(
applier.generateSqlModeQuery(),
`sql_mode = REPLACE(REPLACE(CONCAT(@@session.sql_mode, ',NO_AUTO_VALUE_ON_ZERO,STRICT_ALL_TABLES'), 'NO_ZERO_IN_DATE', ''), 'NO_ZERO_DATE', '')`,
)
}
{
migrationContext.SkipStrictMode = true
migrationContext.AllowZeroInDate = true
test.S(t).ExpectEquals(
applier.generateSqlModeQuery(),
`sql_mode = REPLACE(REPLACE(CONCAT(@@session.sql_mode, ',NO_AUTO_VALUE_ON_ZERO'), 'NO_ZERO_IN_DATE', ''), 'NO_ZERO_DATE', '')`,
)
}
}
func TestApplierUpdateModifiesUniqueKeyColumns(t *testing.T) {
columns := sql.NewColumnList([]string{"id", "item_id"})
columnValues := sql.ToColumnValues([]interface{}{123456, 42})
migrationContext := base.NewMigrationContext()
migrationContext.OriginalTableColumns = columns
migrationContext.UniqueKey = &sql.UniqueKey{
Name: t.Name(),
Columns: *columns,
}
applier := NewApplier(migrationContext)
t.Run("unmodified", func(t *testing.T) {
modifiedColumn, isModified := applier.updateModifiesUniqueKeyColumns(&binlog.BinlogDMLEvent{
DatabaseName: "test",
DML: binlog.UpdateDML,
NewColumnValues: columnValues,
WhereColumnValues: columnValues,
})
test.S(t).ExpectEquals(modifiedColumn, "")
test.S(t).ExpectFalse(isModified)
})
t.Run("modified", func(t *testing.T) {
modifiedColumn, isModified := applier.updateModifiesUniqueKeyColumns(&binlog.BinlogDMLEvent{
DatabaseName: "test",
DML: binlog.UpdateDML,
NewColumnValues: sql.ToColumnValues([]interface{}{123456, 24}),
WhereColumnValues: columnValues,
})
test.S(t).ExpectEquals(modifiedColumn, "item_id")
test.S(t).ExpectTrue(isModified)
})
}
func TestApplierBuildDMLEventQuery(t *testing.T) {
columns := sql.NewColumnList([]string{"id", "item_id"})
columnValues := sql.ToColumnValues([]interface{}{123456, 42})
migrationContext := base.NewMigrationContext()
migrationContext.OriginalTableName = "test"
migrationContext.OriginalTableColumns = columns
migrationContext.SharedColumns = columns
migrationContext.MappedSharedColumns = columns
migrationContext.UniqueKey = &sql.UniqueKey{
Name: t.Name(),
Columns: *columns,
}
applier := NewApplier(migrationContext)
t.Run("delete", func(t *testing.T) {
binlogEvent := &binlog.BinlogDMLEvent{
DatabaseName: "test",
DML: binlog.DeleteDML,
WhereColumnValues: columnValues,
}
res := applier.buildDMLEventQuery(binlogEvent)
test.S(t).ExpectEquals(len(res), 1)
test.S(t).ExpectNil(res[0].err)
test.S(t).ExpectEquals(strings.TrimSpace(res[0].query),
`delete /* gh-ost `+"`test`.`_test_gho`"+` */
from
`+"`test`.`_test_gho`"+`
where
((`+"`id`"+` = ?) and (`+"`item_id`"+` = ?))`)
test.S(t).ExpectEquals(len(res[0].args), 2)
test.S(t).ExpectEquals(res[0].args[0], 123456)
test.S(t).ExpectEquals(res[0].args[1], 42)
})
t.Run("insert", func(t *testing.T) {
binlogEvent := &binlog.BinlogDMLEvent{
DatabaseName: "test",
DML: binlog.InsertDML,
NewColumnValues: columnValues,
}
res := applier.buildDMLEventQuery(binlogEvent)
test.S(t).ExpectEquals(len(res), 1)
test.S(t).ExpectNil(res[0].err)
test.S(t).ExpectEquals(strings.TrimSpace(res[0].query),
`replace /* gh-ost `+"`test`.`_test_gho`"+` */ into
`+"`test`.`_test_gho`"+`
`+"(`id`, `item_id`)"+`
values
(?, ?)`)
test.S(t).ExpectEquals(len(res[0].args), 2)
test.S(t).ExpectEquals(res[0].args[0], 123456)
test.S(t).ExpectEquals(res[0].args[1], 42)
})
t.Run("update", func(t *testing.T) {
binlogEvent := &binlog.BinlogDMLEvent{
DatabaseName: "test",
DML: binlog.UpdateDML,
NewColumnValues: columnValues,
WhereColumnValues: columnValues,
}
res := applier.buildDMLEventQuery(binlogEvent)
test.S(t).ExpectEquals(len(res), 1)
test.S(t).ExpectNil(res[0].err)
test.S(t).ExpectEquals(strings.TrimSpace(res[0].query),
`update /* gh-ost `+"`test`.`_test_gho`"+` */
`+"`test`.`_test_gho`"+`
set
`+"`id`"+`=?, `+"`item_id`"+`=?
where
((`+"`id`"+` = ?) and (`+"`item_id`"+` = ?))`)
test.S(t).ExpectEquals(len(res[0].args), 4)
test.S(t).ExpectEquals(res[0].args[0], 123456)
test.S(t).ExpectEquals(res[0].args[1], 42)
test.S(t).ExpectEquals(res[0].args[2], 123456)
test.S(t).ExpectEquals(res[0].args[3], 42)
})
}