From 51f2eb4c6c0c06be42403f7a438afbcda14d2e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=B1=E5=B2=9A?= <36239017+YuJuncen@users.noreply.github.com> Date: Wed, 23 Mar 2022 13:44:32 +0800 Subject: [PATCH 1/2] cherry pick #33313 to release-5.3 Signed-off-by: ti-srebot --- br/pkg/restore/split_test.go | 136 +++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/br/pkg/restore/split_test.go b/br/pkg/restore/split_test.go index 7a39785af2cb9..17ffec55813c2 100644 --- a/br/pkg/restore/split_test.go +++ b/br/pkg/restore/split_test.go @@ -434,6 +434,7 @@ func (s *testRangeSuite) TestNeedSplit(c *C) { }, }, } +<<<<<<< HEAD // Out of region c.Assert(restore.NeedSplit([]byte("a"), regions), IsNil) // Region start key @@ -446,4 +447,139 @@ func (s *testRangeSuite) TestNeedSplit(c *C) { c.Assert(restore.NeedSplit([]byte("d"), regions), IsNil) // Out of region c.Assert(restore.NeedSplit([]byte("e"), regions), IsNil) +======= + for _, ca := range cases { + err := restore.CheckRegionConsistency(ca.startKey, ca.endKey, ca.regions) + require.Error(t, err) + require.Regexp(t, ca.err, err.Error()) + } +} + +type fakeRestorer struct { + mu sync.Mutex + + errorInSplit bool + splitRanges []rtree.Range + restoredFiles []*backuppb.File +} + +func (f *fakeRestorer) SplitRanges(ctx context.Context, ranges []rtree.Range, rewriteRules *restore.RewriteRules, updateCh glue.Progress, isRawKv bool) error { + f.mu.Lock() + defer f.mu.Unlock() + + if ctx.Err() != nil { + return ctx.Err() + } + f.splitRanges = append(f.splitRanges, ranges...) + if f.errorInSplit { + err := errors.Annotatef(berrors.ErrRestoreSplitFailed, + "the key space takes many efforts and finally get together, how dare you split them again... :<") + log.Error("error happens :3", logutil.ShortError(err)) + return err + } + return nil +} + +func (f *fakeRestorer) RestoreFiles(ctx context.Context, files []*backuppb.File, rewriteRules *restore.RewriteRules, updateCh glue.Progress) error { + f.mu.Lock() + defer f.mu.Unlock() + + if ctx.Err() != nil { + return ctx.Err() + } + f.restoredFiles = append(f.restoredFiles, files...) + err := errors.Annotatef(berrors.ErrRestoreWriteAndIngest, "the files to restore are taken by a hijacker, meow :3") + log.Error("error happens :3", logutil.ShortError(err)) + return err +} + +func fakeRanges(keys ...string) (r restore.DrainResult) { + for i := range keys { + if i+1 == len(keys) { + return + } + r.Ranges = append(r.Ranges, rtree.Range{ + StartKey: []byte(keys[i]), + EndKey: []byte(keys[i+1]), + Files: []*backuppb.File{{Name: "fake.sst"}}, + }) + } + return +} + +type errorInTimeSink struct { + ctx context.Context + errCh chan error + t *testing.T +} + +func (e errorInTimeSink) EmitTables(tables ...restore.CreatedTable) {} + +func (e errorInTimeSink) EmitError(err error) { + e.errCh <- err +} + +func (e errorInTimeSink) Close() {} + +func (e errorInTimeSink) Wait() { + select { + case <-e.ctx.Done(): + e.t.Logf("The context is canceled but no error happen") + e.t.FailNow() + case <-e.errCh: + } +} + +func assertErrorEmitInTime(ctx context.Context, t *testing.T) errorInTimeSink { + errCh := make(chan error, 1) + return errorInTimeSink{ + ctx: ctx, + errCh: errCh, + t: t, + } +} + +func TestRestoreFailed(t *testing.T) { + ranges := []restore.DrainResult{ + fakeRanges("aax", "abx", "abz"), + fakeRanges("abz", "bbz", "bcy"), + fakeRanges("bcy", "cad", "xxy"), + } + r := &fakeRestorer{} + sender, err := restore.NewTiKVSender(context.TODO(), r, nil, 1) + require.NoError(t, err) + dctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + sink := assertErrorEmitInTime(dctx, t) + sender.PutSink(sink) + for _, r := range ranges { + sender.RestoreBatch(r) + } + sink.Wait() + sink.Close() + sender.Close() + require.GreaterOrEqual(t, len(r.restoredFiles), 1) +} + +func TestSplitFailed(t *testing.T) { + ranges := []restore.DrainResult{ + fakeRanges("aax", "abx", "abz"), + fakeRanges("abz", "bbz", "bcy"), + fakeRanges("bcy", "cad", "xxy"), + } + r := &fakeRestorer{errorInSplit: true} + sender, err := restore.NewTiKVSender(context.TODO(), r, nil, 1) + require.NoError(t, err) + dctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + sink := assertErrorEmitInTime(dctx, t) + sender.PutSink(sink) + for _, r := range ranges { + sender.RestoreBatch(r) + } + sink.Wait() + sender.Close() + require.GreaterOrEqual(t, len(r.splitRanges), 2) + require.Len(t, r.restoredFiles, 0) +>>>>>>> e2ad790a2... br: fix race in test `Test(Split|Restore)Failed` (#33313) } From d3c1758832092a13250ead3516a5eb0e15882961 Mon Sep 17 00:00:00 2001 From: 3pointer Date: Fri, 17 Jun 2022 18:33:14 +0800 Subject: [PATCH 2/2] resolve conflict --- br/pkg/restore/split_test.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/br/pkg/restore/split_test.go b/br/pkg/restore/split_test.go index 2b4433a4da2ce..656f9a1c4aafc 100644 --- a/br/pkg/restore/split_test.go +++ b/br/pkg/restore/split_test.go @@ -467,13 +467,7 @@ func (s *testRangeSuite) testNeedSplit(c *C, isRawKv bool) { // Region end key c.Assert(restore.NeedSplit([]byte("d"), regions, isRawKv), IsNil) // Out of region - c.Assert(restore.NeedSplit([]byte("e"), regions), IsNil) - - for _, ca := range cases { - err := restore.CheckRegionConsistency(ca.startKey, ca.endKey, ca.regions) - require.Error(t, err) - require.Regexp(t, ca.err, err.Error()) - } + c.Assert(restore.NeedSplit([]byte("e"), regions, isRawKv), IsNil) } type fakeRestorer struct {