github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/milevadb-server/einsteindb/store_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 einsteindb 15 16 import ( 17 "context" 18 "sync" 19 "time" 20 21 fidel "github.com/einsteindb/fidel/client" 22 . "github.com/whtcorpsinc/check" 23 "github.com/whtcorpsinc/ekvproto/pkg/FIDelpb" 24 pb "github.com/whtcorpsinc/ekvproto/pkg/ekvrpcpb" 25 "github.com/whtcorpsinc/ekvproto/pkg/spacetimepb" 26 "github.com/whtcorpsinc/errors" 27 "github.com/whtcorpsinc/failpoint" 28 "github.com/whtcorpsinc/milevadb/causetstore/einsteindb/einsteindbrpc" 29 "github.com/whtcorpsinc/milevadb/causetstore/mockoracle" 30 "github.com/whtcorpsinc/milevadb/ekv" 31 ) 32 33 var errStopped = errors.New("stopped") 34 35 type testStoreSuite struct { 36 testStoreSuiteBase 37 } 38 39 type testStoreSerialSuite struct { 40 testStoreSuiteBase 41 } 42 43 type testStoreSuiteBase struct { 44 OneByOneSuite 45 causetstore *einsteindbStore 46 } 47 48 var _ = Suite(&testStoreSuite{}) 49 var _ = SerialSuites(&testStoreSerialSuite{}) 50 51 func (s *testStoreSuiteBase) SetUpTest(c *C) { 52 s.causetstore = NewTestStore(c).(*einsteindbStore) 53 } 54 55 func (s *testStoreSuiteBase) TearDownTest(c *C) { 56 c.Assert(s.causetstore.Close(), IsNil) 57 } 58 59 func (s *testStoreSuite) TestOracle(c *C) { 60 o := &mockoracle.MockOracle{} 61 s.causetstore.oracle = o 62 63 ctx := context.Background() 64 t1, err := s.causetstore.getTimestampWithRetry(NewBackofferWithVars(ctx, 100, nil)) 65 c.Assert(err, IsNil) 66 t2, err := s.causetstore.getTimestampWithRetry(NewBackofferWithVars(ctx, 100, nil)) 67 c.Assert(err, IsNil) 68 c.Assert(t1, Less, t2) 69 70 t1, err = o.GetLowResolutionTimestamp(ctx) 71 c.Assert(err, IsNil) 72 t2, err = o.GetLowResolutionTimestamp(ctx) 73 c.Assert(err, IsNil) 74 c.Assert(t1, Less, t2) 75 f := o.GetLowResolutionTimestampAsync(ctx) 76 c.Assert(f, NotNil) 77 _ = o.UntilExpired(0, 0) 78 79 // Check retry. 80 var wg sync.WaitGroup 81 wg.Add(2) 82 83 o.Disable() 84 go func() { 85 defer wg.Done() 86 time.Sleep(time.Millisecond * 100) 87 o.Enable() 88 }() 89 90 go func() { 91 defer wg.Done() 92 t3, err := s.causetstore.getTimestampWithRetry(NewBackofferWithVars(ctx, tsoMaxBackoff, nil)) 93 c.Assert(err, IsNil) 94 c.Assert(t2, Less, t3) 95 expired := s.causetstore.oracle.IsExpired(t2, 50) 96 c.Assert(expired, IsTrue) 97 }() 98 99 wg.Wait() 100 } 101 102 type mockFIDelClient struct { 103 sync.RWMutex 104 client fidel.Client 105 stop bool 106 } 107 108 func (c *mockFIDelClient) enable() { 109 c.Lock() 110 defer c.Unlock() 111 c.stop = false 112 } 113 114 func (c *mockFIDelClient) disable() { 115 c.Lock() 116 defer c.Unlock() 117 c.stop = true 118 } 119 120 func (c *mockFIDelClient) GetMemberInfo(ctx context.Context) ([]*FIDelpb.Member, error) { 121 return nil, nil 122 } 123 124 func (c *mockFIDelClient) GetClusterID(context.Context) uint64 { 125 return 1 126 } 127 128 func (c *mockFIDelClient) GetTS(ctx context.Context) (int64, int64, error) { 129 c.RLock() 130 defer c.RUnlock() 131 132 if c.stop { 133 return 0, 0, errors.Trace(errStopped) 134 } 135 return c.client.GetTS(ctx) 136 } 137 138 func (c *mockFIDelClient) GetTSAsync(ctx context.Context) fidel.TSFuture { 139 return nil 140 } 141 142 func (c *mockFIDelClient) GetRegion(ctx context.Context, key []byte) (*fidel.Region, error) { 143 c.RLock() 144 defer c.RUnlock() 145 146 if c.stop { 147 return nil, errors.Trace(errStopped) 148 } 149 return c.client.GetRegion(ctx, key) 150 } 151 152 func (c *mockFIDelClient) GetPrevRegion(ctx context.Context, key []byte) (*fidel.Region, error) { 153 c.RLock() 154 defer c.RUnlock() 155 156 if c.stop { 157 return nil, errors.Trace(errStopped) 158 } 159 return c.client.GetPrevRegion(ctx, key) 160 } 161 162 func (c *mockFIDelClient) GetRegionByID(ctx context.Context, regionID uint64) (*fidel.Region, error) { 163 c.RLock() 164 defer c.RUnlock() 165 166 if c.stop { 167 return nil, errors.Trace(errStopped) 168 } 169 return c.client.GetRegionByID(ctx, regionID) 170 } 171 172 func (c *mockFIDelClient) ScanRegions(ctx context.Context, startKey []byte, endKey []byte, limit int) ([]*fidel.Region, error) { 173 c.RLock() 174 defer c.RUnlock() 175 176 if c.stop { 177 return nil, errors.Trace(errStopped) 178 } 179 return c.client.ScanRegions(ctx, startKey, endKey, limit) 180 } 181 182 func (c *mockFIDelClient) GetStore(ctx context.Context, storeID uint64) (*spacetimepb.CausetStore, error) { 183 c.RLock() 184 defer c.RUnlock() 185 186 if c.stop { 187 return nil, errors.Trace(errStopped) 188 } 189 return c.client.GetStore(ctx, storeID) 190 } 191 192 func (c *mockFIDelClient) GetAllStores(ctx context.Context, opts ...fidel.GetStoreOption) ([]*spacetimepb.CausetStore, error) { 193 c.RLock() 194 defer c.Unlock() 195 196 if c.stop { 197 return nil, errors.Trace(errStopped) 198 } 199 return c.client.GetAllStores(ctx) 200 } 201 202 func (c *mockFIDelClient) UFIDelateGCSafePoint(ctx context.Context, safePoint uint64) (uint64, error) { 203 panic("unimplemented") 204 } 205 206 func (c *mockFIDelClient) UFIDelateServiceGCSafePoint(ctx context.Context, serviceID string, ttl int64, safePoint uint64) (uint64, error) { 207 panic("unimplemented") 208 } 209 210 func (c *mockFIDelClient) Close() {} 211 212 func (c *mockFIDelClient) ScatterRegion(ctx context.Context, regionID uint64) error { 213 return nil 214 } 215 216 func (c *mockFIDelClient) GetOperator(ctx context.Context, regionID uint64) (*FIDelpb.GetOperatorResponse, error) { 217 return &FIDelpb.GetOperatorResponse{Status: FIDelpb.OperatorStatus_SUCCESS}, nil 218 } 219 220 func (c *mockFIDelClient) GetLeaderAddr() string { return "mockFIDel" } 221 222 func (c *mockFIDelClient) ScatterRegionWithOption(ctx context.Context, regionID uint64, opts ...fidel.ScatterRegionOption) error { 223 return nil 224 } 225 226 type checkRequestClient struct { 227 Client 228 priority pb.CommandPri 229 } 230 231 func (c *checkRequestClient) SendRequest(ctx context.Context, addr string, req *einsteindbrpc.Request, timeout time.Duration) (*einsteindbrpc.Response, error) { 232 resp, err := c.Client.SendRequest(ctx, addr, req, timeout) 233 if c.priority != req.Priority { 234 if resp.Resp != nil { 235 if getResp, ok := resp.Resp.(*pb.GetResponse); ok { 236 getResp.Error = &pb.KeyError{ 237 Abort: "request check error", 238 } 239 } 240 } 241 } 242 return resp, err 243 } 244 245 func (s *testStoreSuite) TestRequestPriority(c *C) { 246 client := &checkRequestClient{ 247 Client: s.causetstore.client, 248 } 249 s.causetstore.client = client 250 251 // Cover 2PC commit. 252 txn, err := s.causetstore.Begin() 253 c.Assert(err, IsNil) 254 client.priority = pb.CommandPri_High 255 txn.SetOption(ekv.Priority, ekv.PriorityHigh) 256 err = txn.Set([]byte("key"), []byte("value")) 257 c.Assert(err, IsNil) 258 err = txn.Commit(context.Background()) 259 c.Assert(err, IsNil) 260 261 // Cover the basic Get request. 262 txn, err = s.causetstore.Begin() 263 c.Assert(err, IsNil) 264 client.priority = pb.CommandPri_Low 265 txn.SetOption(ekv.Priority, ekv.PriorityLow) 266 _, err = txn.Get(context.TODO(), []byte("key")) 267 c.Assert(err, IsNil) 268 269 // A counter example. 270 client.priority = pb.CommandPri_Low 271 txn.SetOption(ekv.Priority, ekv.PriorityNormal) 272 _, err = txn.Get(context.TODO(), []byte("key")) 273 // err is translated to "try again later" by backoffer, so doesn't check error value here. 274 c.Assert(err, NotNil) 275 276 // Cover Seek request. 277 client.priority = pb.CommandPri_High 278 txn.SetOption(ekv.Priority, ekv.PriorityHigh) 279 iter, err := txn.Iter([]byte("key"), nil) 280 c.Assert(err, IsNil) 281 for iter.Valid() { 282 c.Assert(iter.Next(), IsNil) 283 } 284 iter.Close() 285 } 286 287 func (s *testStoreSerialSuite) TestOracleChangeByFailpoint(c *C) { 288 defer func() { 289 failpoint.Disable("github.com/whtcorpsinc/milevadb/causetstore/einsteindb/oracle/changeTSFromFIDel") 290 }() 291 c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/causetstore/einsteindb/oracle/changeTSFromFIDel", 292 "return(10000)"), IsNil) 293 o := &mockoracle.MockOracle{} 294 s.causetstore.oracle = o 295 ctx := context.Background() 296 t1, err := s.causetstore.getTimestampWithRetry(NewBackofferWithVars(ctx, 100, nil)) 297 c.Assert(err, IsNil) 298 c.Assert(failpoint.Disable("github.com/whtcorpsinc/milevadb/causetstore/einsteindb/oracle/changeTSFromFIDel"), IsNil) 299 t2, err := s.causetstore.getTimestampWithRetry(NewBackofferWithVars(ctx, 100, nil)) 300 c.Assert(err, IsNil) 301 c.Assert(t1, Greater, t2) 302 }