github.com/pingcap/br@v5.3.0-alpha.0.20220125034240-ec59c7b6ce30+incompatible/pkg/lightning/backend/importer/importer_test.go (about) 1 // Copyright 2019 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 importer 15 16 import ( 17 "context" 18 "encoding/json" 19 "net/http" 20 "net/http/httptest" 21 "sync" 22 "testing" 23 24 "github.com/golang/mock/gomock" 25 "github.com/google/uuid" 26 . "github.com/pingcap/check" 27 "github.com/pingcap/errors" 28 kvpb "github.com/pingcap/kvproto/pkg/import_kvpb" 29 30 "github.com/pingcap/br/pkg/lightning/backend" 31 "github.com/pingcap/br/pkg/lightning/backend/kv" 32 "github.com/pingcap/br/pkg/lightning/common" 33 "github.com/pingcap/br/pkg/mock" 34 ) 35 36 type importerSuite struct { 37 controller *gomock.Controller 38 mockClient *mock.MockImportKVClient 39 mockWriter *mock.MockImportKV_WriteEngineClient 40 ctx context.Context 41 engineUUID []byte 42 engine *backend.OpenedEngine 43 kvPairs kv.Rows 44 } 45 46 var _ = Suite(&importerSuite{}) 47 48 const testPDAddr = "pd-addr:2379" 49 50 // FIXME: Cannot use the real SetUpTest/TearDownTest to set up the mock 51 // otherwise the mock error will be ignored. 52 53 func (s *importerSuite) setUpTest(c *C) { 54 s.controller = gomock.NewController(c) 55 s.mockClient = mock.NewMockImportKVClient(s.controller) 56 s.mockWriter = mock.NewMockImportKV_WriteEngineClient(s.controller) 57 importer := NewMockImporter(s.mockClient, testPDAddr) 58 59 s.ctx = context.Background() 60 engineUUID := uuid.MustParse("7e3f3a3c-67ce-506d-af34-417ec138fbcb") 61 s.engineUUID = engineUUID[:] 62 s.kvPairs = kv.MakeRowsFromKvPairs([]common.KvPair{ 63 { 64 Key: []byte("k1"), 65 Val: []byte("v1"), 66 }, 67 { 68 Key: []byte("k2"), 69 Val: []byte("v2"), 70 }, 71 }) 72 73 s.mockClient.EXPECT(). 74 OpenEngine(s.ctx, &kvpb.OpenEngineRequest{Uuid: s.engineUUID}). 75 Return(nil, nil) 76 77 var err error 78 s.engine, err = importer.OpenEngine(s.ctx, &backend.EngineConfig{}, "`db`.`table`", -1) 79 c.Assert(err, IsNil) 80 } 81 82 func (s *importerSuite) tearDownTest() { 83 s.controller.Finish() 84 } 85 86 func (s *importerSuite) TestWriteRows(c *C) { 87 s.setUpTest(c) 88 defer s.tearDownTest() 89 90 s.mockClient.EXPECT().WriteEngine(s.ctx).Return(s.mockWriter, nil) 91 92 headSendCall := s.mockWriter.EXPECT(). 93 Send(&kvpb.WriteEngineRequest{ 94 Chunk: &kvpb.WriteEngineRequest_Head{ 95 Head: &kvpb.WriteHead{Uuid: s.engineUUID}, 96 }, 97 }). 98 Return(nil) 99 batchSendCall := s.mockWriter.EXPECT(). 100 Send(gomock.Any()). 101 DoAndReturn(func(x *kvpb.WriteEngineRequest) error { 102 c.Assert(x.GetBatch().GetMutations(), DeepEquals, []*kvpb.Mutation{ 103 {Op: kvpb.Mutation_Put, Key: []byte("k1"), Value: []byte("v1")}, 104 {Op: kvpb.Mutation_Put, Key: []byte("k2"), Value: []byte("v2")}, 105 }) 106 return nil 107 }). 108 After(headSendCall) 109 s.mockWriter.EXPECT(). 110 CloseAndRecv(). 111 Return(nil, nil). 112 After(batchSendCall) 113 114 writer, err := s.engine.LocalWriter(s.ctx, nil) 115 c.Assert(err, IsNil) 116 err = writer.WriteRows(s.ctx, nil, s.kvPairs) 117 c.Assert(err, IsNil) 118 st, err := writer.Close(s.ctx) 119 c.Assert(err, IsNil) 120 c.Assert(st, IsNil) 121 } 122 123 func (s *importerSuite) TestWriteHeadSendFailed(c *C) { 124 s.setUpTest(c) 125 defer s.tearDownTest() 126 127 s.mockClient.EXPECT().WriteEngine(s.ctx).Return(s.mockWriter, nil) 128 129 headSendCall := s.mockWriter.EXPECT(). 130 Send(gomock.Any()). 131 DoAndReturn(func(x *kvpb.WriteEngineRequest) error { 132 c.Assert(x.GetHead(), NotNil) 133 return errors.Annotate(context.Canceled, "fake unrecoverable write head error") 134 }) 135 s.mockWriter.EXPECT(). 136 CloseAndRecv(). 137 Return(nil, errors.Annotate(context.Canceled, "fake unrecoverable close stream error")). 138 After(headSendCall) 139 140 writer, err := s.engine.LocalWriter(s.ctx, nil) 141 c.Assert(err, IsNil) 142 err = writer.WriteRows(s.ctx, nil, s.kvPairs) 143 c.Assert(err, ErrorMatches, "fake unrecoverable write head error.*") 144 } 145 146 func (s *importerSuite) TestWriteBatchSendFailed(c *C) { 147 s.setUpTest(c) 148 defer s.tearDownTest() 149 150 s.mockClient.EXPECT().WriteEngine(s.ctx).Return(s.mockWriter, nil) 151 152 headSendCall := s.mockWriter.EXPECT(). 153 Send(gomock.Any()). 154 DoAndReturn(func(x *kvpb.WriteEngineRequest) error { 155 c.Assert(x.GetHead(), NotNil) 156 return nil 157 }) 158 batchSendCall := s.mockWriter.EXPECT(). 159 Send(gomock.Any()). 160 DoAndReturn(func(x *kvpb.WriteEngineRequest) error { 161 c.Assert(x.GetBatch(), NotNil) 162 return errors.Annotate(context.Canceled, "fake unrecoverable write batch error") 163 }). 164 After(headSendCall) 165 s.mockWriter.EXPECT(). 166 CloseAndRecv(). 167 Return(nil, errors.Annotate(context.Canceled, "fake unrecoverable close stream error")). 168 After(batchSendCall) 169 170 writer, err := s.engine.LocalWriter(s.ctx, nil) 171 c.Assert(err, IsNil) 172 err = writer.WriteRows(s.ctx, nil, s.kvPairs) 173 c.Assert(err, ErrorMatches, "fake unrecoverable write batch error.*") 174 } 175 176 func (s *importerSuite) TestWriteCloseFailed(c *C) { 177 s.setUpTest(c) 178 defer s.tearDownTest() 179 180 s.mockClient.EXPECT().WriteEngine(s.ctx).Return(s.mockWriter, nil) 181 182 headSendCall := s.mockWriter.EXPECT(). 183 Send(gomock.Any()). 184 DoAndReturn(func(x *kvpb.WriteEngineRequest) error { 185 c.Assert(x.GetHead(), NotNil) 186 return nil 187 }) 188 batchSendCall := s.mockWriter.EXPECT(). 189 Send(gomock.Any()). 190 DoAndReturn(func(x *kvpb.WriteEngineRequest) error { 191 c.Assert(x.GetBatch(), NotNil) 192 return nil 193 }). 194 After(headSendCall) 195 s.mockWriter.EXPECT(). 196 CloseAndRecv(). 197 Return(nil, errors.Annotate(context.Canceled, "fake unrecoverable close stream error")). 198 After(batchSendCall) 199 200 writer, err := s.engine.LocalWriter(s.ctx, nil) 201 c.Assert(err, IsNil) 202 err = writer.WriteRows(s.ctx, nil, s.kvPairs) 203 c.Assert(err, ErrorMatches, "fake unrecoverable close stream error.*") 204 } 205 206 func (s *importerSuite) TestCloseImportCleanupEngine(c *C) { 207 s.setUpTest(c) 208 defer s.tearDownTest() 209 210 s.mockClient.EXPECT(). 211 CloseEngine(s.ctx, &kvpb.CloseEngineRequest{Uuid: s.engineUUID}). 212 Return(nil, nil) 213 s.mockClient.EXPECT(). 214 ImportEngine(s.ctx, &kvpb.ImportEngineRequest{Uuid: s.engineUUID, PdAddr: testPDAddr}). 215 Return(nil, nil) 216 s.mockClient.EXPECT(). 217 CleanupEngine(s.ctx, &kvpb.CleanupEngineRequest{Uuid: s.engineUUID}). 218 Return(nil, nil) 219 220 engine, err := s.engine.Close(s.ctx, nil) 221 c.Assert(err, IsNil) 222 err = engine.Import(s.ctx) 223 c.Assert(err, IsNil) 224 err = engine.Cleanup(s.ctx) 225 c.Assert(err, IsNil) 226 } 227 228 func BenchmarkMutationAlloc(b *testing.B) { 229 var g *kvpb.Mutation 230 for i := 0; i < b.N; i++ { 231 m := &kvpb.Mutation{ 232 Op: kvpb.Mutation_Put, 233 Key: nil, 234 Value: nil, 235 } 236 g = m 237 } 238 239 _ = g 240 } 241 242 func BenchmarkMutationPool(b *testing.B) { 243 p := sync.Pool{ 244 New: func() interface{} { 245 return &kvpb.Mutation{} 246 }, 247 } 248 var g *kvpb.Mutation 249 250 for i := 0; i < b.N; i++ { 251 m := p.Get().(*kvpb.Mutation) 252 m.Op = kvpb.Mutation_Put 253 m.Key = nil 254 m.Value = nil 255 256 g = m 257 258 p.Put(m) 259 } 260 261 _ = g 262 } 263 264 func (s *importerSuite) TestCheckTiDBVersion(c *C) { 265 var version string 266 ctx := context.Background() 267 268 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 269 c.Assert(req.URL.Path, Equals, "/status") 270 w.WriteHeader(http.StatusOK) 271 err := json.NewEncoder(w).Encode(map[string]interface{}{ 272 "version": version, 273 }) 274 c.Assert(err, IsNil) 275 })) 276 277 tls := common.NewTLSFromMockServer(mockServer) 278 279 version = "5.7.25-TiDB-v4.0.0" 280 c.Assert(checkTiDBVersionByTLS(ctx, tls, requiredMinTiDBVersion, requiredMaxTiDBVersion), IsNil) 281 282 version = "5.7.25-TiDB-v9999.0.0" 283 c.Assert(checkTiDBVersionByTLS(ctx, tls, requiredMinTiDBVersion, requiredMaxTiDBVersion), ErrorMatches, "TiDB version too new.*") 284 285 version = "5.7.25-TiDB-v6.0.0" 286 c.Assert(checkTiDBVersionByTLS(ctx, tls, requiredMinTiDBVersion, requiredMaxTiDBVersion), ErrorMatches, "TiDB version too new.*") 287 288 version = "5.7.25-TiDB-v6.0.0-beta" 289 c.Assert(checkTiDBVersionByTLS(ctx, tls, requiredMinTiDBVersion, requiredMaxTiDBVersion), ErrorMatches, "TiDB version too new.*") 290 291 version = "5.7.25-TiDB-v1.0.0" 292 c.Assert(checkTiDBVersionByTLS(ctx, tls, requiredMinTiDBVersion, requiredMaxTiDBVersion), ErrorMatches, "TiDB version too old.*") 293 }