Handle Subscribe() and Unsubscribe() error
[ric-plt/sdlgo.git] / internal / sdlgoredis / sdlgoredis_test.go
1 /*
2    Copyright (c) 2019 AT&T Intellectual Property.
3    Copyright (c) 2018-2022 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                 "6379",
193                 "dbaasmaster-cluster-0",
194                 "26379",
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                 "6379", "", "", "", 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(addr, sentinelPort, masterName, nodeCnt string) *sdlgoredis.Sentinel {
255                         s := &sdlgoredis.Sentinel{
256                                 IredisSentinelClient: smock,
257                                 MasterName:           masterName,
258                                 NodeCnt:              nodeCnt,
259                         }
260                         return s
261                 },
262         )
263         ret.db = clients
264         return ret
265 }
266
267 func newMockRedisMasterCallResp(role, ip, port, flag string) map[string]string {
268         resp := map[string]string{}
269         if role != "" {
270                 resp["role-reported"] = role
271                 resp["ip"] = ip
272                 resp["port"] = port
273                 resp["flags"] = flag
274         }
275         return resp
276 }
277
278 type mockRedisSlaves struct {
279         resp []interface{}
280 }
281
282 func newMockRedisSlavesCall() *mockRedisSlaves {
283         return new(mockRedisSlaves)
284 }
285
286 func (mrr *mockRedisSlaves) add(role, ip, port, link, flag string) {
287         mrr.resp = append(mrr.resp,
288                 []interface{}{
289                         "role-reported", role,
290                         "ip", ip,
291                         "port", port,
292                         "master-link-status", link,
293                         "flags", flag,
294                 },
295         )
296 }
297
298 type mockRedisSentinels struct {
299         resp []interface{}
300 }
301
302 func newMockRedisSentinelsCall() *mockRedisSentinels {
303         return new(mockRedisSentinels)
304 }
305
306 func (mrs *mockRedisSentinels) add(ip, port, flag string) {
307         mrs.resp = append(mrs.resp,
308                 []interface{}{
309                         "ip", ip,
310                         "port", port,
311                         "flags", flag,
312                 },
313         )
314 }
315
316 type ExpDbState struct {
317         s sdlgoredis.DbState
318 }
319
320 func newExpDbState(nodeCnt int, err error) *ExpDbState {
321         state := new(ExpDbState)
322         state.s.ConfigNodeCnt = nodeCnt
323         state.s.Err = err
324         return state
325 }
326
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{
330                 Role:  role,
331                 Ip:    ip,
332                 Port:  port,
333                 Flags: flag,
334         }
335 }
336
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)
341         }
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{
347                                         Role:              role,
348                                         Ip:                ip,
349                                         Port:              port,
350                                         PrimaryLinkStatus: link,
351                                         Flags:             flag,
352                                 },
353                         },
354                 )
355         }
356 }
357
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)
362         }
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{
368                                         Ip:    ip,
369                                         Port:  port,
370                                         Flags: flag,
371                                 },
372                         },
373                 )
374         }
375 }
376
377 func TestCloseDbSuccessfully(t *testing.T) {
378         _, r, db := setupHaEnv(true)
379         r.On("Close").Return(nil)
380         err := db.CloseDB()
381         assert.Nil(t, err)
382         r.AssertExpectations(t)
383 }
384
385 func TestCloseDbFailure(t *testing.T) {
386         _, r, db := setupHaEnv(true)
387         r.On("Close").Return(errors.New("Some error"))
388         err := db.CloseDB()
389         assert.NotNil(t, err)
390         r.AssertExpectations(t)
391 }
392
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)
398         assert.Nil(t, err)
399         r.AssertExpectations(t)
400 }
401
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)
409 }
410
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)
419 }
420
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)
429 }
430
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)
439
440 }
441
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)
449         assert.Nil(t, err)
450         r.AssertExpectations(t)
451 }
452
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)
463 }
464
465 func TestDelMPubSuccessfully(t *testing.T) {
466         _, r, db := setupHaEnv(true)
467         expectedMessage := []interface{}{"DELMPUB", 2, 2, "key1", "key2", "chan1", "event1",
468                 "chan2", "event2"}
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)
473 }
474
475 func TestDelMPubFailure(t *testing.T) {
476         _, r, db := setupHaEnv(true)
477         expectedMessage := []interface{}{"DELMPUB", 2, 2, "key1", "key2", "chan1", "event1",
478                 "chan2", "event2"}
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)
483 }
484
485 func TestDelMPubCommandMissing(t *testing.T) {
486         _, r, db := setupHaEnv(false)
487         expectedMessage := []interface{}{"DELMPUB", 2, 2, "key1", "key2", "chan1", "event1",
488                 "chan2", "event2"}
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)
493 }
494
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)
501 }
502
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)
509 }
510
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)
518         assert.Nil(t, err)
519         r.AssertExpectations(t)
520 }
521
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)
531 }
532
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)
539         assert.Nil(t, err)
540         r.AssertExpectations(t)
541 }
542
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)
549         assert.Nil(t, err)
550         r.AssertExpectations(t)
551 }
552
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)
561 }
562
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)
571 }
572
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)
579         assert.Nil(t, err)
580         r.AssertExpectations(t)
581 }
582
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)
589         assert.Nil(t, err)
590         r.AssertExpectations(t)
591 }
592
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)
601 }
602
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)
611 }
612
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)
619         assert.Nil(t, err)
620         r.AssertExpectations(t)
621 }
622
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)
629         assert.Nil(t, err)
630         r.AssertExpectations(t)
631 }
632
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)
641 }
642
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)
651 }
652
653 func TestSetNXSuccessfully(t *testing.T) {
654         _, r, db := setupHaEnv(true)
655         expectedKey := "key"
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)
660         assert.Nil(t, err)
661         r.AssertExpectations(t)
662 }
663
664 func TestSetNXUnsuccessfully(t *testing.T) {
665         _, r, db := setupHaEnv(true)
666         expectedKey := "key"
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)
671         assert.Nil(t, err)
672         r.AssertExpectations(t)
673 }
674
675 func TestSetNXFailure(t *testing.T) {
676         _, r, db := setupHaEnv(true)
677         expectedKey := "key"
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)
685 }
686
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)
693         assert.Nil(t, err)
694         r.AssertExpectations(t)
695 }
696
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)
703         assert.Nil(t, err)
704         r.AssertExpectations(t)
705 }
706
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)
713         assert.Nil(t, err)
714         r.AssertExpectations(t)
715 }
716
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)
725 }
726
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)
735 }
736
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)
743         assert.Nil(t, err)
744         r.AssertExpectations(t)
745 }
746
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)
753         assert.Nil(t, err)
754         r.AssertExpectations(t)
755 }
756
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)
763         assert.Nil(t, err)
764         r.AssertExpectations(t)
765 }
766
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)
775 }
776
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)
785 }
786
787 func TestSAddSuccessfully(t *testing.T) {
788         _, r, db := setupHaEnv(true)
789         expectedKey := "key"
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)
794 }
795
796 func TestSAddFailure(t *testing.T) {
797         _, r, db := setupHaEnv(true)
798         expectedKey := "key"
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)
803 }
804
805 func TestSRemSuccessfully(t *testing.T) {
806         _, r, db := setupHaEnv(true)
807         expectedKey := "key"
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)
812 }
813
814 func TestSRemFailure(t *testing.T) {
815         _, r, db := setupHaEnv(true)
816         expectedKey := "key"
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)
821 }
822
823 func TestSMembersSuccessfully(t *testing.T) {
824         _, r, db := setupHaEnv(true)
825         expectedKey := "key"
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)
830         assert.Nil(t, err)
831         r.AssertExpectations(t)
832 }
833
834 func TestSMembersFailure(t *testing.T) {
835         _, r, db := setupHaEnv(true)
836         expectedKey := "key"
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)
844 }
845
846 func TestSIsMemberIsMember(t *testing.T) {
847         _, r, db := setupHaEnv(true)
848         expectedKey := "key"
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)
853         assert.Nil(t, err)
854         r.AssertExpectations(t)
855 }
856
857 func TestSIsMemberIsNotMember(t *testing.T) {
858         _, r, db := setupHaEnv(true)
859         expectedKey := "key"
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)
864         assert.Nil(t, err)
865         r.AssertExpectations(t)
866 }
867
868 func TestSIsMemberFailure(t *testing.T) {
869         _, r, db := setupHaEnv(true)
870         expectedKey := "key"
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)
878 }
879
880 func TestSCardSuccessfully(t *testing.T) {
881         _, r, db := setupHaEnv(true)
882         expectedKey := "key"
883         r.On("SCard", expectedKey).Return(redis.NewIntResult(1, nil))
884         result, err := db.SCard("key")
885         assert.Equal(t, int64(1), result)
886         assert.Nil(t, err)
887         r.AssertExpectations(t)
888 }
889
890 func TestSCardFailure(t *testing.T) {
891         _, r, db := setupHaEnv(true)
892         expectedKey := "key"
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)
898 }
899
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",
905                 Pattern: "pattern",
906                 Payload: "event",
907         }
908         ps.On("Channel").Return(ch)
909         ps.On("Subscribe").Return(nil)
910         ps.On("Unsubscribe").Return(nil)
911         ps.On("Close").Return(nil)
912         count := 0
913         receivedChannel := ""
914         err := db.SubscribeChannelDB(func(channel string, payload ...string) {
915                 count++
916                 receivedChannel = channel
917         }, "{prefix},channel")
918         assert.Nil(t, err)
919         ch <- &msg
920         err = db.UnsubscribeChannelDB("{prefix},channel")
921         assert.Nil(t, err)
922         time.Sleep(1 * time.Second)
923         assert.Equal(t, 1, count)
924         assert.Equal(t, "channel", receivedChannel)
925         r.AssertExpectations(t)
926         ps.AssertExpectations(t)
927 }
928
929 func TestSubscribeChannelDBFailure(t *testing.T) {
930         mockedErr := errors.New("Some DB Backend Subscribe Error")
931         ps, r, db := setupHaEnv(true)
932         ch := make(chan *redis.Message)
933         ps.On("Channel").Return(ch)
934         ps.On("Subscribe").Return(mockedErr)
935         err := db.SubscribeChannelDB(func(channel string, payload ...string) {
936         }, "{prefix},channel")
937         assert.NotNil(t, err)
938         assert.Contains(t, err.Error(), mockedErr.Error())
939         r.AssertExpectations(t)
940         ps.AssertExpectations(t)
941 }
942
943 func TestUnsubscribeChannelDBFailure(t *testing.T) {
944         mockedErr := errors.New("Some DB Backend Unsubscribe Error")
945         ps, r, db := setupHaEnv(true)
946         ch := make(chan *redis.Message)
947         ps.On("Channel").Return(ch)
948         ps.On("Subscribe").Return(nil)
949         ps.On("Unsubscribe").Return(mockedErr)
950         err := db.SubscribeChannelDB(func(channel string, payload ...string) {
951         }, "{prefix},channel")
952         assert.Nil(t, err)
953         err = db.UnsubscribeChannelDB("{prefix},channel")
954         assert.NotNil(t, err)
955         assert.Contains(t, err.Error(), mockedErr.Error())
956         r.AssertExpectations(t)
957         ps.AssertExpectations(t)
958 }
959
960 func TestSubscribeChannelDBSubscribeTwoUnsubscribeOne(t *testing.T) {
961         ps, r, db := setupHaEnv(true)
962         ch := make(chan *redis.Message)
963         msg1 := redis.Message{
964                 Channel: "{prefix},channel1",
965                 Pattern: "pattern",
966                 Payload: "event",
967         }
968         msg2 := redis.Message{
969                 Channel: "{prefix},channel2",
970                 Pattern: "pattern",
971                 Payload: "event",
972         }
973         ps.On("Channel").Return(ch)
974         ps.On("Subscribe").Return(nil)
975         ps.On("Unsubscribe").Return(nil)
976         ps.On("Unsubscribe").Return(nil)
977         ps.On("Close").Return(nil)
978         count := 0
979         receivedChannel1 := ""
980         err := db.SubscribeChannelDB(func(channel string, payload ...string) {
981                 count++
982                 receivedChannel1 = channel
983         }, "{prefix},channel1")
984         assert.Nil(t, err)
985         ch <- &msg1
986         receivedChannel2 := ""
987         err = db.SubscribeChannelDB(func(channel string, payload ...string) {
988                 count++
989                 receivedChannel2 = channel
990         }, "{prefix},channel2")
991         assert.Nil(t, err)
992         time.Sleep(1 * time.Second)
993         err = db.UnsubscribeChannelDB("{prefix},channel1")
994         assert.Nil(t, err)
995         ch <- &msg2
996         err = db.UnsubscribeChannelDB("{prefix},channel2")
997         assert.Nil(t, err)
998         time.Sleep(1 * time.Second)
999         assert.Equal(t, 2, count)
1000         assert.Equal(t, "channel1", receivedChannel1)
1001         assert.Equal(t, "channel2", receivedChannel2)
1002         r.AssertExpectations(t)
1003         ps.AssertExpectations(t)
1004 }
1005
1006 func TestSubscribeChannelDBTwoSubscribesWithUnequalPrefixAndUnsubscribes(t *testing.T) {
1007         ps, r, db := setupHaEnv(true)
1008         ch := make(chan *redis.Message)
1009         msg1 := redis.Message{
1010                 Channel: "{prefix1},channel",
1011                 Pattern: "pattern",
1012                 Payload: "event",
1013         }
1014         msg2 := redis.Message{
1015                 Channel: "{prefix2},channel",
1016                 Pattern: "pattern",
1017                 Payload: "event",
1018         }
1019         ps.On("Channel").Return(ch)
1020         ps.On("Subscribe").Return(nil)
1021         ps.On("Unsubscribe").Return(nil)
1022         ps.On("Unsubscribe").Return(nil)
1023         ps.On("Close").Return(nil)
1024         count := 0
1025         receivedChannel1 := ""
1026         err := db.SubscribeChannelDB(func(channel string, payload ...string) {
1027                 count++
1028                 receivedChannel1 = channel
1029         }, "{prefix1},channel")
1030         assert.Nil(t, err)
1031         ch <- &msg1
1032         receivedChannel2 := ""
1033         err = db.SubscribeChannelDB(func(channel string, payload ...string) {
1034                 count++
1035                 receivedChannel2 = channel
1036         }, "{prefix2},channel")
1037         assert.Nil(t, err)
1038         time.Sleep(1 * time.Second)
1039         err = db.UnsubscribeChannelDB("{prefix1},channel")
1040         assert.Nil(t, err)
1041         ch <- &msg2
1042         err = db.UnsubscribeChannelDB("{prefix2},channel")
1043         assert.Nil(t, err)
1044         time.Sleep(1 * time.Second)
1045         assert.Equal(t, 2, count)
1046         assert.Equal(t, "channel", receivedChannel1)
1047         assert.Equal(t, "channel", receivedChannel2)
1048         r.AssertExpectations(t)
1049         ps.AssertExpectations(t)
1050 }
1051
1052 func TestSubscribeChannelReDBSubscribeAfterUnsubscribe(t *testing.T) {
1053         ps, r, db := setupHaEnv(true)
1054         ch := make(chan *redis.Message)
1055         msg := redis.Message{
1056                 Channel: "{prefix},channel",
1057                 Pattern: "pattern",
1058                 Payload: "event",
1059         }
1060         ps.On("Channel").Return(ch)
1061         ps.On("Subscribe").Return(nil)
1062         ps.On("Unsubscribe").Return(nil)
1063         ps.On("Close").Return(nil)
1064         count := 0
1065         receivedChannel := ""
1066
1067         err := db.SubscribeChannelDB(func(channel string, payload ...string) {
1068                 count++
1069                 receivedChannel = channel
1070         }, "{prefix},channel")
1071         assert.Nil(t, err)
1072         ch <- &msg
1073         err = db.UnsubscribeChannelDB("{prefix},channel")
1074         assert.Nil(t, err)
1075         time.Sleep(1 * time.Second)
1076
1077         err = db.SubscribeChannelDB(func(channel string, payload ...string) {
1078                 count++
1079                 receivedChannel = channel
1080         }, "{prefix}", "---", "{prefix},channel")
1081         assert.Nil(t, err)
1082         ch <- &msg
1083         err = db.UnsubscribeChannelDB("{prefix},channel")
1084         assert.Nil(t, err)
1085
1086         time.Sleep(1 * time.Second)
1087         assert.Equal(t, 2, count)
1088         assert.Equal(t, "channel", receivedChannel)
1089         r.AssertExpectations(t)
1090         ps.AssertExpectations(t)
1091 }
1092
1093 func TestSubscribeChannelDBSubscribeReceivedEventIgnoredIfChannelNameIsUnknown(t *testing.T) {
1094         ps, r, db := setupHaEnv(true)
1095         ch := make(chan *redis.Message)
1096         msg := redis.Message{
1097                 Channel: "missingNsPrefixchannel",
1098                 Pattern: "pattern",
1099                 Payload: "event",
1100         }
1101         ps.On("Channel").Return(ch)
1102         ps.On("Subscribe").Return(nil)
1103         ps.On("Unsubscribe").Return(nil)
1104         ps.On("Close").Return(nil)
1105         count := 0
1106         receivedChannel := ""
1107         err := db.SubscribeChannelDB(func(channel string, payload ...string) {
1108                 count++
1109                 receivedChannel = channel
1110         }, "{prefix},channel")
1111         assert.Nil(t, err)
1112         ch <- &msg
1113         err = db.UnsubscribeChannelDB("{prefix},channel")
1114         assert.Nil(t, err)
1115         time.Sleep(1 * time.Second)
1116         assert.Equal(t, 0, count)
1117         assert.Equal(t, "", receivedChannel)
1118         r.AssertExpectations(t)
1119         ps.AssertExpectations(t)
1120 }
1121
1122 func TestPTTLSuccessfully(t *testing.T) {
1123         _, r, db := setupHaEnv(true)
1124         expectedKey := "key"
1125         expectedResult := time.Duration(1)
1126         r.On("PTTL", expectedKey).Return(redis.NewDurationResult(expectedResult,
1127                 nil))
1128         result, err := db.PTTL("key")
1129         assert.Equal(t, result, expectedResult)
1130         assert.Nil(t, err)
1131         r.AssertExpectations(t)
1132 }
1133
1134 func TestPTTLFailure(t *testing.T) {
1135         _, r, db := setupHaEnv(true)
1136         expectedKey := "key"
1137         expectedResult := time.Duration(1)
1138         r.On("PTTL", expectedKey).Return(redis.NewDurationResult(expectedResult,
1139                 errors.New("Some error")))
1140         result, err := db.PTTL("key")
1141         assert.Equal(t, result, expectedResult)
1142         assert.NotNil(t, err)
1143         r.AssertExpectations(t)
1144 }
1145
1146 func TestPExpireIESuccessfully(t *testing.T) {
1147         _, r, db := setupHaEnv(true)
1148         expectedKey := "key"
1149         expectedData := "data"
1150         expectedDuration := strconv.FormatInt(int64(10000), 10)
1151
1152         r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
1153                 Return(redis.NewCmdResult(int64(1), nil))
1154
1155         err := db.PExpireIE("key", "data", 10*time.Second)
1156         assert.Nil(t, err)
1157         r.AssertExpectations(t)
1158 }
1159
1160 func TestPExpireIEFailure(t *testing.T) {
1161         _, r, db := setupHaEnv(true)
1162         expectedKey := "key"
1163         expectedData := "data"
1164         expectedDuration := strconv.FormatInt(int64(10000), 10)
1165
1166         r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
1167                 Return(redis.NewCmdResult(int64(1), errors.New("Some error")))
1168
1169         err := db.PExpireIE("key", "data", 10*time.Second)
1170         assert.NotNil(t, err)
1171         r.AssertExpectations(t)
1172 }
1173
1174 func TestPExpireIELockNotHeld(t *testing.T) {
1175         _, r, db := setupHaEnv(true)
1176         expectedKey := "key"
1177         expectedData := "data"
1178         expectedDuration := strconv.FormatInt(int64(10000), 10)
1179
1180         r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
1181                 Return(redis.NewCmdResult(int64(0), nil))
1182
1183         err := db.PExpireIE("key", "data", 10*time.Second)
1184         assert.NotNil(t, err)
1185         r.AssertExpectations(t)
1186 }
1187
1188 func TestClientStandaloneRedisLegacyEnv(t *testing.T) {
1189         setupVals := setupEnv(
1190                 true,
1191                 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379", "", "", "", "",
1192         )
1193         assert.Equal(t, 1, len(setupVals.rClient))
1194         assert.Equal(t, 1, len(setupVals.db))
1195
1196         expectedKeysAndValues := []interface{}{"key1", "value1"}
1197         setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1198         err := setupVals.db[0].MSet("key1", "value1")
1199         assert.Nil(t, err)
1200         setupVals.rClient[0].AssertExpectations(t)
1201 }
1202
1203 func TestClientSentinelRedisLegacyEnv(t *testing.T) {
1204         setupVals := setupEnv(
1205                 true,
1206                 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379", "dbaasmaster-cluster-0", "26379", "", "3",
1207         )
1208         assert.Equal(t, 1, len(setupVals.rClient))
1209         assert.Equal(t, 1, len(setupVals.db))
1210
1211         expectedKeysAndValues := []interface{}{"key1", "value1"}
1212         setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1213         err := setupVals.db[0].MSet("key1", "value1")
1214         assert.Nil(t, err)
1215         setupVals.rClient[0].AssertExpectations(t)
1216 }
1217
1218 func TestClientTwoStandaloneRedisEnvs(t *testing.T) {
1219         setupVals := setupEnv(
1220                 true,
1221                 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379,6380", "", "",
1222                 "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "",
1223         )
1224         assert.Equal(t, 2, len(setupVals.rClient))
1225         assert.Equal(t, 2, len(setupVals.db))
1226
1227         expectedKeysAndValues := []interface{}{"key1", "value1"}
1228         setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1229         err := setupVals.db[0].MSet("key1", "value1")
1230         assert.Nil(t, err)
1231         setupVals.rClient[0].AssertExpectations(t)
1232
1233         expectedKeysAndValues = []interface{}{"key2", "value2"}
1234         setupVals.rClient[1].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1235         err = setupVals.db[1].MSet("key2", "value2")
1236         assert.Nil(t, err)
1237         setupVals.rClient[0].AssertExpectations(t)
1238         setupVals.rClient[1].AssertExpectations(t)
1239 }
1240
1241 func TestClientTwoSentinelRedisEnvs(t *testing.T) {
1242         setupVals := setupEnv(
1243                 true,
1244                 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379,6380", "dbaasmaster-cluster-0,dbaasmaster-cluster-1",
1245                 "26379,26380", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1246         )
1247         assert.Equal(t, 2, len(setupVals.rClient))
1248         assert.Equal(t, 2, len(setupVals.db))
1249
1250         expectedKeysAndValues := []interface{}{"key1", "value1"}
1251         setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1252         err := setupVals.db[0].MSet("key1", "value1")
1253         assert.Nil(t, err)
1254         setupVals.rClient[0].AssertExpectations(t)
1255
1256         expectedKeysAndValues = []interface{}{"key2", "value2"}
1257         setupVals.rClient[1].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1258         err = setupVals.db[1].MSet("key2", "value2")
1259         assert.Nil(t, err)
1260         setupVals.rClient[0].AssertExpectations(t)
1261         setupVals.rClient[1].AssertExpectations(t)
1262 }
1263
1264 func TestCompleteConfigIfLessPortsThanAddresses(t *testing.T) {
1265         setupVals := setupEnv(
1266                 true,
1267                 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379", "dbaasmaster-cluster-0,dbaasmaster-cluster-1",
1268                 "", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1269         )
1270         assert.Equal(t, 2, len(setupVals.rClient))
1271         assert.Equal(t, 2, len(setupVals.db))
1272 }
1273
1274 func TestCompleteConfigIfLessSentinelPortsThanAddresses(t *testing.T) {
1275         setupVals := setupEnv(
1276                 true,
1277                 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379,6380", "dbaasmaster-cluster-0,dbaasmaster-cluster-1",
1278                 "26379", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1279         )
1280         assert.Equal(t, 2, len(setupVals.rClient))
1281         assert.Equal(t, 2, len(setupVals.db))
1282 }
1283
1284 func TestCompleteConfigIfLessSentinelNamesThanAddresses(t *testing.T) {
1285         setupVals := setupEnv(
1286                 true,
1287                 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379,6380", "dbaasmaster-cluster-0",
1288                 "26379,26380", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1289         )
1290         assert.Equal(t, 2, len(setupVals.rClient))
1291         assert.Equal(t, 2, len(setupVals.db))
1292 }
1293
1294 func TestInfoOfPrimaryRedisWithTwoReplicasSuccessfully(t *testing.T) {
1295         _, r, db := setupHaEnv(true)
1296         redisInfo := "# Replication\r\n" +
1297                 "role:master\r\n" +
1298                 "connected_slaves:2\r\n" +
1299                 "min_slaves_good_slaves:2\r\n" +
1300                 "slave0:ip=1.2.3.4,port=6379,state=online,offset=100200300,lag=0\r\n" +
1301                 "slave1:ip=5.6.7.8,port=6379,state=online,offset=100200300,lag=0\r\n"
1302         expInfo := &sdlgoredis.DbInfo{
1303                 Fields: sdlgoredis.DbInfoFields{
1304                         PrimaryRole:         true,
1305                         ConnectedReplicaCnt: 2,
1306                 },
1307         }
1308
1309         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1310         info, err := db.Info()
1311         assert.Nil(t, err)
1312         assert.Equal(t, expInfo, info)
1313         r.AssertExpectations(t)
1314 }
1315
1316 func TestInfoOfPrimaryRedisWithOneReplicaOnlineAndOtherReplicaNotOnlineSuccessfully(t *testing.T) {
1317         _, r, db := setupHaEnv(true)
1318         redisInfo := "# Replication\r\n" +
1319                 "role:master\r\n" +
1320                 "connected_slaves:1\r\n" +
1321                 "min_slaves_good_slaves:2\r\n" +
1322                 "slave0:ip=1.2.3.4,port=6379,state=online,offset=100200300,lag=0\r\n" +
1323                 "slave1:ip=5.6.7.8,port=6379,state=wait_bgsave,offset=100200300,lag=0\r\n"
1324         expInfo := &sdlgoredis.DbInfo{
1325                 Fields: sdlgoredis.DbInfoFields{
1326                         PrimaryRole:         true,
1327                         ConnectedReplicaCnt: 1,
1328                 },
1329         }
1330
1331         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1332         info, err := db.Info()
1333         assert.Nil(t, err)
1334         assert.Equal(t, expInfo, info)
1335         r.AssertExpectations(t)
1336 }
1337
1338 func TestInfoOfStandalonePrimaryRedisSuccessfully(t *testing.T) {
1339         _, r, db := setupHaEnv(true)
1340         redisInfo := "# Replication\r\n" +
1341                 "role:master\r\n" +
1342                 "connected_slaves:0\r\n" +
1343                 "min_slaves_good_slaves:0\r\n"
1344         expInfo := &sdlgoredis.DbInfo{
1345                 Fields: sdlgoredis.DbInfoFields{
1346                         PrimaryRole:         true,
1347                         ConnectedReplicaCnt: 0,
1348                 },
1349         }
1350
1351         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1352         info, err := db.Info()
1353         assert.Nil(t, err)
1354         assert.Equal(t, expInfo, info)
1355         r.AssertExpectations(t)
1356 }
1357
1358 func TestInfoOfStandalonePrimaryRedisFailureWhenIntConversionFails(t *testing.T) {
1359         _, r, db := setupHaEnv(true)
1360         redisInfo := "# Replication\r\n" +
1361                 "role:master\r\n" +
1362                 "connected_slaves:not-int\r\n" +
1363                 "min_slaves_good_slaves:0\r\n"
1364         expInfo := &sdlgoredis.DbInfo{
1365                 Fields: sdlgoredis.DbInfoFields{
1366                         PrimaryRole:         true,
1367                         ConnectedReplicaCnt: 0,
1368                 },
1369         }
1370
1371         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1372         info, err := db.Info()
1373         assert.Nil(t, err)
1374         assert.Equal(t, expInfo, info)
1375         r.AssertExpectations(t)
1376 }
1377
1378 func TestInfoWithGibberishContentSuccessfully(t *testing.T) {
1379         _, r, db := setupHaEnv(true)
1380         redisInfo := "!#¤%&?+?´-\r\n"
1381         expInfo := &sdlgoredis.DbInfo{}
1382
1383         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1384         info, err := db.Info()
1385         assert.Nil(t, err)
1386         assert.Equal(t, expInfo, info)
1387         r.AssertExpectations(t)
1388 }
1389
1390 func TestInfoWithEmptyContentSuccessfully(t *testing.T) {
1391         _, r, db := setupHaEnv(true)
1392         var redisInfo string
1393         expInfo := &sdlgoredis.DbInfo{
1394                 Fields: sdlgoredis.DbInfoFields{
1395                         PrimaryRole: false,
1396                 },
1397         }
1398
1399         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1400         info, err := db.Info()
1401         assert.Nil(t, err)
1402         assert.Equal(t, expInfo, info)
1403         r.AssertExpectations(t)
1404 }
1405
1406 func TestInfoWithSomeStatisticsOfStandalonePrimaryRedis(t *testing.T) {
1407         _, r, db := setupHaEnv(true)
1408         redisInfo := "# Replication\r\n" +
1409                 "role:master\r\n" +
1410                 "connected_slaves:0\r\n" +
1411                 "min_slaves_good_slaves:0\r\n" +
1412                 "# Server\r\n" +
1413                 "uptime_in_days:23\r\n" +
1414                 "# Clients\r\n" +
1415                 "connected_clients:2\r\n" +
1416                 "# Memory\r\n" +
1417                 "used_memory:2093808\r\n" +
1418                 "used_memory_human:2.00M\r\n" +
1419                 "mem_fragmentation_ratio:6.44\r\n" +
1420                 "# Stats\r\n" +
1421                 "total_connections_received:278\r\n" +
1422                 "# CPU\r\n" +
1423                 "used_cpu_sys:1775.254919\r\n" +
1424                 "# Commandstats\r\n" +
1425                 "cmdstat_role:calls=1,usec=3,usec_per_call=3.00\r\n" +
1426                 "# Keyspace\r\n" +
1427                 "db0:keys=4,expires=0,avg_ttl=0"
1428         expInfo := &sdlgoredis.DbInfo{
1429                 Fields: sdlgoredis.DbInfoFields{
1430                         PrimaryRole:         true,
1431                         ConnectedReplicaCnt: 0,
1432                         Server: sdlgoredis.ServerInfoFields{
1433                                 UptimeInDays: 23,
1434                         },
1435                         Clients: sdlgoredis.ClientsInfoFields{
1436                                 ConnectedClients: 2,
1437                         },
1438                         Memory: sdlgoredis.MeroryInfoFields{
1439                                 UsedMemory:            2093808,
1440                                 UsedMemoryHuman:       "2.00M",
1441                                 MemFragmentationRatio: 6.44,
1442                         },
1443                         Stats: sdlgoredis.StatsInfoFields{
1444                                 TotalConnectionsReceived: 278,
1445                         },
1446                         Cpu: sdlgoredis.CpuInfoFields{
1447                                 UsedCpuSys: 1775.254919,
1448                         },
1449                         Commandstats: sdlgoredis.CommandstatsInfoFields{
1450                                 CmdstatRole: sdlgoredis.CommandstatsValues{
1451                                         Calls:       1,
1452                                         Usec:        3,
1453                                         UsecPerCall: 3.00,
1454                                 },
1455                         },
1456                         Keyspace: sdlgoredis.KeyspaceInfoFields{
1457                                 Db: sdlgoredis.KeyspaceValues{
1458                                         Keys: 4,
1459                                 },
1460                         },
1461                 },
1462         }
1463
1464         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1465         info, err := db.Info()
1466         assert.Nil(t, err)
1467         assert.Equal(t, expInfo, info)
1468         r.AssertExpectations(t)
1469 }
1470
1471 func TestStateWithPrimaryAndTwoReplicaRedisSuccessfully(t *testing.T) {
1472         _, r, s, db := setupHaEnvWithSentinels(true, "3")
1473
1474         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1475         redisReplicasState := newMockRedisSlavesCall()
1476         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1477         redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1478         redisSentinelsState := newMockRedisSentinelsCall()
1479         redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1480         redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1481
1482         expState := newExpDbState(3, nil)
1483         expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1484         expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1485         expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1486         expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1487         expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1488
1489         s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1490         s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1491         s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1492         ret, err := db.State()
1493         assert.Nil(t, err)
1494         assert.Equal(t, expState.s, *ret)
1495         r.AssertExpectations(t)
1496 }
1497
1498 func TestStateWithTwoSdlClustersContainingPrimaryAndTwoReplicaRedisSuccessfully(t *testing.T) {
1499         setupVals := setupEnv(
1500                 true,
1501                 "", "6379,6380", "dbaasmaster-cluster-0,dbaasmaster-cluster-1",
1502                 "26379,26380", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1503         )
1504         r := setupVals.rClient
1505         s := setupVals.rSentinel
1506         db := setupVals.db
1507
1508         FstRedisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1509         FstRedisReplicasState := newMockRedisSlavesCall()
1510         FstRedisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1511         FstRedisReplicasState.add("slave", "10.20.30.50", "6379", "up", "slave")
1512         FstRedisSentinelsState := newMockRedisSentinelsCall()
1513         FstRedisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1514         FstRedisSentinelsState.add("10.20.30.50", "26379", "sentinel")
1515
1516         SndRedisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.60", "6380", "master")
1517         SndRedisReplicasState := newMockRedisSlavesCall()
1518         SndRedisReplicasState.add("slave", "10.20.30.70", "6380", "up", "slave")
1519         SndRedisReplicasState.add("slave", "10.20.30.80", "6380", "up", "slave")
1520         SndRedisSentinelsState := newMockRedisSentinelsCall()
1521         SndRedisSentinelsState.add("10.20.30.70", "26380", "sentinel")
1522         SndRedisSentinelsState.add("10.20.30.80", "26380", "sentinel")
1523
1524         FstExpState := newExpDbState(3, nil)
1525         FstExpState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1526         FstExpState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1527         FstExpState.addReplica("slave", "10.20.30.50", "6379", "up", "slave", nil)
1528         FstExpState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1529         FstExpState.addSentinel("10.20.30.50", "26379", "sentinel", nil)
1530
1531         SndExpState := newExpDbState(3, nil)
1532         SndExpState.addPrimary("master", "10.20.30.60", "6380", "master", nil)
1533         SndExpState.addReplica("slave", "10.20.30.70", "6380", "up", "slave", nil)
1534         SndExpState.addReplica("slave", "10.20.30.80", "6380", "up", "slave", nil)
1535         SndExpState.addSentinel("10.20.30.70", "26380", "sentinel", nil)
1536         SndExpState.addSentinel("10.20.30.80", "26380", "sentinel", nil)
1537
1538         s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(FstRedisPrimaryState, nil))
1539         s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(FstRedisReplicasState.resp, nil))
1540         s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(FstRedisSentinelsState.resp, nil))
1541
1542         s[0].On("Master", "dbaasmaster-cluster-1").Return(redis.NewStringStringMapResult(SndRedisPrimaryState, nil))
1543         s[0].On("Slaves", "dbaasmaster-cluster-1").Return(redis.NewSliceResult(SndRedisReplicasState.resp, nil))
1544         s[0].On("Sentinels", "dbaasmaster-cluster-1").Return(redis.NewSliceResult(SndRedisSentinelsState.resp, nil))
1545
1546         ret, err := db[0].State()
1547         assert.Nil(t, err)
1548         assert.Equal(t, FstExpState.s, *ret)
1549
1550         ret, err = db[1].State()
1551         assert.Nil(t, err)
1552         assert.Equal(t, SndExpState.s, *ret)
1553         r[0].AssertExpectations(t)
1554 }
1555
1556 func TestStateWithPrimaryAndTwoReplicaRedisFailureInPrimaryRedisCall(t *testing.T) {
1557         expErr := errors.New("Some error")
1558         _, r, s, db := setupHaEnvWithSentinels(true, "3")
1559
1560         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1561         redisReplicasState := newMockRedisSlavesCall()
1562         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1563         redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1564         redisSentinelsState := newMockRedisSentinelsCall()
1565         redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1566         redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1567
1568         expState := newExpDbState(3, nil)
1569         expState.addPrimary("", "", "", "", expErr)
1570         expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1571         expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1572         expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1573         expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1574
1575         s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, expErr))
1576         s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1577         s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1578         ret, err := db.State()
1579         assert.NotNil(t, err)
1580         assert.Equal(t, expState.s, *ret)
1581         r.AssertExpectations(t)
1582 }
1583
1584 func TestStateWithPrimaryAndTwoReplicaRedisFailureInReplicasRedisCall(t *testing.T) {
1585         expErr := errors.New("Some error")
1586         _, r, s, db := setupHaEnvWithSentinels(true, "3")
1587
1588         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1589         redisReplicasState := newMockRedisSlavesCall()
1590         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1591         redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1592         redisSentinelsState := newMockRedisSentinelsCall()
1593         redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1594         redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1595
1596         expState := newExpDbState(3, nil)
1597         expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1598         expState.addReplica("", "", "", "", "", expErr)
1599         expState.addReplica("", "", "", "", "", expErr)
1600         expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1601         expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1602
1603         s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1604         s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, errors.New("Some error")))
1605         s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1606         ret, err := db.State()
1607         assert.NotNil(t, err)
1608         assert.Equal(t, expState.s, *ret)
1609         r.AssertExpectations(t)
1610 }
1611
1612 func TestStateWithPrimaryAndOneReplicaRedisFailureInSentinelsRedisCall(t *testing.T) {
1613         expErr := errors.New("Some error")
1614         _, r, s, db := setupHaEnvWithSentinels(true, "2")
1615
1616         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1617         redisReplicasState := newMockRedisSlavesCall()
1618         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1619         redisSentinelsState := newMockRedisSentinelsCall()
1620         redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1621
1622         expState := newExpDbState(2, nil)
1623         expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1624         expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1625         expState.addSentinel("", "", "", expErr)
1626
1627         s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1628         s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1629         s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, expErr))
1630         ret, err := db.State()
1631         assert.NotNil(t, err)
1632         assert.Equal(t, expState.s, *ret)
1633         r.AssertExpectations(t)
1634 }
1635
1636 func TestStateWithPrimaryAndTwoReplicaRedisFailureWhenIntConversionFails(t *testing.T) {
1637         expErr := errors.New("Sentinel DBAAS_NODE_COUNT configuration value 'no-int' conversion to integer failed")
1638         _, r, s, db := setupHaEnvWithSentinels(true, "no-int")
1639
1640         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1641         redisReplicasState := newMockRedisSlavesCall()
1642         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1643         redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1644         redisSentinelsState := newMockRedisSentinelsCall()
1645         redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1646         redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1647
1648         expState := newExpDbState(0, expErr)
1649         expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1650         expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1651         expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1652         expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1653         expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1654
1655         s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1656         s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1657         s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1658         ret, err := db.State()
1659         assert.Equal(t, expErr, err)
1660         assert.Equal(t, expState.s, *ret)
1661         r.AssertExpectations(t)
1662 }
1663
1664 // Test case to test ignoring of a sentinel entry with zero port. Implementation has been
1665 // done because we miss the fix for the Redis Bug #9240.
1666 func TestStateWithPrimaryAndTwoReplicaFirstSentinelStateIgnoredBecauseZeroPortBugRedisSuccessfully(t *testing.T) {
1667         _, r, s, db := setupHaEnvWithSentinels(true, "3")
1668
1669         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1670         redisReplicasState := newMockRedisSlavesCall()
1671         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1672         redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1673         redisSentinelsState := newMockRedisSentinelsCall()
1674         redisSentinelsState.add("10.20.30.40", "0", "s_down,sentinel,disconnected")
1675         redisSentinelsState.add("10.20.30.50", "26379", "sentinel")
1676
1677         expState := newExpDbState(3, nil)
1678         expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1679         expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1680         expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1681         expState.addSentinel("10.20.30.50", "26379", "sentinel", nil)
1682
1683         s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1684         s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1685         s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1686         ret, err := db.State()
1687         assert.Nil(t, err)
1688         assert.Equal(t, expState.s, *ret)
1689         r.AssertExpectations(t)
1690 }
1691
1692 func TestStateWithSinglePrimaryRedisSuccessfully(t *testing.T) {
1693         _, r, db := setupSingleEnv(true, "1")
1694         redisInfo := "# Replication\r\n" +
1695                 "role:master\r\n" +
1696                 "connected_slaves:0\r\n" +
1697                 "min_slaves_good_slaves:0\r\n"
1698
1699         expState := &sdlgoredis.DbState{
1700                 ConfigNodeCnt: 1,
1701                 PrimaryDbState: sdlgoredis.PrimaryDbState{
1702                         Fields: sdlgoredis.PrimaryDbStateFields{
1703                                 Role:  "master",
1704                                 Ip:    "service-ricplt-dbaas-tcp-cluster-0.ricplt",
1705                                 Port:  "6379",
1706                                 Flags: "master",
1707                         },
1708                 },
1709         }
1710
1711         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1712         ret, err := db.State()
1713         assert.Nil(t, err)
1714         assert.Equal(t, expState, ret)
1715         r.AssertExpectations(t)
1716 }
1717
1718 func TestStateWithSinglePrimaryRedisFailureWhenIntConversionFails(t *testing.T) {
1719         expErr := errors.New("DBAAS_NODE_COUNT configuration value 'no-int' conversion to integer failed")
1720         _, r, db := setupSingleEnv(true, "no-int")
1721         redisInfo := "# Replication\r\n" +
1722                 "role:master\r\n" +
1723                 "connected_slaves:0\r\n" +
1724                 "min_slaves_good_slaves:0\r\n"
1725
1726         expState := &sdlgoredis.DbState{
1727                 Err:           expErr,
1728                 ConfigNodeCnt: 0,
1729                 PrimaryDbState: sdlgoredis.PrimaryDbState{
1730                         Fields: sdlgoredis.PrimaryDbStateFields{
1731                                 Role:  "master",
1732                                 Ip:    "service-ricplt-dbaas-tcp-cluster-0.ricplt",
1733                                 Port:  "6379",
1734                                 Flags: "master",
1735                         },
1736                 },
1737         }
1738
1739         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1740         ret, err := db.State()
1741         assert.Equal(t, expErr, err)
1742         assert.Equal(t, expState, ret)
1743         r.AssertExpectations(t)
1744 }
1745
1746 func TestStateWithSinglePrimaryRedisFailureInInfoCall(t *testing.T) {
1747         expErr := errors.New("Some error")
1748         _, r, db := setupSingleEnv(true, "1")
1749         redisInfo := ""
1750         expState := &sdlgoredis.DbState{
1751                 PrimaryDbState: sdlgoredis.PrimaryDbState{
1752                         Err: expErr,
1753                 },
1754         }
1755
1756         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, errors.New("Some error")))
1757         ret, err := db.State()
1758         assert.NotNil(t, err)
1759         assert.Equal(t, expState, ret)
1760         r.AssertExpectations(t)
1761 }
1762
1763 func TestStatisticsWithSinglePrimaryRedisSuccessfully(t *testing.T) {
1764         _, r, db := setupSingleEnv(true, "1")
1765         redisInfo := "# Replication\r\n" +
1766                 "role:master\r\n" +
1767                 "connected_slaves:0\r\n" +
1768                 "min_slaves_good_slaves:0\r\n" +
1769                 "# Server\r\n" +
1770                 "uptime_in_days:12\r\n"
1771
1772         expStatistics := &sdlgoredis.DbStatistics{
1773                 Stats: []*sdlgoredis.DbStatisticsInfo{
1774                         {
1775                                 IPAddr: "service-ricplt-dbaas-tcp-cluster-0.ricplt",
1776                                 Port:   "6379",
1777                                 Info: &sdlgoredis.DbInfo{
1778                                         Fields: sdlgoredis.DbInfoFields{
1779                                                 PrimaryRole: true,
1780                                                 Server: sdlgoredis.ServerInfoFields{
1781                                                         UptimeInDays: 12,
1782                                                 },
1783                                         },
1784                                 },
1785                         },
1786                 },
1787         }
1788
1789         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1790         ret, err := db.Statistics()
1791         assert.Nil(t, err)
1792         assert.Equal(t, expStatistics, ret)
1793         r.AssertExpectations(t)
1794 }