package services import ( "context" "errors" "testing" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer" grpcService "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/services/tree" "github.com/stretchr/testify/require" "go.uber.org/zap/zaptest" ) type treeClientMock struct { address string err bool } func (t *treeClientMock) TreeClient(context.Context) (grpcService.TreeServiceClient, error) { if t.err { return nil, errors.New("error") } return nil, nil } func (t *treeClientMock) Address() string { return t.address } func TestHandleError(t *testing.T) { defaultError := errors.New("default error") for _, tc := range []struct { err error expectedError error }{ { err: defaultError, expectedError: defaultError, }, { err: errors.New("something not found"), expectedError: layer.ErrNodeNotFound, }, { err: errors.New("something is denied by some acl rule"), expectedError: layer.ErrNodeAccessDenied, }, } { t.Run("", func(t *testing.T) { err := handleError("err message", tc.err) require.True(t, errors.Is(err, tc.expectedError)) }) } } func TestRetry(t *testing.T) { ctx := context.Background() log := zaptest.NewLogger(t) cl := &ServiceClientGRPC{ log: zaptest.NewLogger(t), clients: []TreeClient{ &treeClientMock{address: "node0"}, &treeClientMock{address: "node1"}, &treeClientMock{address: "node2"}, &treeClientMock{address: "node3"}, }, } makeFn := func(client grpcService.TreeServiceClient) error { return nil } t.Run("first ok", func(t *testing.T) { err := cl.requestWithRetry(ctx, log, makeFn) require.NoError(t, err) require.Equal(t, 0, cl.getStartIndex()) resetClients(cl) }) t.Run("first failed", func(t *testing.T) { setErrors(cl.clients[:1]) err := cl.requestWithRetry(ctx, log, makeFn) require.NoError(t, err) require.Equal(t, 1, cl.getStartIndex()) resetClients(cl) }) t.Run("all failed", func(t *testing.T) { setErrors(cl.clients) err := cl.requestWithRetry(ctx, log, makeFn) require.Error(t, err) require.Equal(t, 0, cl.getStartIndex()) resetClients(cl) }) t.Run("round", func(t *testing.T) { setErrors(cl.clients[:2]) err := cl.requestWithRetry(ctx, log, makeFn) require.NoError(t, err) require.Equal(t, 2, cl.getStartIndex()) resetClientsErrors(cl) setErrors(cl.clients[2:]) err = cl.requestWithRetry(ctx, log, makeFn) require.NoError(t, err) require.Equal(t, 0, cl.getStartIndex()) resetClients(cl) }) } func resetClients(cl *ServiceClientGRPC) { resetClientsErrors(cl) cl.setStartIndex(0) } func resetClientsErrors(cl *ServiceClientGRPC) { for _, client := range cl.clients { node := client.(*treeClientMock) node.err = false } } func setErrors(clients []TreeClient) { for _, client := range clients { node := client.(*treeClientMock) node.err = true } }