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("Unsubscribe").Return(nil)
910 ps.On("Close").Return(nil)
912 receivedChannel := ""
913 db.SubscribeChannelDB(func(channel string, payload ...string) {
915 receivedChannel = channel
916 }, "{prefix},channel")
918 db.UnsubscribeChannelDB("{prefix},channel")
919 time.Sleep(1 * time.Second)
920 assert.Equal(t, 1, count)
921 assert.Equal(t, "channel", receivedChannel)
922 r.AssertExpectations(t)
923 ps.AssertExpectations(t)
926 func TestSubscribeChannelDBSubscribeTwoUnsubscribeOne(t *testing.T) {
927 ps, r, db := setupHaEnv(true)
928 ch := make(chan *redis.Message)
929 msg1 := redis.Message{
930 Channel: "{prefix},channel1",
934 msg2 := redis.Message{
935 Channel: "{prefix},channel2",
939 ps.On("Channel").Return(ch)
940 ps.On("Subscribe").Return(nil)
941 ps.On("Unsubscribe").Return(nil)
942 ps.On("Unsubscribe").Return(nil)
943 ps.On("Close").Return(nil)
945 receivedChannel1 := ""
946 db.SubscribeChannelDB(func(channel string, payload ...string) {
948 receivedChannel1 = channel
949 }, "{prefix},channel1")
951 receivedChannel2 := ""
952 db.SubscribeChannelDB(func(channel string, payload ...string) {
954 receivedChannel2 = channel
955 }, "{prefix},channel2")
957 time.Sleep(1 * time.Second)
958 db.UnsubscribeChannelDB("{prefix},channel1")
960 db.UnsubscribeChannelDB("{prefix},channel2")
961 time.Sleep(1 * time.Second)
962 assert.Equal(t, 2, count)
963 assert.Equal(t, "channel1", receivedChannel1)
964 assert.Equal(t, "channel2", receivedChannel2)
965 r.AssertExpectations(t)
966 ps.AssertExpectations(t)
969 func TestSubscribeChannelDBTwoSubscribesWithUnequalPrefixAndUnsubscribes(t *testing.T) {
970 ps, r, db := setupHaEnv(true)
971 ch := make(chan *redis.Message)
972 msg1 := redis.Message{
973 Channel: "{prefix1},channel",
977 msg2 := redis.Message{
978 Channel: "{prefix2},channel",
982 ps.On("Channel").Return(ch)
983 ps.On("Subscribe").Return(nil)
984 ps.On("Unsubscribe").Return(nil)
985 ps.On("Unsubscribe").Return(nil)
986 ps.On("Close").Return(nil)
988 receivedChannel1 := ""
989 db.SubscribeChannelDB(func(channel string, payload ...string) {
991 receivedChannel1 = channel
992 }, "{prefix1},channel")
994 receivedChannel2 := ""
995 db.SubscribeChannelDB(func(channel string, payload ...string) {
997 receivedChannel2 = channel
998 }, "{prefix2},channel")
1000 time.Sleep(1 * time.Second)
1001 db.UnsubscribeChannelDB("{prefix1},channel")
1003 db.UnsubscribeChannelDB("{prefix2},channel")
1004 time.Sleep(1 * time.Second)
1005 assert.Equal(t, 2, count)
1006 assert.Equal(t, "channel", receivedChannel1)
1007 assert.Equal(t, "channel", receivedChannel2)
1008 r.AssertExpectations(t)
1009 ps.AssertExpectations(t)
1012 func TestSubscribeChannelReDBSubscribeAfterUnsubscribe(t *testing.T) {
1013 ps, r, db := setupHaEnv(true)
1014 ch := make(chan *redis.Message)
1015 msg := redis.Message{
1016 Channel: "{prefix},channel",
1020 ps.On("Channel").Return(ch)
1021 ps.On("Unsubscribe").Return(nil)
1022 ps.On("Close").Return(nil)
1024 receivedChannel := ""
1026 db.SubscribeChannelDB(func(channel string, payload ...string) {
1028 receivedChannel = channel
1029 }, "{prefix},channel")
1031 db.UnsubscribeChannelDB("{prefix},channel")
1032 time.Sleep(1 * time.Second)
1034 db.SubscribeChannelDB(func(channel string, payload ...string) {
1036 receivedChannel = channel
1037 }, "{prefix}", "---", "{prefix},channel")
1039 db.UnsubscribeChannelDB("{prefix},channel")
1041 time.Sleep(1 * time.Second)
1042 assert.Equal(t, 2, count)
1043 assert.Equal(t, "channel", receivedChannel)
1044 r.AssertExpectations(t)
1045 ps.AssertExpectations(t)
1048 func TestSubscribeChannelDBSubscribeReceivedEventIgnoredIfChannelNameIsUnknown(t *testing.T) {
1049 ps, r, db := setupHaEnv(true)
1050 ch := make(chan *redis.Message)
1051 msg := redis.Message{
1052 Channel: "missingNsPrefixchannel",
1056 ps.On("Channel").Return(ch)
1057 ps.On("Unsubscribe").Return(nil)
1058 ps.On("Close").Return(nil)
1060 receivedChannel := ""
1061 db.SubscribeChannelDB(func(channel string, payload ...string) {
1063 receivedChannel = channel
1064 }, "{prefix},channel")
1066 db.UnsubscribeChannelDB("{prefix},channel")
1067 time.Sleep(1 * time.Second)
1068 assert.Equal(t, 0, count)
1069 assert.Equal(t, "", receivedChannel)
1070 r.AssertExpectations(t)
1071 ps.AssertExpectations(t)
1074 func TestPTTLSuccessfully(t *testing.T) {
1075 _, r, db := setupHaEnv(true)
1076 expectedKey := "key"
1077 expectedResult := time.Duration(1)
1078 r.On("PTTL", expectedKey).Return(redis.NewDurationResult(expectedResult,
1080 result, err := db.PTTL("key")
1081 assert.Equal(t, result, expectedResult)
1083 r.AssertExpectations(t)
1086 func TestPTTLFailure(t *testing.T) {
1087 _, r, db := setupHaEnv(true)
1088 expectedKey := "key"
1089 expectedResult := time.Duration(1)
1090 r.On("PTTL", expectedKey).Return(redis.NewDurationResult(expectedResult,
1091 errors.New("Some error")))
1092 result, err := db.PTTL("key")
1093 assert.Equal(t, result, expectedResult)
1094 assert.NotNil(t, err)
1095 r.AssertExpectations(t)
1098 func TestPExpireIESuccessfully(t *testing.T) {
1099 _, r, db := setupHaEnv(true)
1100 expectedKey := "key"
1101 expectedData := "data"
1102 expectedDuration := strconv.FormatInt(int64(10000), 10)
1104 r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
1105 Return(redis.NewCmdResult(int64(1), nil))
1107 err := db.PExpireIE("key", "data", 10*time.Second)
1109 r.AssertExpectations(t)
1112 func TestPExpireIEFailure(t *testing.T) {
1113 _, r, db := setupHaEnv(true)
1114 expectedKey := "key"
1115 expectedData := "data"
1116 expectedDuration := strconv.FormatInt(int64(10000), 10)
1118 r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
1119 Return(redis.NewCmdResult(int64(1), errors.New("Some error")))
1121 err := db.PExpireIE("key", "data", 10*time.Second)
1122 assert.NotNil(t, err)
1123 r.AssertExpectations(t)
1126 func TestPExpireIELockNotHeld(t *testing.T) {
1127 _, r, db := setupHaEnv(true)
1128 expectedKey := "key"
1129 expectedData := "data"
1130 expectedDuration := strconv.FormatInt(int64(10000), 10)
1132 r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
1133 Return(redis.NewCmdResult(int64(0), nil))
1135 err := db.PExpireIE("key", "data", 10*time.Second)
1136 assert.NotNil(t, err)
1137 r.AssertExpectations(t)
1140 func TestClientStandaloneRedisLegacyEnv(t *testing.T) {
1141 setupVals := setupEnv(
1143 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379", "", "", "", "",
1145 assert.Equal(t, 1, len(setupVals.rClient))
1146 assert.Equal(t, 1, len(setupVals.db))
1148 expectedKeysAndValues := []interface{}{"key1", "value1"}
1149 setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1150 err := setupVals.db[0].MSet("key1", "value1")
1152 setupVals.rClient[0].AssertExpectations(t)
1155 func TestClientSentinelRedisLegacyEnv(t *testing.T) {
1156 setupVals := setupEnv(
1158 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379", "dbaasmaster-cluster-0", "26379", "", "3",
1160 assert.Equal(t, 1, len(setupVals.rClient))
1161 assert.Equal(t, 1, len(setupVals.db))
1163 expectedKeysAndValues := []interface{}{"key1", "value1"}
1164 setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1165 err := setupVals.db[0].MSet("key1", "value1")
1167 setupVals.rClient[0].AssertExpectations(t)
1170 func TestClientTwoStandaloneRedisEnvs(t *testing.T) {
1171 setupVals := setupEnv(
1173 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379,6380", "", "",
1174 "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "",
1176 assert.Equal(t, 2, len(setupVals.rClient))
1177 assert.Equal(t, 2, len(setupVals.db))
1179 expectedKeysAndValues := []interface{}{"key1", "value1"}
1180 setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1181 err := setupVals.db[0].MSet("key1", "value1")
1183 setupVals.rClient[0].AssertExpectations(t)
1185 expectedKeysAndValues = []interface{}{"key2", "value2"}
1186 setupVals.rClient[1].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1187 err = setupVals.db[1].MSet("key2", "value2")
1189 setupVals.rClient[0].AssertExpectations(t)
1190 setupVals.rClient[1].AssertExpectations(t)
1193 func TestClientTwoSentinelRedisEnvs(t *testing.T) {
1194 setupVals := setupEnv(
1196 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379,6380", "dbaasmaster-cluster-0,dbaasmaster-cluster-1",
1197 "26379,26380", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1199 assert.Equal(t, 2, len(setupVals.rClient))
1200 assert.Equal(t, 2, len(setupVals.db))
1202 expectedKeysAndValues := []interface{}{"key1", "value1"}
1203 setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1204 err := setupVals.db[0].MSet("key1", "value1")
1206 setupVals.rClient[0].AssertExpectations(t)
1208 expectedKeysAndValues = []interface{}{"key2", "value2"}
1209 setupVals.rClient[1].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1210 err = setupVals.db[1].MSet("key2", "value2")
1212 setupVals.rClient[0].AssertExpectations(t)
1213 setupVals.rClient[1].AssertExpectations(t)
1216 func TestCompleteConfigIfLessPortsThanAddresses(t *testing.T) {
1217 setupVals := setupEnv(
1219 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379", "dbaasmaster-cluster-0,dbaasmaster-cluster-1",
1220 "", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1222 assert.Equal(t, 2, len(setupVals.rClient))
1223 assert.Equal(t, 2, len(setupVals.db))
1226 func TestCompleteConfigIfLessSentinelPortsThanAddresses(t *testing.T) {
1227 setupVals := setupEnv(
1229 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379,6380", "dbaasmaster-cluster-0,dbaasmaster-cluster-1",
1230 "26379", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1232 assert.Equal(t, 2, len(setupVals.rClient))
1233 assert.Equal(t, 2, len(setupVals.db))
1236 func TestCompleteConfigIfLessSentinelNamesThanAddresses(t *testing.T) {
1237 setupVals := setupEnv(
1239 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379,6380", "dbaasmaster-cluster-0",
1240 "26379,26380", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1242 assert.Equal(t, 2, len(setupVals.rClient))
1243 assert.Equal(t, 2, len(setupVals.db))
1246 func TestInfoOfPrimaryRedisWithTwoReplicasSuccessfully(t *testing.T) {
1247 _, r, db := setupHaEnv(true)
1248 redisInfo := "# Replication\r\n" +
1250 "connected_slaves:2\r\n" +
1251 "min_slaves_good_slaves:2\r\n" +
1252 "slave0:ip=1.2.3.4,port=6379,state=online,offset=100200300,lag=0\r\n" +
1253 "slave1:ip=5.6.7.8,port=6379,state=online,offset=100200300,lag=0\r\n"
1254 expInfo := &sdlgoredis.DbInfo{
1255 Fields: sdlgoredis.DbInfoFields{
1257 ConnectedReplicaCnt: 2,
1261 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1262 info, err := db.Info()
1264 assert.Equal(t, expInfo, info)
1265 r.AssertExpectations(t)
1268 func TestInfoOfPrimaryRedisWithOneReplicaOnlineAndOtherReplicaNotOnlineSuccessfully(t *testing.T) {
1269 _, r, db := setupHaEnv(true)
1270 redisInfo := "# Replication\r\n" +
1272 "connected_slaves:1\r\n" +
1273 "min_slaves_good_slaves:2\r\n" +
1274 "slave0:ip=1.2.3.4,port=6379,state=online,offset=100200300,lag=0\r\n" +
1275 "slave1:ip=5.6.7.8,port=6379,state=wait_bgsave,offset=100200300,lag=0\r\n"
1276 expInfo := &sdlgoredis.DbInfo{
1277 Fields: sdlgoredis.DbInfoFields{
1279 ConnectedReplicaCnt: 1,
1283 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1284 info, err := db.Info()
1286 assert.Equal(t, expInfo, info)
1287 r.AssertExpectations(t)
1290 func TestInfoOfStandalonePrimaryRedisSuccessfully(t *testing.T) {
1291 _, r, db := setupHaEnv(true)
1292 redisInfo := "# Replication\r\n" +
1294 "connected_slaves:0\r\n" +
1295 "min_slaves_good_slaves:0\r\n"
1296 expInfo := &sdlgoredis.DbInfo{
1297 Fields: sdlgoredis.DbInfoFields{
1299 ConnectedReplicaCnt: 0,
1303 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1304 info, err := db.Info()
1306 assert.Equal(t, expInfo, info)
1307 r.AssertExpectations(t)
1310 func TestInfoOfStandalonePrimaryRedisFailureWhenIntConversionFails(t *testing.T) {
1311 _, r, db := setupHaEnv(true)
1312 redisInfo := "# Replication\r\n" +
1314 "connected_slaves:not-int\r\n" +
1315 "min_slaves_good_slaves:0\r\n"
1316 expInfo := &sdlgoredis.DbInfo{
1317 Fields: sdlgoredis.DbInfoFields{
1319 ConnectedReplicaCnt: 0,
1323 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1324 info, err := db.Info()
1326 assert.Equal(t, expInfo, info)
1327 r.AssertExpectations(t)
1330 func TestInfoWithGibberishContentSuccessfully(t *testing.T) {
1331 _, r, db := setupHaEnv(true)
1332 redisInfo := "!#¤%&?+?´-\r\n"
1333 expInfo := &sdlgoredis.DbInfo{}
1335 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1336 info, err := db.Info()
1338 assert.Equal(t, expInfo, info)
1339 r.AssertExpectations(t)
1342 func TestInfoWithEmptyContentSuccessfully(t *testing.T) {
1343 _, r, db := setupHaEnv(true)
1344 var redisInfo string
1345 expInfo := &sdlgoredis.DbInfo{
1346 Fields: sdlgoredis.DbInfoFields{
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 TestInfoWithSomeStatisticsOfStandalonePrimaryRedis(t *testing.T) {
1359 _, r, db := setupHaEnv(true)
1360 redisInfo := "# Replication\r\n" +
1362 "connected_slaves:0\r\n" +
1363 "min_slaves_good_slaves:0\r\n" +
1365 "uptime_in_days:23\r\n" +
1367 "connected_clients:2\r\n" +
1369 "used_memory:2093808\r\n" +
1370 "used_memory_human:2.00M\r\n" +
1371 "mem_fragmentation_ratio:6.44\r\n" +
1373 "total_connections_received:278\r\n" +
1375 "used_cpu_sys:1775.254919\r\n" +
1376 "# Commandstats\r\n" +
1377 "cmdstat_role:calls=1,usec=3,usec_per_call=3.00\r\n" +
1379 "db0:keys=4,expires=0,avg_ttl=0"
1380 expInfo := &sdlgoredis.DbInfo{
1381 Fields: sdlgoredis.DbInfoFields{
1383 ConnectedReplicaCnt: 0,
1384 Server: sdlgoredis.ServerInfoFields{
1387 Clients: sdlgoredis.ClientsInfoFields{
1388 ConnectedClients: 2,
1390 Memory: sdlgoredis.MeroryInfoFields{
1391 UsedMemory: 2093808,
1392 UsedMemoryHuman: "2.00M",
1393 MemFragmentationRatio: 6.44,
1395 Stats: sdlgoredis.StatsInfoFields{
1396 TotalConnectionsReceived: 278,
1398 Cpu: sdlgoredis.CpuInfoFields{
1399 UsedCpuSys: 1775.254919,
1401 Commandstats: sdlgoredis.CommandstatsInfoFields{
1402 CmdstatRole: sdlgoredis.CommandstatsValues{
1408 Keyspace: sdlgoredis.KeyspaceInfoFields{
1409 Db: sdlgoredis.KeyspaceValues{
1416 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1417 info, err := db.Info()
1419 assert.Equal(t, expInfo, info)
1420 r.AssertExpectations(t)
1423 func TestStateWithPrimaryAndTwoReplicaRedisSuccessfully(t *testing.T) {
1424 _, r, s, db := setupHaEnvWithSentinels(true, "3")
1426 redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1427 redisReplicasState := newMockRedisSlavesCall()
1428 redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1429 redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1430 redisSentinelsState := newMockRedisSentinelsCall()
1431 redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1432 redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1434 expState := newExpDbState(3, nil)
1435 expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1436 expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1437 expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1438 expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1439 expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1441 s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1442 s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1443 s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1444 ret, err := db.State()
1446 assert.Equal(t, expState.s, *ret)
1447 r.AssertExpectations(t)
1450 func TestStateWithTwoSdlClustersContainingPrimaryAndTwoReplicaRedisSuccessfully(t *testing.T) {
1451 setupVals := setupEnv(
1453 "", "6379,6380", "dbaasmaster-cluster-0,dbaasmaster-cluster-1",
1454 "26379,26380", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1456 r := setupVals.rClient
1457 s := setupVals.rSentinel
1460 FstRedisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1461 FstRedisReplicasState := newMockRedisSlavesCall()
1462 FstRedisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1463 FstRedisReplicasState.add("slave", "10.20.30.50", "6379", "up", "slave")
1464 FstRedisSentinelsState := newMockRedisSentinelsCall()
1465 FstRedisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1466 FstRedisSentinelsState.add("10.20.30.50", "26379", "sentinel")
1468 SndRedisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.60", "6380", "master")
1469 SndRedisReplicasState := newMockRedisSlavesCall()
1470 SndRedisReplicasState.add("slave", "10.20.30.70", "6380", "up", "slave")
1471 SndRedisReplicasState.add("slave", "10.20.30.80", "6380", "up", "slave")
1472 SndRedisSentinelsState := newMockRedisSentinelsCall()
1473 SndRedisSentinelsState.add("10.20.30.70", "26380", "sentinel")
1474 SndRedisSentinelsState.add("10.20.30.80", "26380", "sentinel")
1476 FstExpState := newExpDbState(3, nil)
1477 FstExpState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1478 FstExpState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1479 FstExpState.addReplica("slave", "10.20.30.50", "6379", "up", "slave", nil)
1480 FstExpState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1481 FstExpState.addSentinel("10.20.30.50", "26379", "sentinel", nil)
1483 SndExpState := newExpDbState(3, nil)
1484 SndExpState.addPrimary("master", "10.20.30.60", "6380", "master", nil)
1485 SndExpState.addReplica("slave", "10.20.30.70", "6380", "up", "slave", nil)
1486 SndExpState.addReplica("slave", "10.20.30.80", "6380", "up", "slave", nil)
1487 SndExpState.addSentinel("10.20.30.70", "26380", "sentinel", nil)
1488 SndExpState.addSentinel("10.20.30.80", "26380", "sentinel", nil)
1490 s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(FstRedisPrimaryState, nil))
1491 s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(FstRedisReplicasState.resp, nil))
1492 s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(FstRedisSentinelsState.resp, nil))
1494 s[0].On("Master", "dbaasmaster-cluster-1").Return(redis.NewStringStringMapResult(SndRedisPrimaryState, nil))
1495 s[0].On("Slaves", "dbaasmaster-cluster-1").Return(redis.NewSliceResult(SndRedisReplicasState.resp, nil))
1496 s[0].On("Sentinels", "dbaasmaster-cluster-1").Return(redis.NewSliceResult(SndRedisSentinelsState.resp, nil))
1498 ret, err := db[0].State()
1500 assert.Equal(t, FstExpState.s, *ret)
1502 ret, err = db[1].State()
1504 assert.Equal(t, SndExpState.s, *ret)
1505 r[0].AssertExpectations(t)
1508 func TestStateWithPrimaryAndTwoReplicaRedisFailureInPrimaryRedisCall(t *testing.T) {
1509 expErr := errors.New("Some error")
1510 _, r, s, db := setupHaEnvWithSentinels(true, "3")
1512 redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1513 redisReplicasState := newMockRedisSlavesCall()
1514 redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1515 redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1516 redisSentinelsState := newMockRedisSentinelsCall()
1517 redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1518 redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1520 expState := newExpDbState(3, nil)
1521 expState.addPrimary("", "", "", "", expErr)
1522 expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1523 expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1524 expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1525 expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1527 s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, expErr))
1528 s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1529 s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1530 ret, err := db.State()
1531 assert.NotNil(t, err)
1532 assert.Equal(t, expState.s, *ret)
1533 r.AssertExpectations(t)
1536 func TestStateWithPrimaryAndTwoReplicaRedisFailureInReplicasRedisCall(t *testing.T) {
1537 expErr := errors.New("Some error")
1538 _, r, s, db := setupHaEnvWithSentinels(true, "3")
1540 redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1541 redisReplicasState := newMockRedisSlavesCall()
1542 redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1543 redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1544 redisSentinelsState := newMockRedisSentinelsCall()
1545 redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1546 redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1548 expState := newExpDbState(3, nil)
1549 expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1550 expState.addReplica("", "", "", "", "", expErr)
1551 expState.addReplica("", "", "", "", "", expErr)
1552 expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1553 expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1555 s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1556 s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, errors.New("Some error")))
1557 s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1558 ret, err := db.State()
1559 assert.NotNil(t, err)
1560 assert.Equal(t, expState.s, *ret)
1561 r.AssertExpectations(t)
1564 func TestStateWithPrimaryAndOneReplicaRedisFailureInSentinelsRedisCall(t *testing.T) {
1565 expErr := errors.New("Some error")
1566 _, r, s, db := setupHaEnvWithSentinels(true, "2")
1568 redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1569 redisReplicasState := newMockRedisSlavesCall()
1570 redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1571 redisSentinelsState := newMockRedisSentinelsCall()
1572 redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1574 expState := newExpDbState(2, nil)
1575 expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1576 expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1577 expState.addSentinel("", "", "", expErr)
1579 s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1580 s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1581 s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, expErr))
1582 ret, err := db.State()
1583 assert.NotNil(t, err)
1584 assert.Equal(t, expState.s, *ret)
1585 r.AssertExpectations(t)
1588 func TestStateWithPrimaryAndTwoReplicaRedisFailureWhenIntConversionFails(t *testing.T) {
1589 expErr := errors.New("Sentinel DBAAS_NODE_COUNT configuration value 'no-int' conversion to integer failed")
1590 _, r, s, db := setupHaEnvWithSentinels(true, "no-int")
1592 redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1593 redisReplicasState := newMockRedisSlavesCall()
1594 redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1595 redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1596 redisSentinelsState := newMockRedisSentinelsCall()
1597 redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1598 redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1600 expState := newExpDbState(0, expErr)
1601 expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1602 expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1603 expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1604 expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1605 expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1607 s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1608 s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1609 s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1610 ret, err := db.State()
1611 assert.Equal(t, expErr, err)
1612 assert.Equal(t, expState.s, *ret)
1613 r.AssertExpectations(t)
1616 // Test case to test ignoring of a sentinel entry with zero port. Implementation has been
1617 // done because we miss the fix for the Redis Bug #9240.
1618 func TestStateWithPrimaryAndTwoReplicaFirstSentinelStateIgnoredBecauseZeroPortBugRedisSuccessfully(t *testing.T) {
1619 _, r, s, db := setupHaEnvWithSentinels(true, "3")
1621 redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1622 redisReplicasState := newMockRedisSlavesCall()
1623 redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1624 redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1625 redisSentinelsState := newMockRedisSentinelsCall()
1626 redisSentinelsState.add("10.20.30.40", "0", "s_down,sentinel,disconnected")
1627 redisSentinelsState.add("10.20.30.50", "26379", "sentinel")
1629 expState := newExpDbState(3, nil)
1630 expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1631 expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1632 expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1633 expState.addSentinel("10.20.30.50", "26379", "sentinel", nil)
1635 s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1636 s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1637 s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1638 ret, err := db.State()
1640 assert.Equal(t, expState.s, *ret)
1641 r.AssertExpectations(t)
1644 func TestStateWithSinglePrimaryRedisSuccessfully(t *testing.T) {
1645 _, r, db := setupSingleEnv(true, "1")
1646 redisInfo := "# Replication\r\n" +
1648 "connected_slaves:0\r\n" +
1649 "min_slaves_good_slaves:0\r\n"
1651 expState := &sdlgoredis.DbState{
1653 PrimaryDbState: sdlgoredis.PrimaryDbState{
1654 Fields: sdlgoredis.PrimaryDbStateFields{
1656 Ip: "service-ricplt-dbaas-tcp-cluster-0.ricplt",
1663 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1664 ret, err := db.State()
1666 assert.Equal(t, expState, ret)
1667 r.AssertExpectations(t)
1670 func TestStateWithSinglePrimaryRedisFailureWhenIntConversionFails(t *testing.T) {
1671 expErr := errors.New("DBAAS_NODE_COUNT configuration value 'no-int' conversion to integer failed")
1672 _, r, db := setupSingleEnv(true, "no-int")
1673 redisInfo := "# Replication\r\n" +
1675 "connected_slaves:0\r\n" +
1676 "min_slaves_good_slaves:0\r\n"
1678 expState := &sdlgoredis.DbState{
1681 PrimaryDbState: sdlgoredis.PrimaryDbState{
1682 Fields: sdlgoredis.PrimaryDbStateFields{
1684 Ip: "service-ricplt-dbaas-tcp-cluster-0.ricplt",
1691 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1692 ret, err := db.State()
1693 assert.Equal(t, expErr, err)
1694 assert.Equal(t, expState, ret)
1695 r.AssertExpectations(t)
1698 func TestStateWithSinglePrimaryRedisFailureInInfoCall(t *testing.T) {
1699 expErr := errors.New("Some error")
1700 _, r, db := setupSingleEnv(true, "1")
1702 expState := &sdlgoredis.DbState{
1703 PrimaryDbState: sdlgoredis.PrimaryDbState{
1708 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, errors.New("Some error")))
1709 ret, err := db.State()
1710 assert.NotNil(t, err)
1711 assert.Equal(t, expState, ret)
1712 r.AssertExpectations(t)
1715 func TestStatisticsWithSinglePrimaryRedisSuccessfully(t *testing.T) {
1716 _, r, db := setupSingleEnv(true, "1")
1717 redisInfo := "# Replication\r\n" +
1719 "connected_slaves:0\r\n" +
1720 "min_slaves_good_slaves:0\r\n" +
1722 "uptime_in_days:12\r\n"
1724 expStatistics := &sdlgoredis.DbStatistics{
1725 Stats: []*sdlgoredis.DbStatisticsInfo{
1727 IPAddr: "service-ricplt-dbaas-tcp-cluster-0.ricplt",
1729 Info: &sdlgoredis.DbInfo{
1730 Fields: sdlgoredis.DbInfoFields{
1732 Server: sdlgoredis.ServerInfoFields{
1741 r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1742 ret, err := db.Statistics()
1744 assert.Equal(t, expStatistics, ret)
1745 r.AssertExpectations(t)