File: err_cacher_test.go

package info (click to toggle)
gitlab-agent 16.1.3-2
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid, trixie
  • size: 6,324 kB
  • sloc: makefile: 175; sh: 52; ruby: 3
file content (141 lines) | stat: -rw-r--r-- 4,277 bytes parent folder | download
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)
}