Bump Redis client version to v8.11.4
[ric-plt/sdlgo.git] / internal / sdlgoredis / sdlgoredis_test.go
1 /*
2    Copyright (c) 2019 AT&T Intellectual Property.
3    Copyright (c) 2018-2019 Nokia.
4
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
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
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.
16 */
17
18 /*
19  * This source code is part of the near-RT RIC (RAN Intelligent Controller)
20  * platform project (RICP).
21  */
22
23 package sdlgoredis_test
24
25 import (
26         "context"
27         "errors"
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"
32         "strconv"
33         "testing"
34         "time"
35 )
36
37 type clientMock struct {
38         mock.Mock
39 }
40
41 type pubSubMock struct {
42         mock.Mock
43 }
44
45 type MockOS struct {
46         mock.Mock
47 }
48
49 func (m *pubSubMock) Channel(opts ...redis.ChannelOption) <-chan *redis.Message {
50         return m.Called().Get(0).(chan *redis.Message)
51 }
52
53 func (m *pubSubMock) Subscribe(ctx context.Context, channels ...string) error {
54         return m.Called().Error(0)
55 }
56
57 func (m *pubSubMock) Unsubscribe(ctx context.Context, channels ...string) error {
58         return m.Called().Error(0)
59 }
60
61 func (m *pubSubMock) Close() error {
62         return m.Called().Error(0)
63 }
64
65 func (m *clientMock) Command(ctx context.Context) *redis.CommandsInfoCmd {
66         return m.Called().Get(0).(*redis.CommandsInfoCmd)
67 }
68
69 func (m *clientMock) Close() error {
70         return m.Called().Error(0)
71 }
72
73 func (m *clientMock) Subscribe(ctx context.Context, channels ...string) *redis.PubSub {
74         return m.Called(channels).Get(0).(*redis.PubSub)
75 }
76
77 func (m *clientMock) MSet(ctx context.Context, pairs ...interface{}) *redis.StatusCmd {
78         return m.Called(pairs).Get(0).(*redis.StatusCmd)
79 }
80
81 func (m *clientMock) Do(ctx context.Context, args ...interface{}) *redis.Cmd {
82         return m.Called(args).Get(0).(*redis.Cmd)
83 }
84
85 func (m *clientMock) MGet(ctx context.Context, keys ...string) *redis.SliceCmd {
86         return m.Called(keys).Get(0).(*redis.SliceCmd)
87 }
88
89 func (m *clientMock) Del(ctx context.Context, keys ...string) *redis.IntCmd {
90         return m.Called(keys).Get(0).(*redis.IntCmd)
91 }
92
93 func (m *clientMock) Keys(ctx context.Context, pattern string) *redis.StringSliceCmd {
94         return m.Called(pattern).Get(0).(*redis.StringSliceCmd)
95 }
96
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)
99 }
100
101 func (m *clientMock) SAdd(ctx context.Context, key string, members ...interface{}) *redis.IntCmd {
102         return m.Called(key, members).Get(0).(*redis.IntCmd)
103 }
104
105 func (m *clientMock) SRem(ctx context.Context, key string, members ...interface{}) *redis.IntCmd {
106         return m.Called(key, members).Get(0).(*redis.IntCmd)
107 }
108
109 func (m *clientMock) SMembers(ctx context.Context, key string) *redis.StringSliceCmd {
110         return m.Called(key).Get(0).(*redis.StringSliceCmd)
111 }
112
113 func (m *clientMock) SIsMember(ctx context.Context, key string, member interface{}) *redis.BoolCmd {
114         return m.Called(key, member).Get(0).(*redis.BoolCmd)
115 }
116
117 func (m *clientMock) SCard(ctx context.Context, key string) *redis.IntCmd {
118         return m.Called(key).Get(0).(*redis.IntCmd)
119 }
120
121 func (m *clientMock) PTTL(ctx context.Context, key string) *redis.DurationCmd {
122         return m.Called(key).Get(0).(*redis.DurationCmd)
123 }
124
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)
127 }
128
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)
131 }
132
133 func (m *clientMock) ScriptExists(ctx context.Context, scripts ...string) *redis.BoolSliceCmd {
134         return m.Called(scripts).Get(0).(*redis.BoolSliceCmd)
135 }
136
137 func (m *clientMock) ScriptLoad(ctx context.Context, script string) *redis.StringCmd {
138         return m.Called(script).Get(0).(*redis.StringCmd)
139 }
140
141 func (m *clientMock) Info(ctx context.Context, section ...string) *redis.StringCmd {
142         return m.Called(section).Get(0).(*redis.StringCmd)
143 }
144
145 type MockRedisSentinel struct {
146         mock.Mock
147 }
148
149 func (m *MockRedisSentinel) Master(ctx context.Context, name string) *redis.StringStringMapCmd {
150         a := m.Called(name)
151         return a.Get(0).(*redis.StringStringMapCmd)
152 }
153
154 func (m *MockRedisSentinel) Slaves(ctx context.Context, name string) *redis.SliceCmd {
155         a := m.Called(name)
156         return a.Get(0).(*redis.SliceCmd)
157 }
158
159 func (m *MockRedisSentinel) Sentinels(ctx context.Context, name string) *redis.SliceCmd {
160         a := m.Called(name)
161         return a.Get(0).(*redis.SliceCmd)
162 }
163
164 func setSubscribeNotifications() (*pubSubMock, sdlgoredis.SubscribeFn) {
165         mock := new(pubSubMock)
166         return mock, func(ctx context.Context, client sdlgoredis.RedisClient, channels ...string) sdlgoredis.Subscriber {
167                 return mock
168         }
169 }
170
171 func (m *MockOS) Getenv(key string, defValue string) string {
172         a := m.Called(key, defValue)
173         return a.String(0)
174 }
175
176 type setupEv struct {
177         pubSubMock []*pubSubMock
178         rClient    []*clientMock
179         rSentinel  []*MockRedisSentinel
180         db         []*sdlgoredis.DB
181 }
182
183 func setupHaEnv(commandsExists bool) (*pubSubMock, *clientMock, *sdlgoredis.DB) {
184         psm, cm, _, db := setupHaEnvWithSentinels(commandsExists, "3")
185         return psm, cm, db
186 }
187
188 func setupHaEnvWithSentinels(commandsExists bool, nodeCnt string) (*pubSubMock, *clientMock, []*MockRedisSentinel, *sdlgoredis.DB) {
189         setupVals := setupEnv(
190                 commandsExists,
191                 "service-ricplt-dbaas-tcp-cluster-0.ricplt",
192                 "6376",
193                 "dbaasmaster",
194                 "26376",
195                 "",
196                 nodeCnt,
197         )
198         return setupVals.pubSubMock[0], setupVals.rClient[0], setupVals.rSentinel, setupVals.db[0]
199 }
200
201 func setupSingleEnv(commandsExists bool, nodeCnt string) (*pubSubMock, *clientMock, *sdlgoredis.DB) {
202         setupVals := setupEnv(
203                 commandsExists,
204                 "service-ricplt-dbaas-tcp-cluster-0.ricplt",
205                 "6376", "", "", "", nodeCnt,
206         )
207         return setupVals.pubSubMock[0], setupVals.rClient[0], setupVals.db[0]
208 }
209
210 func setupEnv(commandsExists bool, host, port, msname, sntport, clsaddrlist, nodeCnt string) setupEv {
211         var ret setupEv
212
213         dummyCommandInfo := redis.CommandInfo{
214                 Name: "dummy",
215         }
216
217         cmdResult := make(map[string]*redis.CommandInfo, 0)
218         if commandsExists {
219                 cmdResult = map[string]*redis.CommandInfo{
220                         "setie":    &dummyCommandInfo,
221                         "delie":    &dummyCommandInfo,
222                         "setiepub": &dummyCommandInfo,
223                         "setnxpub": &dummyCommandInfo,
224                         "msetmpub": &dummyCommandInfo,
225                         "delmpub":  &dummyCommandInfo,
226                 }
227         } else {
228                 cmdResult = map[string]*redis.CommandInfo{
229                         "dummy": &dummyCommandInfo,
230                 }
231         }
232
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)
240
241         pubSubMock, subscribeNotifications := setSubscribeNotifications()
242         smock := new(MockRedisSentinel)
243         ret.rSentinel = append(ret.rSentinel, smock)
244         clients := sdlgoredis.ReadConfigAndCreateDbClients(
245                 osmock,
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)
251                         return clm
252                 },
253                 subscribeNotifications,
254                 func(cfg *sdlgoredis.Config, addr string) *sdlgoredis.Sentinel {
255                         s := &sdlgoredis.Sentinel{
256                                 IredisSentinelClient: smock,
257                                 Cfg:                  cfg,
258                         }
259                         return s
260                 },
261         )
262         ret.db = clients
263         return ret
264 }
265
266 func newMockRedisMasterCallResp(role, ip, port, flag string) map[string]string {
267         resp := map[string]string{}
268         if role != "" {
269                 resp["role-reported"] = role
270                 resp["ip"] = ip
271                 resp["port"] = port
272                 resp["flags"] = flag
273         }
274         return resp
275 }
276
277 type mockRedisSlaves struct {
278         resp []interface{}
279 }
280
281 func newMockRedisSlavesCall() *mockRedisSlaves {
282         return new(mockRedisSlaves)
283 }
284
285 func (mrr *mockRedisSlaves) add(role, ip, port, link, flag string) {
286         mrr.resp = append(mrr.resp,
287                 []interface{}{
288                         "role-reported", role,
289                         "ip", ip,
290                         "port", port,
291                         "master-link-status", link,
292                         "flags", flag,
293                 },
294         )
295 }
296
297 type mockRedisSentinels struct {
298         resp []interface{}
299 }
300
301 func newMockRedisSentinelsCall() *mockRedisSentinels {
302         return new(mockRedisSentinels)
303 }
304
305 func (mrs *mockRedisSentinels) add(ip, port, flag string) {
306         mrs.resp = append(mrs.resp,
307                 []interface{}{
308                         "ip", ip,
309                         "port", port,
310                         "flags", flag,
311                 },
312         )
313 }
314
315 type ExpDbState struct {
316         s sdlgoredis.DbState
317 }
318
319 func newExpDbState(nodeCnt int, err error) *ExpDbState {
320         state := new(ExpDbState)
321         state.s.ConfigNodeCnt = nodeCnt
322         state.s.Err = err
323         return state
324 }
325
326 func (edbs *ExpDbState) addPrimary(role, ip, port, flag string, err error) {
327         edbs.s.PrimaryDbState.Err = err
328         edbs.s.PrimaryDbState.Fields = sdlgoredis.PrimaryDbStateFields{
329                 Role:  role,
330                 Ip:    ip,
331                 Port:  port,
332                 Flags: flag,
333         }
334 }
335
336 func (edbs *ExpDbState) addReplica(role, ip, port, link, flag string, err error) {
337         if edbs.s.ReplicasDbState == nil {
338                 edbs.s.ReplicasDbState = new(sdlgoredis.ReplicasDbState)
339                 edbs.s.ReplicasDbState.States = make([]*sdlgoredis.ReplicaDbState, 0)
340         }
341         edbs.s.ReplicasDbState.Err = err
342         if ip != "" || port != "" || link != "" || flag != "" {
343                 edbs.s.ReplicasDbState.States = append(edbs.s.ReplicasDbState.States,
344                         &sdlgoredis.ReplicaDbState{
345                                 Fields: sdlgoredis.ReplicaDbStateFields{
346                                         Role:              role,
347                                         Ip:                ip,
348                                         Port:              port,
349                                         PrimaryLinkStatus: link,
350                                         Flags:             flag,
351                                 },
352                         },
353                 )
354         }
355 }
356
357 func (edbs *ExpDbState) addSentinel(ip, port, flag string, err error) {
358         if edbs.s.SentinelsDbState == nil {
359                 edbs.s.SentinelsDbState = new(sdlgoredis.SentinelsDbState)
360                 edbs.s.SentinelsDbState.States = make([]*sdlgoredis.SentinelDbState, 0)
361         }
362         edbs.s.SentinelsDbState.Err = err
363         if ip != "" || port != "" || flag != "" {
364                 edbs.s.SentinelsDbState.States = append(edbs.s.SentinelsDbState.States,
365                         &sdlgoredis.SentinelDbState{
366                                 Fields: sdlgoredis.SentinelDbStateFields{
367                                         Ip:    ip,
368                                         Port:  port,
369                                         Flags: flag,
370                                 },
371                         },
372                 )
373         }
374 }
375
376 func TestCloseDbSuccessfully(t *testing.T) {
377         _, r, db := setupHaEnv(true)
378         r.On("Close").Return(nil)
379         err := db.CloseDB()
380         assert.Nil(t, err)
381         r.AssertExpectations(t)
382 }
383
384 func TestCloseDbFailure(t *testing.T) {
385         _, r, db := setupHaEnv(true)
386         r.On("Close").Return(errors.New("Some error"))
387         err := db.CloseDB()
388         assert.NotNil(t, err)
389         r.AssertExpectations(t)
390 }
391
392 func TestMSetSuccessfully(t *testing.T) {
393         _, r, db := setupHaEnv(true)
394         expectedKeysAndValues := []interface{}{"key1", "value1", "key2", 2}
395         r.On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
396         err := db.MSet("key1", "value1", "key2", 2)
397         assert.Nil(t, err)
398         r.AssertExpectations(t)
399 }
400
401 func TestMSetFailure(t *testing.T) {
402         _, r, db := setupHaEnv(true)
403         expectedKeysAndValues := []interface{}{"key1", "value1", "key2", 2}
404         r.On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", errors.New("Some error")))
405         err := db.MSet("key1", "value1", "key2", 2)
406         assert.NotNil(t, err)
407         r.AssertExpectations(t)
408 }
409
410 func TestMSetMPubSuccessfully(t *testing.T) {
411         _, r, db := setupHaEnv(true)
412         expectedMessage := []interface{}{"MSETMPUB", 2, 2, "key1", "val1", "key2", "val2",
413                 "chan1", "event1", "chan2", "event2"}
414         r.On("Do", expectedMessage).Return(redis.NewCmdResult("", nil))
415         assert.Nil(t, db.MSetMPub([]string{"chan1", "event1", "chan2", "event2"},
416                 "key1", "val1", "key2", "val2"))
417         r.AssertExpectations(t)
418 }
419
420 func TestMsetMPubFailure(t *testing.T) {
421         _, r, db := setupHaEnv(true)
422         expectedMessage := []interface{}{"MSETMPUB", 2, 2, "key1", "val1", "key2", "val2",
423                 "chan1", "event1", "chan2", "event2"}
424         r.On("Do", expectedMessage).Return(redis.NewCmdResult("", errors.New("Some error")))
425         assert.NotNil(t, db.MSetMPub([]string{"chan1", "event1", "chan2", "event2"},
426                 "key1", "val1", "key2", "val2"))
427         r.AssertExpectations(t)
428 }
429
430 func TestMSetMPubCommandMissing(t *testing.T) {
431         _, r, db := setupHaEnv(false)
432         expectedMessage := []interface{}{"MSETMPUB", 2, 2, "key1", "val1", "key2", "val2",
433                 "chan1", "event1", "chan2", "event2"}
434         r.AssertNotCalled(t, "Do", expectedMessage)
435         assert.NotNil(t, db.MSetMPub([]string{"chan1", "event1", "chan2", "event2"},
436                 "key1", "val1", "key2", "val2"))
437         r.AssertExpectations(t)
438
439 }
440
441 func TestMGetSuccessfully(t *testing.T) {
442         _, r, db := setupHaEnv(true)
443         expectedKeys := []string{"key1", "key2", "key3"}
444         expectedResult := []interface{}{"val1", 2, nil}
445         r.On("MGet", expectedKeys).Return(redis.NewSliceResult(expectedResult, nil))
446         result, err := db.MGet([]string{"key1", "key2", "key3"})
447         assert.Equal(t, result, expectedResult)
448         assert.Nil(t, err)
449         r.AssertExpectations(t)
450 }
451
452 func TestMGetFailure(t *testing.T) {
453         _, r, db := setupHaEnv(true)
454         expectedKeys := []string{"key1", "key2", "key3"}
455         expectedResult := []interface{}{nil}
456         r.On("MGet", expectedKeys).Return(redis.NewSliceResult(expectedResult,
457                 errors.New("Some error")))
458         result, err := db.MGet([]string{"key1", "key2", "key3"})
459         assert.Equal(t, result, expectedResult)
460         assert.NotNil(t, err)
461         r.AssertExpectations(t)
462 }
463
464 func TestDelMPubSuccessfully(t *testing.T) {
465         _, r, db := setupHaEnv(true)
466         expectedMessage := []interface{}{"DELMPUB", 2, 2, "key1", "key2", "chan1", "event1",
467                 "chan2", "event2"}
468         r.On("Do", expectedMessage).Return(redis.NewCmdResult("", nil))
469         assert.Nil(t, db.DelMPub([]string{"chan1", "event1", "chan2", "event2"},
470                 []string{"key1", "key2"}))
471         r.AssertExpectations(t)
472 }
473
474 func TestDelMPubFailure(t *testing.T) {
475         _, r, db := setupHaEnv(true)
476         expectedMessage := []interface{}{"DELMPUB", 2, 2, "key1", "key2", "chan1", "event1",
477                 "chan2", "event2"}
478         r.On("Do", expectedMessage).Return(redis.NewCmdResult("", errors.New("Some error")))
479         assert.NotNil(t, db.DelMPub([]string{"chan1", "event1", "chan2", "event2"},
480                 []string{"key1", "key2"}))
481         r.AssertExpectations(t)
482 }
483
484 func TestDelMPubCommandMissing(t *testing.T) {
485         _, r, db := setupHaEnv(false)
486         expectedMessage := []interface{}{"DELMPUB", 2, 2, "key1", "key2", "chan1", "event1",
487                 "chan2", "event2"}
488         r.AssertNotCalled(t, "Do", expectedMessage)
489         assert.NotNil(t, db.DelMPub([]string{"chan1", "event1", "chan2", "event2"},
490                 []string{"key1", "key2"}))
491         r.AssertExpectations(t)
492 }
493
494 func TestDelSuccessfully(t *testing.T) {
495         _, r, db := setupHaEnv(true)
496         expectedKeys := []string{"key1", "key2"}
497         r.On("Del", expectedKeys).Return(redis.NewIntResult(2, nil))
498         assert.Nil(t, db.Del([]string{"key1", "key2"}))
499         r.AssertExpectations(t)
500 }
501
502 func TestDelFailure(t *testing.T) {
503         _, r, db := setupHaEnv(true)
504         expectedKeys := []string{"key1", "key2"}
505         r.On("Del", expectedKeys).Return(redis.NewIntResult(2, errors.New("Some error")))
506         assert.NotNil(t, db.Del([]string{"key1", "key2"}))
507         r.AssertExpectations(t)
508 }
509
510 func TestKeysSuccessfully(t *testing.T) {
511         _, r, db := setupHaEnv(true)
512         expectedPattern := "pattern*"
513         expectedResult := []string{"pattern1", "pattern2"}
514         r.On("Keys", expectedPattern).Return(redis.NewStringSliceResult(expectedResult, nil))
515         result, err := db.Keys("pattern*")
516         assert.Equal(t, result, expectedResult)
517         assert.Nil(t, err)
518         r.AssertExpectations(t)
519 }
520
521 func TestKeysFailure(t *testing.T) {
522         _, r, db := setupHaEnv(true)
523         expectedPattern := "pattern*"
524         expectedResult := []string{}
525         r.On("Keys", expectedPattern).Return(redis.NewStringSliceResult(expectedResult,
526                 errors.New("Some error")))
527         _, err := db.Keys("pattern*")
528         assert.NotNil(t, err)
529         r.AssertExpectations(t)
530 }
531
532 func TestSetIEKeyExists(t *testing.T) {
533         _, r, db := setupHaEnv(true)
534         expectedMessage := []interface{}{"SETIE", "key", "newdata", "olddata"}
535         r.On("Do", expectedMessage).Return(redis.NewCmdResult("OK", nil))
536         result, err := db.SetIE("key", "olddata", "newdata")
537         assert.True(t, result)
538         assert.Nil(t, err)
539         r.AssertExpectations(t)
540 }
541
542 func TestSetIEKeyDoesntExists(t *testing.T) {
543         _, r, db := setupHaEnv(true)
544         expectedMessage := []interface{}{"SETIE", "key", "newdata", "olddata"}
545         r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, nil))
546         result, err := db.SetIE("key", "olddata", "newdata")
547         assert.False(t, result)
548         assert.Nil(t, err)
549         r.AssertExpectations(t)
550 }
551
552 func TestSetIEFailure(t *testing.T) {
553         _, r, db := setupHaEnv(true)
554         expectedMessage := []interface{}{"SETIE", "key", "newdata", "olddata"}
555         r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, errors.New("Some error")))
556         result, err := db.SetIE("key", "olddata", "newdata")
557         assert.False(t, result)
558         assert.NotNil(t, err)
559         r.AssertExpectations(t)
560 }
561
562 func TestSetIECommandMissing(t *testing.T) {
563         _, r, db := setupHaEnv(false)
564         expectedMessage := []interface{}{"SETIE", "key", "newdata", "olddata"}
565         r.AssertNotCalled(t, "Do", expectedMessage)
566         result, err := db.SetIE("key", "olddata", "newdata")
567         assert.False(t, result)
568         assert.NotNil(t, err)
569         r.AssertExpectations(t)
570 }
571
572 func TestSetIEPubKeyExists(t *testing.T) {
573         _, r, db := setupHaEnv(true)
574         expectedMessage := []interface{}{"SETIEMPUB", "key", "newdata", "olddata", "channel", "message"}
575         r.On("Do", expectedMessage).Return(redis.NewCmdResult("OK", nil))
576         result, err := db.SetIEPub([]string{"channel", "message"}, "key", "olddata", "newdata")
577         assert.True(t, result)
578         assert.Nil(t, err)
579         r.AssertExpectations(t)
580 }
581
582 func TestSetIEPubKeyDoesntExists(t *testing.T) {
583         _, r, db := setupHaEnv(true)
584         expectedMessage := []interface{}{"SETIEMPUB", "key", "newdata", "olddata", "channel", "message"}
585         r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, nil))
586         result, err := db.SetIEPub([]string{"channel", "message"}, "key", "olddata", "newdata")
587         assert.False(t, result)
588         assert.Nil(t, err)
589         r.AssertExpectations(t)
590 }
591
592 func TestSetIEPubFailure(t *testing.T) {
593         _, r, db := setupHaEnv(true)
594         expectedMessage := []interface{}{"SETIEMPUB", "key", "newdata", "olddata", "channel", "message"}
595         r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, errors.New("Some error")))
596         result, err := db.SetIEPub([]string{"channel", "message"}, "key", "olddata", "newdata")
597         assert.False(t, result)
598         assert.NotNil(t, err)
599         r.AssertExpectations(t)
600 }
601
602 func TestSetIEPubCommandMissing(t *testing.T) {
603         _, r, db := setupHaEnv(false)
604         expectedMessage := []interface{}{"SETIEMPUB", "key", "newdata", "olddata", "channel", "message"}
605         r.AssertNotCalled(t, "Do", expectedMessage)
606         result, err := db.SetIEPub([]string{"channel", "message"}, "key", "olddata", "newdata")
607         assert.False(t, result)
608         assert.NotNil(t, err)
609         r.AssertExpectations(t)
610 }
611
612 func TestSetNXPubKeyDoesntExist(t *testing.T) {
613         _, r, db := setupHaEnv(true)
614         expectedMessage := []interface{}{"SETNXMPUB", "key", "data", "channel", "message"}
615         r.On("Do", expectedMessage).Return(redis.NewCmdResult("OK", nil))
616         result, err := db.SetNXPub([]string{"channel", "message"}, "key", "data")
617         assert.True(t, result)
618         assert.Nil(t, err)
619         r.AssertExpectations(t)
620 }
621
622 func TestSetNXPubKeyExists(t *testing.T) {
623         _, r, db := setupHaEnv(true)
624         expectedMessage := []interface{}{"SETNXMPUB", "key", "data", "channel", "message"}
625         r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, nil))
626         result, err := db.SetNXPub([]string{"channel", "message"}, "key", "data")
627         assert.False(t, result)
628         assert.Nil(t, err)
629         r.AssertExpectations(t)
630 }
631
632 func TestSetNXPubFailure(t *testing.T) {
633         _, r, db := setupHaEnv(true)
634         expectedMessage := []interface{}{"SETNXMPUB", "key", "data", "channel", "message"}
635         r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, errors.New("Some error")))
636         result, err := db.SetNXPub([]string{"channel", "message"}, "key", "data")
637         assert.False(t, result)
638         assert.NotNil(t, err)
639         r.AssertExpectations(t)
640 }
641
642 func TestSetNXPubCommandMissing(t *testing.T) {
643         _, r, db := setupHaEnv(false)
644         expectedMessage := []interface{}{"SETNXMPUB", "key", "data", "channel", "message"}
645         r.AssertNotCalled(t, "Do", expectedMessage)
646         result, err := db.SetNXPub([]string{"channel", "message"}, "key", "data")
647         assert.False(t, result)
648         assert.NotNil(t, err)
649         r.AssertExpectations(t)
650 }
651
652 func TestSetNXSuccessfully(t *testing.T) {
653         _, r, db := setupHaEnv(true)
654         expectedKey := "key"
655         expectedData := "data"
656         r.On("SetNX", expectedKey, expectedData, time.Duration(0)).Return(redis.NewBoolResult(true, nil))
657         result, err := db.SetNX("key", "data", 0)
658         assert.True(t, result)
659         assert.Nil(t, err)
660         r.AssertExpectations(t)
661 }
662
663 func TestSetNXUnsuccessfully(t *testing.T) {
664         _, r, db := setupHaEnv(true)
665         expectedKey := "key"
666         expectedData := "data"
667         r.On("SetNX", expectedKey, expectedData, time.Duration(0)).Return(redis.NewBoolResult(false, nil))
668         result, err := db.SetNX("key", "data", 0)
669         assert.False(t, result)
670         assert.Nil(t, err)
671         r.AssertExpectations(t)
672 }
673
674 func TestSetNXFailure(t *testing.T) {
675         _, r, db := setupHaEnv(true)
676         expectedKey := "key"
677         expectedData := "data"
678         r.On("SetNX", expectedKey, expectedData, time.Duration(0)).
679                 Return(redis.NewBoolResult(false, errors.New("Some error")))
680         result, err := db.SetNX("key", "data", 0)
681         assert.False(t, result)
682         assert.NotNil(t, err)
683         r.AssertExpectations(t)
684 }
685
686 func TestDelIEPubKeyDoesntExist(t *testing.T) {
687         _, r, db := setupHaEnv(true)
688         expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
689         r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(0), nil))
690         result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
691         assert.False(t, result)
692         assert.Nil(t, err)
693         r.AssertExpectations(t)
694 }
695
696 func TestDelIEPubKeyExists(t *testing.T) {
697         _, r, db := setupHaEnv(true)
698         expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
699         r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(1), nil))
700         result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
701         assert.True(t, result)
702         assert.Nil(t, err)
703         r.AssertExpectations(t)
704 }
705
706 func TestDelIEPubKeyExistsIntTypeRedisValue(t *testing.T) {
707         _, r, db := setupHaEnv(true)
708         expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
709         r.On("Do", expectedMessage).Return(redis.NewCmdResult(1, nil))
710         result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
711         assert.True(t, result)
712         assert.Nil(t, err)
713         r.AssertExpectations(t)
714 }
715
716 func TestDelIEPubFailure(t *testing.T) {
717         _, r, db := setupHaEnv(true)
718         expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
719         r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(0), errors.New("Some error")))
720         result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
721         assert.False(t, result)
722         assert.NotNil(t, err)
723         r.AssertExpectations(t)
724 }
725
726 func TestDelIEPubCommandMissing(t *testing.T) {
727         _, r, db := setupHaEnv(false)
728         expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
729         r.AssertNotCalled(t, "Do", expectedMessage)
730         result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
731         assert.False(t, result)
732         assert.NotNil(t, err)
733         r.AssertExpectations(t)
734 }
735
736 func TestDelIEKeyDoesntExist(t *testing.T) {
737         _, r, db := setupHaEnv(true)
738         expectedMessage := []interface{}{"DELIE", "key", "data"}
739         r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(0), nil))
740         result, err := db.DelIE("key", "data")
741         assert.False(t, result)
742         assert.Nil(t, err)
743         r.AssertExpectations(t)
744 }
745
746 func TestDelIEKeyExists(t *testing.T) {
747         _, r, db := setupHaEnv(true)
748         expectedMessage := []interface{}{"DELIE", "key", "data"}
749         r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(1), nil))
750         result, err := db.DelIE("key", "data")
751         assert.True(t, result)
752         assert.Nil(t, err)
753         r.AssertExpectations(t)
754 }
755
756 func TestDelIEKeyExistsIntTypeRedisValue(t *testing.T) {
757         _, r, db := setupHaEnv(true)
758         expectedMessage := []interface{}{"DELIE", "key", "data"}
759         r.On("Do", expectedMessage).Return(redis.NewCmdResult(1, nil))
760         result, err := db.DelIE("key", "data")
761         assert.True(t, result)
762         assert.Nil(t, err)
763         r.AssertExpectations(t)
764 }
765
766 func TestDelIEFailure(t *testing.T) {
767         _, r, db := setupHaEnv(true)
768         expectedMessage := []interface{}{"DELIE", "key", "data"}
769         r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(0), errors.New("Some error")))
770         result, err := db.DelIE("key", "data")
771         assert.False(t, result)
772         assert.NotNil(t, err)
773         r.AssertExpectations(t)
774 }
775
776 func TestDelIECommandMissing(t *testing.T) {
777         _, r, db := setupHaEnv(false)
778         expectedMessage := []interface{}{"DELIE", "key", "data"}
779         r.AssertNotCalled(t, "Do", expectedMessage)
780         result, err := db.DelIE("key", "data")
781         assert.False(t, result)
782         assert.NotNil(t, err)
783         r.AssertExpectations(t)
784 }
785
786 func TestSAddSuccessfully(t *testing.T) {
787         _, r, db := setupHaEnv(true)
788         expectedKey := "key"
789         expectedData := []interface{}{"data", 2}
790         r.On("SAdd", expectedKey, expectedData).Return(redis.NewIntResult(2, nil))
791         assert.Nil(t, db.SAdd("key", "data", 2))
792         r.AssertExpectations(t)
793 }
794
795 func TestSAddFailure(t *testing.T) {
796         _, r, db := setupHaEnv(true)
797         expectedKey := "key"
798         expectedData := []interface{}{"data", 2}
799         r.On("SAdd", expectedKey, expectedData).Return(redis.NewIntResult(2, errors.New("Some error")))
800         assert.NotNil(t, db.SAdd("key", "data", 2))
801         r.AssertExpectations(t)
802 }
803
804 func TestSRemSuccessfully(t *testing.T) {
805         _, r, db := setupHaEnv(true)
806         expectedKey := "key"
807         expectedData := []interface{}{"data", 2}
808         r.On("SRem", expectedKey, expectedData).Return(redis.NewIntResult(2, nil))
809         assert.Nil(t, db.SRem("key", "data", 2))
810         r.AssertExpectations(t)
811 }
812
813 func TestSRemFailure(t *testing.T) {
814         _, r, db := setupHaEnv(true)
815         expectedKey := "key"
816         expectedData := []interface{}{"data", 2}
817         r.On("SRem", expectedKey, expectedData).Return(redis.NewIntResult(2, errors.New("Some error")))
818         assert.NotNil(t, db.SRem("key", "data", 2))
819         r.AssertExpectations(t)
820 }
821
822 func TestSMembersSuccessfully(t *testing.T) {
823         _, r, db := setupHaEnv(true)
824         expectedKey := "key"
825         expectedResult := []string{"member1", "member2"}
826         r.On("SMembers", expectedKey).Return(redis.NewStringSliceResult(expectedResult, nil))
827         result, err := db.SMembers("key")
828         assert.Equal(t, result, expectedResult)
829         assert.Nil(t, err)
830         r.AssertExpectations(t)
831 }
832
833 func TestSMembersFailure(t *testing.T) {
834         _, r, db := setupHaEnv(true)
835         expectedKey := "key"
836         expectedResult := []string{"member1", "member2"}
837         r.On("SMembers", expectedKey).Return(redis.NewStringSliceResult(expectedResult,
838                 errors.New("Some error")))
839         result, err := db.SMembers("key")
840         assert.Equal(t, result, expectedResult)
841         assert.NotNil(t, err)
842         r.AssertExpectations(t)
843 }
844
845 func TestSIsMemberIsMember(t *testing.T) {
846         _, r, db := setupHaEnv(true)
847         expectedKey := "key"
848         expectedData := "data"
849         r.On("SIsMember", expectedKey, expectedData).Return(redis.NewBoolResult(true, nil))
850         result, err := db.SIsMember("key", "data")
851         assert.True(t, result)
852         assert.Nil(t, err)
853         r.AssertExpectations(t)
854 }
855
856 func TestSIsMemberIsNotMember(t *testing.T) {
857         _, r, db := setupHaEnv(true)
858         expectedKey := "key"
859         expectedData := "data"
860         r.On("SIsMember", expectedKey, expectedData).Return(redis.NewBoolResult(false, nil))
861         result, err := db.SIsMember("key", "data")
862         assert.False(t, result)
863         assert.Nil(t, err)
864         r.AssertExpectations(t)
865 }
866
867 func TestSIsMemberFailure(t *testing.T) {
868         _, r, db := setupHaEnv(true)
869         expectedKey := "key"
870         expectedData := "data"
871         r.On("SIsMember", expectedKey, expectedData).
872                 Return(redis.NewBoolResult(false, errors.New("Some error")))
873         result, err := db.SIsMember("key", "data")
874         assert.False(t, result)
875         assert.NotNil(t, err)
876         r.AssertExpectations(t)
877 }
878
879 func TestSCardSuccessfully(t *testing.T) {
880         _, r, db := setupHaEnv(true)
881         expectedKey := "key"
882         r.On("SCard", expectedKey).Return(redis.NewIntResult(1, nil))
883         result, err := db.SCard("key")
884         assert.Equal(t, int64(1), result)
885         assert.Nil(t, err)
886         r.AssertExpectations(t)
887 }
888
889 func TestSCardFailure(t *testing.T) {
890         _, r, db := setupHaEnv(true)
891         expectedKey := "key"
892         r.On("SCard", expectedKey).Return(redis.NewIntResult(1, errors.New("Some error")))
893         result, err := db.SCard("key")
894         assert.Equal(t, int64(1), result)
895         assert.NotNil(t, err)
896         r.AssertExpectations(t)
897 }
898
899 func TestSubscribeChannelDBSubscribeRXUnsubscribe(t *testing.T) {
900         ps, r, db := setupHaEnv(true)
901         ch := make(chan *redis.Message)
902         msg := redis.Message{
903                 Channel: "{prefix}channel",
904                 Pattern: "pattern",
905                 Payload: "event",
906         }
907         ps.On("Channel").Return(ch)
908         ps.On("Unsubscribe").Return(nil)
909         ps.On("Close").Return(nil)
910         count := 0
911         receivedChannel := ""
912         db.SubscribeChannelDB(func(channel string, payload ...string) {
913                 count++
914                 receivedChannel = channel
915         }, "{prefix}", "---", "{prefix}channel")
916         ch <- &msg
917         db.UnsubscribeChannelDB("{prefix}channel")
918         time.Sleep(1 * time.Second)
919         assert.Equal(t, 1, count)
920         assert.Equal(t, "channel", receivedChannel)
921         r.AssertExpectations(t)
922         ps.AssertExpectations(t)
923 }
924
925 func TestSubscribeChannelDBSubscribeTwoUnsubscribeOne(t *testing.T) {
926         ps, r, db := setupHaEnv(true)
927         ch := make(chan *redis.Message)
928         msg1 := redis.Message{
929                 Channel: "{prefix}channel1",
930                 Pattern: "pattern",
931                 Payload: "event",
932         }
933         msg2 := redis.Message{
934                 Channel: "{prefix}channel2",
935                 Pattern: "pattern",
936                 Payload: "event",
937         }
938         ps.On("Channel").Return(ch)
939         ps.On("Subscribe").Return(nil)
940         ps.On("Unsubscribe").Return(nil)
941         ps.On("Unsubscribe").Return(nil)
942         ps.On("Close").Return(nil)
943         count := 0
944         receivedChannel1 := ""
945         db.SubscribeChannelDB(func(channel string, payload ...string) {
946                 count++
947                 receivedChannel1 = channel
948         }, "{prefix}", "---", "{prefix}channel1")
949         ch <- &msg1
950         receivedChannel2 := ""
951         db.SubscribeChannelDB(func(channel string, payload ...string) {
952                 count++
953                 receivedChannel2 = channel
954         }, "{prefix}", "---", "{prefix}channel2")
955
956         time.Sleep(1 * time.Second)
957         db.UnsubscribeChannelDB("{prefix}channel1")
958         ch <- &msg2
959         db.UnsubscribeChannelDB("{prefix}channel2")
960         time.Sleep(1 * time.Second)
961         assert.Equal(t, 2, count)
962         assert.Equal(t, "channel1", receivedChannel1)
963         assert.Equal(t, "channel2", receivedChannel2)
964         r.AssertExpectations(t)
965         ps.AssertExpectations(t)
966 }
967
968 func TestSubscribeChannelReDBSubscribeAfterUnsubscribe(t *testing.T) {
969         ps, r, db := setupHaEnv(true)
970         ch := make(chan *redis.Message)
971         msg := redis.Message{
972                 Channel: "{prefix}channel",
973                 Pattern: "pattern",
974                 Payload: "event",
975         }
976         ps.On("Channel").Return(ch)
977         ps.On("Unsubscribe").Return(nil)
978         ps.On("Close").Return(nil)
979         count := 0
980         receivedChannel := ""
981
982         db.SubscribeChannelDB(func(channel string, payload ...string) {
983                 count++
984                 receivedChannel = channel
985         }, "{prefix}", "---", "{prefix}channel")
986         ch <- &msg
987         db.UnsubscribeChannelDB("{prefix}channel")
988         time.Sleep(1 * time.Second)
989
990         db.SubscribeChannelDB(func(channel string, payload ...string) {
991                 count++
992                 receivedChannel = channel
993         }, "{prefix}", "---", "{prefix}channel")
994         ch <- &msg
995         db.UnsubscribeChannelDB("{prefix}channel")
996
997         time.Sleep(1 * time.Second)
998         assert.Equal(t, 2, count)
999         assert.Equal(t, "channel", receivedChannel)
1000         r.AssertExpectations(t)
1001         ps.AssertExpectations(t)
1002 }
1003
1004 func TestPTTLSuccessfully(t *testing.T) {
1005         _, r, db := setupHaEnv(true)
1006         expectedKey := "key"
1007         expectedResult := time.Duration(1)
1008         r.On("PTTL", expectedKey).Return(redis.NewDurationResult(expectedResult,
1009                 nil))
1010         result, err := db.PTTL("key")
1011         assert.Equal(t, result, expectedResult)
1012         assert.Nil(t, err)
1013         r.AssertExpectations(t)
1014 }
1015
1016 func TestPTTLFailure(t *testing.T) {
1017         _, r, db := setupHaEnv(true)
1018         expectedKey := "key"
1019         expectedResult := time.Duration(1)
1020         r.On("PTTL", expectedKey).Return(redis.NewDurationResult(expectedResult,
1021                 errors.New("Some error")))
1022         result, err := db.PTTL("key")
1023         assert.Equal(t, result, expectedResult)
1024         assert.NotNil(t, err)
1025         r.AssertExpectations(t)
1026 }
1027
1028 func TestPExpireIESuccessfully(t *testing.T) {
1029         _, r, db := setupHaEnv(true)
1030         expectedKey := "key"
1031         expectedData := "data"
1032         expectedDuration := strconv.FormatInt(int64(10000), 10)
1033
1034         r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
1035                 Return(redis.NewCmdResult(int64(1), nil))
1036
1037         err := db.PExpireIE("key", "data", 10*time.Second)
1038         assert.Nil(t, err)
1039         r.AssertExpectations(t)
1040 }
1041
1042 func TestPExpireIEFailure(t *testing.T) {
1043         _, r, db := setupHaEnv(true)
1044         expectedKey := "key"
1045         expectedData := "data"
1046         expectedDuration := strconv.FormatInt(int64(10000), 10)
1047
1048         r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
1049                 Return(redis.NewCmdResult(int64(1), errors.New("Some error")))
1050
1051         err := db.PExpireIE("key", "data", 10*time.Second)
1052         assert.NotNil(t, err)
1053         r.AssertExpectations(t)
1054 }
1055
1056 func TestPExpireIELockNotHeld(t *testing.T) {
1057         _, r, db := setupHaEnv(true)
1058         expectedKey := "key"
1059         expectedData := "data"
1060         expectedDuration := strconv.FormatInt(int64(10000), 10)
1061
1062         r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
1063                 Return(redis.NewCmdResult(int64(0), nil))
1064
1065         err := db.PExpireIE("key", "data", 10*time.Second)
1066         assert.NotNil(t, err)
1067         r.AssertExpectations(t)
1068 }
1069
1070 func TestClientStandaloneRedisLegacyEnv(t *testing.T) {
1071         setupVals := setupEnv(
1072                 true,
1073                 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6376", "", "", "", "",
1074         )
1075         assert.Equal(t, 1, len(setupVals.rClient))
1076         assert.Equal(t, 1, len(setupVals.db))
1077
1078         expectedKeysAndValues := []interface{}{"key1", "value1"}
1079         setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1080         err := setupVals.db[0].MSet("key1", "value1")
1081         assert.Nil(t, err)
1082         setupVals.rClient[0].AssertExpectations(t)
1083 }
1084
1085 func TestClientSentinelRedisLegacyEnv(t *testing.T) {
1086         setupVals := setupEnv(
1087                 true,
1088                 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6376", "dbaasmaster", "26376", "", "3",
1089         )
1090         assert.Equal(t, 1, len(setupVals.rClient))
1091         assert.Equal(t, 1, len(setupVals.db))
1092
1093         expectedKeysAndValues := []interface{}{"key1", "value1"}
1094         setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1095         err := setupVals.db[0].MSet("key1", "value1")
1096         assert.Nil(t, err)
1097         setupVals.rClient[0].AssertExpectations(t)
1098 }
1099
1100 func TestClientTwoStandaloneRedisEnvs(t *testing.T) {
1101         setupVals := setupEnv(
1102                 true,
1103                 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6376", "", "",
1104                 "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "",
1105         )
1106         assert.Equal(t, 2, len(setupVals.rClient))
1107         assert.Equal(t, 2, len(setupVals.db))
1108
1109         expectedKeysAndValues := []interface{}{"key1", "value1"}
1110         setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1111         err := setupVals.db[0].MSet("key1", "value1")
1112         assert.Nil(t, err)
1113         setupVals.rClient[0].AssertExpectations(t)
1114
1115         expectedKeysAndValues = []interface{}{"key2", "value2"}
1116         setupVals.rClient[1].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1117         err = setupVals.db[1].MSet("key2", "value2")
1118         assert.Nil(t, err)
1119         setupVals.rClient[0].AssertExpectations(t)
1120         setupVals.rClient[1].AssertExpectations(t)
1121 }
1122
1123 func TestClientTwoSentinelRedisEnvs(t *testing.T) {
1124         setupVals := setupEnv(
1125                 true,
1126                 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6376", "dbaasmaster", "26376",
1127                 "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1128         )
1129         assert.Equal(t, 2, len(setupVals.rClient))
1130         assert.Equal(t, 2, len(setupVals.db))
1131
1132         expectedKeysAndValues := []interface{}{"key1", "value1"}
1133         setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1134         err := setupVals.db[0].MSet("key1", "value1")
1135         assert.Nil(t, err)
1136         setupVals.rClient[0].AssertExpectations(t)
1137
1138         expectedKeysAndValues = []interface{}{"key2", "value2"}
1139         setupVals.rClient[1].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1140         err = setupVals.db[1].MSet("key2", "value2")
1141         assert.Nil(t, err)
1142         setupVals.rClient[0].AssertExpectations(t)
1143         setupVals.rClient[1].AssertExpectations(t)
1144 }
1145
1146 func TestInfoOfPrimaryRedisWithTwoReplicasSuccessfully(t *testing.T) {
1147         _, r, db := setupHaEnv(true)
1148         redisInfo := "# Replication\r\n" +
1149                 "role:master\r\n" +
1150                 "connected_slaves:2\r\n" +
1151                 "min_slaves_good_slaves:2\r\n" +
1152                 "slave0:ip=1.2.3.4,port=6379,state=online,offset=100200300,lag=0\r\n" +
1153                 "slave1:ip=5.6.7.8,port=6379,state=online,offset=100200300,lag=0\r\n"
1154         expInfo := &sdlgoredis.DbInfo{
1155                 Fields: sdlgoredis.DbInfoFields{
1156                         PrimaryRole:         true,
1157                         ConnectedReplicaCnt: 2,
1158                 },
1159         }
1160
1161         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1162         info, err := db.Info()
1163         assert.Nil(t, err)
1164         assert.Equal(t, expInfo, info)
1165         r.AssertExpectations(t)
1166 }
1167
1168 func TestInfoOfPrimaryRedisWithOneReplicaOnlineAndOtherReplicaNotOnlineSuccessfully(t *testing.T) {
1169         _, r, db := setupHaEnv(true)
1170         redisInfo := "# Replication\r\n" +
1171                 "role:master\r\n" +
1172                 "connected_slaves:1\r\n" +
1173                 "min_slaves_good_slaves:2\r\n" +
1174                 "slave0:ip=1.2.3.4,port=6379,state=online,offset=100200300,lag=0\r\n" +
1175                 "slave1:ip=5.6.7.8,port=6379,state=wait_bgsave,offset=100200300,lag=0\r\n"
1176         expInfo := &sdlgoredis.DbInfo{
1177                 Fields: sdlgoredis.DbInfoFields{
1178                         PrimaryRole:         true,
1179                         ConnectedReplicaCnt: 1,
1180                 },
1181         }
1182
1183         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1184         info, err := db.Info()
1185         assert.Nil(t, err)
1186         assert.Equal(t, expInfo, info)
1187         r.AssertExpectations(t)
1188 }
1189
1190 func TestInfoOfStandalonePrimaryRedisSuccessfully(t *testing.T) {
1191         _, r, db := setupHaEnv(true)
1192         redisInfo := "# Replication\r\n" +
1193                 "role:master\r\n" +
1194                 "connected_slaves:0\r\n" +
1195                 "min_slaves_good_slaves:0\r\n"
1196         expInfo := &sdlgoredis.DbInfo{
1197                 Fields: sdlgoredis.DbInfoFields{
1198                         PrimaryRole:         true,
1199                         ConnectedReplicaCnt: 0,
1200                 },
1201         }
1202
1203         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1204         info, err := db.Info()
1205         assert.Nil(t, err)
1206         assert.Equal(t, expInfo, info)
1207         r.AssertExpectations(t)
1208 }
1209
1210 func TestInfoOfStandalonePrimaryRedisFailureWhenIntConversionFails(t *testing.T) {
1211         _, r, db := setupHaEnv(true)
1212         redisInfo := "# Replication\r\n" +
1213                 "role:master\r\n" +
1214                 "connected_slaves:not-int\r\n" +
1215                 "min_slaves_good_slaves:0\r\n"
1216         expInfo := &sdlgoredis.DbInfo{
1217                 Fields: sdlgoredis.DbInfoFields{
1218                         PrimaryRole:         true,
1219                         ConnectedReplicaCnt: 0,
1220                 },
1221         }
1222
1223         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1224         info, err := db.Info()
1225         assert.Nil(t, err)
1226         assert.Equal(t, expInfo, info)
1227         r.AssertExpectations(t)
1228 }
1229
1230 func TestInfoWithGibberishContentSuccessfully(t *testing.T) {
1231         _, r, db := setupHaEnv(true)
1232         redisInfo := "!#¤%&?+?´-\r\n"
1233         expInfo := &sdlgoredis.DbInfo{}
1234
1235         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1236         info, err := db.Info()
1237         assert.Nil(t, err)
1238         assert.Equal(t, expInfo, info)
1239         r.AssertExpectations(t)
1240 }
1241
1242 func TestInfoWithEmptyContentSuccessfully(t *testing.T) {
1243         _, r, db := setupHaEnv(true)
1244         var redisInfo string
1245         expInfo := &sdlgoredis.DbInfo{
1246                 Fields: sdlgoredis.DbInfoFields{
1247                         PrimaryRole: false,
1248                 },
1249         }
1250
1251         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1252         info, err := db.Info()
1253         assert.Nil(t, err)
1254         assert.Equal(t, expInfo, info)
1255         r.AssertExpectations(t)
1256 }
1257
1258 func TestInfoWithSomeStatisticsOfStandalonePrimaryRedis(t *testing.T) {
1259         _, r, db := setupHaEnv(true)
1260         redisInfo := "# Replication\r\n" +
1261                 "role:master\r\n" +
1262                 "connected_slaves:0\r\n" +
1263                 "min_slaves_good_slaves:0\r\n" +
1264                 "# Server\r\n" +
1265                 "uptime_in_days:23\r\n" +
1266                 "# Clients\r\n" +
1267                 "connected_clients:2\r\n" +
1268                 "# Memory\r\n" +
1269                 "used_memory:2093808\r\n" +
1270                 "used_memory_human:2.00M\r\n" +
1271                 "mem_fragmentation_ratio:6.44\r\n" +
1272                 "# Stats\r\n" +
1273                 "total_connections_received:278\r\n" +
1274                 "# CPU\r\n" +
1275                 "used_cpu_sys:1775.254919\r\n" +
1276                 "# Commandstats\r\n" +
1277                 "cmdstat_role:calls=1,usec=3,usec_per_call=3.00\r\n" +
1278                 "# Keyspace\r\n" +
1279                 "db0:keys=4,expires=0,avg_ttl=0"
1280         expInfo := &sdlgoredis.DbInfo{
1281                 Fields: sdlgoredis.DbInfoFields{
1282                         PrimaryRole:         true,
1283                         ConnectedReplicaCnt: 0,
1284                         Server: sdlgoredis.ServerInfoFields{
1285                                 UptimeInDays: 23,
1286                         },
1287                         Clients: sdlgoredis.ClientsInfoFields{
1288                                 ConnectedClients: 2,
1289                         },
1290                         Memory: sdlgoredis.MeroryInfoFields{
1291                                 UsedMemory:            2093808,
1292                                 UsedMemoryHuman:       "2.00M",
1293                                 MemFragmentationRatio: 6.44,
1294                         },
1295                         Stats: sdlgoredis.StatsInfoFields{
1296                                 TotalConnectionsReceived: 278,
1297                         },
1298                         Cpu: sdlgoredis.CpuInfoFields{
1299                                 UsedCpuSys: 1775.254919,
1300                         },
1301                         Commandstats: sdlgoredis.CommandstatsInfoFields{
1302                                 CmdstatRole: sdlgoredis.CommandstatsValues{
1303                                         Calls:       1,
1304                                         Usec:        3,
1305                                         UsecPerCall: 3.00,
1306                                 },
1307                         },
1308                         Keyspace: sdlgoredis.KeyspaceInfoFields{
1309                                 Db: sdlgoredis.KeyspaceValues{
1310                                         Keys: 4,
1311                                 },
1312                         },
1313                 },
1314         }
1315
1316         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1317         info, err := db.Info()
1318         assert.Nil(t, err)
1319         assert.Equal(t, expInfo, info)
1320         r.AssertExpectations(t)
1321 }
1322
1323 func TestStateWithPrimaryAndTwoReplicaRedisSuccessfully(t *testing.T) {
1324         _, r, s, db := setupHaEnvWithSentinels(true, "3")
1325
1326         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1327         redisReplicasState := newMockRedisSlavesCall()
1328         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1329         redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1330         redisSentinelsState := newMockRedisSentinelsCall()
1331         redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1332         redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1333
1334         expState := newExpDbState(3, nil)
1335         expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1336         expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1337         expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1338         expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1339         expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1340
1341         s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1342         s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1343         s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1344         ret, err := db.State()
1345         assert.Nil(t, err)
1346         assert.Equal(t, expState.s, *ret)
1347         r.AssertExpectations(t)
1348 }
1349
1350 func TestStateWithPrimaryAndTwoReplicaRedisFailureInPrimaryRedisCall(t *testing.T) {
1351         expErr := errors.New("Some error")
1352         _, r, s, db := setupHaEnvWithSentinels(true, "3")
1353
1354         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1355         redisReplicasState := newMockRedisSlavesCall()
1356         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1357         redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1358         redisSentinelsState := newMockRedisSentinelsCall()
1359         redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1360         redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1361
1362         expState := newExpDbState(3, nil)
1363         expState.addPrimary("", "", "", "", expErr)
1364         expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1365         expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1366         expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1367         expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1368
1369         s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, expErr))
1370         s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1371         s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1372         ret, err := db.State()
1373         assert.NotNil(t, err)
1374         assert.Equal(t, expState.s, *ret)
1375         r.AssertExpectations(t)
1376 }
1377
1378 func TestStateWithPrimaryAndTwoReplicaRedisFailureInReplicasRedisCall(t *testing.T) {
1379         expErr := errors.New("Some error")
1380         _, r, s, db := setupHaEnvWithSentinels(true, "3")
1381
1382         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1383         redisReplicasState := newMockRedisSlavesCall()
1384         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1385         redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1386         redisSentinelsState := newMockRedisSentinelsCall()
1387         redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1388         redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1389
1390         expState := newExpDbState(3, nil)
1391         expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1392         expState.addReplica("", "", "", "", "", expErr)
1393         expState.addReplica("", "", "", "", "", expErr)
1394         expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1395         expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1396
1397         s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1398         s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, errors.New("Some error")))
1399         s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1400         ret, err := db.State()
1401         assert.NotNil(t, err)
1402         assert.Equal(t, expState.s, *ret)
1403         r.AssertExpectations(t)
1404 }
1405
1406 func TestStateWithPrimaryAndOneReplicaRedisFailureInSentinelsRedisCall(t *testing.T) {
1407         expErr := errors.New("Some error")
1408         _, r, s, db := setupHaEnvWithSentinels(true, "2")
1409
1410         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1411         redisReplicasState := newMockRedisSlavesCall()
1412         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1413         redisSentinelsState := newMockRedisSentinelsCall()
1414         redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1415
1416         expState := newExpDbState(2, nil)
1417         expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1418         expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1419         expState.addSentinel("", "", "", expErr)
1420
1421         s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1422         s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1423         s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, expErr))
1424         ret, err := db.State()
1425         assert.NotNil(t, err)
1426         assert.Equal(t, expState.s, *ret)
1427         r.AssertExpectations(t)
1428 }
1429
1430 func TestStateWithPrimaryAndTwoReplicaRedisFailureWhenIntConversionFails(t *testing.T) {
1431         expErr := errors.New("Sentinel DBAAS_NODE_COUNT configuration value 'no-int' conversion to integer failed")
1432         _, r, s, db := setupHaEnvWithSentinels(true, "no-int")
1433
1434         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1435         redisReplicasState := newMockRedisSlavesCall()
1436         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1437         redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1438         redisSentinelsState := newMockRedisSentinelsCall()
1439         redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1440         redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1441
1442         expState := newExpDbState(0, expErr)
1443         expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1444         expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1445         expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1446         expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1447         expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1448
1449         s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1450         s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1451         s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1452         ret, err := db.State()
1453         assert.Equal(t, expErr, err)
1454         assert.Equal(t, expState.s, *ret)
1455         r.AssertExpectations(t)
1456 }
1457
1458 // Test case to test ignoring of a sentinel entry with zero port. Implementation has been
1459 // done because we miss the fix for the Redis Bug #9240.
1460 func TestStateWithPrimaryAndTwoReplicaFirstSentinelStateIgnoredBecauseZeroPortBugRedisSuccessfully(t *testing.T) {
1461         _, r, s, db := setupHaEnvWithSentinels(true, "3")
1462
1463         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1464         redisReplicasState := newMockRedisSlavesCall()
1465         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1466         redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1467         redisSentinelsState := newMockRedisSentinelsCall()
1468         redisSentinelsState.add("10.20.30.40", "0", "s_down,sentinel,disconnected")
1469         redisSentinelsState.add("10.20.30.50", "26379", "sentinel")
1470
1471         expState := newExpDbState(3, nil)
1472         expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1473         expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1474         expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1475         expState.addSentinel("10.20.30.50", "26379", "sentinel", nil)
1476
1477         s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1478         s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1479         s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1480         ret, err := db.State()
1481         assert.Nil(t, err)
1482         assert.Equal(t, expState.s, *ret)
1483         r.AssertExpectations(t)
1484 }
1485
1486 func TestStateWithSinglePrimaryRedisSuccessfully(t *testing.T) {
1487         _, r, db := setupSingleEnv(true, "1")
1488         redisInfo := "# Replication\r\n" +
1489                 "role:master\r\n" +
1490                 "connected_slaves:0\r\n" +
1491                 "min_slaves_good_slaves:0\r\n"
1492
1493         expState := &sdlgoredis.DbState{
1494                 ConfigNodeCnt: 1,
1495                 PrimaryDbState: sdlgoredis.PrimaryDbState{
1496                         Fields: sdlgoredis.PrimaryDbStateFields{
1497                                 Role:  "master",
1498                                 Ip:    "service-ricplt-dbaas-tcp-cluster-0.ricplt",
1499                                 Port:  "6376",
1500                                 Flags: "master",
1501                         },
1502                 },
1503         }
1504
1505         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1506         ret, err := db.State()
1507         assert.Nil(t, err)
1508         assert.Equal(t, expState, ret)
1509         r.AssertExpectations(t)
1510 }
1511
1512 func TestStateWithSinglePrimaryRedisFailureWhenIntConversionFails(t *testing.T) {
1513         expErr := errors.New("DBAAS_NODE_COUNT configuration value 'no-int' conversion to integer failed")
1514         _, r, db := setupSingleEnv(true, "no-int")
1515         redisInfo := "# Replication\r\n" +
1516                 "role:master\r\n" +
1517                 "connected_slaves:0\r\n" +
1518                 "min_slaves_good_slaves:0\r\n"
1519
1520         expState := &sdlgoredis.DbState{
1521                 Err:           expErr,
1522                 ConfigNodeCnt: 0,
1523                 PrimaryDbState: sdlgoredis.PrimaryDbState{
1524                         Fields: sdlgoredis.PrimaryDbStateFields{
1525                                 Role:  "master",
1526                                 Ip:    "service-ricplt-dbaas-tcp-cluster-0.ricplt",
1527                                 Port:  "6376",
1528                                 Flags: "master",
1529                         },
1530                 },
1531         }
1532
1533         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1534         ret, err := db.State()
1535         assert.Equal(t, expErr, err)
1536         assert.Equal(t, expState, ret)
1537         r.AssertExpectations(t)
1538 }
1539
1540 func TestStateWithSinglePrimaryRedisFailureInInfoCall(t *testing.T) {
1541         expErr := errors.New("Some error")
1542         _, r, db := setupSingleEnv(true, "1")
1543         redisInfo := ""
1544         expState := &sdlgoredis.DbState{
1545                 PrimaryDbState: sdlgoredis.PrimaryDbState{
1546                         Err: expErr,
1547                 },
1548         }
1549
1550         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, errors.New("Some error")))
1551         ret, err := db.State()
1552         assert.NotNil(t, err)
1553         assert.Equal(t, expState, ret)
1554         r.AssertExpectations(t)
1555 }
1556
1557 func TestStatisticsWithSinglePrimaryRedisSuccessfully(t *testing.T) {
1558         _, r, db := setupSingleEnv(true, "1")
1559         redisInfo := "# Replication\r\n" +
1560                 "role:master\r\n" +
1561                 "connected_slaves:0\r\n" +
1562                 "min_slaves_good_slaves:0\r\n" +
1563                 "# Server\r\n" +
1564                 "uptime_in_days:12\r\n"
1565
1566         expStatistics := &sdlgoredis.DbStatistics{
1567                 Stats: []*sdlgoredis.DbStatisticsInfo{
1568                         {
1569                                 IPAddr: "service-ricplt-dbaas-tcp-cluster-0.ricplt",
1570                                 Port:   "6376",
1571                                 Info: &sdlgoredis.DbInfo{
1572                                         Fields: sdlgoredis.DbInfoFields{
1573                                                 PrimaryRole: true,
1574                                                 Server: sdlgoredis.ServerInfoFields{
1575                                                         UptimeInDays: 12,
1576                                                 },
1577                                         },
1578                                 },
1579                         },
1580                 },
1581         }
1582
1583         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1584         ret, err := db.Statistics()
1585         assert.Nil(t, err)
1586         assert.Equal(t, expStatistics, ret)
1587         r.AssertExpectations(t)
1588 }