2 Copyright (c) 2019 AT&T Intellectual Property.
3 Copyright (c) 2018-2022 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
28 "gerrit.o-ran-sc.org/r/ric-plt/sdlgo/internal/sdlgoredis"
29 "github.com/go-redis/redis/v8"
30 "github.com/stretchr/testify/assert"
31 "github.com/stretchr/testify/mock"
37 type clientMock struct {
41 type pubSubMock struct {
49 func (m *pubSubMock) Channel(opts ...redis.ChannelOption) <-chan *redis.Message {
50 return m.Called().Get(0).(chan *redis.Message)
53 func (m *pubSubMock) Subscribe(ctx context.Context, channels ...string) error {
54 return m.Called().Error(0)
57 func (m *pubSubMock) Unsubscribe(ctx context.Context, channels ...string) error {
58 return m.Called().Error(0)
61 func (m *pubSubMock) Close() error {
62 return m.Called().Error(0)
65 func (m *clientMock) Command(ctx context.Context) *redis.CommandsInfoCmd {
66 return m.Called().Get(0).(*redis.CommandsInfoCmd)
69 func (m *clientMock) Close() error {
70 return m.Called().Error(0)
73 func (m *clientMock) Subscribe(ctx context.Context, channels ...string) *redis.PubSub {
74 return m.Called(channels).Get(0).(*redis.PubSub)
77 func (m *clientMock) MSet(ctx context.Context, pairs ...interface{}) *redis.StatusCmd {
78 return m.Called(pairs).Get(0).(*redis.StatusCmd)
81 func (m *clientMock) Do(ctx context.Context, args ...interface{}) *redis.Cmd {
82 return m.Called(args).Get(0).(*redis.Cmd)
85 func (m *clientMock) MGet(ctx context.Context, keys ...string) *redis.SliceCmd {
86 return m.Called(keys).Get(0).(*redis.SliceCmd)
89 func (m *clientMock) Del(ctx context.Context, keys ...string) *redis.IntCmd {
90 return m.Called(keys).Get(0).(*redis.IntCmd)
93 func (m *clientMock) Keys(ctx context.Context, pattern string) *redis.StringSliceCmd {
94 return m.Called(pattern).Get(0).(*redis.StringSliceCmd)
97 func (m *clientMock) SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) *redis.BoolCmd {
98 return m.Called(key, value, expiration).Get(0).(*redis.BoolCmd)
101 func (m *clientMock) SAdd(ctx context.Context, key string, members ...interface{}) *redis.IntCmd {
102 return m.Called(key, members).Get(0).(*redis.IntCmd)
105 func (m *clientMock) SRem(ctx context.Context, key string, members ...interface{}) *redis.IntCmd {
106 return m.Called(key, members).Get(0).(*redis.IntCmd)
109 func (m *clientMock) SMembers(ctx context.Context, key string) *redis.StringSliceCmd {
110 return m.Called(key).Get(0).(*redis.StringSliceCmd)
113 func (m *clientMock) SIsMember(ctx context.Context, key string, member interface{}) *redis.BoolCmd {
114 return m.Called(key, member).Get(0).(*redis.BoolCmd)
117 func (m *clientMock) SCard(ctx context.Context, key string) *redis.IntCmd {
118 return m.Called(key).Get(0).(*redis.IntCmd)
121 func (m *clientMock) PTTL(ctx context.Context, key string) *redis.DurationCmd {
122 return m.Called(key).Get(0).(*redis.DurationCmd)
125 func (m *clientMock) Eval(ctx context.Context, script string, keys []string, args ...interface{}) *redis.Cmd {
126 return m.Called(script, keys).Get(0).(*redis.Cmd)
129 func (m *clientMock) EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *redis.Cmd {
130 return m.Called(sha1, keys, args).Get(0).(*redis.Cmd)
133 func (m *clientMock) ScriptExists(ctx context.Context, scripts ...string) *redis.BoolSliceCmd {
134 return m.Called(scripts).Get(0).(*redis.BoolSliceCmd)
137 func (m *clientMock) ScriptLoad(ctx context.Context, script string) *redis.StringCmd {
138 return m.Called(script).Get(0).(*redis.StringCmd)
141 func (m *clientMock) Info(ctx context.Context, section ...string) *redis.StringCmd {
142 return m.Called(section).Get(0).(*redis.StringCmd)
145 type MockRedisSentinel struct {
149 func (m *MockRedisSentinel) Master(ctx context.Context, name string) *redis.StringStringMapCmd {
151 return a.Get(0).(*redis.StringStringMapCmd)
154 func (m *MockRedisSentinel) Slaves(ctx context.Context, name string) *redis.SliceCmd {
156 return a.Get(0).(*redis.SliceCmd)
159 func (m *MockRedisSentinel) Sentinels(ctx context.Context, name string) *redis.SliceCmd {
161 return a.Get(0).(*redis.SliceCmd)
164 func setSubscribeNotifications() (*pubSubMock, sdlgoredis.SubscribeFn) {
165 mock := new(pubSubMock)
166 return mock, func(ctx context.Context, client sdlgoredis.RedisClient, channels ...string) sdlgoredis.Subscriber {
171 func (m *MockOS) Getenv(key string, defValue string) string {
172 a := m.Called(key, defValue)
176 type setupEv struct {
177 pubSubMock []*pubSubMock
178 rClient []*clientMock
179 rSentinel []*MockRedisSentinel
183 func setupHaEnv(commandsExists bool) (*pubSubMock, *clientMock, *sdlgoredis.DB) {
184 psm, cm, _, db := setupHaEnvWithSentinels(commandsExists, "3")
188 func setupHaEnvWithSentinels(commandsExists bool, nodeCnt string) (*pubSubMock, *clientMock, []*MockRedisSentinel, *sdlgoredis.DB) {
189 setupVals := setupEnv(
191 "service-ricplt-dbaas-tcp-cluster-0.ricplt",
193 "dbaasmaster-cluster-0",
198 return setupVals.pubSubMock[0], setupVals.rClient[0], setupVals.rSentinel, setupVals.db[0]
201 func setupSingleEnv(commandsExists bool, nodeCnt string) (*pubSubMock, *clientMock, *sdlgoredis.DB) {
202 setupVals := setupEnv(
204 "service-ricplt-dbaas-tcp-cluster-0.ricplt",
205 "6379", "", "", "", nodeCnt,
207 return setupVals.pubSubMock[0], setupVals.rClient[0], setupVals.db[0]
210 func setupEnv(commandsExists bool, host, port, msname, sntport, clsaddrlist, nodeCnt string) setupEv {
213 dummyCommandInfo := redis.CommandInfo{
217 cmdResult := make(map[string]*redis.CommandInfo, 0)
219 cmdResult = map[string]*redis.CommandInfo{
220 "setie": &dummyCommandInfo,
221 "delie": &dummyCommandInfo,
222 "setiepub": &dummyCommandInfo,
223 "setnxpub": &dummyCommandInfo,
224 "msetmpub": &dummyCommandInfo,
225 "delmpub": &dummyCommandInfo,
228 cmdResult = map[string]*redis.CommandInfo{
229 "dummy": &dummyCommandInfo,
233 osmock := new(MockOS)
234 osmock.On("Getenv", "DBAAS_SERVICE_HOST", "localhost").Return(host)
235 osmock.On("Getenv", "DBAAS_SERVICE_PORT", "6379").Return(port)
236 osmock.On("Getenv", "DBAAS_MASTER_NAME", "").Return(msname)
237 osmock.On("Getenv", "DBAAS_SERVICE_SENTINEL_PORT", "").Return(sntport)
238 osmock.On("Getenv", "DBAAS_CLUSTER_ADDR_LIST", "").Return(clsaddrlist)
239 osmock.On("Getenv", "DBAAS_NODE_COUNT", "1").Return(nodeCnt)
241 pubSubMock, subscribeNotifications := setSubscribeNotifications()
242 smock := new(MockRedisSentinel)
243 ret.rSentinel = append(ret.rSentinel, smock)
244 clients := sdlgoredis.ReadConfigAndCreateDbClients(
246 func(addr, port, clusterName string, isHa bool) sdlgoredis.RedisClient {
247 clm := new(clientMock)
248 clm.On("Command").Return(redis.NewCommandsInfoCmdResult(cmdResult, nil))
249 ret.rClient = append(ret.rClient, clm)
250 ret.pubSubMock = append(ret.pubSubMock, pubSubMock)
253 subscribeNotifications,
254 func(addr, sentinelPort, masterName, nodeCnt string) *sdlgoredis.Sentinel {
255 s := &sdlgoredis.Sentinel{
256 IredisSentinelClient: smock,
257 MasterName: masterName,
267 func newMockRedisMasterCallResp(role, ip, port, flag string) map[string]string {
268 resp := map[string]string{}
270 resp["role-reported"] = role
278 type mockRedisSlaves struct {
282 func newMockRedisSlavesCall() *mockRedisSlaves {
283 return new(mockRedisSlaves)
286 func (mrr *mockRedisSlaves) add(role, ip, port, link, flag string) {
287 mrr.resp = append(mrr.resp,
289 "role-reported", role,
292 "master-link-status", link,
298 type mockRedisSentinels struct {
302 func newMockRedisSentinelsCall() *mockRedisSentinels {
303 return new(mockRedisSentinels)
306 func (mrs *mockRedisSentinels) add(ip, port, flag string) {
307 mrs.resp = append(mrs.resp,
316 type ExpDbState struct {
320 func newExpDbState(nodeCnt int, err error) *ExpDbState {
321 state := new(ExpDbState)
322 state.s.ConfigNodeCnt = nodeCnt
327 func (edbs *ExpDbState) addPrimary(role, ip, port, flag string, err error) {
328 edbs.s.PrimaryDbState.Err = err
329 edbs.s.PrimaryDbState.Fields = sdlgoredis.PrimaryDbStateFields{
337 func (edbs *ExpDbState) addReplica(role, ip, port, link, flag string, err error) {
338 if edbs.s.ReplicasDbState == nil {
339 edbs.s.ReplicasDbState = new(sdlgoredis.ReplicasDbState)
340 edbs.s.ReplicasDbState.States = make([]*sdlgoredis.ReplicaDbState, 0)
342 edbs.s.ReplicasDbState.Err = err
343 if ip != "" || port != "" || link != "" || flag != "" {
344 edbs.s.ReplicasDbState.States = append(edbs.s.ReplicasDbState.States,
345 &sdlgoredis.ReplicaDbState{
346 Fields: sdlgoredis.ReplicaDbStateFields{
350 PrimaryLinkStatus: link,
358 func (edbs *ExpDbState) addSentinel(ip, port, flag string, err error) {
359 if edbs.s.SentinelsDbState == nil {
360 edbs.s.SentinelsDbState = new(sdlgoredis.SentinelsDbState)
361 edbs.s.SentinelsDbState.States = make([]*sdlgoredis.SentinelDbState, 0)
363 edbs.s.SentinelsDbState.Err = err
364 if ip != "" || port != "" || flag != "" {
365 edbs.s.SentinelsDbState.States = append(edbs.s.SentinelsDbState.States,
366 &sdlgoredis.SentinelDbState{
367 Fields: sdlgoredis.SentinelDbStateFields{
377 func TestCloseDbSuccessfully(t *testing.T) {
378 _, r, db := setupHaEnv(true)
379 r.On("Close").Return(nil)
382 r.AssertExpectations(t)
385 func TestCloseDbFailure(t *testing.T) {
386 _, r, db := setupHaEnv(true)
387 r.On("Close").Return(errors.New("Some error"))
389 assert.NotNil(t, err)
390 r.AssertExpectations(t)
393 func TestMSetSuccessfully(t *testing.T) {
394 _, r, db := setupHaEnv(true)
395 expectedKeysAndValues := []interface{}{"key1", "value1", "key2", 2}
396 r.On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
397 err := db.MSet("key1", "value1", "key2", 2)
399 r.AssertExpectations(t)
402 func TestMSetFailure(t *testing.T) {
403 _, r, db := setupHaEnv(true)
404 expectedKeysAndValues := []interface{}{"key1", "value1", "key2", 2}
405 r.On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", errors.New("Some error")))
406 err := db.MSet("key1", "value1", "key2", 2)
407 assert.NotNil(t, err)
408 r.AssertExpectations(t)
411 func TestMSetMPubSuccessfully(t *testing.T) {
412 _, r, db := setupHaEnv(true)
413 expectedMessage := []interface{}{"MSETMPUB", 2, 2, "key1", "val1", "key2", "val2",
414 "chan1", "event1", "chan2", "event2"}
415 r.On("Do", expectedMessage).Return(redis.NewCmdResult("", nil))
416 assert.Nil(t, db.MSetMPub([]string{"chan1", "event1", "chan2", "event2"},
417 "key1", "val1", "key2", "val2"))
418 r.AssertExpectations(t)
421 func TestMsetMPubFailure(t *testing.T) {
422 _, r, db := setupHaEnv(true)
423 expectedMessage := []interface{}{"MSETMPUB", 2, 2, "key1", "val1", "key2", "val2",
424 "chan1", "event1", "chan2", "event2"}
425 r.On("Do", expectedMessage).Return(redis.NewCmdResult("", errors.New("Some error")))
426 assert.NotNil(t, db.MSetMPub([]string{"chan1", "event1", "chan2", "event2"},
427 "key1", "val1", "key2", "val2"))
428 r.AssertExpectations(t)
431 func TestMSetMPubCommandMissing(t *testing.T) {
432 _, r, db := setupHaEnv(false)
433 expectedMessage := []interface{}{"MSETMPUB", 2, 2, "key1", "val1", "key2", "val2",
434 "chan1", "event1", "chan2", "event2"}
435 r.AssertNotCalled(t, "Do", expectedMessage)
436 assert.NotNil(t, db.MSetMPub([]string{"chan1", "event1", "chan2", "event2"},
437 "key1", "val1", "key2", "val2"))
438 r.AssertExpectations(t)
442 func TestMGetSuccessfully(t *testing.T) {
443 _, r, db := setupHaEnv(true)
444 expectedKeys := []string{"key1", "key2", "key3"}
445 expectedResult := []interface{}{"val1", 2, nil}
446 r.On("MGet", expectedKeys).Return(redis.NewSliceResult(expectedResult, nil))
447 result, err := db.MGet([]string{"key1", "key2", "key3"})
448 assert.Equal(t, result, expectedResult)
450 r.AssertExpectations(t)
453 func TestMGetFailure(t *testing.T) {
454 _, r, db := setupHaEnv(true)
455 expectedKeys := []string{"key1", "key2", "key3"}
456 expectedResult := []interface{}{nil}
457 r.On("MGet", expectedKeys).Return(redis.NewSliceResult(expectedResult,
458 errors.New("Some error")))
459 result, err := db.MGet([]string{"key1", "key2", "key3"})
460 assert.Equal(t, result, expectedResult)
461 assert.NotNil(t, err)
462 r.AssertExpectations(t)
465 func TestDelMPubSuccessfully(t *testing.T) {
466 _, r, db := setupHaEnv(true)
467 expectedMessage := []interface{}{"DELMPUB", 2, 2, "key1", "key2", "chan1", "event1",
469 r.On("Do", expectedMessage).Return(redis.NewCmdResult("", nil))
470 assert.Nil(t, db.DelMPub([]string{"chan1", "event1", "chan2", "event2"},
471 []string{"key1", "key2"}))
472 r.AssertExpectations(t)
475 func TestDelMPubFailure(t *testing.T) {
476 _, r, db := setupHaEnv(true)
477 expectedMessage := []interface{}{"DELMPUB", 2, 2, "key1", "key2", "chan1", "event1",
479 r.On("Do", expectedMessage).Return(redis.NewCmdResult("", errors.New("Some error")))
480 assert.NotNil(t, db.DelMPub([]string{"chan1", "event1", "chan2", "event2"},
481 []string{"key1", "key2"}))
482 r.AssertExpectations(t)
485 func TestDelMPubCommandMissing(t *testing.T) {
486 _, r, db := setupHaEnv(false)
487 expectedMessage := []interface{}{"DELMPUB", 2, 2, "key1", "key2", "chan1", "event1",
489 r.AssertNotCalled(t, "Do", expectedMessage)
490 assert.NotNil(t, db.DelMPub([]string{"chan1", "event1", "chan2", "event2"},
491 []string{"key1", "key2"}))
492 r.AssertExpectations(t)
495 func TestDelSuccessfully(t *testing.T) {
496 _, r, db := setupHaEnv(true)
497 expectedKeys := []string{"key1", "key2"}
498 r.On("Del", expectedKeys).Return(redis.NewIntResult(2, nil))
499 assert.Nil(t, db.Del([]string{"key1", "key2"}))
500 r.AssertExpectations(t)
503 func TestDelFailure(t *testing.T) {
504 _, r, db := setupHaEnv(true)
505 expectedKeys := []string{"key1", "key2"}
506 r.On("Del", expectedKeys).Return(redis.NewIntResult(2, errors.New("Some error")))
507 assert.NotNil(t, db.Del([]string{"key1", "key2"}))
508 r.AssertExpectations(t)
511 func TestKeysSuccessfully(t *testing.T) {
512 _, r, db := setupHaEnv(true)
513 expectedPattern := "pattern*"
514 expectedResult := []string{"pattern1", "pattern2"}
515 r.On("Keys", expectedPattern).Return(redis.NewStringSliceResult(expectedResult, nil))
516 result, err := db.Keys("pattern*")
517 assert.Equal(t, result, expectedResult)
519 r.AssertExpectations(t)
522 func TestKeysFailure(t *testing.T) {
523 _, r, db := setupHaEnv(true)
524 expectedPattern := "pattern*"
525 expectedResult := []string{}
526 r.On("Keys", expectedPattern).Return(redis.NewStringSliceResult(expectedResult,
527 errors.New("Some error")))
528 _, err := db.Keys("pattern*")
529 assert.NotNil(t, err)
530 r.AssertExpectations(t)
533 func TestSetIEKeyExists(t *testing.T) {
534 _, r, db := setupHaEnv(true)
535 expectedMessage := []interface{}{"SETIE", "key", "newdata", "olddata"}
536 r.On("Do", expectedMessage).Return(redis.NewCmdResult("OK", nil))
537 result, err := db.SetIE("key", "olddata", "newdata")
538 assert.True(t, result)
540 r.AssertExpectations(t)
543 func TestSetIEKeyDoesntExists(t *testing.T) {
544 _, r, db := setupHaEnv(true)
545 expectedMessage := []interface{}{"SETIE", "key", "newdata", "olddata"}
546 r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, nil))
547 result, err := db.SetIE("key", "olddata", "newdata")
548 assert.False(t, result)
550 r.AssertExpectations(t)
553 func TestSetIEFailure(t *testing.T) {
554 _, r, db := setupHaEnv(true)
555 expectedMessage := []interface{}{"SETIE", "key", "newdata", "olddata"}
556 r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, errors.New("Some error")))
557 result, err := db.SetIE("key", "olddata", "newdata")
558 assert.False(t, result)
559 assert.NotNil(t, err)
560 r.AssertExpectations(t)
563 func TestSetIECommandMissing(t *testing.T) {
564 _, r, db := setupHaEnv(false)
565 expectedMessage := []interface{}{"SETIE", "key", "newdata", "olddata"}
566 r.AssertNotCalled(t, "Do", expectedMessage)
567 result, err := db.SetIE("key", "olddata", "newdata")
568 assert.False(t, result)
569 assert.NotNil(t, err)
570 r.AssertExpectations(t)
573 func TestSetIEPubKeyExists(t *testing.T) {
574 _, r, db := setupHaEnv(true)
575 expectedMessage := []interface{}{"SETIEMPUB", "key", "newdata", "olddata", "channel", "message"}
576 r.On("Do", expectedMessage).Return(redis.NewCmdResult("OK", nil))
577 result, err := db.SetIEPub([]string{"channel", "message"}, "key", "olddata", "newdata")
578 assert.True(t, result)
580 r.AssertExpectations(t)
583 func TestSetIEPubKeyDoesntExists(t *testing.T) {
584 _, r, db := setupHaEnv(true)
585 expectedMessage := []interface{}{"SETIEMPUB", "key", "newdata", "olddata", "channel", "message"}
586 r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, nil))
587 result, err := db.SetIEPub([]string{"channel", "message"}, "key", "olddata", "newdata")
588 assert.False(t, result)
590 r.AssertExpectations(t)
593 func TestSetIEPubFailure(t *testing.T) {
594 _, r, db := setupHaEnv(true)
595 expectedMessage := []interface{}{"SETIEMPUB", "key", "newdata", "olddata", "channel", "message"}
596 r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, errors.New("Some error")))
597 result, err := db.SetIEPub([]string{"channel", "message"}, "key", "olddata", "newdata")
598 assert.False(t, result)
599 assert.NotNil(t, err)
600 r.AssertExpectations(t)
603 func TestSetIEPubCommandMissing(t *testing.T) {
604 _, r, db := setupHaEnv(false)
605 expectedMessage := []interface{}{"SETIEMPUB", "key", "newdata", "olddata", "channel", "message"}
606 r.AssertNotCalled(t, "Do", expectedMessage)
607 result, err := db.SetIEPub([]string{"channel", "message"}, "key", "olddata", "newdata")
608 assert.False(t, result)
609 assert.NotNil(t, err)
610 r.AssertExpectations(t)
613 func TestSetNXPubKeyDoesntExist(t *testing.T) {
614 _, r, db := setupHaEnv(true)
615 expectedMessage := []interface{}{"SETNXMPUB", "key", "data", "channel", "message"}
616 r.On("Do", expectedMessage).Return(redis.NewCmdResult("OK", nil))
617 result, err := db.SetNXPub([]string{"channel", "message"}, "key", "data")
618 assert.True(t, result)
620 r.AssertExpectations(t)
623 func TestSetNXPubKeyExists(t *testing.T) {
624 _, r, db := setupHaEnv(true)
625 expectedMessage := []interface{}{"SETNXMPUB", "key", "data", "channel", "message"}
626 r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, nil))
627 result, err := db.SetNXPub([]string{"channel", "message"}, "key", "data")
628 assert.False(t, result)
630 r.AssertExpectations(t)
633 func TestSetNXPubFailure(t *testing.T) {
634 _, r, db := setupHaEnv(true)
635 expectedMessage := []interface{}{"SETNXMPUB", "key", "data", "channel", "message"}
636 r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, errors.New("Some error")))
637 result, err := db.SetNXPub([]string{"channel", "message"}, "key", "data")
638 assert.False(t, result)
639 assert.NotNil(t, err)
640 r.AssertExpectations(t)
643 func TestSetNXPubCommandMissing(t *testing.T) {
644 _, r, db := setupHaEnv(false)
645 expectedMessage := []interface{}{"SETNXMPUB", "key", "data", "channel", "message"}
646 r.AssertNotCalled(t, "Do", expectedMessage)
647 result, err := db.SetNXPub([]string{"channel", "message"}, "key", "data")
648 assert.False(t, result)
649 assert.NotNil(t, err)
650 r.AssertExpectations(t)
653 func TestSetNXSuccessfully(t *testing.T) {
654 _, r, db := setupHaEnv(true)
656 expectedData := "data"
657 r.On("SetNX", expectedKey, expectedData, time.Duration(0)).Return(redis.NewBoolResult(true, nil))
658 result, err := db.SetNX("key", "data", 0)
659 assert.True(t, result)
661 r.AssertExpectations(t)
664 func TestSetNXUnsuccessfully(t *testing.T) {
665 _, r, db := setupHaEnv(true)
667 expectedData := "data"
668 r.On("SetNX", expectedKey, expectedData, time.Duration(0)).Return(redis.NewBoolResult(false, nil))
669 result, err := db.SetNX("key", "data", 0)
670 assert.False(t, result)
672 r.AssertExpectations(t)
675 func TestSetNXFailure(t *testing.T) {
676 _, r, db := setupHaEnv(true)
678 expectedData := "data"
679 r.On("SetNX", expectedKey, expectedData, time.Duration(0)).
680 Return(redis.NewBoolResult(false, errors.New("Some error")))
681 result, err := db.SetNX("key", "data", 0)
682 assert.False(t, result)
683 assert.NotNil(t, err)
684 r.AssertExpectations(t)
687 func TestDelIEPubKeyDoesntExist(t *testing.T) {
688 _, r, db := setupHaEnv(true)
689 expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
690 r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(0), nil))
691 result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
692 assert.False(t, result)
694 r.AssertExpectations(t)
697 func TestDelIEPubKeyExists(t *testing.T) {
698 _, r, db := setupHaEnv(true)
699 expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
700 r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(1), nil))
701 result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
702 assert.True(t, result)
704 r.AssertExpectations(t)
707 func TestDelIEPubKeyExistsIntTypeRedisValue(t *testing.T) {
708 _, r, db := setupHaEnv(true)
709 expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
710 r.On("Do", expectedMessage).Return(redis.NewCmdResult(1, nil))
711 result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
712 assert.True(t, result)
714 r.AssertExpectations(t)
717 func TestDelIEPubFailure(t *testing.T) {
718 _, r, db := setupHaEnv(true)
719 expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
720 r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(0), errors.New("Some error")))
721 result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
722 assert.False(t, result)
723 assert.NotNil(t, err)
724 r.AssertExpectations(t)
727 func TestDelIEPubCommandMissing(t *testing.T) {
728 _, r, db := setupHaEnv(false)
729 expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
730 r.AssertNotCalled(t, "Do", expectedMessage)
731 result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
732 assert.False(t, result)
733 assert.NotNil(t, err)
734 r.AssertExpectations(t)
737 func TestDelIEKeyDoesntExist(t *testing.T) {
738 _, r, db := setupHaEnv(true)
739 expectedMessage := []interface{}{"DELIE", "key", "data"}
740 r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(0), nil))
741 result, err := db.DelIE("key", "data")
742 assert.False(t, result)
744 r.AssertExpectations(t)
747 func TestDelIEKeyExists(t *testing.T) {
748 _, r, db := setupHaEnv(true)
749 expectedMessage := []interface{}{"DELIE", "key", "data"}
750 r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(1), nil))
751 result, err := db.DelIE("key", "data")
752 assert.True(t, result)
754 r.AssertExpectations(t)
757 func TestDelIEKeyExistsIntTypeRedisValue(t *testing.T) {
758 _, r, db := setupHaEnv(true)
759 expectedMessage := []interface{}{"DELIE", "key", "data"}
760 r.On("Do", expectedMessage).Return(redis.NewCmdResult(1, nil))
761 result, err := db.DelIE("key", "data")
762 assert.True(t, result)
764 r.AssertExpectations(t)
767 func TestDelIEFailure(t *testing.T) {
768 _, r, db := setupHaEnv(true)
769 expectedMessage := []interface{}{"DELIE", "key", "data"}
770 r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(0), errors.New("Some error")))
771 result, err := db.DelIE("key", "data")
772 assert.False(t, result)
773 assert.NotNil(t, err)
774 r.AssertExpectations(t)
777 func TestDelIECommandMissing(t *testing.T) {
778 _, r, db := setupHaEnv(false)
779 expectedMessage := []interface{}{"DELIE", "key", "data"}
780 r.AssertNotCalled(t, "Do", expectedMessage)
781 result, err := db.DelIE("key", "data")
782 assert.False(t, result)
783 assert.NotNil(t, err)
784 r.AssertExpectations(t)
787 func TestSAddSuccessfully(t *testing.T) {
788 _, r, db := setupHaEnv(true)
790 expectedData := []interface{}{"data", 2}
791 r.On("SAdd", expectedKey, expectedData).Return(redis.NewIntResult(2, nil))
792 assert.Nil(t, db.SAdd("key", "data", 2))
793 r.AssertExpectations(t)
796 func TestSAddFailure(t *testing.T) {
797 _, r, db := setupHaEnv(true)
799 expectedData := []interface{}{"data", 2}
800 r.On("SAdd", expectedKey, expectedData).Return(redis.NewIntResult(2, errors.New("Some error")))
801 assert.NotNil(t, db.SAdd("key", "data", 2))
802 r.AssertExpectations(t)
805 func TestSRemSuccessfully(t *testing.T) {
806 _, r, db := setupHaEnv(true)
808 expectedData := []interface{}{"data", 2}
809 r.On("SRem", expectedKey, expectedData).Return(redis.NewIntResult(2, nil))
810 assert.Nil(t, db.SRem("key", "data", 2))
811 r.AssertExpectations(t)
814 func TestSRemFailure(t *testing.T) {
815 _, r, db := setupHaEnv(true)
817 expectedData := []interface{}{"data", 2}
818 r.On("SRem", expectedKey, expectedData).Return(redis.NewIntResult(2, errors.New("Some error")))
819 assert.NotNil(t, db.SRem("key", "data", 2))
820 r.AssertExpectations(t)
823 func TestSMembersSuccessfully(t *testing.T) {
824 _, r, db := setupHaEnv(true)
826 expectedResult := []string{"member1", "member2"}
827 r.On("SMembers", expectedKey).Return(redis.NewStringSliceResult(expectedResult, nil))
828 result, err := db.SMembers("key")
829 assert.Equal(t, result, expectedResult)
831 r.AssertExpectations(t)
834 func TestSMembersFailure(t *testing.T) {
835 _, r, db := setupHaEnv(true)
837 expectedResult := []string{"member1", "member2"}
838 r.On("SMembers", expectedKey).Return(redis.NewStringSliceResult(expectedResult,
839 errors.New("Some error")))
840 result, err := db.SMembers("key")
841 assert.Equal(t, result, expectedResult)
842 assert.NotNil(t, err)
843 r.AssertExpectations(t)
846 func TestSIsMemberIsMember(t *testing.T) {
847 _, r, db := setupHaEnv(true)
849 expectedData := "data"
850 r.On("SIsMember", expectedKey, expectedData).Return(redis.NewBoolResult(true, nil))
851 result, err := db.SIsMember("key", "data")
852 assert.True(t, result)
854 r.AssertExpectations(t)
857 func TestSIsMemberIsNotMember(t *testing.T) {
858 _, r, db := setupHaEnv(true)
860 expectedData := "data"
861 r.On("SIsMember", expectedKey, expectedData).Return(redis.NewBoolResult(false, nil))
862 result, err := db.SIsMember("key", "data")
863 assert.False(t, result)
865 r.AssertExpectations(t)
868 func TestSIsMemberFailure(t *testing.T) {
869 _, r, db := setupHaEnv(true)
871 expectedData := "data"
872 r.On("SIsMember", expectedKey, expectedData).
873 Return(redis.NewBoolResult(false, errors.New("Some error")))
874 result, err := db.SIsMember("key", "data")
875 assert.False(t, result)
876 assert.NotNil(t, err)
877 r.AssertExpectations(t)
880 func TestSCardSuccessfully(t *testing.T) {
881 _, r, db := setupHaEnv(true)
883 r.On("SCard", expectedKey).Return(redis.NewIntResult(1, nil))
884 result, err := db.SCard("key")
885 assert.Equal(t, int64(1), result)
887 r.AssertExpectations(t)
890 func TestSCardFailure(t *testing.T) {
891 _, r, db := setupHaEnv(true)
893 r.On("SCard", expectedKey).Return(redis.NewIntResult(1, errors.New("Some error")))
894 result, err := db.SCard("key")
895 assert.Equal(t, int64(1), result)
896 assert.NotNil(t, err)
897 r.AssertExpectations(t)
900 func TestSubscribeChannelDBSubscribeRXUnsubscribe(t *testing.T) {
901 ps, r, db := setupHaEnv(true)
902 ch := make(chan *redis.Message)
903 msg := redis.Message{
904 Channel: "{prefix},channel",
908 ps.On("Channel").Return(ch)
909 ps.On("Subscribe").Return(nil)
910 ps.On("Unsubscribe").Return(nil)
911 ps.On("Close").Return(nil)
913 receivedChannel := ""
914 err := db.SubscribeChannelDB(func(channel string, payload ...string) {
916 receivedChannel = channel
917 }, "{prefix},channel")
920 err = db.UnsubscribeChannelDB("{prefix},channel")
922 time.Sleep(1 * time.Second)
923 assert.Equal(t, 1, count)
924 assert.Equal(t, "channel", receivedChannel)
925 r.AssertExpectations(t)
926 ps.AssertExpectations(t)
929 func TestSubscribeChannelDBFailure(t *testing.T) {
930 mockedErr := errors.New("Some DB Backend Subscribe Error")
931 ps, r, db := setupHaEnv(true)
932 ch := make(chan *redis.Message)
933 ps.On("Channel").Return(ch)
934 ps.On("Subscribe").Return(mockedErr)
935 err := db.SubscribeChannelDB(func(channel string, payload ...string) {
936 }, "{prefix},channel")
937 assert.NotNil(t, err)
938 assert.Contains(t, err.Error(), mockedErr.Error())
939 r.AssertExpectations(t)
940 ps.AssertExpectations(t)
943 func TestUnsubscribeChannelDBFailure(t *testing.T) {
944 mockedErr := errors.New("Some DB Backend Unsubscribe Error")
945 ps, r, db := setupHaEnv(true)
946 ch := make(chan *redis.Message)
947 ps.On("Channel").Return(ch)
948 ps.On("Subscribe").Return(nil)
949 ps.On("Unsubscribe").Return(mockedErr)
950 err := db.SubscribeChannelDB(func(channel string, payload ...string) {
951 }, "{prefix},channel")
953 err = db.UnsubscribeChannelDB("{prefix},channel")
954 assert.NotNil(t, err)
955 assert.Contains(t, err.Error(), mockedErr.Error())
956 r.AssertExpectations(t)
957 ps.AssertExpectations(t)
960 func TestSubscribeChannelDBSubscribeTwoUnsubscribeOne(t *testing.T) {
961 ps, r, db := setupHaEnv(true)
962 ch := make(chan *redis.Message)
963 msg1 := redis.Message{
964 Channel: "{prefix},channel1",
968 msg2 := redis.Message{
969 Channel: "{prefix},channel2",
973 ps.On("Channel").Return(ch)
974 ps.On("Subscribe").Return(nil)
975 ps.On("Unsubscribe").Return(nil)
976 ps.On("Unsubscribe").Return(nil)
977 ps.On("Close").Return(nil)
979 receivedChannel1 := ""
980 err := db.SubscribeChannelDB(func(channel string, payload ...string) {
982 receivedChannel1 = channel
983 }, "{prefix},channel1")
986 receivedChannel2 := ""
987 err = db.SubscribeChannelDB(func(channel string, payload ...string) {
989 receivedChannel2 = channel
990 }, "{prefix},channel2")
992 time.Sleep(1 * time.Second)
993 err = db.UnsubscribeChannelDB("{prefix},channel1")
996 err = db.UnsubscribeChannelDB("{prefix},channel2")
998 time.Sleep(1 * time.Second)
999 assert.Equal(t, 2, count)
1000 assert.Equal(t, "channel1", receivedChannel1)
1001 assert.Equal(t, "channel2", receivedChannel2)
1002 r.AssertExpectations(t)
1003 ps.AssertExpectations(t)
1006 func TestSubscribeChannelDBTwoSubscribesWithUnequalPrefixAndUnsubscribes(t *testing.T) {
1007 ps, r, db := setupHaEnv(true)
1008 ch := make(chan *redis.Message)
1009 msg1 := redis.Message{
1010 Channel: "{prefix1},channel",
1014 msg2 := redis.Message{
1015 Channel: "{prefix2},channel",
1019 ps.On("Channel").Return(ch)
1020 ps.On("Subscribe").Return(nil)
1021 ps.On("Unsubscribe").Return(nil)
1022 ps.On("Unsubscribe").Return(nil)
1023 ps.On("Close").Return(nil)
1025 receivedChannel1 := ""
1026 err := db.SubscribeChannelDB(func(channel string, payload ...string) {
1028 receivedChannel1 = channel
1029 }, "{prefix1},channel")
1032 receivedChannel2 := ""
1033 err = db.SubscribeChannelDB(func(channel string, payload ...string) {
1035 receivedChannel2 = channel
1036 }, "{prefix2},channel")
1038 time.Sleep(1 * time.Second)
1039 err = db.UnsubscribeChannelDB("{prefix1},channel")
1042 err = db.UnsubscribeChannelDB("{prefix2},channel")
1044 time.Sleep(1 * time.Second)
1045 assert.Equal(t, 2, count)
1046 assert.Equal(t, "channel", receivedChannel1)
1047 assert.Equal(t, "channel", receivedChannel2)
1048 r.AssertExpectations(t)
1049 ps.AssertExpectations(t)
1052 func TestSubscribeChannelReDBSubscribeAfterUnsubscribe(t *testing.T) {
1053 ps, r, db := setupHaEnv(true)
1054 ch := make(chan *redis.Message)
1055 msg := redis.Message{
1056 Channel: "{prefix},channel",
1060 ps.On("Channel").Return(ch)
1061 ps.On("Subscribe").Return(nil)
1062 ps.On("Unsubscribe").Return(nil)
1063 ps.On("Close").Return(nil)
1065 receivedChannel := ""
1067 err := db.SubscribeChannelDB(func(channel string, payload ...string) {
1069 receivedChannel = channel
1070 }, "{prefix},channel")
1073 err = db.UnsubscribeChannelDB("{prefix},channel")
1075 time.Sleep(1 * time.Second)
1077 err = db.SubscribeChannelDB(func(channel string, payload ...string) {
1079 receivedChannel = channel
1080 }, "{prefix}", "---", "{prefix},channel")
1083 err = db.UnsubscribeChannelDB("{prefix},channel")
1086 time.Sleep(1 * time.Second)
1087 assert.Equal(t, 2, count)
1088 assert.Equal(t, "channel", receivedChannel)
1089 r.AssertExpectations(t)
1090 ps.AssertExpectations(t)
1093 func TestSubscribeChannelDBSubscribeReceivedEventIgnoredIfChannelNameIsUnknown(t *testing.T) {
1094 ps, r, db := setupHaEnv(true)
1095 ch := make(chan *redis.Message)
1096 msg := redis.Message{
1097 Channel: "missingNsPrefixchannel",
1101 ps.On("Channel").Return(ch)
1102 ps.On("Subscribe").Return(nil)
1103 ps.On("Unsubscribe").Return(nil)
1104 ps.On("Close").Return(nil)
1106 receivedChannel := ""
1107 err := db.SubscribeChannelDB(func(channel string, payload ...string) {
1109 receivedChannel = channel
1110 }, "{prefix},channel")
1113 err = db.UnsubscribeChannelDB("{prefix},channel")
1115 time.Sleep(1 * time.Second)
1116 assert.Equal(t, 0, count)
1117 assert.Equal(t, "", receivedChannel)
1118 r.AssertExpectations(t)
1119 ps.AssertExpectations(t)
1122 func TestPTTLSuccessfully(t *testing.T) {
1123 _, r, db := setupHaEnv(true)
1124 expectedKey := "key"
1125 expectedResult := time.Duration(1)
1126 r.On("PTTL", expectedKey).Return(redis.NewDurationResult(expectedResult,
1128 result, err := db.PTTL("key")
1129 assert.Equal(t, result, expectedResult)
1131 r.AssertExpectations(t)
1134 func TestPTTLFailure(t *testing.T) {
1135 _, r, db := setupHaEnv(true)
1136 expectedKey := "key"
1137 expectedResult := time.Duration(1)
1138 r.On("PTTL", expectedKey).Return(redis.NewDurationResult(expectedResult,
1139 errors.New("Some error")))
1140 result, err := db.PTTL("key")
1141 assert.Equal(t, result, expectedResult)
1142 assert.NotNil(t, err)
1143 r.AssertExpectations(t)
1146 func TestPExpireIESuccessfully(t *testing.T) {
1147 _, r, db := setupHaEnv(true)
1148 expectedKey := "key"
1149 expectedData := "data"
1150 expectedDuration := strconv.FormatInt(int64(10000), 10)
1152 r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
1153 Return(redis.NewCmdResult(int64(1), nil))
1155 err := db.PExpireIE("key", "data", 10*time.Second)
1157 r.AssertExpectations(t)
1160 func TestPExpireIEFailure(t *testing.T) {
1161 _, r, db := setupHaEnv(true)
1162 expectedKey := "key"
1163 expectedData := "data"
1164 expectedDuration := strconv.FormatInt(int64(10000), 10)
1166 r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
1167 Return(redis.NewCmdResult(int64(1), errors.New("Some error")))
1169 err := db.PExpireIE("key", "data", 10*time.Second)
1170 assert.NotNil(t, err)
1171 r.AssertExpectations(t)
1174 func TestPExpireIELockNotHeld(t *testing.T) {
1175 _, r, db := setupHaEnv(true)
1176 expectedKey := "key"
1177 expectedData := "data"
1178 expectedDuration := strconv.FormatInt(int64(10000), 10)
1180 r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
1181 Return(redis.NewCmdResult(int64(0), nil))
1183 err := db.PExpireIE("key", "data", 10*time.Second)
1184 assert.NotNil(t, err)
1185 r.AssertExpectations(t)
1188 func TestClientStandaloneRedisLegacyEnv(t *testing.T) {
1189 setupVals := setupEnv(
1191 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379", "", "", "", "",
1193 assert.Equal(t, 1, len(setupVals.rClient))
1194 assert.Equal(t, 1, len(setupVals.db))
1196 expectedKeysAndValues := []interface{}{"key1", "value1"}
1197 setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1198 err := setupVals.db[0].MSet("key1", "value1")
1200 setupVals.rClient[0].AssertExpectations(t)
1203 func TestClientSentinelRedisLegacyEnv(t *testing.T) {
1204 setupVals := setupEnv(
1206 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379", "dbaasmaster-cluster-0", "26379", "", "3",
1208 assert.Equal(t, 1, len(setupVals.rClient))
1209 assert.Equal(t, 1, len(setupVals.db))
1211 expectedKeysAndValues := []interface{}{"key1", "value1"}
1212 setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1213 err := setupVals.db[0].MSet("key1", "value1")
1215 setupVals.rClient[0].AssertExpectations(t)
1218 func TestClientTwoStandaloneRedisEnvs(t *testing.T) {
1219 setupVals := setupEnv(
1221 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379,6380", "", "",
1222 "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "",
1224 assert.Equal(t, 2, len(setupVals.rClient))
1225 assert.Equal(t, 2, len(setupVals.db))
1227 expectedKeysAndValues := []interface{}{"key1", "value1"}
1228 setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1229 err := setupVals.db[0].MSet("key1", "value1")
1231 setupVals.rClient[0].AssertExpectations(t)
1233 expectedKeysAndValues = []interface{}{"key2", "value2"}
1234 setupVals.rClient[1].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1235 err = setupVals.db[1].MSet("key2", "value2")
1237 setupVals.rClient[0].AssertExpectations(t)
1238 setupVals.rClient[1].AssertExpectations(t)
1241 func TestClientTwoSentinelRedisEnvs(t *testing.T) {
1242 setupVals := setupEnv(
1244 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379,6380", "dbaasmaster-cluster-0,dbaasmaster-cluster-1",
1245 "26379,26380", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1247 assert.Equal(t, 2, len(setupVals.rClient))
1248 assert.Equal(t, 2, len(setupVals.db))
1250 expectedKeysAndValues := []interface{}{"key1", "value1"}
1251 setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1252 err := setupVals.db[0].MSet("key1", "value1")
1254 setupVals.rClient[0].AssertExpectations(t)
1256 expectedKeysAndValues = []interface{}{"key2", "value2"}
1257 setupVals.rClient[1].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1258 err = setupVals.db[1].MSet("key2", "value2")
1260 setupVals.rClient[0].AssertExpectations(t)
1261 setupVals.rClient[1].AssertExpectations(t)
1264 func TestCompleteConfigIfLessPortsThanAddresses(t *testing.T) {
1265 setupVals := setupEnv(
1267 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379", "dbaasmaster-cluster-0,dbaasmaster-cluster-1",
1268 "", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1270 assert.Equal(t, 2, len(setupVals.rClient))
1271 assert.Equal(t, 2, len(setupVals.db))
1274 func TestCompleteConfigIfLessSentinelPortsThanAddresses(t *testing.T) {
1275 setupVals := setupEnv(
1277 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379,6380", "dbaasmaster-cluster-0,dbaasmaster-cluster-1",
1278 "26379", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1280 assert.Equal(t, 2, len(setupVals.rClient))
1281 assert.Equal(t, 2, len(setupVals.db))
1284 func TestCompleteConfigIfLessSentinelNamesThanAddresses(t *testing.T) {
1285 setupVals := setupEnv(
1287 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379,6380", "dbaasmaster-cluster-0",
1288 "26379,26380", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1290 assert.Equal(t, 2, len(setupVals.rClient))
1291 assert.Equal(t, 2, len(setupVals.db))
1294 func TestInfoOfPrimaryRedisWithTwoReplicasSuccessfully(t *testing.T) {
1295 _, r, db := setupHaEnv(true)
1296 redisInfo := "# Replication\r\n" +
1298 "connected_slaves:2\r\n" +
1299 "min_slaves_good_slaves:2\r\n" +
1300 "slave0:ip=1.2.3.4,port=6379,state=online,offset=100200300,lag=0\r\n" +
1301 "slave1:ip=5.6.7.8,port=6379,state=online,offset=100200300,lag=0\r\n"
1302 expInfo := &sdlgoredis.DbInfo{
1303 Fields: sdlgoredis.DbInfoFields{
1305 ConnectedReplicaCnt: 2,
1309 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1310 info, err := db.Info()
1312 assert.Equal(t, expInfo, info)
1313 r.AssertExpectations(t)
1316 func TestInfoOfPrimaryRedisWithOneReplicaOnlineAndOtherReplicaNotOnlineSuccessfully(t *testing.T) {
1317 _, r, db := setupHaEnv(true)
1318 redisInfo := "# Replication\r\n" +
1320 "connected_slaves:1\r\n" +
1321 "min_slaves_good_slaves:2\r\n" +
1322 "slave0:ip=1.2.3.4,port=6379,state=online,offset=100200300,lag=0\r\n" +
1323 "slave1:ip=5.6.7.8,port=6379,state=wait_bgsave,offset=100200300,lag=0\r\n"
1324 expInfo := &sdlgoredis.DbInfo{
1325 Fields: sdlgoredis.DbInfoFields{
1327 ConnectedReplicaCnt: 1,
1331 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1332 info, err := db.Info()
1334 assert.Equal(t, expInfo, info)
1335 r.AssertExpectations(t)
1338 func TestInfoOfStandalonePrimaryRedisSuccessfully(t *testing.T) {
1339 _, r, db := setupHaEnv(true)
1340 redisInfo := "# Replication\r\n" +
1342 "connected_slaves:0\r\n" +
1343 "min_slaves_good_slaves:0\r\n"
1344 expInfo := &sdlgoredis.DbInfo{
1345 Fields: sdlgoredis.DbInfoFields{
1347 ConnectedReplicaCnt: 0,
1351 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1352 info, err := db.Info()
1354 assert.Equal(t, expInfo, info)
1355 r.AssertExpectations(t)
1358 func TestInfoOfStandalonePrimaryRedisFailureWhenIntConversionFails(t *testing.T) {
1359 _, r, db := setupHaEnv(true)
1360 redisInfo := "# Replication\r\n" +
1362 "connected_slaves:not-int\r\n" +
1363 "min_slaves_good_slaves:0\r\n"
1364 expInfo := &sdlgoredis.DbInfo{
1365 Fields: sdlgoredis.DbInfoFields{
1367 ConnectedReplicaCnt: 0,
1371 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1372 info, err := db.Info()
1374 assert.Equal(t, expInfo, info)
1375 r.AssertExpectations(t)
1378 func TestInfoWithGibberishContentSuccessfully(t *testing.T) {
1379 _, r, db := setupHaEnv(true)
1380 redisInfo := "!#¤%&?+?´-\r\n"
1381 expInfo := &sdlgoredis.DbInfo{}
1383 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1384 info, err := db.Info()
1386 assert.Equal(t, expInfo, info)
1387 r.AssertExpectations(t)
1390 func TestInfoWithEmptyContentSuccessfully(t *testing.T) {
1391 _, r, db := setupHaEnv(true)
1392 var redisInfo string
1393 expInfo := &sdlgoredis.DbInfo{
1394 Fields: sdlgoredis.DbInfoFields{
1399 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1400 info, err := db.Info()
1402 assert.Equal(t, expInfo, info)
1403 r.AssertExpectations(t)
1406 func TestInfoWithSomeStatisticsOfStandalonePrimaryRedis(t *testing.T) {
1407 _, r, db := setupHaEnv(true)
1408 redisInfo := "# Replication\r\n" +
1410 "connected_slaves:0\r\n" +
1411 "min_slaves_good_slaves:0\r\n" +
1413 "uptime_in_days:23\r\n" +
1415 "connected_clients:2\r\n" +
1417 "used_memory:2093808\r\n" +
1418 "used_memory_human:2.00M\r\n" +
1419 "mem_fragmentation_ratio:6.44\r\n" +
1421 "total_connections_received:278\r\n" +
1423 "used_cpu_sys:1775.254919\r\n" +
1424 "# Commandstats\r\n" +
1425 "cmdstat_role:calls=1,usec=3,usec_per_call=3.00\r\n" +
1427 "db0:keys=4,expires=0,avg_ttl=0"
1428 expInfo := &sdlgoredis.DbInfo{
1429 Fields: sdlgoredis.DbInfoFields{
1431 ConnectedReplicaCnt: 0,
1432 Server: sdlgoredis.ServerInfoFields{
1435 Clients: sdlgoredis.ClientsInfoFields{
1436 ConnectedClients: 2,
1438 Memory: sdlgoredis.MeroryInfoFields{
1439 UsedMemory: 2093808,
1440 UsedMemoryHuman: "2.00M",
1441 MemFragmentationRatio: 6.44,
1443 Stats: sdlgoredis.StatsInfoFields{
1444 TotalConnectionsReceived: 278,
1446 Cpu: sdlgoredis.CpuInfoFields{
1447 UsedCpuSys: 1775.254919,
1449 Commandstats: sdlgoredis.CommandstatsInfoFields{
1450 CmdstatRole: sdlgoredis.CommandstatsValues{
1456 Keyspace: sdlgoredis.KeyspaceInfoFields{
1457 Db: sdlgoredis.KeyspaceValues{
1464 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1465 info, err := db.Info()
1467 assert.Equal(t, expInfo, info)
1468 r.AssertExpectations(t)
1471 func TestStateWithPrimaryAndTwoReplicaRedisSuccessfully(t *testing.T) {
1472 _, r, s, db := setupHaEnvWithSentinels(true, "3")
1474 redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1475 redisReplicasState := newMockRedisSlavesCall()
1476 redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1477 redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1478 redisSentinelsState := newMockRedisSentinelsCall()
1479 redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1480 redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1482 expState := newExpDbState(3, nil)
1483 expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1484 expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1485 expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1486 expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1487 expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1489 s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1490 s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1491 s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1492 ret, err := db.State()
1494 assert.Equal(t, expState.s, *ret)
1495 r.AssertExpectations(t)
1498 func TestStateWithTwoSdlClustersContainingPrimaryAndTwoReplicaRedisSuccessfully(t *testing.T) {
1499 setupVals := setupEnv(
1501 "", "6379,6380", "dbaasmaster-cluster-0,dbaasmaster-cluster-1",
1502 "26379,26380", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1504 r := setupVals.rClient
1505 s := setupVals.rSentinel
1508 FstRedisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1509 FstRedisReplicasState := newMockRedisSlavesCall()
1510 FstRedisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1511 FstRedisReplicasState.add("slave", "10.20.30.50", "6379", "up", "slave")
1512 FstRedisSentinelsState := newMockRedisSentinelsCall()
1513 FstRedisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1514 FstRedisSentinelsState.add("10.20.30.50", "26379", "sentinel")
1516 SndRedisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.60", "6380", "master")
1517 SndRedisReplicasState := newMockRedisSlavesCall()
1518 SndRedisReplicasState.add("slave", "10.20.30.70", "6380", "up", "slave")
1519 SndRedisReplicasState.add("slave", "10.20.30.80", "6380", "up", "slave")
1520 SndRedisSentinelsState := newMockRedisSentinelsCall()
1521 SndRedisSentinelsState.add("10.20.30.70", "26380", "sentinel")
1522 SndRedisSentinelsState.add("10.20.30.80", "26380", "sentinel")
1524 FstExpState := newExpDbState(3, nil)
1525 FstExpState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1526 FstExpState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1527 FstExpState.addReplica("slave", "10.20.30.50", "6379", "up", "slave", nil)
1528 FstExpState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1529 FstExpState.addSentinel("10.20.30.50", "26379", "sentinel", nil)
1531 SndExpState := newExpDbState(3, nil)
1532 SndExpState.addPrimary("master", "10.20.30.60", "6380", "master", nil)
1533 SndExpState.addReplica("slave", "10.20.30.70", "6380", "up", "slave", nil)
1534 SndExpState.addReplica("slave", "10.20.30.80", "6380", "up", "slave", nil)
1535 SndExpState.addSentinel("10.20.30.70", "26380", "sentinel", nil)
1536 SndExpState.addSentinel("10.20.30.80", "26380", "sentinel", nil)
1538 s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(FstRedisPrimaryState, nil))
1539 s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(FstRedisReplicasState.resp, nil))
1540 s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(FstRedisSentinelsState.resp, nil))
1542 s[0].On("Master", "dbaasmaster-cluster-1").Return(redis.NewStringStringMapResult(SndRedisPrimaryState, nil))
1543 s[0].On("Slaves", "dbaasmaster-cluster-1").Return(redis.NewSliceResult(SndRedisReplicasState.resp, nil))
1544 s[0].On("Sentinels", "dbaasmaster-cluster-1").Return(redis.NewSliceResult(SndRedisSentinelsState.resp, nil))
1546 ret, err := db[0].State()
1548 assert.Equal(t, FstExpState.s, *ret)
1550 ret, err = db[1].State()
1552 assert.Equal(t, SndExpState.s, *ret)
1553 r[0].AssertExpectations(t)
1556 func TestStateWithPrimaryAndTwoReplicaRedisFailureInPrimaryRedisCall(t *testing.T) {
1557 expErr := errors.New("Some error")
1558 _, r, s, db := setupHaEnvWithSentinels(true, "3")
1560 redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1561 redisReplicasState := newMockRedisSlavesCall()
1562 redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1563 redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1564 redisSentinelsState := newMockRedisSentinelsCall()
1565 redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1566 redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1568 expState := newExpDbState(3, nil)
1569 expState.addPrimary("", "", "", "", expErr)
1570 expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1571 expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1572 expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1573 expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1575 s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, expErr))
1576 s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1577 s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1578 ret, err := db.State()
1579 assert.NotNil(t, err)
1580 assert.Equal(t, expState.s, *ret)
1581 r.AssertExpectations(t)
1584 func TestStateWithPrimaryAndTwoReplicaRedisFailureInReplicasRedisCall(t *testing.T) {
1585 expErr := errors.New("Some error")
1586 _, r, s, db := setupHaEnvWithSentinels(true, "3")
1588 redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1589 redisReplicasState := newMockRedisSlavesCall()
1590 redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1591 redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1592 redisSentinelsState := newMockRedisSentinelsCall()
1593 redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1594 redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1596 expState := newExpDbState(3, nil)
1597 expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1598 expState.addReplica("", "", "", "", "", expErr)
1599 expState.addReplica("", "", "", "", "", expErr)
1600 expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1601 expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1603 s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1604 s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, errors.New("Some error")))
1605 s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1606 ret, err := db.State()
1607 assert.NotNil(t, err)
1608 assert.Equal(t, expState.s, *ret)
1609 r.AssertExpectations(t)
1612 func TestStateWithPrimaryAndOneReplicaRedisFailureInSentinelsRedisCall(t *testing.T) {
1613 expErr := errors.New("Some error")
1614 _, r, s, db := setupHaEnvWithSentinels(true, "2")
1616 redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1617 redisReplicasState := newMockRedisSlavesCall()
1618 redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1619 redisSentinelsState := newMockRedisSentinelsCall()
1620 redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1622 expState := newExpDbState(2, nil)
1623 expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1624 expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1625 expState.addSentinel("", "", "", expErr)
1627 s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1628 s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1629 s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, expErr))
1630 ret, err := db.State()
1631 assert.NotNil(t, err)
1632 assert.Equal(t, expState.s, *ret)
1633 r.AssertExpectations(t)
1636 func TestStateWithPrimaryAndTwoReplicaRedisFailureWhenIntConversionFails(t *testing.T) {
1637 expErr := errors.New("Sentinel DBAAS_NODE_COUNT configuration value 'no-int' conversion to integer failed")
1638 _, r, s, db := setupHaEnvWithSentinels(true, "no-int")
1640 redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1641 redisReplicasState := newMockRedisSlavesCall()
1642 redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1643 redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1644 redisSentinelsState := newMockRedisSentinelsCall()
1645 redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1646 redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1648 expState := newExpDbState(0, expErr)
1649 expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1650 expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1651 expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1652 expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1653 expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1655 s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1656 s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1657 s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1658 ret, err := db.State()
1659 assert.Equal(t, expErr, err)
1660 assert.Equal(t, expState.s, *ret)
1661 r.AssertExpectations(t)
1664 // Test case to test ignoring of a sentinel entry with zero port. Implementation has been
1665 // done because we miss the fix for the Redis Bug #9240.
1666 func TestStateWithPrimaryAndTwoReplicaFirstSentinelStateIgnoredBecauseZeroPortBugRedisSuccessfully(t *testing.T) {
1667 _, r, s, db := setupHaEnvWithSentinels(true, "3")
1669 redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1670 redisReplicasState := newMockRedisSlavesCall()
1671 redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1672 redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1673 redisSentinelsState := newMockRedisSentinelsCall()
1674 redisSentinelsState.add("10.20.30.40", "0", "s_down,sentinel,disconnected")
1675 redisSentinelsState.add("10.20.30.50", "26379", "sentinel")
1677 expState := newExpDbState(3, nil)
1678 expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1679 expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1680 expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1681 expState.addSentinel("10.20.30.50", "26379", "sentinel", nil)
1683 s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1684 s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1685 s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1686 ret, err := db.State()
1688 assert.Equal(t, expState.s, *ret)
1689 r.AssertExpectations(t)
1692 func TestStateWithSinglePrimaryRedisSuccessfully(t *testing.T) {
1693 _, r, db := setupSingleEnv(true, "1")
1694 redisInfo := "# Replication\r\n" +
1696 "connected_slaves:0\r\n" +
1697 "min_slaves_good_slaves:0\r\n"
1699 expState := &sdlgoredis.DbState{
1701 PrimaryDbState: sdlgoredis.PrimaryDbState{
1702 Fields: sdlgoredis.PrimaryDbStateFields{
1704 Ip: "service-ricplt-dbaas-tcp-cluster-0.ricplt",
1711 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1712 ret, err := db.State()
1714 assert.Equal(t, expState, ret)
1715 r.AssertExpectations(t)
1718 func TestStateWithSinglePrimaryRedisFailureWhenIntConversionFails(t *testing.T) {
1719 expErr := errors.New("DBAAS_NODE_COUNT configuration value 'no-int' conversion to integer failed")
1720 _, r, db := setupSingleEnv(true, "no-int")
1721 redisInfo := "# Replication\r\n" +
1723 "connected_slaves:0\r\n" +
1724 "min_slaves_good_slaves:0\r\n"
1726 expState := &sdlgoredis.DbState{
1729 PrimaryDbState: sdlgoredis.PrimaryDbState{
1730 Fields: sdlgoredis.PrimaryDbStateFields{
1732 Ip: "service-ricplt-dbaas-tcp-cluster-0.ricplt",
1739 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1740 ret, err := db.State()
1741 assert.Equal(t, expErr, err)
1742 assert.Equal(t, expState, ret)
1743 r.AssertExpectations(t)
1746 func TestStateWithSinglePrimaryRedisFailureInInfoCall(t *testing.T) {
1747 expErr := errors.New("Some error")
1748 _, r, db := setupSingleEnv(true, "1")
1750 expState := &sdlgoredis.DbState{
1751 PrimaryDbState: sdlgoredis.PrimaryDbState{
1756 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, errors.New("Some error")))
1757 ret, err := db.State()
1758 assert.NotNil(t, err)
1759 assert.Equal(t, expState, ret)
1760 r.AssertExpectations(t)
1763 func TestStatisticsWithSinglePrimaryRedisSuccessfully(t *testing.T) {
1764 _, r, db := setupSingleEnv(true, "1")
1765 redisInfo := "# Replication\r\n" +
1767 "connected_slaves:0\r\n" +
1768 "min_slaves_good_slaves:0\r\n" +
1770 "uptime_in_days:12\r\n"
1772 expStatistics := &sdlgoredis.DbStatistics{
1773 Stats: []*sdlgoredis.DbStatisticsInfo{
1775 IPAddr: "service-ricplt-dbaas-tcp-cluster-0.ricplt",
1777 Info: &sdlgoredis.DbInfo{
1778 Fields: sdlgoredis.DbInfoFields{
1780 Server: sdlgoredis.ServerInfoFields{
1789 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1790 ret, err := db.Statistics()
1792 assert.Equal(t, expStatistics, ret)
1793 r.AssertExpectations(t)