github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/schemareplicant/infoschema_test.go (about) 1 // Copyright 2020 WHTCORPS INC, 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 schemareplicant_test 15 16 import ( 17 "sync" 18 "testing" 19 20 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 21 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 22 . "github.com/whtcorpsinc/check" 23 "github.com/whtcorpsinc/errors" 24 "github.com/whtcorpsinc/milevadb/causetstore/mockstore" 25 "github.com/whtcorpsinc/milevadb/ekv" 26 "github.com/whtcorpsinc/milevadb/schemareplicant" 27 "github.com/whtcorpsinc/milevadb/soliton" 28 "github.com/whtcorpsinc/milevadb/soliton/solitonutil" 29 "github.com/whtcorpsinc/milevadb/soliton/testleak" 30 "github.com/whtcorpsinc/milevadb/spacetime" 31 "github.com/whtcorpsinc/milevadb/stochastik" 32 "github.com/whtcorpsinc/milevadb/types" 33 ) 34 35 func TestT(t *testing.T) { 36 CustomVerboseFlag = true 37 TestingT(t) 38 } 39 40 var _ = Suite(&testSuite{}) 41 42 type testSuite struct { 43 } 44 45 func (*testSuite) TestT(c *C) { 46 defer testleak.AfterTest(c)() 47 causetstore, err := mockstore.NewMockStore() 48 c.Assert(err, IsNil) 49 defer causetstore.Close() 50 // Make sure it calls perfschema.Init(). 51 dom, err := stochastik.BootstrapStochastik(causetstore) 52 c.Assert(err, IsNil) 53 defer dom.Close() 54 55 handle := schemareplicant.NewHandle(causetstore) 56 dbName := perceptron.NewCIStr("Test") 57 tbName := perceptron.NewCIStr("T") 58 defCausName := perceptron.NewCIStr("A") 59 idxName := perceptron.NewCIStr("idx") 60 noexist := perceptron.NewCIStr("noexist") 61 62 defCausID, err := genGlobalID(causetstore) 63 c.Assert(err, IsNil) 64 defCausInfo := &perceptron.DeferredCausetInfo{ 65 ID: defCausID, 66 Name: defCausName, 67 Offset: 0, 68 FieldType: *types.NewFieldType(allegrosql.TypeLonglong), 69 State: perceptron.StatePublic, 70 } 71 72 idxInfo := &perceptron.IndexInfo{ 73 Name: idxName, 74 Block: tbName, 75 DeferredCausets: []*perceptron.IndexDeferredCauset{ 76 { 77 Name: defCausName, 78 Offset: 0, 79 Length: 10, 80 }, 81 }, 82 Unique: true, 83 Primary: true, 84 State: perceptron.StatePublic, 85 } 86 87 tbID, err := genGlobalID(causetstore) 88 c.Assert(err, IsNil) 89 tblInfo := &perceptron.BlockInfo{ 90 ID: tbID, 91 Name: tbName, 92 DeferredCausets: []*perceptron.DeferredCausetInfo{defCausInfo}, 93 Indices: []*perceptron.IndexInfo{idxInfo}, 94 State: perceptron.StatePublic, 95 } 96 97 dbID, err := genGlobalID(causetstore) 98 c.Assert(err, IsNil) 99 dbInfo := &perceptron.DBInfo{ 100 ID: dbID, 101 Name: dbName, 102 Blocks: []*perceptron.BlockInfo{tblInfo}, 103 State: perceptron.StatePublic, 104 } 105 106 dbInfos := []*perceptron.DBInfo{dbInfo} 107 err = ekv.RunInNewTxn(causetstore, true, func(txn ekv.Transaction) error { 108 spacetime.NewMeta(txn).CreateDatabase(dbInfo) 109 return errors.Trace(err) 110 }) 111 c.Assert(err, IsNil) 112 113 builder, err := schemareplicant.NewBuilder(handle).InitWithDBInfos(dbInfos, 1) 114 c.Assert(err, IsNil) 115 116 txn, err := causetstore.Begin() 117 c.Assert(err, IsNil) 118 checkApplyCreateNonExistsSchemaDoesNotPanic(c, txn, builder) 119 checkApplyCreateNonExistsBlockDoesNotPanic(c, txn, builder, dbID) 120 txn.Rollback() 121 122 builder.Build() 123 is := handle.Get() 124 125 schemaNames := is.AllSchemaNames() 126 c.Assert(schemaNames, HasLen, 4) 127 c.Assert(solitonutil.CompareUnorderedStringSlice(schemaNames, []string{soliton.InformationSchemaName.O, soliton.MetricSchemaName.O, soliton.PerformanceSchemaName.O, "Test"}), IsTrue) 128 129 schemas := is.AllSchemas() 130 c.Assert(schemas, HasLen, 4) 131 schemas = is.Clone() 132 c.Assert(schemas, HasLen, 4) 133 134 c.Assert(is.SchemaExists(dbName), IsTrue) 135 c.Assert(is.SchemaExists(noexist), IsFalse) 136 137 schemaReplicant, ok := is.SchemaByID(dbID) 138 c.Assert(ok, IsTrue) 139 c.Assert(schemaReplicant, NotNil) 140 141 schemaReplicant, ok = is.SchemaByID(tbID) 142 c.Assert(ok, IsFalse) 143 c.Assert(schemaReplicant, IsNil) 144 145 schemaReplicant, ok = is.SchemaByName(dbName) 146 c.Assert(ok, IsTrue) 147 c.Assert(schemaReplicant, NotNil) 148 149 schemaReplicant, ok = is.SchemaByName(noexist) 150 c.Assert(ok, IsFalse) 151 c.Assert(schemaReplicant, IsNil) 152 153 schemaReplicant, ok = is.SchemaByBlock(tblInfo) 154 c.Assert(ok, IsTrue) 155 c.Assert(schemaReplicant, NotNil) 156 157 noexistTblInfo := &perceptron.BlockInfo{ID: 12345, Name: tblInfo.Name} 158 schemaReplicant, ok = is.SchemaByBlock(noexistTblInfo) 159 c.Assert(ok, IsFalse) 160 c.Assert(schemaReplicant, IsNil) 161 162 c.Assert(is.BlockExists(dbName, tbName), IsTrue) 163 c.Assert(is.BlockExists(dbName, noexist), IsFalse) 164 c.Assert(is.BlockIsView(dbName, tbName), IsFalse) 165 c.Assert(is.BlockIsSequence(dbName, tbName), IsFalse) 166 167 tb, ok := is.BlockByID(tbID) 168 c.Assert(ok, IsTrue) 169 c.Assert(tb, NotNil) 170 171 tb, ok = is.BlockByID(dbID) 172 c.Assert(ok, IsFalse) 173 c.Assert(tb, IsNil) 174 175 alloc, ok := is.AllocByID(tbID) 176 c.Assert(ok, IsTrue) 177 c.Assert(alloc, NotNil) 178 179 tb, err = is.BlockByName(dbName, tbName) 180 c.Assert(err, IsNil) 181 c.Assert(tb, NotNil) 182 183 _, err = is.BlockByName(dbName, noexist) 184 c.Assert(err, NotNil) 185 186 tbs := is.SchemaBlocks(dbName) 187 c.Assert(tbs, HasLen, 1) 188 189 tbs = is.SchemaBlocks(noexist) 190 c.Assert(tbs, HasLen, 0) 191 192 // Make sure partitions causet exists 193 tb, err = is.BlockByName(perceptron.NewCIStr("information_schema"), perceptron.NewCIStr("partitions")) 194 c.Assert(err, IsNil) 195 c.Assert(tb, NotNil) 196 197 err = ekv.RunInNewTxn(causetstore, true, func(txn ekv.Transaction) error { 198 spacetime.NewMeta(txn).CreateBlockOrView(dbID, tblInfo) 199 return errors.Trace(err) 200 }) 201 c.Assert(err, IsNil) 202 txn, err = causetstore.Begin() 203 c.Assert(err, IsNil) 204 _, err = builder.ApplyDiff(spacetime.NewMeta(txn), &perceptron.SchemaDiff{Type: perceptron.CausetActionRenameBlock, SchemaID: dbID, BlockID: tbID, OldSchemaID: dbID}) 205 c.Assert(err, IsNil) 206 txn.Rollback() 207 builder.Build() 208 is = handle.Get() 209 schemaReplicant, ok = is.SchemaByID(dbID) 210 c.Assert(ok, IsTrue) 211 c.Assert(len(schemaReplicant.Blocks), Equals, 1) 212 213 emptyHandle := handle.EmptyClone() 214 c.Assert(emptyHandle.Get(), IsNil) 215 } 216 217 func (testSuite) TestMockSchemaReplicant(c *C) { 218 tblID := int64(1234) 219 tblName := perceptron.NewCIStr("tbl_m") 220 blockInfo := &perceptron.BlockInfo{ 221 ID: tblID, 222 Name: tblName, 223 State: perceptron.StatePublic, 224 } 225 defCausInfo := &perceptron.DeferredCausetInfo{ 226 State: perceptron.StatePublic, 227 Offset: 0, 228 Name: perceptron.NewCIStr("h"), 229 FieldType: *types.NewFieldType(allegrosql.TypeLong), 230 ID: 1, 231 } 232 blockInfo.DeferredCausets = []*perceptron.DeferredCausetInfo{defCausInfo} 233 is := schemareplicant.MockSchemaReplicant([]*perceptron.BlockInfo{blockInfo}) 234 tbl, ok := is.BlockByID(tblID) 235 c.Assert(ok, IsTrue) 236 c.Assert(tbl.Meta().Name, Equals, tblName) 237 c.Assert(tbl.DefCauss()[0].DeferredCausetInfo, Equals, defCausInfo) 238 } 239 240 func checkApplyCreateNonExistsSchemaDoesNotPanic(c *C, txn ekv.Transaction, builder *schemareplicant.Builder) { 241 m := spacetime.NewMeta(txn) 242 _, err := builder.ApplyDiff(m, &perceptron.SchemaDiff{Type: perceptron.CausetActionCreateSchema, SchemaID: 999}) 243 c.Assert(schemareplicant.ErrDatabaseNotExists.Equal(err), IsTrue) 244 } 245 246 func checkApplyCreateNonExistsBlockDoesNotPanic(c *C, txn ekv.Transaction, builder *schemareplicant.Builder, dbID int64) { 247 m := spacetime.NewMeta(txn) 248 _, err := builder.ApplyDiff(m, &perceptron.SchemaDiff{Type: perceptron.CausetActionCreateBlock, SchemaID: dbID, BlockID: 999}) 249 c.Assert(schemareplicant.ErrBlockNotExists.Equal(err), IsTrue) 250 } 251 252 // TestConcurrent makes sure it is safe to concurrently create handle on multiple stores. 253 func (testSuite) TestConcurrent(c *C) { 254 defer testleak.AfterTest(c)() 255 storeCount := 5 256 stores := make([]ekv.CausetStorage, storeCount) 257 for i := 0; i < storeCount; i++ { 258 causetstore, err := mockstore.NewMockStore() 259 c.Assert(err, IsNil) 260 stores[i] = causetstore 261 } 262 defer func() { 263 for _, causetstore := range stores { 264 causetstore.Close() 265 } 266 }() 267 var wg sync.WaitGroup 268 wg.Add(storeCount) 269 for _, causetstore := range stores { 270 go func(s ekv.CausetStorage) { 271 defer wg.Done() 272 _ = schemareplicant.NewHandle(s) 273 }(causetstore) 274 } 275 wg.Wait() 276 } 277 278 // TestInfoBlocks makes sure that all blocks of information_schema could be found in schemareplicant handle. 279 func (*testSuite) TestInfoBlocks(c *C) { 280 defer testleak.AfterTest(c)() 281 causetstore, err := mockstore.NewMockStore() 282 c.Assert(err, IsNil) 283 defer causetstore.Close() 284 handle := schemareplicant.NewHandle(causetstore) 285 builder, err := schemareplicant.NewBuilder(handle).InitWithDBInfos(nil, 0) 286 c.Assert(err, IsNil) 287 builder.Build() 288 is := handle.Get() 289 c.Assert(is, NotNil) 290 291 infoBlocks := []string{ 292 "SCHEMATA", 293 "TABLES", 294 "COLUMNS", 295 "STATISTICS", 296 "CHARACTER_SETS", 297 "COLLATIONS", 298 "FILES", 299 "PROFILING", 300 "PARTITIONS", 301 "KEY_COLUMN_USAGE", 302 "REFERENTIAL_CONSTRAINTS", 303 "SESSION_VARIABLES", 304 "PLUGINS", 305 "TABLE_CONSTRAINTS", 306 "TRIGGERS", 307 "USER_PRIVILEGES", 308 "ENGINES", 309 "VIEWS", 310 "ROUTINES", 311 "SCHEMA_PRIVILEGES", 312 "COLUMN_PRIVILEGES", 313 "TABLE_PRIVILEGES", 314 "PARAMETERS", 315 "EVENTS", 316 "GLOBAL_STATUS", 317 "GLOBAL_VARIABLES", 318 "SESSION_STATUS", 319 "OPTIMIZER_TRACE", 320 "TABLESPACES", 321 "COLLATION_CHARACTER_SET_APPLICABILITY", 322 "PROCESSLIST", 323 } 324 for _, t := range infoBlocks { 325 tb, err1 := is.BlockByName(soliton.InformationSchemaName, perceptron.NewCIStr(t)) 326 c.Assert(err1, IsNil) 327 c.Assert(tb, NotNil) 328 } 329 } 330 331 func genGlobalID(causetstore ekv.CausetStorage) (int64, error) { 332 var globalID int64 333 err := ekv.RunInNewTxn(causetstore, true, func(txn ekv.Transaction) error { 334 var err error 335 globalID, err = spacetime.NewMeta(txn).GenGlobalID() 336 return errors.Trace(err) 337 }) 338 return globalID, errors.Trace(err) 339 }