github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/milevadb-server/einsteindb/client_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 "fmt" 19 "sync" 20 "testing" 21 "time" 22 23 . "github.com/whtcorpsinc/check" 24 "github.com/whtcorpsinc/ekvproto/pkg/einsteindbpb" 25 "github.com/whtcorpsinc/ekvproto/pkg/ekvrpcpb" 26 "github.com/whtcorpsinc/ekvproto/pkg/spacetimepb" 27 "github.com/whtcorpsinc/errors" 28 "github.com/whtcorpsinc/milevadb/causetstore/einsteindb/einsteindbrpc" 29 "github.com/whtcorpsinc/milevadb/config" 30 ) 31 32 func TestT(t *testing.T) { 33 CustomVerboseFlag = true 34 TestingT(t) 35 } 36 37 type testClientSuite struct { 38 OneByOneSuite 39 } 40 41 type testClientSerialSuite struct { 42 OneByOneSuite 43 } 44 45 var _ = Suite(&testClientSuite{}) 46 var _ = SerialSuites(&testClientFailSuite{}) 47 var _ = SerialSuites(&testClientSerialSuite{}) 48 49 func setMaxBatchSize(size uint) { 50 newConf := config.NewConfig() 51 newConf.EinsteinDBClient.MaxBatchSize = size 52 config.StoreGlobalConfig(newConf) 53 } 54 55 func (s *testClientSerialSuite) TestConn(c *C) { 56 maxBatchSize := config.GetGlobalConfig().EinsteinDBClient.MaxBatchSize 57 setMaxBatchSize(0) 58 59 client := newRPCClient(config.Security{}) 60 61 addr := "127.0.0.1:6379" 62 conn1, err := client.getConnArray(addr, true) 63 c.Assert(err, IsNil) 64 65 conn2, err := client.getConnArray(addr, true) 66 c.Assert(err, IsNil) 67 c.Assert(conn2.Get(), Not(Equals), conn1.Get()) 68 69 client.Close() 70 conn3, err := client.getConnArray(addr, true) 71 c.Assert(err, NotNil) 72 c.Assert(conn3, IsNil) 73 setMaxBatchSize(maxBatchSize) 74 } 75 76 func (s *testClientSuite) TestRemoveCanceledRequests(c *C) { 77 req := new(einsteindbpb.BatchCommandsRequest_Request) 78 entries := []*batchCommandsEntry{ 79 {canceled: 1, req: req}, 80 {canceled: 0, req: req}, 81 {canceled: 1, req: req}, 82 {canceled: 1, req: req}, 83 {canceled: 0, req: req}, 84 } 85 entryPtr := &entries[0] 86 requests := make([]*einsteindbpb.BatchCommandsRequest_Request, len(entries)) 87 for i := range entries { 88 requests[i] = entries[i].req 89 } 90 entries, requests = removeCanceledRequests(entries, requests) 91 c.Assert(len(entries), Equals, 2) 92 for _, e := range entries { 93 c.Assert(e.isCanceled(), IsFalse) 94 } 95 c.Assert(len(requests), Equals, 2) 96 newEntryPtr := &entries[0] 97 c.Assert(entryPtr, Equals, newEntryPtr) 98 } 99 100 func (s *testClientSuite) TestCancelTimeoutRetErr(c *C) { 101 req := new(einsteindbpb.BatchCommandsRequest_Request) 102 a := newBatchConn(1, 1, nil) 103 104 ctx, cancel := context.WithCancel(context.TODO()) 105 cancel() 106 _, err := sendBatchRequest(ctx, "", a, req, 2*time.Second) 107 c.Assert(errors.Cause(err), Equals, context.Canceled) 108 109 _, err = sendBatchRequest(context.Background(), "", a, req, 0) 110 c.Assert(errors.Cause(err), Equals, context.DeadlineExceeded) 111 } 112 113 func (s *testClientSuite) TestSendWhenReconnect(c *C) { 114 server, port := startMockEinsteinDBService() 115 c.Assert(port > 0, IsTrue) 116 117 rpcClient := newRPCClient(config.Security{}) 118 addr := fmt.Sprintf("%s:%d", "127.0.0.1", port) 119 conn, err := rpcClient.getConnArray(addr, true) 120 c.Assert(err, IsNil) 121 122 // Suppose all connections are re-establishing. 123 for _, client := range conn.batchConn.batchCommandsClients { 124 client.lockForRecreate() 125 } 126 127 req := einsteindbrpc.NewRequest(einsteindbrpc.CmdEmpty, &einsteindbpb.BatchCommandsEmptyRequest{}) 128 _, err = rpcClient.SendRequest(context.Background(), addr, req, 100*time.Second) 129 c.Assert(err.Error() == "no available connections", IsTrue) 130 conn.Close() 131 server.Stop() 132 } 133 134 // chanClient sends received requests to the channel. 135 type chanClient struct { 136 wg *sync.WaitGroup 137 ch chan<- *einsteindbrpc.Request 138 } 139 140 func (c *chanClient) Close() error { 141 return nil 142 } 143 144 func (c *chanClient) SendRequest(ctx context.Context, addr string, req *einsteindbrpc.Request, timeout time.Duration) (*einsteindbrpc.Response, error) { 145 c.wg.Wait() 146 c.ch <- req 147 return nil, nil 148 } 149 150 func (s *testClientSuite) TestDefCauslapseResolveLock(c *C) { 151 buildResolveLockReq := func(regionID uint64, startTS uint64, commitTS uint64, keys [][]byte) *einsteindbrpc.Request { 152 region := &spacetimepb.Region{Id: regionID} 153 req := einsteindbrpc.NewRequest(einsteindbrpc.CmdResolveLock, &ekvrpcpb.ResolveLockRequest{ 154 StartVersion: startTS, 155 CommitVersion: commitTS, 156 Keys: keys, 157 }) 158 einsteindbrpc.SetContext(req, region, nil) 159 return req 160 } 161 buildBatchResolveLockReq := func(regionID uint64, txnInfos []*ekvrpcpb.TxnInfo) *einsteindbrpc.Request { 162 region := &spacetimepb.Region{Id: regionID} 163 req := einsteindbrpc.NewRequest(einsteindbrpc.CmdResolveLock, &ekvrpcpb.ResolveLockRequest{ 164 TxnInfos: txnInfos, 165 }) 166 einsteindbrpc.SetContext(req, region, nil) 167 return req 168 } 169 170 var wg sync.WaitGroup 171 reqCh := make(chan *einsteindbrpc.Request) 172 client := reqDefCauslapse{&chanClient{wg: &wg, ch: reqCh}} 173 ctx := context.Background() 174 175 // DefCauslapse ResolveLock. 176 resolveLockReq := buildResolveLockReq(1, 10, 20, nil) 177 wg.Add(1) 178 go client.SendRequest(ctx, "", resolveLockReq, time.Second) 179 go client.SendRequest(ctx, "", resolveLockReq, time.Second) 180 time.Sleep(300 * time.Millisecond) 181 wg.Done() 182 req := <-reqCh 183 c.Assert(*req, DeepEquals, *resolveLockReq) 184 select { 185 case <-reqCh: 186 c.Fatal("fail to collapse ResolveLock") 187 default: 188 } 189 190 // Don't collapse ResolveLockLite. 191 resolveLockLiteReq := buildResolveLockReq(1, 10, 20, [][]byte{[]byte("foo")}) 192 wg.Add(1) 193 go client.SendRequest(ctx, "", resolveLockLiteReq, time.Second) 194 go client.SendRequest(ctx, "", resolveLockLiteReq, time.Second) 195 time.Sleep(300 * time.Millisecond) 196 wg.Done() 197 for i := 0; i < 2; i++ { 198 req := <-reqCh 199 c.Assert(*req, DeepEquals, *resolveLockLiteReq) 200 } 201 202 // Don't collapse BatchResolveLock. 203 batchResolveLockReq := buildBatchResolveLockReq(1, []*ekvrpcpb.TxnInfo{ 204 {Txn: 10, Status: 20}, 205 }) 206 wg.Add(1) 207 go client.SendRequest(ctx, "", batchResolveLockReq, time.Second) 208 go client.SendRequest(ctx, "", batchResolveLockReq, time.Second) 209 time.Sleep(300 * time.Millisecond) 210 wg.Done() 211 for i := 0; i < 2; i++ { 212 req := <-reqCh 213 c.Assert(*req, DeepEquals, *batchResolveLockReq) 214 } 215 216 // Mixed 217 wg.Add(1) 218 go client.SendRequest(ctx, "", resolveLockReq, time.Second) 219 go client.SendRequest(ctx, "", resolveLockLiteReq, time.Second) 220 go client.SendRequest(ctx, "", batchResolveLockReq, time.Second) 221 time.Sleep(300 * time.Millisecond) 222 wg.Done() 223 for i := 0; i < 3; i++ { 224 <-reqCh 225 } 226 select { 227 case <-reqCh: 228 c.Fatal("unexpected request") 229 default: 230 } 231 }