7ed7d70ce2d4c3e982c8a30f679882d80158238e
[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         _, r, db := setupHaEnv(true)
1211         redisInfo := "# Replication\r\n" +
1212                 "role:master\r\n" +
1213                 "connected_slaves:not-int\r\n" +
1214                 "min_slaves_good_slaves:0\r\n"
1215         expInfo := &sdlgoredis.DbInfo{
1216                 Fields: sdlgoredis.DbInfoFields{
1217                         PrimaryRole:         true,
1218                         ConnectedReplicaCnt: 0,
1219                 },
1220         }
1221
1222         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1223         info, err := db.Info()
1224         assert.Nil(t, err)
1225         assert.Equal(t, expInfo, info)
1226         r.AssertExpectations(t)
1227 }
1228
1229 func TestInfoWithGibberishContentSuccessfully(t *testing.T) {
1230         _, r, db := setupHaEnv(true)
1231         redisInfo := "!#¤%&?+?´-\r\n"
1232         expInfo := &sdlgoredis.DbInfo{}
1233
1234         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1235         info, err := db.Info()
1236         assert.Nil(t, err)
1237         assert.Equal(t, expInfo, info)
1238         r.AssertExpectations(t)
1239 }
1240
1241 func TestInfoWithEmptyContentSuccessfully(t *testing.T) {
1242         _, r, db := setupHaEnv(true)
1243         var redisInfo string
1244         expInfo := &sdlgoredis.DbInfo{
1245                 Fields: sdlgoredis.DbInfoFields{
1246                         PrimaryRole: false,
1247                 },
1248         }
1249
1250         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1251         info, err := db.Info()
1252         assert.Nil(t, err)
1253         assert.Equal(t, expInfo, info)
1254         r.AssertExpectations(t)
1255 }
1256
1257 func TestInfoWithSomeStatisticsOfStandalonePrimaryRedis(t *testing.T) {
1258         _, r, db := setupHaEnv(true)
1259         redisInfo := "# Replication\r\n" +
1260                 "role:master\r\n" +
1261                 "connected_slaves:0\r\n" +
1262                 "min_slaves_good_slaves:0\r\n" +
1263                 "# Server\r\n" +
1264                 "uptime_in_days:23\r\n" +
1265                 "# Clients\r\n" +
1266                 "connected_clients:2\r\n" +
1267                 "# Memory\r\n" +
1268                 "used_memory:2093808\r\n" +
1269                 "used_memory_human:2.00M\r\n" +
1270                 "mem_fragmentation_ratio:6.44\r\n" +
1271                 "# Stats\r\n" +
1272                 "total_connections_received:278\r\n" +
1273                 "# CPU\r\n" +
1274                 "used_cpu_sys:1775.254919\r\n" +
1275                 "# Commandstats\r\n" +
1276                 "cmdstat_role:calls=1,usec=3,usec_per_call=3.00\r\n" +
1277                 "# Keyspace\r\n" +
1278                 "db0:keys=4,expires=0,avg_ttl=0"
1279         expInfo := &sdlgoredis.DbInfo{
1280                 Fields: sdlgoredis.DbInfoFields{
1281                         PrimaryRole:         true,
1282                         ConnectedReplicaCnt: 0,
1283                         Server: sdlgoredis.ServerInfoFields{
1284                                 UptimeInDays: 23,
1285                         },
1286                         Clients: sdlgoredis.ClientsInfoFields{
1287                                 ConnectedClients: 2,
1288                         },
1289                         Memory: sdlgoredis.MeroryInfoFields{
1290                                 UsedMemory:            2093808,
1291                                 UsedMemoryHuman:       "2.00M",
1292                                 MemFragmentationRatio: 6.44,
1293                         },
1294                         Stats: sdlgoredis.StatsInfoFields{
1295                                 TotalConnectionsReceived: 278,
1296                         },
1297                         Cpu: sdlgoredis.CpuInfoFields{
1298                                 UsedCpuSys: 1775.254919,
1299                         },
1300                         Commandstats: sdlgoredis.CommandstatsInfoFields{
1301                                 CmdstatRole: sdlgoredis.CommandstatsValues{
1302                                         Calls:       1,
1303                                         Usec:        3,
1304                                         UsecPerCall: 3.00,
1305                                 },
1306                         },
1307                         Keyspace: sdlgoredis.KeyspaceInfoFields{
1308                                 Db: sdlgoredis.KeyspaceValues{
1309                                         Keys: 4,
1310                                 },
1311                         },
1312                 },
1313         }
1314
1315         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1316         info, err := db.Info()
1317         assert.Nil(t, err)
1318         assert.Equal(t, expInfo, info)
1319         r.AssertExpectations(t)
1320 }
1321
1322 func TestStateWithPrimaryAndTwoReplicaRedisSuccessfully(t *testing.T) {
1323         _, r, s, db := setupHaEnvWithSentinels(true, "3")
1324
1325         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1326         redisReplicasState := newMockRedisSlavesCall()
1327         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1328         redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1329         redisSentinelsState := newMockRedisSentinelsCall()
1330         redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1331         redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1332
1333         expState := newExpDbState(3, nil)
1334         expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1335         expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1336         expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1337         expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1338         expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1339
1340         s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1341         s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1342         s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1343         ret, err := db.State()
1344         assert.Nil(t, err)
1345         assert.Equal(t, expState.s, *ret)
1346         r.AssertExpectations(t)
1347 }
1348
1349 func TestStateWithPrimaryAndTwoReplicaRedisFailureInPrimaryRedisCall(t *testing.T) {
1350         expErr := errors.New("Some error")
1351         _, r, s, db := setupHaEnvWithSentinels(true, "3")
1352
1353         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1354         redisReplicasState := newMockRedisSlavesCall()
1355         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1356         redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1357         redisSentinelsState := newMockRedisSentinelsCall()
1358         redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1359         redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1360
1361         expState := newExpDbState(3, nil)
1362         expState.addPrimary("", "", "", "", expErr)
1363         expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1364         expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1365         expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1366         expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1367
1368         s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, expErr))
1369         s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1370         s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1371         ret, err := db.State()
1372         assert.NotNil(t, err)
1373         assert.Equal(t, expState.s, *ret)
1374         r.AssertExpectations(t)
1375 }
1376
1377 func TestStateWithPrimaryAndTwoReplicaRedisFailureInReplicasRedisCall(t *testing.T) {
1378         expErr := errors.New("Some error")
1379         _, r, s, db := setupHaEnvWithSentinels(true, "3")
1380
1381         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1382         redisReplicasState := newMockRedisSlavesCall()
1383         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1384         redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1385         redisSentinelsState := newMockRedisSentinelsCall()
1386         redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1387         redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1388
1389         expState := newExpDbState(3, nil)
1390         expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1391         expState.addReplica("", "", "", "", "", expErr)
1392         expState.addReplica("", "", "", "", "", expErr)
1393         expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1394         expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1395
1396         s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1397         s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, errors.New("Some error")))
1398         s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1399         ret, err := db.State()
1400         assert.NotNil(t, err)
1401         assert.Equal(t, expState.s, *ret)
1402         r.AssertExpectations(t)
1403 }
1404
1405 func TestStateWithPrimaryAndOneReplicaRedisFailureInSentinelsRedisCall(t *testing.T) {
1406         expErr := errors.New("Some error")
1407         _, r, s, db := setupHaEnvWithSentinels(true, "2")
1408
1409         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1410         redisReplicasState := newMockRedisSlavesCall()
1411         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1412         redisSentinelsState := newMockRedisSentinelsCall()
1413         redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1414
1415         expState := newExpDbState(2, nil)
1416         expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1417         expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1418         expState.addSentinel("", "", "", expErr)
1419
1420         s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1421         s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1422         s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, expErr))
1423         ret, err := db.State()
1424         assert.NotNil(t, err)
1425         assert.Equal(t, expState.s, *ret)
1426         r.AssertExpectations(t)
1427 }
1428
1429 func TestStateWithPrimaryAndTwoReplicaRedisFailureWhenIntConversionFails(t *testing.T) {
1430         expErr := errors.New("Sentinel DBAAS_NODE_COUNT configuration value 'no-int' conversion to integer failed")
1431         _, r, s, db := setupHaEnvWithSentinels(true, "no-int")
1432
1433         redisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master")
1434         redisReplicasState := newMockRedisSlavesCall()
1435         redisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave")
1436         redisReplicasState.add("slave", "10.20.30.50", "30000", "up", "slave")
1437         redisSentinelsState := newMockRedisSentinelsCall()
1438         redisSentinelsState.add("10.20.30.40", "26379", "sentinel")
1439         redisSentinelsState.add("10.20.30.50", "30001", "sentinel")
1440
1441         expState := newExpDbState(0, expErr)
1442         expState.addPrimary("master", "10.20.30.30", "6379", "master", nil)
1443         expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil)
1444         expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil)
1445         expState.addSentinel("10.20.30.40", "26379", "sentinel", nil)
1446         expState.addSentinel("10.20.30.50", "30001", "sentinel", nil)
1447
1448         s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, nil))
1449         s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, nil))
1450         s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, nil))
1451         ret, err := db.State()
1452         assert.Equal(t, expErr, err)
1453         assert.Equal(t, expState.s, *ret)
1454         r.AssertExpectations(t)
1455 }
1456
1457 func TestStateWithSinglePrimaryRedisSuccessfully(t *testing.T) {
1458         _, r, db := setupSingleEnv(true, "1")
1459         redisInfo := "# Replication\r\n" +
1460                 "role:master\r\n" +
1461                 "connected_slaves:0\r\n" +
1462                 "min_slaves_good_slaves:0\r\n"
1463
1464         expState := &sdlgoredis.DbState{
1465                 ConfigNodeCnt: 1,
1466                 PrimaryDbState: sdlgoredis.PrimaryDbState{
1467                         Fields: sdlgoredis.PrimaryDbStateFields{
1468                                 Role:  "master",
1469                                 Ip:    "service-ricplt-dbaas-tcp-cluster-0.ricplt",
1470                                 Port:  "6376",
1471                                 Flags: "master",
1472                         },
1473                 },
1474         }
1475
1476         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1477         ret, err := db.State()
1478         assert.Nil(t, err)
1479         assert.Equal(t, expState, ret)
1480         r.AssertExpectations(t)
1481 }
1482
1483 func TestStateWithSinglePrimaryRedisFailureWhenIntConversionFails(t *testing.T) {
1484         expErr := errors.New("DBAAS_NODE_COUNT configuration value 'no-int' conversion to integer failed")
1485         _, r, db := setupSingleEnv(true, "no-int")
1486         redisInfo := "# Replication\r\n" +
1487                 "role:master\r\n" +
1488                 "connected_slaves:0\r\n" +
1489                 "min_slaves_good_slaves:0\r\n"
1490
1491         expState := &sdlgoredis.DbState{
1492                 Err:           expErr,
1493                 ConfigNodeCnt: 0,
1494                 PrimaryDbState: sdlgoredis.PrimaryDbState{
1495                         Fields: sdlgoredis.PrimaryDbStateFields{
1496                                 Role:  "master",
1497                                 Ip:    "service-ricplt-dbaas-tcp-cluster-0.ricplt",
1498                                 Port:  "6376",
1499                                 Flags: "master",
1500                         },
1501                 },
1502         }
1503
1504         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1505         ret, err := db.State()
1506         assert.Equal(t, expErr, err)
1507         assert.Equal(t, expState, ret)
1508         r.AssertExpectations(t)
1509 }
1510
1511 func TestStateWithSinglePrimaryRedisFailureInInfoCall(t *testing.T) {
1512         expErr := errors.New("Some error")
1513         _, r, db := setupSingleEnv(true, "1")
1514         redisInfo := ""
1515         expState := &sdlgoredis.DbState{
1516                 PrimaryDbState: sdlgoredis.PrimaryDbState{
1517                         Err: expErr,
1518                 },
1519         }
1520
1521         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, errors.New("Some error")))
1522         ret, err := db.State()
1523         assert.NotNil(t, err)
1524         assert.Equal(t, expState, ret)
1525         r.AssertExpectations(t)
1526 }
1527
1528 func TestStatisticsWithSinglePrimaryRedisSuccessfully(t *testing.T) {
1529         _, r, db := setupSingleEnv(true, "1")
1530         redisInfo := "# Replication\r\n" +
1531                 "role:master\r\n" +
1532                 "connected_slaves:0\r\n" +
1533                 "min_slaves_good_slaves:0\r\n" +
1534                 "# Server\r\n" +
1535                 "uptime_in_days:12\r\n"
1536
1537         expStatistics := &sdlgoredis.DbStatistics{
1538                 Stats: []*sdlgoredis.DbStatisticsInfo{
1539                         {
1540                                 IPAddr: "service-ricplt-dbaas-tcp-cluster-0.ricplt",
1541                                 Port:   "6376",
1542                                 Info: &sdlgoredis.DbInfo{
1543                                         Fields: sdlgoredis.DbInfoFields{
1544                                                 PrimaryRole: true,
1545                                                 Server: sdlgoredis.ServerInfoFields{
1546                                                         UptimeInDays: 12,
1547                                                 },
1548                                         },
1549                                 },
1550                         },
1551                 },
1552         }
1553
1554         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1555         ret, err := db.Statistics()
1556         assert.Nil(t, err)
1557         assert.Equal(t, expStatistics, ret)
1558         r.AssertExpectations(t)
1559 }