2 Copyright (c) 2019 AT&T Intellectual Property.
3 Copyright (c) 2018-2019 Nokia.
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
9 http://www.apache.org/licenses/LICENSE-2.0
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
19 * This source code is part of the near-RT RIC (RAN Intelligent Controller)
20 * platform project (RICP).
23 package sdlgoredis_test
27 "gerrit.o-ran-sc.org/r/ric-plt/sdlgo/internal/sdlgoredis"
28 "github.com/go-redis/redis/v7"
29 "github.com/stretchr/testify/assert"
30 "github.com/stretchr/testify/mock"
36 type clientMock struct {
40 type pubSubMock struct {
48 func (m *pubSubMock) Channel() <-chan *redis.Message {
49 return m.Called().Get(0).(chan *redis.Message)
52 func (m *pubSubMock) Subscribe(channels ...string) error {
53 return m.Called().Error(0)
56 func (m *pubSubMock) Unsubscribe(channels ...string) error {
57 return m.Called().Error(0)
60 func (m *pubSubMock) Close() error {
61 return m.Called().Error(0)
64 func (m *clientMock) Command() *redis.CommandsInfoCmd {
65 return m.Called().Get(0).(*redis.CommandsInfoCmd)
68 func (m *clientMock) Close() error {
69 return m.Called().Error(0)
72 func (m *clientMock) Subscribe(channels ...string) *redis.PubSub {
73 return m.Called(channels).Get(0).(*redis.PubSub)
76 func (m *clientMock) MSet(pairs ...interface{}) *redis.StatusCmd {
77 return m.Called(pairs).Get(0).(*redis.StatusCmd)
80 func (m *clientMock) Do(args ...interface{}) *redis.Cmd {
81 return m.Called(args).Get(0).(*redis.Cmd)
84 func (m *clientMock) MGet(keys ...string) *redis.SliceCmd {
85 return m.Called(keys).Get(0).(*redis.SliceCmd)
88 func (m *clientMock) Del(keys ...string) *redis.IntCmd {
89 return m.Called(keys).Get(0).(*redis.IntCmd)
92 func (m *clientMock) Keys(pattern string) *redis.StringSliceCmd {
93 return m.Called(pattern).Get(0).(*redis.StringSliceCmd)
96 func (m *clientMock) SetNX(key string, value interface{}, expiration time.Duration) *redis.BoolCmd {
97 return m.Called(key, value, expiration).Get(0).(*redis.BoolCmd)
100 func (m *clientMock) SAdd(key string, members ...interface{}) *redis.IntCmd {
101 return m.Called(key, members).Get(0).(*redis.IntCmd)
104 func (m *clientMock) SRem(key string, members ...interface{}) *redis.IntCmd {
105 return m.Called(key, members).Get(0).(*redis.IntCmd)
108 func (m *clientMock) SMembers(key string) *redis.StringSliceCmd {
109 return m.Called(key).Get(0).(*redis.StringSliceCmd)
112 func (m *clientMock) SIsMember(key string, member interface{}) *redis.BoolCmd {
113 return m.Called(key, member).Get(0).(*redis.BoolCmd)
116 func (m *clientMock) SCard(key string) *redis.IntCmd {
117 return m.Called(key).Get(0).(*redis.IntCmd)
120 func (m *clientMock) PTTL(key string) *redis.DurationCmd {
121 return m.Called(key).Get(0).(*redis.DurationCmd)
124 func (m *clientMock) Eval(script string, keys []string, args ...interface{}) *redis.Cmd {
125 return m.Called(script, keys).Get(0).(*redis.Cmd)
128 func (m *clientMock) EvalSha(sha1 string, keys []string, args ...interface{}) *redis.Cmd {
129 return m.Called(sha1, keys, args).Get(0).(*redis.Cmd)
132 func (m *clientMock) ScriptExists(scripts ...string) *redis.BoolSliceCmd {
133 return m.Called(scripts).Get(0).(*redis.BoolSliceCmd)
136 func (m *clientMock) ScriptLoad(script string) *redis.StringCmd {
137 return m.Called(script).Get(0).(*redis.StringCmd)
140 func (m *clientMock) Info(section ...string) *redis.StringCmd {
141 return m.Called(section).Get(0).(*redis.StringCmd)
144 type MockRedisSentinel struct {
148 func (m *MockRedisSentinel) Master(name string) *redis.StringStringMapCmd {
150 return a.Get(0).(*redis.StringStringMapCmd)
152 func (m *MockRedisSentinel) Slaves(name string) *redis.SliceCmd {
154 return a.Get(0).(*redis.SliceCmd)
157 func setSubscribeNotifications() (*pubSubMock, sdlgoredis.SubscribeFn) {
158 mock := new(pubSubMock)
159 return mock, func(client sdlgoredis.RedisClient, channels ...string) sdlgoredis.Subscriber {
164 func (m *MockOS) Getenv(key string, defValue string) string {
165 a := m.Called(key, defValue)
169 type setupEv struct {
170 pubSubMock []*pubSubMock
171 rClient []*clientMock
172 rSentinel []*MockRedisSentinel
176 func setupHaEnv(commandsExists bool) (*pubSubMock, *clientMock, *sdlgoredis.DB) {
177 psm, cm, _, db := setupHaEnvWithSentinels(commandsExists)
181 func setupHaEnvWithSentinels(commandsExists bool) (*pubSubMock, *clientMock, []*MockRedisSentinel, *sdlgoredis.DB) {
182 setupVals := setupEnv(
184 "service-ricplt-dbaas-tcp-cluster-0.ricplt",
191 return setupVals.pubSubMock[0], setupVals.rClient[0], setupVals.rSentinel, setupVals.db[0]
194 func setupSingleEnv(commandsExists bool) (*pubSubMock, *clientMock, *sdlgoredis.DB) {
195 setupVals := setupEnv(
197 "service-ricplt-dbaas-tcp-cluster-0.ricplt",
198 "6376", "", "", "", "",
200 return setupVals.pubSubMock[0], setupVals.rClient[0], setupVals.db[0]
203 func setupEnv(commandsExists bool, host, port, msname, sntport, clsaddrlist, nodeCnt string) setupEv {
206 dummyCommandInfo := redis.CommandInfo{
210 cmdResult := make(map[string]*redis.CommandInfo, 0)
212 cmdResult = map[string]*redis.CommandInfo{
213 "setie": &dummyCommandInfo,
214 "delie": &dummyCommandInfo,
215 "setiepub": &dummyCommandInfo,
216 "setnxpub": &dummyCommandInfo,
217 "msetmpub": &dummyCommandInfo,
218 "delmpub": &dummyCommandInfo,
221 cmdResult = map[string]*redis.CommandInfo{
222 "dummy": &dummyCommandInfo,
226 osmock := new(MockOS)
227 osmock.On("Getenv", "DBAAS_SERVICE_HOST", "localhost").Return(host)
228 osmock.On("Getenv", "DBAAS_SERVICE_PORT", "6379").Return(port)
229 osmock.On("Getenv", "DBAAS_MASTER_NAME", "").Return(msname)
230 osmock.On("Getenv", "DBAAS_SERVICE_SENTINEL_PORT", "").Return(sntport)
231 osmock.On("Getenv", "DBAAS_CLUSTER_ADDR_LIST", "").Return(clsaddrlist)
232 osmock.On("Getenv", "DBAAS_SERVICE_NODE_COUNT", "").Return(nodeCnt)
234 pubSubMock, subscribeNotifications := setSubscribeNotifications()
235 smock := new(MockRedisSentinel)
236 ret.rSentinel = append(ret.rSentinel, smock)
237 clients := sdlgoredis.ReadConfigAndCreateDbClients(
239 func(addr, port, clusterName string, isHa bool) sdlgoredis.RedisClient {
240 clm := new(clientMock)
241 clm.On("Command").Return(redis.NewCommandsInfoCmdResult(cmdResult, nil))
242 ret.rClient = append(ret.rClient, clm)
243 ret.pubSubMock = append(ret.pubSubMock, pubSubMock)
246 subscribeNotifications,
247 func(cfg *sdlgoredis.Config, addr string) *sdlgoredis.Sentinel {
248 s := &sdlgoredis.Sentinel{
249 IredisSentinelClient: smock,
259 func TestCloseDbSuccessfully(t *testing.T) {
260 _, r, db := setupHaEnv(true)
261 r.On("Close").Return(nil)
264 r.AssertExpectations(t)
267 func TestCloseDbFailure(t *testing.T) {
268 _, r, db := setupHaEnv(true)
269 r.On("Close").Return(errors.New("Some error"))
271 assert.NotNil(t, err)
272 r.AssertExpectations(t)
275 func TestMSetSuccessfully(t *testing.T) {
276 _, r, db := setupHaEnv(true)
277 expectedKeysAndValues := []interface{}{"key1", "value1", "key2", 2}
278 r.On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
279 err := db.MSet("key1", "value1", "key2", 2)
281 r.AssertExpectations(t)
284 func TestMSetFailure(t *testing.T) {
285 _, r, db := setupHaEnv(true)
286 expectedKeysAndValues := []interface{}{"key1", "value1", "key2", 2}
287 r.On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", errors.New("Some error")))
288 err := db.MSet("key1", "value1", "key2", 2)
289 assert.NotNil(t, err)
290 r.AssertExpectations(t)
293 func TestMSetMPubSuccessfully(t *testing.T) {
294 _, r, db := setupHaEnv(true)
295 expectedMessage := []interface{}{"MSETMPUB", 2, 2, "key1", "val1", "key2", "val2",
296 "chan1", "event1", "chan2", "event2"}
297 r.On("Do", expectedMessage).Return(redis.NewCmdResult("", nil))
298 assert.Nil(t, db.MSetMPub([]string{"chan1", "event1", "chan2", "event2"},
299 "key1", "val1", "key2", "val2"))
300 r.AssertExpectations(t)
303 func TestMsetMPubFailure(t *testing.T) {
304 _, r, db := setupHaEnv(true)
305 expectedMessage := []interface{}{"MSETMPUB", 2, 2, "key1", "val1", "key2", "val2",
306 "chan1", "event1", "chan2", "event2"}
307 r.On("Do", expectedMessage).Return(redis.NewCmdResult("", errors.New("Some error")))
308 assert.NotNil(t, db.MSetMPub([]string{"chan1", "event1", "chan2", "event2"},
309 "key1", "val1", "key2", "val2"))
310 r.AssertExpectations(t)
313 func TestMSetMPubCommandMissing(t *testing.T) {
314 _, r, db := setupHaEnv(false)
315 expectedMessage := []interface{}{"MSETMPUB", 2, 2, "key1", "val1", "key2", "val2",
316 "chan1", "event1", "chan2", "event2"}
317 r.AssertNotCalled(t, "Do", expectedMessage)
318 assert.NotNil(t, db.MSetMPub([]string{"chan1", "event1", "chan2", "event2"},
319 "key1", "val1", "key2", "val2"))
320 r.AssertExpectations(t)
324 func TestMGetSuccessfully(t *testing.T) {
325 _, r, db := setupHaEnv(true)
326 expectedKeys := []string{"key1", "key2", "key3"}
327 expectedResult := []interface{}{"val1", 2, nil}
328 r.On("MGet", expectedKeys).Return(redis.NewSliceResult(expectedResult, nil))
329 result, err := db.MGet([]string{"key1", "key2", "key3"})
330 assert.Equal(t, result, expectedResult)
332 r.AssertExpectations(t)
335 func TestMGetFailure(t *testing.T) {
336 _, r, db := setupHaEnv(true)
337 expectedKeys := []string{"key1", "key2", "key3"}
338 expectedResult := []interface{}{nil}
339 r.On("MGet", expectedKeys).Return(redis.NewSliceResult(expectedResult,
340 errors.New("Some error")))
341 result, err := db.MGet([]string{"key1", "key2", "key3"})
342 assert.Equal(t, result, expectedResult)
343 assert.NotNil(t, err)
344 r.AssertExpectations(t)
347 func TestDelMPubSuccessfully(t *testing.T) {
348 _, r, db := setupHaEnv(true)
349 expectedMessage := []interface{}{"DELMPUB", 2, 2, "key1", "key2", "chan1", "event1",
351 r.On("Do", expectedMessage).Return(redis.NewCmdResult("", nil))
352 assert.Nil(t, db.DelMPub([]string{"chan1", "event1", "chan2", "event2"},
353 []string{"key1", "key2"}))
354 r.AssertExpectations(t)
357 func TestDelMPubFailure(t *testing.T) {
358 _, r, db := setupHaEnv(true)
359 expectedMessage := []interface{}{"DELMPUB", 2, 2, "key1", "key2", "chan1", "event1",
361 r.On("Do", expectedMessage).Return(redis.NewCmdResult("", errors.New("Some error")))
362 assert.NotNil(t, db.DelMPub([]string{"chan1", "event1", "chan2", "event2"},
363 []string{"key1", "key2"}))
364 r.AssertExpectations(t)
367 func TestDelMPubCommandMissing(t *testing.T) {
368 _, r, db := setupHaEnv(false)
369 expectedMessage := []interface{}{"DELMPUB", 2, 2, "key1", "key2", "chan1", "event1",
371 r.AssertNotCalled(t, "Do", expectedMessage)
372 assert.NotNil(t, db.DelMPub([]string{"chan1", "event1", "chan2", "event2"},
373 []string{"key1", "key2"}))
374 r.AssertExpectations(t)
377 func TestDelSuccessfully(t *testing.T) {
378 _, r, db := setupHaEnv(true)
379 expectedKeys := []string{"key1", "key2"}
380 r.On("Del", expectedKeys).Return(redis.NewIntResult(2, nil))
381 assert.Nil(t, db.Del([]string{"key1", "key2"}))
382 r.AssertExpectations(t)
385 func TestDelFailure(t *testing.T) {
386 _, r, db := setupHaEnv(true)
387 expectedKeys := []string{"key1", "key2"}
388 r.On("Del", expectedKeys).Return(redis.NewIntResult(2, errors.New("Some error")))
389 assert.NotNil(t, db.Del([]string{"key1", "key2"}))
390 r.AssertExpectations(t)
393 func TestKeysSuccessfully(t *testing.T) {
394 _, r, db := setupHaEnv(true)
395 expectedPattern := "pattern*"
396 expectedResult := []string{"pattern1", "pattern2"}
397 r.On("Keys", expectedPattern).Return(redis.NewStringSliceResult(expectedResult, nil))
398 result, err := db.Keys("pattern*")
399 assert.Equal(t, result, expectedResult)
401 r.AssertExpectations(t)
404 func TestKeysFailure(t *testing.T) {
405 _, r, db := setupHaEnv(true)
406 expectedPattern := "pattern*"
407 expectedResult := []string{}
408 r.On("Keys", expectedPattern).Return(redis.NewStringSliceResult(expectedResult,
409 errors.New("Some error")))
410 _, err := db.Keys("pattern*")
411 assert.NotNil(t, err)
412 r.AssertExpectations(t)
415 func TestSetIEKeyExists(t *testing.T) {
416 _, r, db := setupHaEnv(true)
417 expectedMessage := []interface{}{"SETIE", "key", "newdata", "olddata"}
418 r.On("Do", expectedMessage).Return(redis.NewCmdResult("OK", nil))
419 result, err := db.SetIE("key", "olddata", "newdata")
420 assert.True(t, result)
422 r.AssertExpectations(t)
425 func TestSetIEKeyDoesntExists(t *testing.T) {
426 _, r, db := setupHaEnv(true)
427 expectedMessage := []interface{}{"SETIE", "key", "newdata", "olddata"}
428 r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, nil))
429 result, err := db.SetIE("key", "olddata", "newdata")
430 assert.False(t, result)
432 r.AssertExpectations(t)
435 func TestSetIEFailure(t *testing.T) {
436 _, r, db := setupHaEnv(true)
437 expectedMessage := []interface{}{"SETIE", "key", "newdata", "olddata"}
438 r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, errors.New("Some error")))
439 result, err := db.SetIE("key", "olddata", "newdata")
440 assert.False(t, result)
441 assert.NotNil(t, err)
442 r.AssertExpectations(t)
445 func TestSetIECommandMissing(t *testing.T) {
446 _, r, db := setupHaEnv(false)
447 expectedMessage := []interface{}{"SETIE", "key", "newdata", "olddata"}
448 r.AssertNotCalled(t, "Do", expectedMessage)
449 result, err := db.SetIE("key", "olddata", "newdata")
450 assert.False(t, result)
451 assert.NotNil(t, err)
452 r.AssertExpectations(t)
455 func TestSetIEPubKeyExists(t *testing.T) {
456 _, r, db := setupHaEnv(true)
457 expectedMessage := []interface{}{"SETIEMPUB", "key", "newdata", "olddata", "channel", "message"}
458 r.On("Do", expectedMessage).Return(redis.NewCmdResult("OK", nil))
459 result, err := db.SetIEPub([]string{"channel", "message"}, "key", "olddata", "newdata")
460 assert.True(t, result)
462 r.AssertExpectations(t)
465 func TestSetIEPubKeyDoesntExists(t *testing.T) {
466 _, r, db := setupHaEnv(true)
467 expectedMessage := []interface{}{"SETIEMPUB", "key", "newdata", "olddata", "channel", "message"}
468 r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, nil))
469 result, err := db.SetIEPub([]string{"channel", "message"}, "key", "olddata", "newdata")
470 assert.False(t, result)
472 r.AssertExpectations(t)
475 func TestSetIEPubFailure(t *testing.T) {
476 _, r, db := setupHaEnv(true)
477 expectedMessage := []interface{}{"SETIEMPUB", "key", "newdata", "olddata", "channel", "message"}
478 r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, errors.New("Some error")))
479 result, err := db.SetIEPub([]string{"channel", "message"}, "key", "olddata", "newdata")
480 assert.False(t, result)
481 assert.NotNil(t, err)
482 r.AssertExpectations(t)
485 func TestSetIEPubCommandMissing(t *testing.T) {
486 _, r, db := setupHaEnv(false)
487 expectedMessage := []interface{}{"SETIEMPUB", "key", "newdata", "olddata", "channel", "message"}
488 r.AssertNotCalled(t, "Do", expectedMessage)
489 result, err := db.SetIEPub([]string{"channel", "message"}, "key", "olddata", "newdata")
490 assert.False(t, result)
491 assert.NotNil(t, err)
492 r.AssertExpectations(t)
495 func TestSetNXPubKeyDoesntExist(t *testing.T) {
496 _, r, db := setupHaEnv(true)
497 expectedMessage := []interface{}{"SETNXMPUB", "key", "data", "channel", "message"}
498 r.On("Do", expectedMessage).Return(redis.NewCmdResult("OK", nil))
499 result, err := db.SetNXPub([]string{"channel", "message"}, "key", "data")
500 assert.True(t, result)
502 r.AssertExpectations(t)
505 func TestSetNXPubKeyExists(t *testing.T) {
506 _, r, db := setupHaEnv(true)
507 expectedMessage := []interface{}{"SETNXMPUB", "key", "data", "channel", "message"}
508 r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, nil))
509 result, err := db.SetNXPub([]string{"channel", "message"}, "key", "data")
510 assert.False(t, result)
512 r.AssertExpectations(t)
515 func TestSetNXPubFailure(t *testing.T) {
516 _, r, db := setupHaEnv(true)
517 expectedMessage := []interface{}{"SETNXMPUB", "key", "data", "channel", "message"}
518 r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, errors.New("Some error")))
519 result, err := db.SetNXPub([]string{"channel", "message"}, "key", "data")
520 assert.False(t, result)
521 assert.NotNil(t, err)
522 r.AssertExpectations(t)
525 func TestSetNXPubCommandMissing(t *testing.T) {
526 _, r, db := setupHaEnv(false)
527 expectedMessage := []interface{}{"SETNXMPUB", "key", "data", "channel", "message"}
528 r.AssertNotCalled(t, "Do", expectedMessage)
529 result, err := db.SetNXPub([]string{"channel", "message"}, "key", "data")
530 assert.False(t, result)
531 assert.NotNil(t, err)
532 r.AssertExpectations(t)
535 func TestSetNXSuccessfully(t *testing.T) {
536 _, r, db := setupHaEnv(true)
538 expectedData := "data"
539 r.On("SetNX", expectedKey, expectedData, time.Duration(0)).Return(redis.NewBoolResult(true, nil))
540 result, err := db.SetNX("key", "data", 0)
541 assert.True(t, result)
543 r.AssertExpectations(t)
546 func TestSetNXUnsuccessfully(t *testing.T) {
547 _, r, db := setupHaEnv(true)
549 expectedData := "data"
550 r.On("SetNX", expectedKey, expectedData, time.Duration(0)).Return(redis.NewBoolResult(false, nil))
551 result, err := db.SetNX("key", "data", 0)
552 assert.False(t, result)
554 r.AssertExpectations(t)
557 func TestSetNXFailure(t *testing.T) {
558 _, r, db := setupHaEnv(true)
560 expectedData := "data"
561 r.On("SetNX", expectedKey, expectedData, time.Duration(0)).
562 Return(redis.NewBoolResult(false, errors.New("Some error")))
563 result, err := db.SetNX("key", "data", 0)
564 assert.False(t, result)
565 assert.NotNil(t, err)
566 r.AssertExpectations(t)
569 func TestDelIEPubKeyDoesntExist(t *testing.T) {
570 _, r, db := setupHaEnv(true)
571 expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
572 r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(0), nil))
573 result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
574 assert.False(t, result)
576 r.AssertExpectations(t)
579 func TestDelIEPubKeyExists(t *testing.T) {
580 _, r, db := setupHaEnv(true)
581 expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
582 r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(1), nil))
583 result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
584 assert.True(t, result)
586 r.AssertExpectations(t)
589 func TestDelIEPubKeyExistsIntTypeRedisValue(t *testing.T) {
590 _, r, db := setupHaEnv(true)
591 expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
592 r.On("Do", expectedMessage).Return(redis.NewCmdResult(1, nil))
593 result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
594 assert.True(t, result)
596 r.AssertExpectations(t)
599 func TestDelIEPubFailure(t *testing.T) {
600 _, r, db := setupHaEnv(true)
601 expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
602 r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(0), errors.New("Some error")))
603 result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
604 assert.False(t, result)
605 assert.NotNil(t, err)
606 r.AssertExpectations(t)
609 func TestDelIEPubCommandMissing(t *testing.T) {
610 _, r, db := setupHaEnv(false)
611 expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
612 r.AssertNotCalled(t, "Do", expectedMessage)
613 result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
614 assert.False(t, result)
615 assert.NotNil(t, err)
616 r.AssertExpectations(t)
619 func TestDelIEKeyDoesntExist(t *testing.T) {
620 _, r, db := setupHaEnv(true)
621 expectedMessage := []interface{}{"DELIE", "key", "data"}
622 r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(0), nil))
623 result, err := db.DelIE("key", "data")
624 assert.False(t, result)
626 r.AssertExpectations(t)
629 func TestDelIEKeyExists(t *testing.T) {
630 _, r, db := setupHaEnv(true)
631 expectedMessage := []interface{}{"DELIE", "key", "data"}
632 r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(1), nil))
633 result, err := db.DelIE("key", "data")
634 assert.True(t, result)
636 r.AssertExpectations(t)
639 func TestDelIEKeyExistsIntTypeRedisValue(t *testing.T) {
640 _, r, db := setupHaEnv(true)
641 expectedMessage := []interface{}{"DELIE", "key", "data"}
642 r.On("Do", expectedMessage).Return(redis.NewCmdResult(1, nil))
643 result, err := db.DelIE("key", "data")
644 assert.True(t, result)
646 r.AssertExpectations(t)
649 func TestDelIEFailure(t *testing.T) {
650 _, r, db := setupHaEnv(true)
651 expectedMessage := []interface{}{"DELIE", "key", "data"}
652 r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(0), errors.New("Some error")))
653 result, err := db.DelIE("key", "data")
654 assert.False(t, result)
655 assert.NotNil(t, err)
656 r.AssertExpectations(t)
659 func TestDelIECommandMissing(t *testing.T) {
660 _, r, db := setupHaEnv(false)
661 expectedMessage := []interface{}{"DELIE", "key", "data"}
662 r.AssertNotCalled(t, "Do", expectedMessage)
663 result, err := db.DelIE("key", "data")
664 assert.False(t, result)
665 assert.NotNil(t, err)
666 r.AssertExpectations(t)
669 func TestSAddSuccessfully(t *testing.T) {
670 _, r, db := setupHaEnv(true)
672 expectedData := []interface{}{"data", 2}
673 r.On("SAdd", expectedKey, expectedData).Return(redis.NewIntResult(2, nil))
674 assert.Nil(t, db.SAdd("key", "data", 2))
675 r.AssertExpectations(t)
678 func TestSAddFailure(t *testing.T) {
679 _, r, db := setupHaEnv(true)
681 expectedData := []interface{}{"data", 2}
682 r.On("SAdd", expectedKey, expectedData).Return(redis.NewIntResult(2, errors.New("Some error")))
683 assert.NotNil(t, db.SAdd("key", "data", 2))
684 r.AssertExpectations(t)
687 func TestSRemSuccessfully(t *testing.T) {
688 _, r, db := setupHaEnv(true)
690 expectedData := []interface{}{"data", 2}
691 r.On("SRem", expectedKey, expectedData).Return(redis.NewIntResult(2, nil))
692 assert.Nil(t, db.SRem("key", "data", 2))
693 r.AssertExpectations(t)
696 func TestSRemFailure(t *testing.T) {
697 _, r, db := setupHaEnv(true)
699 expectedData := []interface{}{"data", 2}
700 r.On("SRem", expectedKey, expectedData).Return(redis.NewIntResult(2, errors.New("Some error")))
701 assert.NotNil(t, db.SRem("key", "data", 2))
702 r.AssertExpectations(t)
705 func TestSMembersSuccessfully(t *testing.T) {
706 _, r, db := setupHaEnv(true)
708 expectedResult := []string{"member1", "member2"}
709 r.On("SMembers", expectedKey).Return(redis.NewStringSliceResult(expectedResult, nil))
710 result, err := db.SMembers("key")
711 assert.Equal(t, result, expectedResult)
713 r.AssertExpectations(t)
716 func TestSMembersFailure(t *testing.T) {
717 _, r, db := setupHaEnv(true)
719 expectedResult := []string{"member1", "member2"}
720 r.On("SMembers", expectedKey).Return(redis.NewStringSliceResult(expectedResult,
721 errors.New("Some error")))
722 result, err := db.SMembers("key")
723 assert.Equal(t, result, expectedResult)
724 assert.NotNil(t, err)
725 r.AssertExpectations(t)
728 func TestSIsMemberIsMember(t *testing.T) {
729 _, r, db := setupHaEnv(true)
731 expectedData := "data"
732 r.On("SIsMember", expectedKey, expectedData).Return(redis.NewBoolResult(true, nil))
733 result, err := db.SIsMember("key", "data")
734 assert.True(t, result)
736 r.AssertExpectations(t)
739 func TestSIsMemberIsNotMember(t *testing.T) {
740 _, r, db := setupHaEnv(true)
742 expectedData := "data"
743 r.On("SIsMember", expectedKey, expectedData).Return(redis.NewBoolResult(false, nil))
744 result, err := db.SIsMember("key", "data")
745 assert.False(t, result)
747 r.AssertExpectations(t)
750 func TestSIsMemberFailure(t *testing.T) {
751 _, r, db := setupHaEnv(true)
753 expectedData := "data"
754 r.On("SIsMember", expectedKey, expectedData).
755 Return(redis.NewBoolResult(false, errors.New("Some error")))
756 result, err := db.SIsMember("key", "data")
757 assert.False(t, result)
758 assert.NotNil(t, err)
759 r.AssertExpectations(t)
762 func TestSCardSuccessfully(t *testing.T) {
763 _, r, db := setupHaEnv(true)
765 r.On("SCard", expectedKey).Return(redis.NewIntResult(1, nil))
766 result, err := db.SCard("key")
767 assert.Equal(t, int64(1), result)
769 r.AssertExpectations(t)
772 func TestSCardFailure(t *testing.T) {
773 _, r, db := setupHaEnv(true)
775 r.On("SCard", expectedKey).Return(redis.NewIntResult(1, errors.New("Some error")))
776 result, err := db.SCard("key")
777 assert.Equal(t, int64(1), result)
778 assert.NotNil(t, err)
779 r.AssertExpectations(t)
782 func TestSubscribeChannelDBSubscribeRXUnsubscribe(t *testing.T) {
783 ps, r, db := setupHaEnv(true)
784 ch := make(chan *redis.Message)
785 msg := redis.Message{
786 Channel: "{prefix}channel",
790 ps.On("Channel").Return(ch)
791 ps.On("Unsubscribe").Return(nil)
792 ps.On("Close").Return(nil)
794 receivedChannel := ""
795 db.SubscribeChannelDB(func(channel string, payload ...string) {
797 receivedChannel = channel
798 }, "{prefix}", "---", "{prefix}channel")
800 db.UnsubscribeChannelDB("{prefix}channel")
801 time.Sleep(1 * time.Second)
802 assert.Equal(t, 1, count)
803 assert.Equal(t, "channel", receivedChannel)
804 r.AssertExpectations(t)
805 ps.AssertExpectations(t)
808 func TestSubscribeChannelDBSubscribeTwoUnsubscribeOne(t *testing.T) {
809 ps, r, db := setupHaEnv(true)
810 ch := make(chan *redis.Message)
811 msg1 := redis.Message{
812 Channel: "{prefix}channel1",
816 msg2 := redis.Message{
817 Channel: "{prefix}channel2",
821 ps.On("Channel").Return(ch)
822 ps.On("Subscribe").Return(nil)
823 ps.On("Unsubscribe").Return(nil)
824 ps.On("Unsubscribe").Return(nil)
825 ps.On("Close").Return(nil)
827 receivedChannel1 := ""
828 db.SubscribeChannelDB(func(channel string, payload ...string) {
830 receivedChannel1 = channel
831 }, "{prefix}", "---", "{prefix}channel1")
833 receivedChannel2 := ""
834 db.SubscribeChannelDB(func(channel string, payload ...string) {
836 receivedChannel2 = channel
837 }, "{prefix}", "---", "{prefix}channel2")
839 time.Sleep(1 * time.Second)
840 db.UnsubscribeChannelDB("{prefix}channel1")
842 db.UnsubscribeChannelDB("{prefix}channel2")
843 time.Sleep(1 * time.Second)
844 assert.Equal(t, 2, count)
845 assert.Equal(t, "channel1", receivedChannel1)
846 assert.Equal(t, "channel2", receivedChannel2)
847 r.AssertExpectations(t)
848 ps.AssertExpectations(t)
851 func TestSubscribeChannelReDBSubscribeAfterUnsubscribe(t *testing.T) {
852 ps, r, db := setupHaEnv(true)
853 ch := make(chan *redis.Message)
854 msg := redis.Message{
855 Channel: "{prefix}channel",
859 ps.On("Channel").Return(ch)
860 ps.On("Unsubscribe").Return(nil)
861 ps.On("Close").Return(nil)
863 receivedChannel := ""
865 db.SubscribeChannelDB(func(channel string, payload ...string) {
867 receivedChannel = channel
868 }, "{prefix}", "---", "{prefix}channel")
870 db.UnsubscribeChannelDB("{prefix}channel")
871 time.Sleep(1 * time.Second)
873 db.SubscribeChannelDB(func(channel string, payload ...string) {
875 receivedChannel = channel
876 }, "{prefix}", "---", "{prefix}channel")
878 db.UnsubscribeChannelDB("{prefix}channel")
880 time.Sleep(1 * time.Second)
881 assert.Equal(t, 2, count)
882 assert.Equal(t, "channel", receivedChannel)
883 r.AssertExpectations(t)
884 ps.AssertExpectations(t)
887 func TestPTTLSuccessfully(t *testing.T) {
888 _, r, db := setupHaEnv(true)
890 expectedResult := time.Duration(1)
891 r.On("PTTL", expectedKey).Return(redis.NewDurationResult(expectedResult,
893 result, err := db.PTTL("key")
894 assert.Equal(t, result, expectedResult)
896 r.AssertExpectations(t)
899 func TestPTTLFailure(t *testing.T) {
900 _, r, db := setupHaEnv(true)
902 expectedResult := time.Duration(1)
903 r.On("PTTL", expectedKey).Return(redis.NewDurationResult(expectedResult,
904 errors.New("Some error")))
905 result, err := db.PTTL("key")
906 assert.Equal(t, result, expectedResult)
907 assert.NotNil(t, err)
908 r.AssertExpectations(t)
911 func TestPExpireIESuccessfully(t *testing.T) {
912 _, r, db := setupHaEnv(true)
914 expectedData := "data"
915 expectedDuration := strconv.FormatInt(int64(10000), 10)
917 r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
918 Return(redis.NewCmdResult(int64(1), nil))
920 err := db.PExpireIE("key", "data", 10*time.Second)
922 r.AssertExpectations(t)
925 func TestPExpireIEFailure(t *testing.T) {
926 _, r, db := setupHaEnv(true)
928 expectedData := "data"
929 expectedDuration := strconv.FormatInt(int64(10000), 10)
931 r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
932 Return(redis.NewCmdResult(int64(1), errors.New("Some error")))
934 err := db.PExpireIE("key", "data", 10*time.Second)
935 assert.NotNil(t, err)
936 r.AssertExpectations(t)
939 func TestPExpireIELockNotHeld(t *testing.T) {
940 _, r, db := setupHaEnv(true)
942 expectedData := "data"
943 expectedDuration := strconv.FormatInt(int64(10000), 10)
945 r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
946 Return(redis.NewCmdResult(int64(0), nil))
948 err := db.PExpireIE("key", "data", 10*time.Second)
949 assert.NotNil(t, err)
950 r.AssertExpectations(t)
953 func TestClientStandaloneRedisLegacyEnv(t *testing.T) {
954 setupVals := setupEnv(
956 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6376", "", "", "", "",
958 assert.Equal(t, 1, len(setupVals.rClient))
959 assert.Equal(t, 1, len(setupVals.db))
961 expectedKeysAndValues := []interface{}{"key1", "value1"}
962 setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
963 err := setupVals.db[0].MSet("key1", "value1")
965 setupVals.rClient[0].AssertExpectations(t)
968 func TestClientSentinelRedisLegacyEnv(t *testing.T) {
969 setupVals := setupEnv(
971 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6376", "dbaasmaster", "26376", "", "3",
973 assert.Equal(t, 1, len(setupVals.rClient))
974 assert.Equal(t, 1, len(setupVals.db))
976 expectedKeysAndValues := []interface{}{"key1", "value1"}
977 setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
978 err := setupVals.db[0].MSet("key1", "value1")
980 setupVals.rClient[0].AssertExpectations(t)
983 func TestClientTwoStandaloneRedisEnvs(t *testing.T) {
984 setupVals := setupEnv(
986 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6376", "", "",
987 "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "",
989 assert.Equal(t, 2, len(setupVals.rClient))
990 assert.Equal(t, 2, len(setupVals.db))
992 expectedKeysAndValues := []interface{}{"key1", "value1"}
993 setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
994 err := setupVals.db[0].MSet("key1", "value1")
996 setupVals.rClient[0].AssertExpectations(t)
998 expectedKeysAndValues = []interface{}{"key2", "value2"}
999 setupVals.rClient[1].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1000 err = setupVals.db[1].MSet("key2", "value2")
1002 setupVals.rClient[0].AssertExpectations(t)
1003 setupVals.rClient[1].AssertExpectations(t)
1006 func TestClientTwoSentinelRedisEnvs(t *testing.T) {
1007 setupVals := setupEnv(
1009 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6376", "dbaasmaster", "26376",
1010 "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1012 assert.Equal(t, 2, len(setupVals.rClient))
1013 assert.Equal(t, 2, len(setupVals.db))
1015 expectedKeysAndValues := []interface{}{"key1", "value1"}
1016 setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1017 err := setupVals.db[0].MSet("key1", "value1")
1019 setupVals.rClient[0].AssertExpectations(t)
1021 expectedKeysAndValues = []interface{}{"key2", "value2"}
1022 setupVals.rClient[1].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1023 err = setupVals.db[1].MSet("key2", "value2")
1025 setupVals.rClient[0].AssertExpectations(t)
1026 setupVals.rClient[1].AssertExpectations(t)
1029 func TestInfoOfMasterRedisWithTwoSlavesSuccessfully(t *testing.T) {
1030 _, r, db := setupHaEnv(true)
1031 redisInfo := "# Replication\r\n" +
1033 "connected_slaves:2\r\n" +
1034 "min_slaves_good_slaves:2\r\n" +
1035 "slave0:ip=1.2.3.4,port=6379,state=online,offset=100200300,lag=0\r\n" +
1036 "slave1:ip=5.6.7.8,port=6379,state=online,offset=100200300,lag=0\r\n"
1037 expInfo := &sdlgoredis.DbInfo{
1038 Fields: sdlgoredis.DbInfoFields{
1040 ConnectedReplicaCnt: 2,
1044 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1045 info, err := db.Info()
1047 assert.Equal(t, expInfo, info)
1048 r.AssertExpectations(t)
1051 func TestInfoOfMasterRedisWithOneSlaveOnlineAndOtherSlaveNotOnlineSuccessfully(t *testing.T) {
1052 _, r, db := setupHaEnv(true)
1053 redisInfo := "# Replication\r\n" +
1055 "connected_slaves:1\r\n" +
1056 "min_slaves_good_slaves:2\r\n" +
1057 "slave0:ip=1.2.3.4,port=6379,state=online,offset=100200300,lag=0\r\n" +
1058 "slave1:ip=5.6.7.8,port=6379,state=wait_bgsave,offset=100200300,lag=0\r\n"
1059 expInfo := &sdlgoredis.DbInfo{
1060 Fields: sdlgoredis.DbInfoFields{
1062 ConnectedReplicaCnt: 1,
1066 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1067 info, err := db.Info()
1069 assert.Equal(t, expInfo, info)
1070 r.AssertExpectations(t)
1073 func TestInfoOfStandaloneMasterRedisSuccessfully(t *testing.T) {
1074 _, r, db := setupHaEnv(true)
1075 redisInfo := "# Replication\r\n" +
1077 "connected_slaves:0\r\n" +
1078 "min_slaves_good_slaves:0\r\n"
1079 expInfo := &sdlgoredis.DbInfo{
1080 Fields: sdlgoredis.DbInfoFields{
1082 ConnectedReplicaCnt: 0,
1086 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1087 info, err := db.Info()
1089 assert.Equal(t, expInfo, info)
1090 r.AssertExpectations(t)
1093 func TestInfoWithGibberishContentSuccessfully(t *testing.T) {
1094 _, r, db := setupHaEnv(true)
1095 redisInfo := "!#¤%&?+?´-\r\n"
1096 expInfo := &sdlgoredis.DbInfo{}
1098 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1099 info, err := db.Info()
1101 assert.Equal(t, expInfo, info)
1102 r.AssertExpectations(t)
1105 func TestInfoWithEmptyContentSuccessfully(t *testing.T) {
1106 _, r, db := setupHaEnv(true)
1107 var redisInfo string
1108 expInfo := &sdlgoredis.DbInfo{
1109 Fields: sdlgoredis.DbInfoFields{
1114 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1115 info, err := db.Info()
1117 assert.Equal(t, expInfo, info)
1118 r.AssertExpectations(t)
1121 func TestStateWithMasterAndTwoSlaveRedisSuccessfully(t *testing.T) {
1122 _, r, s, db := setupHaEnvWithSentinels(true)
1123 redisMasterState := map[string]string{
1124 "role-reported": "master",
1126 redisSlavesState := make([]interface{}, 2)
1127 redisSlavesState[0] = []interface{}{
1128 "role-reported", "slave",
1129 "ip", "10.20.30.40",
1132 "master-link-status", "up",
1134 redisSlavesState[1] = []interface{}{
1135 "master-link-status", "up",
1136 "ip", "10.20.30.50",
1139 "role-reported", "slave",
1142 expState := &sdlgoredis.DbState{
1143 MasterDbState: sdlgoredis.MasterDbState{
1144 Fields: sdlgoredis.MasterDbStateFields{
1148 ReplicasDbState: &sdlgoredis.ReplicasDbState{
1149 States: []*sdlgoredis.ReplicaDbState{
1150 &sdlgoredis.ReplicaDbState{
1151 Fields: sdlgoredis.ReplicaDbStateFields{
1155 MasterLinkStatus: "up",
1159 &sdlgoredis.ReplicaDbState{
1160 Fields: sdlgoredis.ReplicaDbStateFields{
1164 MasterLinkStatus: "up",
1172 s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisMasterState, nil))
1173 s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisSlavesState, nil))
1174 ret, err := db.State()
1176 assert.Equal(t, expState, ret)
1177 r.AssertExpectations(t)
1180 func TestStateWithMasterAndOneSlaveRedisFailureInMasterRedisCall(t *testing.T) {
1181 _, r, s, db := setupHaEnvWithSentinels(true)
1182 redisMasterState := map[string]string{}
1183 redisSlavesState := make([]interface{}, 1)
1184 redisSlavesState[0] = []interface{}{
1185 "role-reported", "slave",
1186 "ip", "10.20.30.40",
1189 "master-link-status", "up",
1192 expState := &sdlgoredis.DbState{
1193 MasterDbState: sdlgoredis.MasterDbState{
1194 Err: errors.New("Some error"),
1196 ReplicasDbState: &sdlgoredis.ReplicasDbState{
1197 States: []*sdlgoredis.ReplicaDbState{
1198 &sdlgoredis.ReplicaDbState{
1199 Fields: sdlgoredis.ReplicaDbStateFields{
1203 MasterLinkStatus: "up",
1211 s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisMasterState, errors.New("Some error")))
1212 s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisSlavesState, nil))
1213 ret, err := db.State()
1214 assert.NotNil(t, err)
1215 assert.Equal(t, expState, ret)
1216 r.AssertExpectations(t)
1219 func TestStateWithMasterAndOneSlaveRedisFailureInSlavesRedisCall(t *testing.T) {
1220 _, r, s, db := setupHaEnvWithSentinels(true)
1221 redisMasterState := map[string]string{
1222 "role-reported": "master",
1224 redisSlavesState := make([]interface{}, 1)
1225 redisSlavesState[0] = []interface{}{}
1227 expState := &sdlgoredis.DbState{
1228 MasterDbState: sdlgoredis.MasterDbState{
1229 Fields: sdlgoredis.MasterDbStateFields{
1233 ReplicasDbState: &sdlgoredis.ReplicasDbState{
1234 Err: errors.New("Some error"),
1235 States: []*sdlgoredis.ReplicaDbState{},
1239 s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisMasterState, nil))
1240 s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisSlavesState, errors.New("Some error")))
1241 ret, err := db.State()
1242 assert.NotNil(t, err)
1243 assert.Equal(t, expState, ret)
1244 r.AssertExpectations(t)
1247 func TestStateWithSingleMasterRedisSuccessfully(t *testing.T) {
1248 _, r, db := setupSingleEnv(true)
1249 redisInfo := "# Replication\r\n" +
1251 "connected_slaves:0\r\n" +
1252 "min_slaves_good_slaves:0\r\n"
1254 expState := &sdlgoredis.DbState{
1255 MasterDbState: sdlgoredis.MasterDbState{
1256 Fields: sdlgoredis.MasterDbStateFields{
1263 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1264 ret, err := db.State()
1266 assert.Equal(t, expState, ret)
1267 r.AssertExpectations(t)
1270 func TestStateWithSingleMasterRedisFailureInInfoCall(t *testing.T) {
1271 _, r, db := setupSingleEnv(true)
1273 expState := &sdlgoredis.DbState{}
1275 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, errors.New("Some error")))
1276 ret, err := db.State()
1277 assert.NotNil(t, err)
1278 assert.Equal(t, expState, ret)
1279 r.AssertExpectations(t)