Skip to content

Commit

Permalink
ddl: improve ddl test (pingcap#1387)
Browse files Browse the repository at this point in the history
  • Loading branch information
coocood authored Jul 5, 2016
1 parent 0450ba0 commit 5408833
Show file tree
Hide file tree
Showing 16 changed files with 331 additions and 130 deletions.
15 changes: 6 additions & 9 deletions ddl/bg_worker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ func (s *testDDLSuite) TestDropSchemaError(c *C) {
store := testCreateStore(c, "test_drop_schema")
defer store.Close()

lease := 50 * time.Millisecond
d := newDDL(store, nil, nil, lease)
d := newDDL(store, nil, nil, testLease)
defer d.close()

job := &model.Job{
Expand All @@ -47,7 +46,7 @@ func (s *testDDLSuite) TestDropSchemaError(c *C) {
c.Check(err, IsNil)
d.startBgJob(job.Type)

time.Sleep(lease)
time.Sleep(testLease)
verifyBgJobState(c, d, job, model.JobDone)
}

Expand All @@ -68,8 +67,7 @@ func (s *testDDLSuite) TestDropTableError(c *C) {
store := testCreateStore(c, "test_drop_table")
defer store.Close()

lease := 50 * time.Millisecond
d := newDDL(store, nil, nil, lease)
d := newDDL(store, nil, nil, testLease)
defer d.close()

dbInfo := testSchemaInfo(c, d, "test")
Expand All @@ -90,7 +88,7 @@ func (s *testDDLSuite) TestDropTableError(c *C) {
c.Check(err, IsNil)
d.startBgJob(job.Type)

time.Sleep(lease)
time.Sleep(testLease)
verifyBgJobState(c, d, job, model.JobDone)
}

Expand All @@ -99,8 +97,7 @@ func (s *testDDLSuite) TestInvalidBgJobType(c *C) {
store := testCreateStore(c, "test_invalid_bg_job_type")
defer store.Close()

lease := 50 * time.Millisecond
d := newDDL(store, nil, nil, lease)
d := newDDL(store, nil, nil, testLease)
defer d.close()

job := &model.Job{
Expand All @@ -115,6 +112,6 @@ func (s *testDDLSuite) TestInvalidBgJobType(c *C) {
c.Check(err, IsNil)
d.startBgJob(model.ActionDropTable)

time.Sleep(lease)
time.Sleep(testLease)
verifyBgJobState(c, d, job, model.JobCancelled)
}
270 changes: 270 additions & 0 deletions ddl/column_change_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
package ddl

import (
"fmt"

"github.com/juju/errors"
. "github.com/pingcap/check"
"github.com/pingcap/tidb/ast"
"github.com/pingcap/tidb/context"
"github.com/pingcap/tidb/kv"
"github.com/pingcap/tidb/meta"
"github.com/pingcap/tidb/meta/autoid"
"github.com/pingcap/tidb/model"
"github.com/pingcap/tidb/table"
"github.com/pingcap/tidb/util/testleak"
"github.com/pingcap/tidb/util/testutil"
"github.com/pingcap/tidb/util/types"
)

var _ = Suite(&testColumnChangeSuite{})

type testColumnChangeSuite struct {
store kv.Storage
dbInfo *model.DBInfo
}

func (s *testColumnChangeSuite) SetUpSuite(c *C) {
s.store = testCreateStore(c, "test_column_change")
s.dbInfo = &model.DBInfo{
Name: model.NewCIStr("test_column_change"),
ID: 1,
}
err := kv.RunInNewTxn(s.store, true, func(txn kv.Transaction) error {
t := meta.NewMeta(txn)
return errors.Trace(t.CreateDatabase(s.dbInfo))
})
c.Check(err, IsNil)
}

func (s *testColumnChangeSuite) TestColumnChange(c *C) {
defer testleak.AfterTest(c)()
d := newDDL(s.store, nil, nil, testLease)
// create table t (c1 int, c2 int);
tblInfo := testTableInfo(c, d, "t", 2)
ctx := testNewContext(c, d)
_, err := ctx.GetTxn(true)
c.Assert(err, IsNil)
testCreateTable(c, ctx, d, s.dbInfo, tblInfo)
// insert t values (1, 2);
originTable := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID)
row := types.MakeDatums(1, 2)
_, err = originTable.AddRecord(ctx, row)
c.Assert(err, IsNil)
err = ctx.CommitTxn()
c.Assert(err, IsNil)

tc := &testDDLCallback{}
// set up hook
prevState := model.StateNone
var (
deleteOnlyTable table.Table
writeOnlyTable table.Table
publicTable table.Table
)
var checkErr error
tc.onJobUpdated = func(job *model.Job) {
if job.SchemaState == prevState {
return
}
prevState = job.SchemaState
var err error
switch job.SchemaState {
case model.StateDeleteOnly:
deleteOnlyTable, err = getCurrentTable(d, s.dbInfo.ID, tblInfo.ID)
if err != nil {
checkErr = errors.Trace(err)
}
case model.StateWriteOnly:
writeOnlyTable, err = getCurrentTable(d, s.dbInfo.ID, tblInfo.ID)
if err != nil {
checkErr = errors.Trace(err)
}
err = s.checkAddWriteOnly(d, ctx, deleteOnlyTable, writeOnlyTable)
if err != nil {
checkErr = errors.Trace(err)
}
case model.StatePublic:
publicTable, err = getCurrentTable(d, s.dbInfo.ID, tblInfo.ID)
if err != nil {
checkErr = errors.Trace(err)
}
err = s.checkAddPublic(d, ctx, writeOnlyTable, publicTable)
if err != nil {
checkErr = errors.Trace(err)
}
}
}
d.hook = tc
defaultValue := int64(3)
job := testCreateColumn(c, ctx, d, s.dbInfo, tblInfo, "c3", &ast.ColumnPosition{Tp: ast.ColumnPositionNone}, defaultValue)
c.Assert(errors.ErrorStack(checkErr), Equals, "")
testCheckJobDone(c, d, job, true)
s.testColumnDrop(c, ctx, d, publicTable)
d.close()
}

func (s *testColumnChangeSuite) testColumnDrop(c *C, ctx context.Context, d *ddl, tbl table.Table) {
d.close()
dropCol := tbl.Cols()[0]
tc := &testDDLCallback{}
// set up hook
prevState := model.StateNone
var checkErr error
tc.onJobUpdated = func(job *model.Job) {
if job.SchemaState == prevState {
return
}
prevState = job.SchemaState
currentTbl, err := getCurrentTable(d, s.dbInfo.ID, tbl.Meta().ID)
if err != nil {
checkErr = errors.Trace(err)
}
for _, col := range currentTbl.Cols() {
if col.ID == dropCol.ID {
checkErr = errors.Errorf("column is not dropped")
}
}
}
d.hook = tc
d.start()
testDropColumn(c, ctx, d, s.dbInfo, tbl.Meta(), dropCol.Name.L, false)
}

func (s *testColumnChangeSuite) checkAddWriteOnly(d *ddl, ctx context.Context, deleteOnlyTable, writeOnlyTable table.Table) error {
// WriteOnlyTable: insert t values (2, 3)
_, err := writeOnlyTable.AddRecord(ctx, types.MakeDatums(2, 3))
if err != nil {
return errors.Trace(err)
}
err = ctx.CommitTxn()
if err != nil {
return errors.Trace(err)
}
err = checkResult(ctx, writeOnlyTable, testutil.RowsWithSep(" ", "1 2 <nil>", "2 3 3"))
if err != nil {
return errors.Trace(err)
}
// DeleteOnlyTable: select * from t
err = checkResult(ctx, deleteOnlyTable, testutil.RowsWithSep(" ", "1 2", "2 3"))
if err != nil {
return errors.Trace(err)
}
// WriteOnlyTable: update t set c1 = 2 where c1 = 1
h, _, err := writeOnlyTable.Seek(ctx, 0)
if err != nil {
return errors.Trace(err)
}
err = writeOnlyTable.UpdateRecord(ctx, h, types.MakeDatums(1, 2), types.MakeDatums(2, 2), touchedMap(writeOnlyTable))
if err != nil {
return errors.Trace(err)
}
err = ctx.CommitTxn()
if err != nil {
return errors.Trace(err)
}
// After we update the first row, its default value is also set.
err = checkResult(ctx, writeOnlyTable, testutil.RowsWithSep(" ", "2 2 3", "2 3 3"))
if err != nil {
return errors.Trace(err)
}
// DeleteOnlyTable: delete from t where c2 = 2
err = deleteOnlyTable.RemoveRecord(ctx, h, types.MakeDatums(2, 2))
if err != nil {
return errors.Trace(err)
}
err = ctx.CommitTxn()
if err != nil {
return errors.Trace(err)
}
// After delete table has deleted the first row, check the WriteOnly table records.
err = checkResult(ctx, writeOnlyTable, testutil.RowsWithSep(" ", "2 3 3"))
return errors.Trace(err)
}

func touchedMap(t table.Table) map[int]bool {
touched := make(map[int]bool)
for _, col := range t.Cols() {
touched[col.Offset] = true
}
return touched
}

func (s *testColumnChangeSuite) checkAddPublic(d *ddl, ctx context.Context, writeOnlyTable, publicTable table.Table) error {
// publicTable Insert t values (4, 4, 4)
h, err := publicTable.AddRecord(ctx, types.MakeDatums(4, 4, 4))
if err != nil {
return errors.Trace(err)
}
err = ctx.CommitTxn()
if err != nil {
return errors.Trace(err)
}
// writeOnlyTable update t set c1 = 3 where c1 = 4
oldRow, err := writeOnlyTable.RowWithCols(ctx, h, writeOnlyTable.WritableCols())
if err != nil {
return errors.Trace(err)
}
if len(oldRow) != 3 {
return errors.Errorf("%v", oldRow)
}
newRow := types.MakeDatums(3, 4, oldRow[2].GetValue())
err = writeOnlyTable.UpdateRecord(ctx, h, oldRow, newRow, touchedMap(writeOnlyTable))
if err != nil {
return errors.Trace(err)
}
err = ctx.CommitTxn()
if err != nil {
return errors.Trace(err)
}
// publicTable select * from t, make sure the new c3 value 4 is not overwritten to default value 3.
err = checkResult(ctx, publicTable, testutil.RowsWithSep(" ", "2 3 3", "3 4 4"))
if err != nil {
return errors.Trace(err)
}
return nil
}

func getCurrentTable(d *ddl, schemaID, tableID int64) (table.Table, error) {
var tblInfo *model.TableInfo
err := kv.RunInNewTxn(d.store, false, func(txn kv.Transaction) error {
t := meta.NewMeta(txn)
var err error
tblInfo, err = t.GetTable(schemaID, tableID)
if err != nil {
return errors.Trace(err)
}
return nil
})
if err != nil {
return nil, errors.Trace(err)
}
alloc := autoid.NewAllocator(d.store, schemaID)
tbl, err := table.TableFromMeta(alloc, tblInfo)
if err != nil {
return nil, errors.Trace(err)
}
return tbl, err
}

func checkResult(ctx context.Context, t table.Table, rows [][]interface{}) error {
var gotRows [][]interface{}
t.IterRecords(ctx, t.FirstKey(), t.WritableCols(), func(h int64, data []types.Datum, cols []*table.Column) (bool, error) {
gotRows = append(gotRows, datumsToInterfaces(data))
return true, nil
})
got := fmt.Sprintf("%v", gotRows)
expect := fmt.Sprintf("%v", rows)
if got != expect {
return errors.Errorf("expect %v, got %v", expect, got)
}
return nil
}

func datumsToInterfaces(datums []types.Datum) []interface{} {
var ifs []interface{}
for _, d := range datums {
ifs = append(ifs, d.GetValue())
}
return ifs
}
16 changes: 4 additions & 12 deletions ddl/column_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ package ddl

import (
"reflect"
"time"

"github.com/juju/errors"
. "github.com/pingcap/check"
Expand Down Expand Up @@ -43,19 +42,14 @@ type testColumnSuite struct {
}

func (s *testColumnSuite) SetUpSuite(c *C) {
trySkipTest(c)

s.store = testCreateStore(c, "test_column")
lease := 50 * time.Millisecond
s.d = newDDL(s.store, nil, nil, lease)
s.d = newDDL(s.store, nil, nil, testLease)

s.dbInfo = testSchemaInfo(c, s.d, "test_column")
testCreateSchema(c, mock.NewContext(), s.d, s.dbInfo)
}

func (s *testColumnSuite) TearDownSuite(c *C) {
trySkipTest(c)

testDropSchema(c, mock.NewContext(), s.d, s.dbInfo)
s.d.close()

Expand Down Expand Up @@ -96,14 +90,12 @@ func testDropColumn(c *C, ctx context.Context, d *ddl, dbInfo *model.DBInfo, tbl
Type: model.ActionDropColumn,
Args: []interface{}{model.NewCIStr(colName)},
}

err := d.doDDLJob(ctx, job)
if isError {
c.Assert(err, NotNil)
return nil
}

c.Assert(err, IsNil)
c.Assert(errors.ErrorStack(err), Equals, "")
return job
}

Expand Down Expand Up @@ -736,7 +728,7 @@ func (s *testColumnSuite) testGetColumn(t table.Table, name string, isExist bool

func (s *testColumnSuite) TestAddColumn(c *C) {
defer testleak.AfterTest(c)()
d := newDDL(s.store, nil, nil, 100*time.Millisecond)
d := newDDL(s.store, nil, nil, testLease)
tblInfo := testTableInfo(c, d, "t", 3)
ctx := testNewContext(c, d)

Expand Down Expand Up @@ -808,7 +800,7 @@ func (s *testColumnSuite) TestAddColumn(c *C) {

func (s *testColumnSuite) TestDropColumn(c *C) {
defer testleak.AfterTest(c)()
d := newDDL(s.store, nil, nil, 100*time.Millisecond)
d := newDDL(s.store, nil, nil, testLease)
tblInfo := testTableInfo(c, d, "t", 4)
ctx := testNewContext(c, d)

Expand Down
Loading

0 comments on commit 5408833

Please sign in to comment.