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