forked from pingcap/br
-
Notifications
You must be signed in to change notification settings - Fork 0
/
backoff_test.go
117 lines (105 loc) · 3.06 KB
/
backoff_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0.
package restore_test
import (
"context"
"time"
. "github.com/pingcap/check"
"github.com/pingcap/tidb/util/testleak"
"go.uber.org/multierr"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
berrors "github.com/pingcap/br/pkg/errors"
"github.com/pingcap/br/pkg/mock"
"github.com/pingcap/br/pkg/restore"
"github.com/pingcap/br/pkg/utils"
)
var _ = Suite(&testBackofferSuite{})
type testBackofferSuite struct {
mock *mock.Cluster
}
func (s *testBackofferSuite) SetUpSuite(c *C) {
var err error
s.mock, err = mock.NewCluster()
c.Assert(err, IsNil)
}
func (s *testBackofferSuite) TearDownSuite(c *C) {
testleak.AfterTest(c)()
}
func (s *testBackofferSuite) TestBackoffWithSuccess(c *C) {
var counter int
backoffer := restore.NewBackoffer(10, time.Nanosecond, time.Nanosecond)
err := utils.WithRetry(context.Background(), func() error {
defer func() { counter++ }()
switch counter {
case 0:
return status.Error(codes.Unavailable, "transport is closing")
case 1:
return berrors.ErrKVEpochNotMatch
case 2:
return nil
}
return nil
}, backoffer)
c.Assert(counter, Equals, 3)
c.Assert(err, IsNil)
}
func (s *testBackofferSuite) TestBackoffWithFatalError(c *C) {
var counter int
backoffer := restore.NewBackoffer(10, time.Nanosecond, time.Nanosecond)
gRPCError := status.Error(codes.Unavailable, "transport is closing")
err := utils.WithRetry(context.Background(), func() error {
defer func() { counter++ }()
switch counter {
case 0:
return gRPCError // nolint:wrapcheck
case 1:
return berrors.ErrKVEpochNotMatch
case 2:
return berrors.ErrKVDownloadFailed
case 3:
return berrors.ErrKVRangeIsEmpty
}
return nil
}, backoffer)
c.Assert(counter, Equals, 4)
c.Assert(multierr.Errors(err), DeepEquals, []error{
gRPCError,
berrors.ErrKVEpochNotMatch,
berrors.ErrKVDownloadFailed,
berrors.ErrKVRangeIsEmpty,
})
}
func (s *testBackofferSuite) TestBackoffWithFatalRawGRPCError(c *C) {
var counter int
canceledError := status.Error(codes.Canceled, "context canceled")
backoffer := restore.NewBackoffer(10, time.Nanosecond, time.Nanosecond)
err := utils.WithRetry(context.Background(), func() error {
defer func() { counter++ }()
return canceledError // nolint:wrapcheck
}, backoffer)
c.Assert(counter, Equals, 1)
c.Assert(multierr.Errors(err), DeepEquals, []error{
canceledError,
})
}
func (s *testBackofferSuite) TestBackoffWithRetryableError(c *C) {
var counter int
backoffer := restore.NewBackoffer(10, time.Nanosecond, time.Nanosecond)
err := utils.WithRetry(context.Background(), func() error {
defer func() { counter++ }()
return berrors.ErrKVEpochNotMatch
}, backoffer)
c.Assert(counter, Equals, 10)
c.Assert(multierr.Errors(err), DeepEquals, []error{
berrors.ErrKVEpochNotMatch,
berrors.ErrKVEpochNotMatch,
berrors.ErrKVEpochNotMatch,
berrors.ErrKVEpochNotMatch,
berrors.ErrKVEpochNotMatch,
berrors.ErrKVEpochNotMatch,
berrors.ErrKVEpochNotMatch,
berrors.ErrKVEpochNotMatch,
berrors.ErrKVEpochNotMatch,
berrors.ErrKVEpochNotMatch,
})
}