File: cache_with_err_test.go

package info (click to toggle)
gitlab-agent 16.11.5-1
  • links: PTS, VCS
  • area: contrib
  • in suites: experimental
  • size: 7,072 kB
  • sloc: makefile: 193; sh: 55; ruby: 3
file content (117 lines) | stat: -rw-r--r-- 3,425 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
package cache

import (
	"context"
	"errors"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v16/internal/tool/testing/mock_cache"
	"go.opentelemetry.io/otel/trace/noop"
	"go.uber.org/mock/gomock"
)

func TestGetItem_HappyPath(t *testing.T) {
	ctrl := gomock.NewController(t)
	errCacher := mock_cache.NewMockErrCacher[int](ctrl)
	errCacher.EXPECT().GetError(gomock.Any(), key)
	tracer := noop.NewTracerProvider().Tracer("")
	c := NewWithError[int, int](time.Minute, time.Minute, errCacher, tracer, alwaysCache)
	item, err := c.GetItem(context.Background(), key, func() (int, error) {
		return itemVal, nil
	})
	require.NoError(t, err)
	assert.Equal(t, itemVal, item)

	item, err = c.GetItem(context.Background(), key, func() (int, error) {
		t.FailNow()
		return 0, nil
	})
	require.NoError(t, err)
	assert.Equal(t, itemVal, item)
}

func TestGetItem_CacheableError(t *testing.T) {
	ctrl := gomock.NewController(t)
	errCacher := mock_cache.NewMockErrCacher[int](ctrl)
	errToCache := errors.New("boom")
	gomock.InOrder(
		errCacher.EXPECT().
			GetError(gomock.Any(), key),
		errCacher.EXPECT().
			CacheError(gomock.Any(), key, errToCache, gomock.Cond(func(errTtl any) bool {
				errTTL := errTtl.(time.Duration)
				return errTTL >= time.Minute && errTTL <= time.Duration(float64(errTTL)*(1+(errTTLJitterPercent/100)))
			})),
		errCacher.EXPECT().
			GetError(gomock.Any(), key).
			Return(errToCache),
	)
	tracer := noop.NewTracerProvider().Tracer("")
	c := NewWithError[int, int](time.Second, time.Minute, errCacher, tracer, alwaysCache)
	_, err := c.GetItem(context.Background(), key, func() (int, error) {
		return 0, errToCache
	})
	assert.EqualError(t, err, "boom")

	_, err = c.GetItem(context.Background(), key, func() (int, error) {
		t.FailNow()
		return 0, nil
	})
	assert.EqualError(t, err, "boom")
}

func TestGetItem_NonCacheableError(t *testing.T) {
	ctrl := gomock.NewController(t)
	errCacher := mock_cache.NewMockErrCacher[int](ctrl)
	errCacher.EXPECT().
		GetError(gomock.Any(), key).
		Times(2)
	tracer := noop.NewTracerProvider().Tracer("")
	c := NewWithError[int, int](time.Minute, time.Minute, errCacher, tracer, func(err error) bool {
		return false
	})
	_, err := c.GetItem(context.Background(), key, func() (int, error) {
		return 0, errors.New("boom")
	})
	assert.EqualError(t, err, "boom")

	_, err = c.GetItem(context.Background(), key, func() (int, error) {
		return 0, errors.New("bAAm")
	})
	assert.EqualError(t, err, "bAAm")
}

func TestGetItem_Context(t *testing.T) {
	ctrl := gomock.NewController(t)
	errCacher := mock_cache.NewMockErrCacher[int](ctrl)
	errCacher.EXPECT().GetError(gomock.Any(), key)
	tracer := noop.NewTracerProvider().Tracer("")
	c := NewWithError[int, int](time.Minute, time.Minute, errCacher, tracer, alwaysCache)
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	start := make(chan struct{})
	done := make(chan struct{})
	go func() {
		defer close(done)
		<-start
		_, err := c.GetItem(ctx, key, func() (int, error) {
			return -itemVal, nil
		})
		assert.Equal(t, context.Canceled, err)
	}()
	item, err := c.GetItem(context.Background(), key, func() (int, error) {
		close(start)
		cancel()
		<-done
		return itemVal, nil
	})
	require.NoError(t, err)
	assert.Equal(t, itemVal, item)
}

func alwaysCache(err error) bool {
	return true
}