github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/ddl/ddl_worker_test.go (about)

     1  // Copyright 2015 PingCAP, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package ddl
    15  
    16  import (
    17  	"flag"
    18  	"fmt"
    19  	"time"
    20  
    21  	. "github.com/insionng/yougam/libraries/pingcap/check"
    22  	"github.com/insionng/yougam/libraries/pingcap/tidb/ast"
    23  	"github.com/insionng/yougam/libraries/pingcap/tidb/kv"
    24  	"github.com/insionng/yougam/libraries/pingcap/tidb/meta"
    25  	"github.com/insionng/yougam/libraries/pingcap/tidb/model"
    26  	"github.com/insionng/yougam/libraries/pingcap/tidb/mysql"
    27  	"github.com/insionng/yougam/libraries/pingcap/tidb/store/localstore"
    28  	"github.com/insionng/yougam/libraries/pingcap/tidb/store/localstore/goleveldb"
    29  	"github.com/insionng/yougam/libraries/pingcap/tidb/terror"
    30  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/testleak"
    31  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/types"
    32  )
    33  
    34  var skipDDL = flag.Bool("skip_ddl", true, "only run simple DDL test")
    35  
    36  func trySkipTest(c *C) {
    37  	if *skipDDL {
    38  		c.Skip("skip, only run simple tests")
    39  	}
    40  }
    41  
    42  var _ = Suite(&testDDLSuite{})
    43  
    44  func testCreateStore(c *C, name string) kv.Storage {
    45  	driver := localstore.Driver{Driver: goleveldb.MemoryDriver{}}
    46  	store, err := driver.Open(fmt.Sprintf("memory:%s", name))
    47  	c.Assert(err, IsNil)
    48  	return store
    49  }
    50  
    51  type testDDLSuite struct {
    52  }
    53  
    54  func testCheckOwner(c *C, d *ddl, isOwner bool, flag JobType) {
    55  	err := kv.RunInNewTxn(d.store, true, func(txn kv.Transaction) error {
    56  		t := meta.NewMeta(txn)
    57  		_, err := d.checkOwner(t, flag)
    58  		return err
    59  	})
    60  	if isOwner {
    61  		c.Assert(err, IsNil)
    62  		return
    63  	}
    64  
    65  	c.Assert(terror.ErrorEqual(err, errNotOwner), IsTrue)
    66  }
    67  
    68  func (s *testDDLSuite) TestCheckOwner(c *C) {
    69  	defer testleak.AfterTest(c)()
    70  	store := testCreateStore(c, "test_owner")
    71  	defer store.Close()
    72  
    73  	lease := 100 * time.Millisecond
    74  	d1 := newDDL(store, nil, nil, lease)
    75  	defer d1.close()
    76  
    77  	time.Sleep(lease)
    78  
    79  	testCheckOwner(c, d1, true, ddlJobFlag)
    80  	testCheckOwner(c, d1, true, bgJobFlag)
    81  
    82  	d2 := newDDL(store, nil, nil, lease)
    83  	defer d2.close()
    84  
    85  	testCheckOwner(c, d2, false, ddlJobFlag)
    86  	testCheckOwner(c, d2, false, bgJobFlag)
    87  	d1.close()
    88  
    89  	time.Sleep(6 * lease)
    90  
    91  	testCheckOwner(c, d2, true, ddlJobFlag)
    92  	testCheckOwner(c, d2, true, bgJobFlag)
    93  
    94  	d2.SetLease(1 * time.Second)
    95  
    96  	err := d2.Stop()
    97  	c.Assert(err, IsNil)
    98  
    99  	err = d1.Start()
   100  	c.Assert(err, IsNil)
   101  
   102  	err = d1.Start()
   103  	c.Assert(err, IsNil)
   104  
   105  	testCheckOwner(c, d1, true, ddlJobFlag)
   106  	testCheckOwner(c, d1, true, bgJobFlag)
   107  
   108  	d2.SetLease(1 * time.Second)
   109  	d2.SetLease(2 * time.Second)
   110  	c.Assert(d2.GetLease(), Equals, 2*time.Second)
   111  }
   112  
   113  func (s *testDDLSuite) TestSchemaError(c *C) {
   114  	defer testleak.AfterTest(c)()
   115  	store := testCreateStore(c, "test_schema_error")
   116  	defer store.Close()
   117  
   118  	lease := 50 * time.Millisecond
   119  
   120  	d := newDDL(store, nil, nil, lease)
   121  	defer d.close()
   122  
   123  	job := &model.Job{
   124  		SchemaID: 1,
   125  		Type:     model.ActionCreateSchema,
   126  		Args:     []interface{}{1},
   127  	}
   128  
   129  	ctx := testNewContext(c, d)
   130  
   131  	err := d.doDDLJob(ctx, job)
   132  	c.Assert(err, NotNil)
   133  	testCheckJobCancelled(c, d, job)
   134  }
   135  
   136  func (s *testDDLSuite) TestTableError(c *C) {
   137  	defer testleak.AfterTest(c)()
   138  	store := testCreateStore(c, "test_table_error")
   139  	defer store.Close()
   140  
   141  	lease := 50 * time.Millisecond
   142  
   143  	d := newDDL(store, nil, nil, lease)
   144  	defer d.close()
   145  
   146  	job := &model.Job{
   147  		SchemaID: 1,
   148  		TableID:  1,
   149  		Type:     model.ActionCreateTable,
   150  		Args:     []interface{}{1},
   151  	}
   152  
   153  	ctx := testNewContext(c, d)
   154  
   155  	err := d.doDDLJob(ctx, job)
   156  	c.Assert(err, NotNil)
   157  	testCheckJobCancelled(c, d, job)
   158  
   159  	job.SchemaID = -1
   160  	job.State = 0
   161  	tblInfo := testTableInfo(c, d, "t", 3)
   162  	job.Args = []interface{}{tblInfo}
   163  
   164  	err = d.doDDLJob(ctx, job)
   165  	c.Assert(err, NotNil)
   166  	testCheckJobCancelled(c, d, job)
   167  
   168  	job = &model.Job{
   169  		SchemaID: 1,
   170  		TableID:  1,
   171  		Type:     model.ActionDropTable,
   172  	}
   173  
   174  	err = d.doDDLJob(ctx, job)
   175  	c.Assert(err, NotNil)
   176  	testCheckJobCancelled(c, d, job)
   177  
   178  	dbInfo := testSchemaInfo(c, d, "test")
   179  	testCreateSchema(c, testNewContext(c, d), d, dbInfo)
   180  
   181  	job = &model.Job{
   182  		SchemaID: dbInfo.ID,
   183  		TableID:  -1,
   184  		Type:     model.ActionDropTable,
   185  	}
   186  
   187  	err = d.doDDLJob(ctx, job)
   188  	c.Assert(err, NotNil)
   189  	testCheckJobCancelled(c, d, job)
   190  
   191  	testCreateTable(c, ctx, d, dbInfo, tblInfo)
   192  
   193  	err = kv.RunInNewTxn(store, false, func(txn kv.Transaction) error {
   194  		job.SchemaID = -1
   195  		job.TableID = -1
   196  		t := meta.NewMeta(txn)
   197  		_, err1 := d.getTableInfo(t, job)
   198  		c.Assert(err1, NotNil)
   199  		job.SchemaID = dbInfo.ID
   200  		_, err1 = d.getTableInfo(t, job)
   201  		c.Assert(err1, NotNil)
   202  		return nil
   203  	})
   204  	c.Assert(err, IsNil)
   205  }
   206  
   207  func (s *testDDLSuite) TestIndexError(c *C) {
   208  	defer testleak.AfterTest(c)()
   209  	store := testCreateStore(c, "test_index_error")
   210  	defer store.Close()
   211  
   212  	lease := 50 * time.Millisecond
   213  
   214  	d := newDDL(store, nil, nil, lease)
   215  	defer d.close()
   216  
   217  	ctx := testNewContext(c, d)
   218  
   219  	job := &model.Job{
   220  		SchemaID: -1,
   221  		TableID:  1,
   222  		Type:     model.ActionAddIndex,
   223  	}
   224  
   225  	err := d.doDDLJob(ctx, job)
   226  	c.Assert(err, NotNil)
   227  	testCheckJobCancelled(c, d, job)
   228  
   229  	job = &model.Job{
   230  		SchemaID: -1,
   231  		TableID:  1,
   232  		Type:     model.ActionDropIndex,
   233  	}
   234  
   235  	err = d.doDDLJob(ctx, job)
   236  	c.Assert(err, NotNil)
   237  	testCheckJobCancelled(c, d, job)
   238  
   239  	dbInfo := testSchemaInfo(c, d, "test")
   240  	tblInfo := testTableInfo(c, d, "t", 3)
   241  
   242  	testCreateSchema(c, ctx, d, dbInfo)
   243  	testCreateTable(c, ctx, d, dbInfo, tblInfo)
   244  
   245  	job = &model.Job{
   246  		SchemaID: dbInfo.ID,
   247  		TableID:  tblInfo.ID,
   248  		Type:     model.ActionAddIndex,
   249  		Args:     []interface{}{1},
   250  	}
   251  	err = d.doDDLJob(ctx, job)
   252  	c.Assert(err, NotNil)
   253  	testCheckJobCancelled(c, d, job)
   254  
   255  	job = &model.Job{
   256  		SchemaID: dbInfo.ID,
   257  		TableID:  tblInfo.ID,
   258  		Type:     model.ActionAddIndex,
   259  		Args:     []interface{}{false, model.NewCIStr("t"), []*ast.IndexColName{{Column: &ast.ColumnName{Name: model.NewCIStr("c")}, Length: 256}}},
   260  	}
   261  	err = d.doDDLJob(ctx, job)
   262  	c.Assert(err, NotNil)
   263  	testCheckJobCancelled(c, d, job)
   264  
   265  	job = &model.Job{
   266  		SchemaID: dbInfo.ID,
   267  		TableID:  tblInfo.ID,
   268  		Type:     model.ActionAddIndex,
   269  		Args:     []interface{}{false, model.NewCIStr("c1_index"), []*ast.IndexColName{{Column: &ast.ColumnName{Name: model.NewCIStr("c")}, Length: 256}}},
   270  	}
   271  	err = d.doDDLJob(ctx, job)
   272  	c.Assert(err, NotNil)
   273  	testCheckJobCancelled(c, d, job)
   274  
   275  	testCreateIndex(c, ctx, d, dbInfo, tblInfo, false, "c1_index", "c1")
   276  
   277  	job = &model.Job{
   278  		SchemaID: dbInfo.ID,
   279  		TableID:  tblInfo.ID,
   280  		Type:     model.ActionAddIndex,
   281  		Args:     []interface{}{false, model.NewCIStr("c1_index"), []*ast.IndexColName{{Column: &ast.ColumnName{Name: model.NewCIStr("c1")}, Length: 256}}},
   282  	}
   283  	err = d.doDDLJob(ctx, job)
   284  	c.Assert(err, NotNil)
   285  	testCheckJobCancelled(c, d, job)
   286  
   287  	job = &model.Job{
   288  		SchemaID: dbInfo.ID,
   289  		TableID:  tblInfo.ID,
   290  		Type:     model.ActionDropIndex,
   291  		Args:     []interface{}{1},
   292  	}
   293  	err = d.doDDLJob(ctx, job)
   294  	c.Assert(err, NotNil)
   295  	testCheckJobCancelled(c, d, job)
   296  
   297  	testDropIndex(c, ctx, d, dbInfo, tblInfo, "c1_index")
   298  
   299  	job = &model.Job{
   300  		SchemaID: dbInfo.ID,
   301  		TableID:  tblInfo.ID,
   302  		Type:     model.ActionDropIndex,
   303  		Args:     []interface{}{model.NewCIStr("c1_index")},
   304  	}
   305  	err = d.doDDLJob(ctx, job)
   306  	c.Assert(err, NotNil)
   307  	testCheckJobCancelled(c, d, job)
   308  }
   309  
   310  func (s *testDDLSuite) TestColumnError(c *C) {
   311  	defer testleak.AfterTest(c)()
   312  	store := testCreateStore(c, "test_column_error")
   313  	defer store.Close()
   314  
   315  	lease := 50 * time.Millisecond
   316  
   317  	d := newDDL(store, nil, nil, lease)
   318  	defer d.close()
   319  
   320  	ctx := testNewContext(c, d)
   321  
   322  	job := &model.Job{
   323  		SchemaID: -1,
   324  		TableID:  1,
   325  		Type:     model.ActionAddColumn,
   326  	}
   327  
   328  	err := d.doDDLJob(ctx, job)
   329  	c.Assert(err, NotNil)
   330  	testCheckJobCancelled(c, d, job)
   331  
   332  	job = &model.Job{
   333  		SchemaID: -1,
   334  		TableID:  1,
   335  		Type:     model.ActionDropColumn,
   336  	}
   337  
   338  	err = d.doDDLJob(ctx, job)
   339  	c.Assert(err, NotNil)
   340  	testCheckJobCancelled(c, d, job)
   341  
   342  	dbInfo := testSchemaInfo(c, d, "test")
   343  	tblInfo := testTableInfo(c, d, "t", 3)
   344  
   345  	testCreateSchema(c, ctx, d, dbInfo)
   346  	testCreateTable(c, ctx, d, dbInfo, tblInfo)
   347  
   348  	col := &model.ColumnInfo{
   349  		Name:         model.NewCIStr("c4"),
   350  		Offset:       len(tblInfo.Columns),
   351  		DefaultValue: 0,
   352  	}
   353  
   354  	col.ID, err = d.genGlobalID()
   355  	c.Assert(err, IsNil)
   356  
   357  	col.FieldType = *types.NewFieldType(mysql.TypeLong)
   358  	pos := &ast.ColumnPosition{Tp: ast.ColumnPositionAfter, RelativeColumn: &ast.ColumnName{Name: model.NewCIStr("c5")}}
   359  
   360  	job = &model.Job{
   361  		SchemaID: dbInfo.ID,
   362  		TableID:  tblInfo.ID,
   363  		Type:     model.ActionAddColumn,
   364  		Args:     []interface{}{col, pos, 0},
   365  	}
   366  
   367  	err = d.doDDLJob(ctx, job)
   368  	c.Assert(err, NotNil)
   369  	testCheckJobCancelled(c, d, job)
   370  
   371  	job = &model.Job{
   372  		SchemaID: -1,
   373  		TableID:  1,
   374  		Type:     model.ActionDropColumn,
   375  		Args:     []interface{}{1},
   376  	}
   377  
   378  	err = d.doDDLJob(ctx, job)
   379  	c.Assert(err, NotNil)
   380  	testCheckJobCancelled(c, d, job)
   381  }