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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
package redistool
import (
"context"
"errors"
"testing"
"time"
"github.com/golang/mock/gomock"
rmock "github.com/redis/rueidis/mock"
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v16/internal/tool/testing/matcher"
"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v16/internal/tool/testing/mock_tool"
"go.uber.org/zap/zaptest"
)
const (
errKey = "test1"
)
func TestErrCacher_GetError_ReturnsNilOnClientError(t *testing.T) {
ec, client, rep := setupNormal(t)
client.EXPECT().
Do(gomock.Any(), rmock.Match("GET", errKey)).
Return(rmock.ErrorResult(errors.New("boom")))
rep.EXPECT().
HandleProcessingError(gomock.Any(), gomock.Any(), "Failed to get cached error from Redis", matcher.ErrorEq("boom"))
err := ec.GetError(context.Background(), errKey)
require.NoError(t, err)
}
func TestErrCacher_GetError_ReturnsNilOnClientNil(t *testing.T) {
ec, client, _ := setupNormal(t)
client.EXPECT().
Do(gomock.Any(), rmock.Match("GET", errKey)).
Return(rmock.Result(rmock.RedisNil()))
err := ec.GetError(context.Background(), errKey)
require.NoError(t, err)
}
func TestErrCacher_GetError_ReturnsNilOnEmptyResponse(t *testing.T) {
ec, client, _ := setupNormal(t)
client.EXPECT().
Do(gomock.Any(), rmock.Match("GET", errKey)).
Return(rmock.Result(rmock.RedisString("")))
err := ec.GetError(context.Background(), errKey)
require.NoError(t, err)
}
func TestErrCacher_GetError_ReturnsNilOnUnmarshalFail(t *testing.T) {
ec, client, rep := setupError(t)
client.EXPECT().
Do(gomock.Any(), rmock.Match("GET", errKey)).
Return(rmock.Result(rmock.RedisString("boom")))
rep.EXPECT().
HandleProcessingError(gomock.Any(), gomock.Any(), "Failed to unmarshal cached error", matcher.ErrorEq("unmarshal error"))
err := ec.GetError(context.Background(), errKey)
require.NoError(t, err)
}
func TestErrCacher_GetError_ReturnsCachedError(t *testing.T) {
ec, client, _ := setupNormal(t)
client.EXPECT().
Do(gomock.Any(), rmock.Match("GET", errKey)).
Return(rmock.Result(rmock.RedisString("boom")))
err := ec.GetError(context.Background(), errKey)
require.EqualError(t, err, "boom")
}
func TestErrCacher_CacheError_HappyPath(t *testing.T) {
ec, client, _ := setupNormal(t)
client.EXPECT().
Do(gomock.Any(), rmock.Match("SET", errKey, "boom", "PX", "60000"))
ec.CacheError(context.Background(), errKey, errors.New("boom"), time.Minute)
}
func TestErrCacher_CacheError_MarshalError(t *testing.T) {
ec, _, rep := setupError(t)
rep.EXPECT().
HandleProcessingError(gomock.Any(), gomock.Any(), "Failed to marshal error for caching", matcher.ErrorEq("marshal error"))
ec.CacheError(context.Background(), errKey, errors.New("boom"), time.Minute)
}
func setupNormal(t *testing.T) (*ErrCacher[string], *rmock.Client, *mock_tool.MockErrReporter) {
ctrl := gomock.NewController(t)
client := rmock.NewClient(ctrl)
rep := mock_tool.NewMockErrReporter(ctrl)
ec := &ErrCacher[string]{
Log: zaptest.NewLogger(t),
ErrRep: rep,
Client: client,
ErrMarshaler: testErrMarshaler{
marshal: func(err error) ([]byte, error) {
return []byte(err.Error()), nil
},
unmarshal: func(data []byte) (error, error) {
return errors.New(string(data)), nil
},
},
KeyToRedisKey: func(key string) string {
return key
},
}
return ec, client, rep
}
func setupError(t *testing.T) (*ErrCacher[string], *rmock.Client, *mock_tool.MockErrReporter) {
ctrl := gomock.NewController(t)
client := rmock.NewClient(ctrl)
rep := mock_tool.NewMockErrReporter(ctrl)
ec := &ErrCacher[string]{
Log: zaptest.NewLogger(t),
ErrRep: rep,
Client: client,
ErrMarshaler: testErrMarshaler{
marshal: func(err error) ([]byte, error) {
return nil, errors.New("marshal error")
},
unmarshal: func(data []byte) (error, error) {
return nil, errors.New("unmarshal error")
},
},
KeyToRedisKey: func(key string) string {
return key
},
}
return ec, client, rep
}
type testErrMarshaler struct {
marshal func(err error) ([]byte, error)
unmarshal func(data []byte) (error, error)
}
func (m testErrMarshaler) Marshal(err error) ([]byte, error) {
return m.marshal(err)
}
func (m testErrMarshaler) Unmarshal(data []byte) (error, error) {
return m.unmarshal(data)
}
|