github.com/Jeffail/benthos/v3@v3.65.0/lib/output/writer/cache_test.go (about) 1 package writer 2 3 import ( 4 "errors" 5 "net/http" 6 "testing" 7 "time" 8 9 "github.com/Jeffail/benthos/v3/lib/log" 10 "github.com/Jeffail/benthos/v3/lib/message" 11 "github.com/Jeffail/benthos/v3/lib/metrics" 12 "github.com/Jeffail/benthos/v3/lib/types" 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func TestCacheSingle(t *testing.T) { 18 c := &basicCache{ 19 values: map[string]string{}, 20 } 21 22 mgr := &fakeMgr{ 23 caches: map[string]types.Cache{ 24 "foocache": c, 25 }, 26 } 27 28 conf := NewCacheConfig() 29 conf.Key = `${!json("id")}` 30 conf.Target = "foocache" 31 32 w, err := NewCache(conf, mgr, log.Noop(), metrics.Noop()) 33 require.NoError(t, err) 34 35 require.NoError(t, w.Write(message.New([][]byte{ 36 []byte(`{"id":"1","value":"first"}`), 37 }))) 38 39 assert.Equal(t, map[string]string{ 40 "1": `{"id":"1","value":"first"}`, 41 }, c.values) 42 } 43 44 func TestCacheBatch(t *testing.T) { 45 c := &basicCache{ 46 values: map[string]string{}, 47 } 48 49 mgr := &fakeMgr{ 50 caches: map[string]types.Cache{ 51 "foocache": c, 52 }, 53 } 54 55 conf := NewCacheConfig() 56 conf.Key = `${!json("id")}` 57 conf.Target = "foocache" 58 59 w, err := NewCache(conf, mgr, log.Noop(), metrics.Noop()) 60 require.NoError(t, err) 61 62 require.NoError(t, w.Write(message.New([][]byte{ 63 []byte(`{"id":"1","value":"first"}`), 64 []byte(`{"id":"2","value":"second"}`), 65 []byte(`{"id":"3","value":"third"}`), 66 []byte(`{"id":"4","value":"fourth"}`), 67 }))) 68 69 assert.Equal(t, map[string]string{ 70 "1": `{"id":"1","value":"first"}`, 71 "2": `{"id":"2","value":"second"}`, 72 "3": `{"id":"3","value":"third"}`, 73 "4": `{"id":"4","value":"fourth"}`, 74 }, c.values) 75 } 76 77 func TestCacheSingleTTL(t *testing.T) { 78 c := &ttlCache{ 79 values: map[string]ttlCacheItem{}, 80 } 81 82 mgr := &fakeMgr{ 83 caches: map[string]types.Cache{ 84 "foocache": c, 85 }, 86 } 87 88 conf := NewCacheConfig() 89 conf.Key = `${!json("id")}` 90 conf.Target = "foocache" 91 conf.TTL = "2s" 92 93 w, err := NewCache(conf, mgr, log.Noop(), metrics.Noop()) 94 require.NoError(t, err) 95 96 require.NoError(t, w.Write(message.New([][]byte{ 97 []byte(`{"id":"1","value":"first"}`), 98 }))) 99 100 twosec := time.Second * 2 101 102 assert.Equal(t, map[string]ttlCacheItem{ 103 "1": { 104 value: `{"id":"1","value":"first"}`, 105 ttl: &twosec, 106 }, 107 }, c.values) 108 } 109 110 func TestCacheBatchTTL(t *testing.T) { 111 c := &ttlCache{ 112 values: map[string]ttlCacheItem{}, 113 } 114 115 mgr := &fakeMgr{ 116 caches: map[string]types.Cache{ 117 "foocache": c, 118 }, 119 } 120 121 conf := NewCacheConfig() 122 conf.Key = `${!json("id")}` 123 conf.Target = "foocache" 124 conf.TTL = "2s" 125 126 w, err := NewCache(conf, mgr, log.Noop(), metrics.Noop()) 127 require.NoError(t, err) 128 129 require.NoError(t, w.Write(message.New([][]byte{ 130 []byte(`{"id":"1","value":"first"}`), 131 []byte(`{"id":"2","value":"second"}`), 132 []byte(`{"id":"3","value":"third"}`), 133 []byte(`{"id":"4","value":"fourth"}`), 134 }))) 135 136 twosec := time.Second * 2 137 138 assert.Equal(t, map[string]ttlCacheItem{ 139 "1": { 140 value: `{"id":"1","value":"first"}`, 141 ttl: &twosec, 142 }, 143 "2": { 144 value: `{"id":"2","value":"second"}`, 145 ttl: &twosec, 146 }, 147 "3": { 148 value: `{"id":"3","value":"third"}`, 149 ttl: &twosec, 150 }, 151 "4": { 152 value: `{"id":"4","value":"fourth"}`, 153 ttl: &twosec, 154 }, 155 }, c.values) 156 } 157 158 //------------------------------------------------------------------------------ 159 160 type fakeMgr struct { 161 caches map[string]types.Cache 162 ratelimits map[string]types.RateLimit 163 } 164 165 func (f *fakeMgr) RegisterEndpoint(path, desc string, h http.HandlerFunc) { 166 } 167 func (f *fakeMgr) GetCache(name string) (types.Cache, error) { 168 if c, exists := f.caches[name]; exists { 169 return c, nil 170 } 171 return nil, types.ErrCacheNotFound 172 } 173 func (f *fakeMgr) GetCondition(name string) (types.Condition, error) { 174 return nil, types.ErrConditionNotFound 175 } 176 func (f *fakeMgr) GetRateLimit(name string) (types.RateLimit, error) { 177 if r, exists := f.ratelimits[name]; exists { 178 return r, nil 179 } 180 return nil, types.ErrRateLimitNotFound 181 } 182 func (f *fakeMgr) GetPlugin(name string) (interface{}, error) { 183 return nil, types.ErrPluginNotFound 184 } 185 func (f *fakeMgr) GetPipe(name string) (<-chan types.Transaction, error) { 186 return nil, types.ErrPipeNotFound 187 } 188 func (f *fakeMgr) SetPipe(name string, prod <-chan types.Transaction) {} 189 func (f *fakeMgr) UnsetPipe(name string, prod <-chan types.Transaction) {} 190 191 //------------------------------------------------------------------------------ 192 193 type basicCache struct { 194 values map[string]string 195 } 196 197 func (b *basicCache) Get(key string) ([]byte, error) { 198 return nil, errors.New("not implemented") 199 } 200 201 func (b *basicCache) Set(key string, value []byte) error { 202 b.values[key] = string(value) 203 return nil 204 } 205 206 func (b *basicCache) SetMulti(items map[string][]byte) error { 207 for k, v := range items { 208 b.values[k] = string(v) 209 } 210 return nil 211 } 212 213 func (b *basicCache) Add(key string, value []byte) error { 214 return errors.New("not implemented") 215 } 216 217 func (b *basicCache) Delete(key string) error { 218 return errors.New("not implemented") 219 } 220 221 func (b *basicCache) CloseAsync() {} 222 223 func (b *basicCache) WaitForClose(time.Duration) error { 224 return nil 225 } 226 227 //------------------------------------------------------------------------------ 228 229 type ttlCacheItem struct { 230 value string 231 ttl *time.Duration 232 } 233 234 type ttlCache struct { 235 values map[string]ttlCacheItem 236 } 237 238 func (t *ttlCache) Get(key string) ([]byte, error) { 239 return nil, errors.New("not implemented") 240 } 241 242 func (t *ttlCache) Set(key string, value []byte) error { 243 t.values[key] = ttlCacheItem{ 244 value: string(value), 245 } 246 return nil 247 } 248 249 func (t *ttlCache) SetWithTTL(key string, value []byte, ttl *time.Duration) error { 250 t.values[key] = ttlCacheItem{ 251 value: string(value), 252 ttl: ttl, 253 } 254 return nil 255 } 256 257 func (t *ttlCache) SetMulti(items map[string][]byte) error { 258 for k, v := range items { 259 t.values[k] = ttlCacheItem{ 260 value: string(v), 261 } 262 } 263 return nil 264 } 265 266 func (t *ttlCache) SetMultiWithTTL(items map[string]types.CacheTTLItem) error { 267 for k, v := range items { 268 t.values[k] = ttlCacheItem{ 269 value: string(v.Value), 270 ttl: v.TTL, 271 } 272 } 273 return nil 274 } 275 276 func (t *ttlCache) Add(key string, value []byte) error { 277 return errors.New("not implemented") 278 } 279 280 func (t *ttlCache) AddWithTTL(key string, value []byte, ttl *time.Duration) error { 281 return errors.New("not implemented") 282 } 283 284 func (t *ttlCache) Delete(key string) error { 285 return errors.New("not implemented") 286 } 287 288 func (t *ttlCache) CloseAsync() {} 289 290 func (t *ttlCache) WaitForClose(time.Duration) error { 291 return nil 292 }