-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdriver_memory_test.go
More file actions
195 lines (154 loc) · 6.73 KB
/
Copy pathdriver_memory_test.go
File metadata and controls
195 lines (154 loc) · 6.73 KB
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package cache
import (
"context"
"errors"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewMemoryCache(t *testing.T) {
ctx := t.Context()
t.Run("NewMemoryCache creates cache with memory driver", func(t *testing.T) {
cache := NewMemoryCache[string](WithMemoryDefaultTTL(10 * time.Millisecond))
require.NotNil(t, cache, "NewMemoryCache should return non-nil cache")
// Verify it works
err := cache.Set(ctx, "test", "value", DefaultTTL)
require.NoError(t, err, "Set should work")
val, found, err := cache.Get(ctx, "test")
require.NoError(t, err, "Get should not return error")
assert.True(t, found, "Get should find the value")
assert.Equal(t, "value", val, "Get should return correct value")
})
t.Run("NewMemoryCache with options", func(t *testing.T) {
cache := NewMemoryCache[string](WithMemoryDefaultTTL(50 * time.Millisecond))
require.NotNil(t, cache, "NewMemoryCache should return non-nil cache")
// Set with default TTL and verify expiration
err := cache.Set(ctx, "expires", "value", DefaultTTL)
require.NoError(t, err, "Set should work")
time.Sleep(60 * time.Millisecond)
_, found, err := cache.Get(ctx, "expires")
require.NoError(t, err, "Get should not return error")
assert.False(t, found, "Value should expire after default TTL")
})
}
func TestMemoryCache(t *testing.T) {
ctx := t.Context()
// Create cache with 1 second default TTL
c := NewMemoryCache[string](WithMemoryDefaultTTL(10 * time.Millisecond))
// Test Set/Get with default TTL
t.Run("Set and Get with default TTL", func(t *testing.T) {
err := c.Set(ctx, "key1", "value1", DefaultTTL)
require.NoError(t, err, "Set failed")
val, found, err := c.Get(ctx, "key1")
require.NoError(t, err, "Get should not return error")
require.True(t, found, "Get should find the key")
assert.Equal(t, "value1", val, "Get should return correct value")
// Wait for expiration
time.Sleep(20 * time.Millisecond)
_, found, err = c.Get(ctx, "key1")
require.NoError(t, err, "Get should not return error")
assert.False(t, found, "Expected key to be expired")
})
// Test Set with custom TTL
t.Run("Set with custom TTL", func(t *testing.T) {
err := c.Set(ctx, "key2", "value2", WithTTL(20*time.Millisecond))
require.NoError(t, err, "Set failed")
// Should still exist after 10 milliseconds
time.Sleep(10 * time.Millisecond)
val, found, err := c.Get(ctx, "key2")
require.NoError(t, err, "Get should not return error")
require.True(t, found, "Get should find the key after 10ms")
assert.Equal(t, "value2", val, "Get should return correct value")
// Should expire after 30 milliseconds
time.Sleep(30 * time.Millisecond)
_, found, err = c.Get(ctx, "key2")
require.NoError(t, err, "Get should not return error")
assert.False(t, found, "Expected key to be expired")
})
// Test Set with Forever
t.Run("Set with Forever", func(t *testing.T) {
err := c.Set(ctx, "key3", "value3", Forever)
require.NoError(t, err, "Set failed")
// Should never expire
time.Sleep(20 * time.Millisecond)
val, found, err := c.Get(ctx, "key3")
require.NoError(t, err, "Get should not return error")
require.True(t, found, "Get should find the key")
assert.Equal(t, "value3", val, "Get should return correct value")
})
// Test Remember
t.Run("Remember", func(t *testing.T) {
fetchCount := 0
fetch := func(_ context.Context) (string, error) {
fetchCount++
return "computed", nil
}
// First call should fetch
val, err := c.Remember(ctx, "key4", WithTTL(10*time.Millisecond), fetch)
require.NoError(t, err, "Remember should not fail")
assert.Equal(t, "computed", val, "Remember should return correct value")
assert.Equal(t, 1, fetchCount, "Fetch should be called once")
// Second call should use cache
val, err = c.Remember(ctx, "key4", WithTTL(10*time.Millisecond), fetch)
require.NoError(t, err, "Remember should not fail")
assert.Equal(t, "computed", val, "Remember should return correct value")
assert.Equal(t, 1, fetchCount, "Fetch should not be called again (cached)")
time.Sleep(20 * time.Millisecond)
// After expiration, Remember should call fetch again and increase fetchCount
val, err = c.Remember(ctx, "key4", WithTTL(10*time.Millisecond), fetch)
require.NoError(t, err, "Remember should not fail after expiration")
assert.Equal(t, "computed", val, "Remember should return correct value")
assert.Equal(t, 2, fetchCount, "Fetch should be called again after expiration")
})
// Test Has
t.Run("Has", func(t *testing.T) {
err := c.Set(ctx, "exists", "yes", DefaultTTL)
require.NoError(t, err, "Set must not fail")
has, err := c.Has(ctx, "exists")
require.NoError(t, err, "Has should not return error")
assert.True(t, has, "Has should return true for existing key")
has, err = c.Has(ctx, "not-exists")
require.NoError(t, err, "Has should not return error")
assert.False(t, has, "Has should return false for non-existing key")
})
// Test Delete
t.Run("Delete", func(t *testing.T) {
err := c.Set(ctx, "to-delete", "value", DefaultTTL)
require.NoError(t, err, "Set must not fail")
has, err := c.Has(ctx, "to-delete")
require.NoError(t, err, "Has should not return error")
require.True(t, has, "Key should be set")
err = c.Delete(ctx, "to-delete")
require.NoError(t, err, "Delete should not fail")
has, err = c.Has(ctx, "to-delete")
require.NoError(t, err, "Has should not return error")
assert.False(t, has, "Key should not exist after delete")
})
}
func TestMemoryCacheRememberSetError(t *testing.T) {
ctx := t.Context()
// Create a memory cache
c := NewMemoryCache[string](WithMemoryDefaultTTL(10 * time.Millisecond))
// Test Remember with a fetch function that returns a value
fetch := func(_ context.Context) (string, error) {
return "test-value", nil
}
// This should work normally since memory cache Set operations don't fail
value, err := c.Remember(ctx, "test-key", DefaultTTL, fetch)
require.NoError(t, err, "Remember should not fail for memory cache")
assert.Equal(t, "test-value", value, "Remember should return correct value")
// Test that the value is cached
value, err = c.Remember(ctx, "test-key", DefaultTTL, func(_ context.Context) (string, error) {
t.Fatal("Fetch function should not be called when value is cached")
return "", nil
})
require.NoError(t, err, "Remember should not fail for cached value")
assert.Equal(t, "test-value", value, "Remember should return cached value")
// Test with a fetch function that returns an error
_, err = c.Remember(ctx, "error-key", DefaultTTL, func(_ context.Context) (string, error) {
return "", errors.New("fetch error")
})
require.Error(t, err, "Remember should fail when fetch function returns error")
assert.Contains(t, err.Error(), "fetch value", "Error should contain 'fetch value'")
}