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 }