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