github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/stochastik/milevadb_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 stochastik 15 16 import ( 17 "context" 18 "fmt" 19 "os" 20 "sync" 21 "sync/atomic" 22 "testing" 23 "time" 24 25 "github.com/whtcorpsinc/BerolinaSQL/auth" 26 . "github.com/whtcorpsinc/check" 27 "github.com/whtcorpsinc/milevadb/blockcodec" 28 "github.com/whtcorpsinc/milevadb/causet/embedded" 29 "github.com/whtcorpsinc/milevadb/causetstore/mockstore" 30 "github.com/whtcorpsinc/milevadb/ekv" 31 "github.com/whtcorpsinc/milevadb/petri" 32 "github.com/whtcorpsinc/milevadb/soliton/logutil" 33 "github.com/whtcorpsinc/milevadb/soliton/sqlexec" 34 "github.com/whtcorpsinc/milevadb/soliton/testleak" 35 "github.com/whtcorpsinc/milevadb/types" 36 ) 37 38 func TestT(t *testing.T) { 39 logLevel := os.Getenv("log_level") 40 logutil.InitLogger(logutil.NewLogConfig(logLevel, logutil.DefaultLogFormat, "", logutil.EmptyFileLogConfig, false)) 41 CustomVerboseFlag = true 42 SetSchemaLease(20 * time.Millisecond) 43 TestingT(t) 44 } 45 46 var _ = Suite(&testMainSuite{}) 47 var _ = SerialSuites(&testBootstrapSuite{}) 48 49 type testMainSuite struct { 50 dbName string 51 causetstore ekv.CausetStorage 52 dom *petri.Petri 53 } 54 55 func (s *testMainSuite) SetUpSuite(c *C) { 56 testleak.BeforeTest() 57 s.dbName = "test_main_db" 58 s.causetstore = newStore(c, s.dbName) 59 dom, err := BootstrapStochastik(s.causetstore) 60 c.Assert(err, IsNil) 61 s.dom = dom 62 } 63 64 func (s *testMainSuite) TearDownSuite(c *C) { 65 defer testleak.AfterTest(c)() 66 s.dom.Close() 67 err := s.causetstore.Close() 68 c.Assert(err, IsNil) 69 removeStore(c, s.dbName) 70 } 71 72 func (s *testMainSuite) TestSysStochastikPoolGoroutineLeak(c *C) { 73 causetstore, dom := newStoreWithBootstrap(c, s.dbName+"goroutine_leak") 74 defer causetstore.Close() 75 defer dom.Close() 76 se, err := createStochastik(causetstore) 77 c.Assert(err, IsNil) 78 79 // Test an issue that sysStochastikPool doesn't call stochastik's Close, cause 80 // asyncGetTSWorker goroutine leak. 81 count := 200 82 var wg sync.WaitGroup 83 wg.Add(count) 84 for i := 0; i < count; i++ { 85 go func(se *stochastik) { 86 _, _, err := se.InterDircRestrictedALLEGROSQL("select * from allegrosql.user limit 1") 87 c.Assert(err, IsNil) 88 wg.Done() 89 }(se) 90 } 91 wg.Wait() 92 } 93 94 func (s *testMainSuite) TestParseErrorWarn(c *C) { 95 ctx := embedded.MockContext() 96 97 nodes, err := Parse(ctx, "select /*+ adf */ 1") 98 c.Assert(err, IsNil) 99 c.Assert(len(nodes), Equals, 1) 100 c.Assert(len(ctx.GetStochastikVars().StmtCtx.GetWarnings()), Equals, 1) 101 102 _, err = Parse(ctx, "select") 103 c.Assert(err, NotNil) 104 } 105 106 func newStore(c *C, dbPath string) ekv.CausetStorage { 107 causetstore, err := mockstore.NewMockStore() 108 c.Assert(err, IsNil) 109 return causetstore 110 } 111 112 func newStoreWithBootstrap(c *C, dbPath string) (ekv.CausetStorage, *petri.Petri) { 113 causetstore, err := mockstore.NewMockStore() 114 c.Assert(err, IsNil) 115 dom, err := BootstrapStochastik(causetstore) 116 c.Assert(err, IsNil) 117 return causetstore, dom 118 } 119 120 var testConnID uint64 121 122 func newStochastik(c *C, causetstore ekv.CausetStorage, dbName string) Stochastik { 123 se, err := CreateStochastik4Test(causetstore) 124 id := atomic.AddUint64(&testConnID, 1) 125 se.SetConnectionID(id) 126 c.Assert(err, IsNil) 127 se.Auth(&auth.UserIdentity{Username: "root", Hostname: `%`}, nil, []byte("012345678901234567890")) 128 mustInterDircALLEGROSQL(c, se, "create database if not exists "+dbName) 129 mustInterDircALLEGROSQL(c, se, "use "+dbName) 130 return se 131 } 132 133 func removeStore(c *C, dbPath string) { 134 os.RemoveAll(dbPath) 135 } 136 137 func exec(se Stochastik, allegrosql string, args ...interface{}) (sqlexec.RecordSet, error) { 138 ctx := context.Background() 139 if len(args) == 0 { 140 rs, err := se.InterDircute(ctx, allegrosql) 141 if err == nil && len(rs) > 0 { 142 return rs[0], nil 143 } 144 return nil, err 145 } 146 stmtID, _, _, err := se.PrepareStmt(allegrosql) 147 if err != nil { 148 return nil, err 149 } 150 params := make([]types.Causet, len(args)) 151 for i := 0; i < len(params); i++ { 152 params[i] = types.NewCauset(args[i]) 153 } 154 rs, err := se.InterDircutePreparedStmt(ctx, stmtID, params) 155 if err != nil { 156 return nil, err 157 } 158 return rs, nil 159 } 160 161 func mustInterDircALLEGROSQL(c *C, se Stochastik, allegrosql string, args ...interface{}) sqlexec.RecordSet { 162 rs, err := exec(se, allegrosql, args...) 163 c.Assert(err, IsNil) 164 return rs 165 } 166 167 func match(c *C, event []types.Causet, expected ...interface{}) { 168 c.Assert(len(event), Equals, len(expected)) 169 for i := range event { 170 got := fmt.Sprintf("%v", event[i].GetValue()) 171 need := fmt.Sprintf("%v", expected[i]) 172 c.Assert(got, Equals, need) 173 } 174 } 175 176 func (s *testMainSuite) TestKeysNeedLock(c *C) { 177 rowKey := blockcodec.EncodeRowKeyWithHandle(1, ekv.IntHandle(1)) 178 indexKey := blockcodec.EncodeIndexSeekKey(1, 1, []byte{1}) 179 uniqueValue := make([]byte, 8) 180 uniqueUntouched := append(uniqueValue, '1') 181 nonUniqueVal := []byte{'0'} 182 nonUniqueUntouched := []byte{'1'} 183 var deleteVal []byte 184 rowVal := []byte{'a', 'b', 'c'} 185 tests := []struct { 186 key []byte 187 val []byte 188 need bool 189 }{ 190 {rowKey, rowVal, true}, 191 {rowKey, deleteVal, true}, 192 {indexKey, nonUniqueVal, false}, 193 {indexKey, nonUniqueUntouched, false}, 194 {indexKey, uniqueValue, true}, 195 {indexKey, uniqueUntouched, false}, 196 {indexKey, deleteVal, false}, 197 } 198 for _, tt := range tests { 199 c.Assert(keyNeedToLock(tt.key, tt.val, 0), Equals, tt.need) 200 } 201 flag := ekv.KeyFlags(1) 202 c.Assert(flag.HasPresumeKeyNotExists(), IsTrue) 203 c.Assert(keyNeedToLock(indexKey, deleteVal, flag), IsTrue) 204 }