740674da1dd938593c306fb2b8313341613a29b6
[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)
184         return psm, cm, db
185 }
186
187 func setupHaEnvWithSentinels(commandsExists bool) (*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                 "3",
196         )
197         return setupVals.pubSubMock[0], setupVals.rClient[0], setupVals.rSentinel, setupVals.db[0]
198 }
199
200 func setupSingleEnv(commandsExists bool) (*pubSubMock, *clientMock, *sdlgoredis.DB) {
201         setupVals := setupEnv(
202                 commandsExists,
203                 "service-ricplt-dbaas-tcp-cluster-0.ricplt",
204                 "6376", "", "", "", "",
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_SERVICE_NODE_COUNT", "").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 TestCloseDbSuccessfully(t *testing.T) {
266         _, r, db := setupHaEnv(true)
267         r.On("Close").Return(nil)
268         err := db.CloseDB()
269         assert.Nil(t, err)
270         r.AssertExpectations(t)
271 }
272
273 func TestCloseDbFailure(t *testing.T) {
274         _, r, db := setupHaEnv(true)
275         r.On("Close").Return(errors.New("Some error"))
276         err := db.CloseDB()
277         assert.NotNil(t, err)
278         r.AssertExpectations(t)
279 }
280
281 func TestMSetSuccessfully(t *testing.T) {
282         _, r, db := setupHaEnv(true)
283         expectedKeysAndValues := []interface{}{"key1", "value1", "key2", 2}
284         r.On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
285         err := db.MSet("key1", "value1", "key2", 2)
286         assert.Nil(t, err)
287         r.AssertExpectations(t)
288 }
289
290 func TestMSetFailure(t *testing.T) {
291         _, r, db := setupHaEnv(true)
292         expectedKeysAndValues := []interface{}{"key1", "value1", "key2", 2}
293         r.On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", errors.New("Some error")))
294         err := db.MSet("key1", "value1", "key2", 2)
295         assert.NotNil(t, err)
296         r.AssertExpectations(t)
297 }
298
299 func TestMSetMPubSuccessfully(t *testing.T) {
300         _, r, db := setupHaEnv(true)
301         expectedMessage := []interface{}{"MSETMPUB", 2, 2, "key1", "val1", "key2", "val2",
302                 "chan1", "event1", "chan2", "event2"}
303         r.On("Do", expectedMessage).Return(redis.NewCmdResult("", nil))
304         assert.Nil(t, db.MSetMPub([]string{"chan1", "event1", "chan2", "event2"},
305                 "key1", "val1", "key2", "val2"))
306         r.AssertExpectations(t)
307 }
308
309 func TestMsetMPubFailure(t *testing.T) {
310         _, r, db := setupHaEnv(true)
311         expectedMessage := []interface{}{"MSETMPUB", 2, 2, "key1", "val1", "key2", "val2",
312                 "chan1", "event1", "chan2", "event2"}
313         r.On("Do", expectedMessage).Return(redis.NewCmdResult("", errors.New("Some error")))
314         assert.NotNil(t, db.MSetMPub([]string{"chan1", "event1", "chan2", "event2"},
315                 "key1", "val1", "key2", "val2"))
316         r.AssertExpectations(t)
317 }
318
319 func TestMSetMPubCommandMissing(t *testing.T) {
320         _, r, db := setupHaEnv(false)
321         expectedMessage := []interface{}{"MSETMPUB", 2, 2, "key1", "val1", "key2", "val2",
322                 "chan1", "event1", "chan2", "event2"}
323         r.AssertNotCalled(t, "Do", expectedMessage)
324         assert.NotNil(t, db.MSetMPub([]string{"chan1", "event1", "chan2", "event2"},
325                 "key1", "val1", "key2", "val2"))
326         r.AssertExpectations(t)
327
328 }
329
330 func TestMGetSuccessfully(t *testing.T) {
331         _, r, db := setupHaEnv(true)
332         expectedKeys := []string{"key1", "key2", "key3"}
333         expectedResult := []interface{}{"val1", 2, nil}
334         r.On("MGet", expectedKeys).Return(redis.NewSliceResult(expectedResult, nil))
335         result, err := db.MGet([]string{"key1", "key2", "key3"})
336         assert.Equal(t, result, expectedResult)
337         assert.Nil(t, err)
338         r.AssertExpectations(t)
339 }
340
341 func TestMGetFailure(t *testing.T) {
342         _, r, db := setupHaEnv(true)
343         expectedKeys := []string{"key1", "key2", "key3"}
344         expectedResult := []interface{}{nil}
345         r.On("MGet", expectedKeys).Return(redis.NewSliceResult(expectedResult,
346                 errors.New("Some error")))
347         result, err := db.MGet([]string{"key1", "key2", "key3"})
348         assert.Equal(t, result, expectedResult)
349         assert.NotNil(t, err)
350         r.AssertExpectations(t)
351 }
352
353 func TestDelMPubSuccessfully(t *testing.T) {
354         _, r, db := setupHaEnv(true)
355         expectedMessage := []interface{}{"DELMPUB", 2, 2, "key1", "key2", "chan1", "event1",
356                 "chan2", "event2"}
357         r.On("Do", expectedMessage).Return(redis.NewCmdResult("", nil))
358         assert.Nil(t, db.DelMPub([]string{"chan1", "event1", "chan2", "event2"},
359                 []string{"key1", "key2"}))
360         r.AssertExpectations(t)
361 }
362
363 func TestDelMPubFailure(t *testing.T) {
364         _, r, db := setupHaEnv(true)
365         expectedMessage := []interface{}{"DELMPUB", 2, 2, "key1", "key2", "chan1", "event1",
366                 "chan2", "event2"}
367         r.On("Do", expectedMessage).Return(redis.NewCmdResult("", errors.New("Some error")))
368         assert.NotNil(t, db.DelMPub([]string{"chan1", "event1", "chan2", "event2"},
369                 []string{"key1", "key2"}))
370         r.AssertExpectations(t)
371 }
372
373 func TestDelMPubCommandMissing(t *testing.T) {
374         _, r, db := setupHaEnv(false)
375         expectedMessage := []interface{}{"DELMPUB", 2, 2, "key1", "key2", "chan1", "event1",
376                 "chan2", "event2"}
377         r.AssertNotCalled(t, "Do", expectedMessage)
378         assert.NotNil(t, db.DelMPub([]string{"chan1", "event1", "chan2", "event2"},
379                 []string{"key1", "key2"}))
380         r.AssertExpectations(t)
381 }
382
383 func TestDelSuccessfully(t *testing.T) {
384         _, r, db := setupHaEnv(true)
385         expectedKeys := []string{"key1", "key2"}
386         r.On("Del", expectedKeys).Return(redis.NewIntResult(2, nil))
387         assert.Nil(t, db.Del([]string{"key1", "key2"}))
388         r.AssertExpectations(t)
389 }
390
391 func TestDelFailure(t *testing.T) {
392         _, r, db := setupHaEnv(true)
393         expectedKeys := []string{"key1", "key2"}
394         r.On("Del", expectedKeys).Return(redis.NewIntResult(2, errors.New("Some error")))
395         assert.NotNil(t, db.Del([]string{"key1", "key2"}))
396         r.AssertExpectations(t)
397 }
398
399 func TestKeysSuccessfully(t *testing.T) {
400         _, r, db := setupHaEnv(true)
401         expectedPattern := "pattern*"
402         expectedResult := []string{"pattern1", "pattern2"}
403         r.On("Keys", expectedPattern).Return(redis.NewStringSliceResult(expectedResult, nil))
404         result, err := db.Keys("pattern*")
405         assert.Equal(t, result, expectedResult)
406         assert.Nil(t, err)
407         r.AssertExpectations(t)
408 }
409
410 func TestKeysFailure(t *testing.T) {
411         _, r, db := setupHaEnv(true)
412         expectedPattern := "pattern*"
413         expectedResult := []string{}
414         r.On("Keys", expectedPattern).Return(redis.NewStringSliceResult(expectedResult,
415                 errors.New("Some error")))
416         _, err := db.Keys("pattern*")
417         assert.NotNil(t, err)
418         r.AssertExpectations(t)
419 }
420
421 func TestSetIEKeyExists(t *testing.T) {
422         _, r, db := setupHaEnv(true)
423         expectedMessage := []interface{}{"SETIE", "key", "newdata", "olddata"}
424         r.On("Do", expectedMessage).Return(redis.NewCmdResult("OK", nil))
425         result, err := db.SetIE("key", "olddata", "newdata")
426         assert.True(t, result)
427         assert.Nil(t, err)
428         r.AssertExpectations(t)
429 }
430
431 func TestSetIEKeyDoesntExists(t *testing.T) {
432         _, r, db := setupHaEnv(true)
433         expectedMessage := []interface{}{"SETIE", "key", "newdata", "olddata"}
434         r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, nil))
435         result, err := db.SetIE("key", "olddata", "newdata")
436         assert.False(t, result)
437         assert.Nil(t, err)
438         r.AssertExpectations(t)
439 }
440
441 func TestSetIEFailure(t *testing.T) {
442         _, r, db := setupHaEnv(true)
443         expectedMessage := []interface{}{"SETIE", "key", "newdata", "olddata"}
444         r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, errors.New("Some error")))
445         result, err := db.SetIE("key", "olddata", "newdata")
446         assert.False(t, result)
447         assert.NotNil(t, err)
448         r.AssertExpectations(t)
449 }
450
451 func TestSetIECommandMissing(t *testing.T) {
452         _, r, db := setupHaEnv(false)
453         expectedMessage := []interface{}{"SETIE", "key", "newdata", "olddata"}
454         r.AssertNotCalled(t, "Do", expectedMessage)
455         result, err := db.SetIE("key", "olddata", "newdata")
456         assert.False(t, result)
457         assert.NotNil(t, err)
458         r.AssertExpectations(t)
459 }
460
461 func TestSetIEPubKeyExists(t *testing.T) {
462         _, r, db := setupHaEnv(true)
463         expectedMessage := []interface{}{"SETIEMPUB", "key", "newdata", "olddata", "channel", "message"}
464         r.On("Do", expectedMessage).Return(redis.NewCmdResult("OK", nil))
465         result, err := db.SetIEPub([]string{"channel", "message"}, "key", "olddata", "newdata")
466         assert.True(t, result)
467         assert.Nil(t, err)
468         r.AssertExpectations(t)
469 }
470
471 func TestSetIEPubKeyDoesntExists(t *testing.T) {
472         _, r, db := setupHaEnv(true)
473         expectedMessage := []interface{}{"SETIEMPUB", "key", "newdata", "olddata", "channel", "message"}
474         r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, nil))
475         result, err := db.SetIEPub([]string{"channel", "message"}, "key", "olddata", "newdata")
476         assert.False(t, result)
477         assert.Nil(t, err)
478         r.AssertExpectations(t)
479 }
480
481 func TestSetIEPubFailure(t *testing.T) {
482         _, r, db := setupHaEnv(true)
483         expectedMessage := []interface{}{"SETIEMPUB", "key", "newdata", "olddata", "channel", "message"}
484         r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, errors.New("Some error")))
485         result, err := db.SetIEPub([]string{"channel", "message"}, "key", "olddata", "newdata")
486         assert.False(t, result)
487         assert.NotNil(t, err)
488         r.AssertExpectations(t)
489 }
490
491 func TestSetIEPubCommandMissing(t *testing.T) {
492         _, r, db := setupHaEnv(false)
493         expectedMessage := []interface{}{"SETIEMPUB", "key", "newdata", "olddata", "channel", "message"}
494         r.AssertNotCalled(t, "Do", expectedMessage)
495         result, err := db.SetIEPub([]string{"channel", "message"}, "key", "olddata", "newdata")
496         assert.False(t, result)
497         assert.NotNil(t, err)
498         r.AssertExpectations(t)
499 }
500
501 func TestSetNXPubKeyDoesntExist(t *testing.T) {
502         _, r, db := setupHaEnv(true)
503         expectedMessage := []interface{}{"SETNXMPUB", "key", "data", "channel", "message"}
504         r.On("Do", expectedMessage).Return(redis.NewCmdResult("OK", nil))
505         result, err := db.SetNXPub([]string{"channel", "message"}, "key", "data")
506         assert.True(t, result)
507         assert.Nil(t, err)
508         r.AssertExpectations(t)
509 }
510
511 func TestSetNXPubKeyExists(t *testing.T) {
512         _, r, db := setupHaEnv(true)
513         expectedMessage := []interface{}{"SETNXMPUB", "key", "data", "channel", "message"}
514         r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, nil))
515         result, err := db.SetNXPub([]string{"channel", "message"}, "key", "data")
516         assert.False(t, result)
517         assert.Nil(t, err)
518         r.AssertExpectations(t)
519 }
520
521 func TestSetNXPubFailure(t *testing.T) {
522         _, r, db := setupHaEnv(true)
523         expectedMessage := []interface{}{"SETNXMPUB", "key", "data", "channel", "message"}
524         r.On("Do", expectedMessage).Return(redis.NewCmdResult(nil, errors.New("Some error")))
525         result, err := db.SetNXPub([]string{"channel", "message"}, "key", "data")
526         assert.False(t, result)
527         assert.NotNil(t, err)
528         r.AssertExpectations(t)
529 }
530
531 func TestSetNXPubCommandMissing(t *testing.T) {
532         _, r, db := setupHaEnv(false)
533         expectedMessage := []interface{}{"SETNXMPUB", "key", "data", "channel", "message"}
534         r.AssertNotCalled(t, "Do", expectedMessage)
535         result, err := db.SetNXPub([]string{"channel", "message"}, "key", "data")
536         assert.False(t, result)
537         assert.NotNil(t, err)
538         r.AssertExpectations(t)
539 }
540
541 func TestSetNXSuccessfully(t *testing.T) {
542         _, r, db := setupHaEnv(true)
543         expectedKey := "key"
544         expectedData := "data"
545         r.On("SetNX", expectedKey, expectedData, time.Duration(0)).Return(redis.NewBoolResult(true, nil))
546         result, err := db.SetNX("key", "data", 0)
547         assert.True(t, result)
548         assert.Nil(t, err)
549         r.AssertExpectations(t)
550 }
551
552 func TestSetNXUnsuccessfully(t *testing.T) {
553         _, r, db := setupHaEnv(true)
554         expectedKey := "key"
555         expectedData := "data"
556         r.On("SetNX", expectedKey, expectedData, time.Duration(0)).Return(redis.NewBoolResult(false, nil))
557         result, err := db.SetNX("key", "data", 0)
558         assert.False(t, result)
559         assert.Nil(t, err)
560         r.AssertExpectations(t)
561 }
562
563 func TestSetNXFailure(t *testing.T) {
564         _, r, db := setupHaEnv(true)
565         expectedKey := "key"
566         expectedData := "data"
567         r.On("SetNX", expectedKey, expectedData, time.Duration(0)).
568                 Return(redis.NewBoolResult(false, errors.New("Some error")))
569         result, err := db.SetNX("key", "data", 0)
570         assert.False(t, result)
571         assert.NotNil(t, err)
572         r.AssertExpectations(t)
573 }
574
575 func TestDelIEPubKeyDoesntExist(t *testing.T) {
576         _, r, db := setupHaEnv(true)
577         expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
578         r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(0), nil))
579         result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
580         assert.False(t, result)
581         assert.Nil(t, err)
582         r.AssertExpectations(t)
583 }
584
585 func TestDelIEPubKeyExists(t *testing.T) {
586         _, r, db := setupHaEnv(true)
587         expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
588         r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(1), nil))
589         result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
590         assert.True(t, result)
591         assert.Nil(t, err)
592         r.AssertExpectations(t)
593 }
594
595 func TestDelIEPubKeyExistsIntTypeRedisValue(t *testing.T) {
596         _, r, db := setupHaEnv(true)
597         expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
598         r.On("Do", expectedMessage).Return(redis.NewCmdResult(1, nil))
599         result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
600         assert.True(t, result)
601         assert.Nil(t, err)
602         r.AssertExpectations(t)
603 }
604
605 func TestDelIEPubFailure(t *testing.T) {
606         _, r, db := setupHaEnv(true)
607         expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
608         r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(0), errors.New("Some error")))
609         result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
610         assert.False(t, result)
611         assert.NotNil(t, err)
612         r.AssertExpectations(t)
613 }
614
615 func TestDelIEPubCommandMissing(t *testing.T) {
616         _, r, db := setupHaEnv(false)
617         expectedMessage := []interface{}{"DELIEMPUB", "key", "data", "channel", "message"}
618         r.AssertNotCalled(t, "Do", expectedMessage)
619         result, err := db.DelIEPub([]string{"channel", "message"}, "key", "data")
620         assert.False(t, result)
621         assert.NotNil(t, err)
622         r.AssertExpectations(t)
623 }
624
625 func TestDelIEKeyDoesntExist(t *testing.T) {
626         _, r, db := setupHaEnv(true)
627         expectedMessage := []interface{}{"DELIE", "key", "data"}
628         r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(0), nil))
629         result, err := db.DelIE("key", "data")
630         assert.False(t, result)
631         assert.Nil(t, err)
632         r.AssertExpectations(t)
633 }
634
635 func TestDelIEKeyExists(t *testing.T) {
636         _, r, db := setupHaEnv(true)
637         expectedMessage := []interface{}{"DELIE", "key", "data"}
638         r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(1), nil))
639         result, err := db.DelIE("key", "data")
640         assert.True(t, result)
641         assert.Nil(t, err)
642         r.AssertExpectations(t)
643 }
644
645 func TestDelIEKeyExistsIntTypeRedisValue(t *testing.T) {
646         _, r, db := setupHaEnv(true)
647         expectedMessage := []interface{}{"DELIE", "key", "data"}
648         r.On("Do", expectedMessage).Return(redis.NewCmdResult(1, nil))
649         result, err := db.DelIE("key", "data")
650         assert.True(t, result)
651         assert.Nil(t, err)
652         r.AssertExpectations(t)
653 }
654
655 func TestDelIEFailure(t *testing.T) {
656         _, r, db := setupHaEnv(true)
657         expectedMessage := []interface{}{"DELIE", "key", "data"}
658         r.On("Do", expectedMessage).Return(redis.NewCmdResult(int64(0), errors.New("Some error")))
659         result, err := db.DelIE("key", "data")
660         assert.False(t, result)
661         assert.NotNil(t, err)
662         r.AssertExpectations(t)
663 }
664
665 func TestDelIECommandMissing(t *testing.T) {
666         _, r, db := setupHaEnv(false)
667         expectedMessage := []interface{}{"DELIE", "key", "data"}
668         r.AssertNotCalled(t, "Do", expectedMessage)
669         result, err := db.DelIE("key", "data")
670         assert.False(t, result)
671         assert.NotNil(t, err)
672         r.AssertExpectations(t)
673 }
674
675 func TestSAddSuccessfully(t *testing.T) {
676         _, r, db := setupHaEnv(true)
677         expectedKey := "key"
678         expectedData := []interface{}{"data", 2}
679         r.On("SAdd", expectedKey, expectedData).Return(redis.NewIntResult(2, nil))
680         assert.Nil(t, db.SAdd("key", "data", 2))
681         r.AssertExpectations(t)
682 }
683
684 func TestSAddFailure(t *testing.T) {
685         _, r, db := setupHaEnv(true)
686         expectedKey := "key"
687         expectedData := []interface{}{"data", 2}
688         r.On("SAdd", expectedKey, expectedData).Return(redis.NewIntResult(2, errors.New("Some error")))
689         assert.NotNil(t, db.SAdd("key", "data", 2))
690         r.AssertExpectations(t)
691 }
692
693 func TestSRemSuccessfully(t *testing.T) {
694         _, r, db := setupHaEnv(true)
695         expectedKey := "key"
696         expectedData := []interface{}{"data", 2}
697         r.On("SRem", expectedKey, expectedData).Return(redis.NewIntResult(2, nil))
698         assert.Nil(t, db.SRem("key", "data", 2))
699         r.AssertExpectations(t)
700 }
701
702 func TestSRemFailure(t *testing.T) {
703         _, r, db := setupHaEnv(true)
704         expectedKey := "key"
705         expectedData := []interface{}{"data", 2}
706         r.On("SRem", expectedKey, expectedData).Return(redis.NewIntResult(2, errors.New("Some error")))
707         assert.NotNil(t, db.SRem("key", "data", 2))
708         r.AssertExpectations(t)
709 }
710
711 func TestSMembersSuccessfully(t *testing.T) {
712         _, r, db := setupHaEnv(true)
713         expectedKey := "key"
714         expectedResult := []string{"member1", "member2"}
715         r.On("SMembers", expectedKey).Return(redis.NewStringSliceResult(expectedResult, nil))
716         result, err := db.SMembers("key")
717         assert.Equal(t, result, expectedResult)
718         assert.Nil(t, err)
719         r.AssertExpectations(t)
720 }
721
722 func TestSMembersFailure(t *testing.T) {
723         _, r, db := setupHaEnv(true)
724         expectedKey := "key"
725         expectedResult := []string{"member1", "member2"}
726         r.On("SMembers", expectedKey).Return(redis.NewStringSliceResult(expectedResult,
727                 errors.New("Some error")))
728         result, err := db.SMembers("key")
729         assert.Equal(t, result, expectedResult)
730         assert.NotNil(t, err)
731         r.AssertExpectations(t)
732 }
733
734 func TestSIsMemberIsMember(t *testing.T) {
735         _, r, db := setupHaEnv(true)
736         expectedKey := "key"
737         expectedData := "data"
738         r.On("SIsMember", expectedKey, expectedData).Return(redis.NewBoolResult(true, nil))
739         result, err := db.SIsMember("key", "data")
740         assert.True(t, result)
741         assert.Nil(t, err)
742         r.AssertExpectations(t)
743 }
744
745 func TestSIsMemberIsNotMember(t *testing.T) {
746         _, r, db := setupHaEnv(true)
747         expectedKey := "key"
748         expectedData := "data"
749         r.On("SIsMember", expectedKey, expectedData).Return(redis.NewBoolResult(false, nil))
750         result, err := db.SIsMember("key", "data")
751         assert.False(t, result)
752         assert.Nil(t, err)
753         r.AssertExpectations(t)
754 }
755
756 func TestSIsMemberFailure(t *testing.T) {
757         _, r, db := setupHaEnv(true)
758         expectedKey := "key"
759         expectedData := "data"
760         r.On("SIsMember", expectedKey, expectedData).
761                 Return(redis.NewBoolResult(false, errors.New("Some error")))
762         result, err := db.SIsMember("key", "data")
763         assert.False(t, result)
764         assert.NotNil(t, err)
765         r.AssertExpectations(t)
766 }
767
768 func TestSCardSuccessfully(t *testing.T) {
769         _, r, db := setupHaEnv(true)
770         expectedKey := "key"
771         r.On("SCard", expectedKey).Return(redis.NewIntResult(1, nil))
772         result, err := db.SCard("key")
773         assert.Equal(t, int64(1), result)
774         assert.Nil(t, err)
775         r.AssertExpectations(t)
776 }
777
778 func TestSCardFailure(t *testing.T) {
779         _, r, db := setupHaEnv(true)
780         expectedKey := "key"
781         r.On("SCard", expectedKey).Return(redis.NewIntResult(1, errors.New("Some error")))
782         result, err := db.SCard("key")
783         assert.Equal(t, int64(1), result)
784         assert.NotNil(t, err)
785         r.AssertExpectations(t)
786 }
787
788 func TestSubscribeChannelDBSubscribeRXUnsubscribe(t *testing.T) {
789         ps, r, db := setupHaEnv(true)
790         ch := make(chan *redis.Message)
791         msg := redis.Message{
792                 Channel: "{prefix}channel",
793                 Pattern: "pattern",
794                 Payload: "event",
795         }
796         ps.On("Channel").Return(ch)
797         ps.On("Unsubscribe").Return(nil)
798         ps.On("Close").Return(nil)
799         count := 0
800         receivedChannel := ""
801         db.SubscribeChannelDB(func(channel string, payload ...string) {
802                 count++
803                 receivedChannel = channel
804         }, "{prefix}", "---", "{prefix}channel")
805         ch <- &msg
806         db.UnsubscribeChannelDB("{prefix}channel")
807         time.Sleep(1 * time.Second)
808         assert.Equal(t, 1, count)
809         assert.Equal(t, "channel", receivedChannel)
810         r.AssertExpectations(t)
811         ps.AssertExpectations(t)
812 }
813
814 func TestSubscribeChannelDBSubscribeTwoUnsubscribeOne(t *testing.T) {
815         ps, r, db := setupHaEnv(true)
816         ch := make(chan *redis.Message)
817         msg1 := redis.Message{
818                 Channel: "{prefix}channel1",
819                 Pattern: "pattern",
820                 Payload: "event",
821         }
822         msg2 := redis.Message{
823                 Channel: "{prefix}channel2",
824                 Pattern: "pattern",
825                 Payload: "event",
826         }
827         ps.On("Channel").Return(ch)
828         ps.On("Subscribe").Return(nil)
829         ps.On("Unsubscribe").Return(nil)
830         ps.On("Unsubscribe").Return(nil)
831         ps.On("Close").Return(nil)
832         count := 0
833         receivedChannel1 := ""
834         db.SubscribeChannelDB(func(channel string, payload ...string) {
835                 count++
836                 receivedChannel1 = channel
837         }, "{prefix}", "---", "{prefix}channel1")
838         ch <- &msg1
839         receivedChannel2 := ""
840         db.SubscribeChannelDB(func(channel string, payload ...string) {
841                 count++
842                 receivedChannel2 = channel
843         }, "{prefix}", "---", "{prefix}channel2")
844
845         time.Sleep(1 * time.Second)
846         db.UnsubscribeChannelDB("{prefix}channel1")
847         ch <- &msg2
848         db.UnsubscribeChannelDB("{prefix}channel2")
849         time.Sleep(1 * time.Second)
850         assert.Equal(t, 2, count)
851         assert.Equal(t, "channel1", receivedChannel1)
852         assert.Equal(t, "channel2", receivedChannel2)
853         r.AssertExpectations(t)
854         ps.AssertExpectations(t)
855 }
856
857 func TestSubscribeChannelReDBSubscribeAfterUnsubscribe(t *testing.T) {
858         ps, r, db := setupHaEnv(true)
859         ch := make(chan *redis.Message)
860         msg := redis.Message{
861                 Channel: "{prefix}channel",
862                 Pattern: "pattern",
863                 Payload: "event",
864         }
865         ps.On("Channel").Return(ch)
866         ps.On("Unsubscribe").Return(nil)
867         ps.On("Close").Return(nil)
868         count := 0
869         receivedChannel := ""
870
871         db.SubscribeChannelDB(func(channel string, payload ...string) {
872                 count++
873                 receivedChannel = channel
874         }, "{prefix}", "---", "{prefix}channel")
875         ch <- &msg
876         db.UnsubscribeChannelDB("{prefix}channel")
877         time.Sleep(1 * time.Second)
878
879         db.SubscribeChannelDB(func(channel string, payload ...string) {
880                 count++
881                 receivedChannel = channel
882         }, "{prefix}", "---", "{prefix}channel")
883         ch <- &msg
884         db.UnsubscribeChannelDB("{prefix}channel")
885
886         time.Sleep(1 * time.Second)
887         assert.Equal(t, 2, count)
888         assert.Equal(t, "channel", receivedChannel)
889         r.AssertExpectations(t)
890         ps.AssertExpectations(t)
891 }
892
893 func TestPTTLSuccessfully(t *testing.T) {
894         _, r, db := setupHaEnv(true)
895         expectedKey := "key"
896         expectedResult := time.Duration(1)
897         r.On("PTTL", expectedKey).Return(redis.NewDurationResult(expectedResult,
898                 nil))
899         result, err := db.PTTL("key")
900         assert.Equal(t, result, expectedResult)
901         assert.Nil(t, err)
902         r.AssertExpectations(t)
903 }
904
905 func TestPTTLFailure(t *testing.T) {
906         _, r, db := setupHaEnv(true)
907         expectedKey := "key"
908         expectedResult := time.Duration(1)
909         r.On("PTTL", expectedKey).Return(redis.NewDurationResult(expectedResult,
910                 errors.New("Some error")))
911         result, err := db.PTTL("key")
912         assert.Equal(t, result, expectedResult)
913         assert.NotNil(t, err)
914         r.AssertExpectations(t)
915 }
916
917 func TestPExpireIESuccessfully(t *testing.T) {
918         _, r, db := setupHaEnv(true)
919         expectedKey := "key"
920         expectedData := "data"
921         expectedDuration := strconv.FormatInt(int64(10000), 10)
922
923         r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
924                 Return(redis.NewCmdResult(int64(1), nil))
925
926         err := db.PExpireIE("key", "data", 10*time.Second)
927         assert.Nil(t, err)
928         r.AssertExpectations(t)
929 }
930
931 func TestPExpireIEFailure(t *testing.T) {
932         _, r, db := setupHaEnv(true)
933         expectedKey := "key"
934         expectedData := "data"
935         expectedDuration := strconv.FormatInt(int64(10000), 10)
936
937         r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
938                 Return(redis.NewCmdResult(int64(1), errors.New("Some error")))
939
940         err := db.PExpireIE("key", "data", 10*time.Second)
941         assert.NotNil(t, err)
942         r.AssertExpectations(t)
943 }
944
945 func TestPExpireIELockNotHeld(t *testing.T) {
946         _, r, db := setupHaEnv(true)
947         expectedKey := "key"
948         expectedData := "data"
949         expectedDuration := strconv.FormatInt(int64(10000), 10)
950
951         r.On("EvalSha", mock.Anything, []string{expectedKey}, []interface{}{expectedData, expectedDuration}).
952                 Return(redis.NewCmdResult(int64(0), nil))
953
954         err := db.PExpireIE("key", "data", 10*time.Second)
955         assert.NotNil(t, err)
956         r.AssertExpectations(t)
957 }
958
959 func TestClientStandaloneRedisLegacyEnv(t *testing.T) {
960         setupVals := setupEnv(
961                 true,
962                 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6376", "", "", "", "",
963         )
964         assert.Equal(t, 1, len(setupVals.rClient))
965         assert.Equal(t, 1, len(setupVals.db))
966
967         expectedKeysAndValues := []interface{}{"key1", "value1"}
968         setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
969         err := setupVals.db[0].MSet("key1", "value1")
970         assert.Nil(t, err)
971         setupVals.rClient[0].AssertExpectations(t)
972 }
973
974 func TestClientSentinelRedisLegacyEnv(t *testing.T) {
975         setupVals := setupEnv(
976                 true,
977                 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6376", "dbaasmaster", "26376", "", "3",
978         )
979         assert.Equal(t, 1, len(setupVals.rClient))
980         assert.Equal(t, 1, len(setupVals.db))
981
982         expectedKeysAndValues := []interface{}{"key1", "value1"}
983         setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
984         err := setupVals.db[0].MSet("key1", "value1")
985         assert.Nil(t, err)
986         setupVals.rClient[0].AssertExpectations(t)
987 }
988
989 func TestClientTwoStandaloneRedisEnvs(t *testing.T) {
990         setupVals := setupEnv(
991                 true,
992                 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6376", "", "",
993                 "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "",
994         )
995         assert.Equal(t, 2, len(setupVals.rClient))
996         assert.Equal(t, 2, len(setupVals.db))
997
998         expectedKeysAndValues := []interface{}{"key1", "value1"}
999         setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1000         err := setupVals.db[0].MSet("key1", "value1")
1001         assert.Nil(t, err)
1002         setupVals.rClient[0].AssertExpectations(t)
1003
1004         expectedKeysAndValues = []interface{}{"key2", "value2"}
1005         setupVals.rClient[1].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1006         err = setupVals.db[1].MSet("key2", "value2")
1007         assert.Nil(t, err)
1008         setupVals.rClient[0].AssertExpectations(t)
1009         setupVals.rClient[1].AssertExpectations(t)
1010 }
1011
1012 func TestClientTwoSentinelRedisEnvs(t *testing.T) {
1013         setupVals := setupEnv(
1014                 true,
1015                 "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6376", "dbaasmaster", "26376",
1016                 "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3",
1017         )
1018         assert.Equal(t, 2, len(setupVals.rClient))
1019         assert.Equal(t, 2, len(setupVals.db))
1020
1021         expectedKeysAndValues := []interface{}{"key1", "value1"}
1022         setupVals.rClient[0].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1023         err := setupVals.db[0].MSet("key1", "value1")
1024         assert.Nil(t, err)
1025         setupVals.rClient[0].AssertExpectations(t)
1026
1027         expectedKeysAndValues = []interface{}{"key2", "value2"}
1028         setupVals.rClient[1].On("MSet", expectedKeysAndValues).Return(redis.NewStatusResult("OK", nil))
1029         err = setupVals.db[1].MSet("key2", "value2")
1030         assert.Nil(t, err)
1031         setupVals.rClient[0].AssertExpectations(t)
1032         setupVals.rClient[1].AssertExpectations(t)
1033 }
1034
1035 func TestInfoOfMasterRedisWithTwoSlavesSuccessfully(t *testing.T) {
1036         _, r, db := setupHaEnv(true)
1037         redisInfo := "# Replication\r\n" +
1038                 "role:master\r\n" +
1039                 "connected_slaves:2\r\n" +
1040                 "min_slaves_good_slaves:2\r\n" +
1041                 "slave0:ip=1.2.3.4,port=6379,state=online,offset=100200300,lag=0\r\n" +
1042                 "slave1:ip=5.6.7.8,port=6379,state=online,offset=100200300,lag=0\r\n"
1043         expInfo := &sdlgoredis.DbInfo{
1044                 Fields: sdlgoredis.DbInfoFields{
1045                         MasterRole:          true,
1046                         ConnectedReplicaCnt: 2,
1047                 },
1048         }
1049
1050         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1051         info, err := db.Info()
1052         assert.Nil(t, err)
1053         assert.Equal(t, expInfo, info)
1054         r.AssertExpectations(t)
1055 }
1056
1057 func TestInfoOfMasterRedisWithOneSlaveOnlineAndOtherSlaveNotOnlineSuccessfully(t *testing.T) {
1058         _, r, db := setupHaEnv(true)
1059         redisInfo := "# Replication\r\n" +
1060                 "role:master\r\n" +
1061                 "connected_slaves:1\r\n" +
1062                 "min_slaves_good_slaves:2\r\n" +
1063                 "slave0:ip=1.2.3.4,port=6379,state=online,offset=100200300,lag=0\r\n" +
1064                 "slave1:ip=5.6.7.8,port=6379,state=wait_bgsave,offset=100200300,lag=0\r\n"
1065         expInfo := &sdlgoredis.DbInfo{
1066                 Fields: sdlgoredis.DbInfoFields{
1067                         MasterRole:          true,
1068                         ConnectedReplicaCnt: 1,
1069                 },
1070         }
1071
1072         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1073         info, err := db.Info()
1074         assert.Nil(t, err)
1075         assert.Equal(t, expInfo, info)
1076         r.AssertExpectations(t)
1077 }
1078
1079 func TestInfoOfStandaloneMasterRedisSuccessfully(t *testing.T) {
1080         _, r, db := setupHaEnv(true)
1081         redisInfo := "# Replication\r\n" +
1082                 "role:master\r\n" +
1083                 "connected_slaves:0\r\n" +
1084                 "min_slaves_good_slaves:0\r\n"
1085         expInfo := &sdlgoredis.DbInfo{
1086                 Fields: sdlgoredis.DbInfoFields{
1087                         MasterRole:          true,
1088                         ConnectedReplicaCnt: 0,
1089                 },
1090         }
1091
1092         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1093         info, err := db.Info()
1094         assert.Nil(t, err)
1095         assert.Equal(t, expInfo, info)
1096         r.AssertExpectations(t)
1097 }
1098
1099 func TestInfoWithGibberishContentSuccessfully(t *testing.T) {
1100         _, r, db := setupHaEnv(true)
1101         redisInfo := "!#¤%&?+?´-\r\n"
1102         expInfo := &sdlgoredis.DbInfo{}
1103
1104         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1105         info, err := db.Info()
1106         assert.Nil(t, err)
1107         assert.Equal(t, expInfo, info)
1108         r.AssertExpectations(t)
1109 }
1110
1111 func TestInfoWithEmptyContentSuccessfully(t *testing.T) {
1112         _, r, db := setupHaEnv(true)
1113         var redisInfo string
1114         expInfo := &sdlgoredis.DbInfo{
1115                 Fields: sdlgoredis.DbInfoFields{
1116                         MasterRole: false,
1117                 },
1118         }
1119
1120         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1121         info, err := db.Info()
1122         assert.Nil(t, err)
1123         assert.Equal(t, expInfo, info)
1124         r.AssertExpectations(t)
1125 }
1126
1127 func TestStateWithMasterAndTwoSlaveRedisSuccessfully(t *testing.T) {
1128         _, r, s, db := setupHaEnvWithSentinels(true)
1129         redisMasterState := map[string]string{
1130                 "role-reported": "master",
1131         }
1132         redisSlavesState := make([]interface{}, 2)
1133         redisSlavesState[0] = []interface{}{
1134                 "role-reported", "slave",
1135                 "ip", "10.20.30.40",
1136                 "port", "6379",
1137                 "flags", "slave",
1138                 "master-link-status", "up",
1139         }
1140         redisSlavesState[1] = []interface{}{
1141                 "master-link-status", "up",
1142                 "ip", "10.20.30.50",
1143                 "flags", "slave",
1144                 "port", "30000",
1145                 "role-reported", "slave",
1146         }
1147         redisSentinelsState := make([]interface{}, 2)
1148         redisSentinelsState[0] = []interface{}{
1149                 "ip", "10.20.30.40",
1150                 "port", "26379",
1151                 "flags", "sentinel",
1152         }
1153         redisSentinelsState[1] = []interface{}{
1154                 "ip", "10.20.30.50",
1155                 "flags", "sentinel",
1156                 "port", "30001",
1157         }
1158
1159         expState := &sdlgoredis.DbState{
1160                 MasterDbState: sdlgoredis.MasterDbState{
1161                         Fields: sdlgoredis.MasterDbStateFields{
1162                                 Role: "master",
1163                         },
1164                 },
1165                 ReplicasDbState: &sdlgoredis.ReplicasDbState{
1166                         States: []*sdlgoredis.ReplicaDbState{
1167                                 &sdlgoredis.ReplicaDbState{
1168                                         Fields: sdlgoredis.ReplicaDbStateFields{
1169                                                 Role:             "slave",
1170                                                 Ip:               "10.20.30.40",
1171                                                 Port:             "6379",
1172                                                 MasterLinkStatus: "up",
1173                                                 Flags:            "slave",
1174                                         },
1175                                 },
1176                                 &sdlgoredis.ReplicaDbState{
1177                                         Fields: sdlgoredis.ReplicaDbStateFields{
1178                                                 Role:             "slave",
1179                                                 Ip:               "10.20.30.50",
1180                                                 Port:             "30000",
1181                                                 MasterLinkStatus: "up",
1182                                                 Flags:            "slave",
1183                                         },
1184                                 },
1185                         },
1186                 },
1187                 SentinelsDbState: &sdlgoredis.SentinelsDbState{
1188                         States: []*sdlgoredis.SentinelDbState{
1189                                 &sdlgoredis.SentinelDbState{
1190                                         Fields: sdlgoredis.SentinelDbStateFields{
1191                                                 Ip:    "10.20.30.40",
1192                                                 Port:  "26379",
1193                                                 Flags: "sentinel",
1194                                         },
1195                                 },
1196                                 &sdlgoredis.SentinelDbState{
1197                                         Fields: sdlgoredis.SentinelDbStateFields{
1198                                                 Ip:    "10.20.30.50",
1199                                                 Port:  "30001",
1200                                                 Flags: "sentinel",
1201                                         },
1202                                 },
1203                         },
1204                 },
1205         }
1206
1207         s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisMasterState, nil))
1208         s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisSlavesState, nil))
1209         s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState, nil))
1210         ret, err := db.State()
1211         assert.Nil(t, err)
1212         assert.Equal(t, expState, ret)
1213         r.AssertExpectations(t)
1214 }
1215
1216 func TestStateWithMasterAndOneSlaveRedisFailureInMasterRedisCall(t *testing.T) {
1217         _, r, s, db := setupHaEnvWithSentinels(true)
1218         redisMasterState := map[string]string{}
1219         redisSlavesState := make([]interface{}, 1)
1220         redisSlavesState[0] = []interface{}{
1221                 "role-reported", "slave",
1222                 "ip", "10.20.30.40",
1223                 "port", "6379",
1224                 "flags", "slave",
1225                 "master-link-status", "up",
1226         }
1227         redisSentinelsState := make([]interface{}, 1)
1228         redisSentinelsState[0] = []interface{}{
1229                 "ip", "10.20.30.40",
1230                 "port", "26379",
1231                 "flags", "sentinel",
1232         }
1233
1234         expState := &sdlgoredis.DbState{
1235                 MasterDbState: sdlgoredis.MasterDbState{
1236                         Err: errors.New("Some error"),
1237                 },
1238                 ReplicasDbState: &sdlgoredis.ReplicasDbState{
1239                         States: []*sdlgoredis.ReplicaDbState{
1240                                 &sdlgoredis.ReplicaDbState{
1241                                         Fields: sdlgoredis.ReplicaDbStateFields{
1242                                                 Role:             "slave",
1243                                                 Ip:               "10.20.30.40",
1244                                                 Port:             "6379",
1245                                                 MasterLinkStatus: "up",
1246                                                 Flags:            "slave",
1247                                         },
1248                                 },
1249                         },
1250                 },
1251                 SentinelsDbState: &sdlgoredis.SentinelsDbState{
1252                         States: []*sdlgoredis.SentinelDbState{
1253                                 &sdlgoredis.SentinelDbState{
1254                                         Fields: sdlgoredis.SentinelDbStateFields{
1255                                                 Ip:    "10.20.30.40",
1256                                                 Port:  "26379",
1257                                                 Flags: "sentinel",
1258                                         },
1259                                 },
1260                         },
1261                 },
1262         }
1263
1264         s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisMasterState, errors.New("Some error")))
1265         s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisSlavesState, nil))
1266         s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState, nil))
1267         ret, err := db.State()
1268         assert.NotNil(t, err)
1269         assert.Equal(t, expState, ret)
1270         r.AssertExpectations(t)
1271 }
1272
1273 func TestStateWithMasterAndOneSlaveRedisFailureInSlavesRedisCall(t *testing.T) {
1274         _, r, s, db := setupHaEnvWithSentinels(true)
1275         redisMasterState := map[string]string{
1276                 "role-reported": "master",
1277         }
1278         redisSlavesState := make([]interface{}, 1)
1279         redisSlavesState[0] = []interface{}{}
1280         redisSentinelsState := make([]interface{}, 1)
1281         redisSentinelsState[0] = []interface{}{
1282                 "ip", "10.20.30.40",
1283                 "port", "26379",
1284                 "flags", "sentinel",
1285         }
1286
1287         expState := &sdlgoredis.DbState{
1288                 MasterDbState: sdlgoredis.MasterDbState{
1289                         Fields: sdlgoredis.MasterDbStateFields{
1290                                 Role: "master",
1291                         },
1292                 },
1293                 ReplicasDbState: &sdlgoredis.ReplicasDbState{
1294                         Err:    errors.New("Some error"),
1295                         States: []*sdlgoredis.ReplicaDbState{},
1296                 },
1297                 SentinelsDbState: &sdlgoredis.SentinelsDbState{
1298                         States: []*sdlgoredis.SentinelDbState{
1299                                 &sdlgoredis.SentinelDbState{
1300                                         Fields: sdlgoredis.SentinelDbStateFields{
1301                                                 Ip:    "10.20.30.40",
1302                                                 Port:  "26379",
1303                                                 Flags: "sentinel",
1304                                         },
1305                                 },
1306                         },
1307                 },
1308         }
1309
1310         s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisMasterState, nil))
1311         s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisSlavesState, errors.New("Some error")))
1312         s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState, nil))
1313         ret, err := db.State()
1314         assert.NotNil(t, err)
1315         assert.Equal(t, expState, ret)
1316         r.AssertExpectations(t)
1317 }
1318
1319 func TestStateWithMasterAndOneSlaveRedisFailureInSentinelsRedisCall(t *testing.T) {
1320         _, r, s, db := setupHaEnvWithSentinels(true)
1321         redisMasterState := map[string]string{
1322                 "role-reported": "master",
1323         }
1324         redisSlavesState := make([]interface{}, 1)
1325         redisSlavesState[0] = []interface{}{
1326                 "role-reported", "slave",
1327                 "ip", "10.20.30.40",
1328                 "port", "6379",
1329                 "flags", "slave",
1330                 "master-link-status", "up",
1331         }
1332         redisSentinelsState := make([]interface{}, 1)
1333         redisSentinelsState[0] = []interface{}{
1334                 "ip", "10.20.30.40",
1335                 "port", "26379",
1336                 "flags", "sentinel",
1337         }
1338
1339         expState := &sdlgoredis.DbState{
1340                 MasterDbState: sdlgoredis.MasterDbState{
1341                         Fields: sdlgoredis.MasterDbStateFields{
1342                                 Role: "master",
1343                         },
1344                 },
1345                 ReplicasDbState: &sdlgoredis.ReplicasDbState{
1346                         States: []*sdlgoredis.ReplicaDbState{
1347                                 &sdlgoredis.ReplicaDbState{
1348                                         Fields: sdlgoredis.ReplicaDbStateFields{
1349                                                 Role:             "slave",
1350                                                 Ip:               "10.20.30.40",
1351                                                 Port:             "6379",
1352                                                 MasterLinkStatus: "up",
1353                                                 Flags:            "slave",
1354                                         },
1355                                 },
1356                         },
1357                 },
1358                 SentinelsDbState: &sdlgoredis.SentinelsDbState{
1359                         Err:    errors.New("Some error"),
1360                         States: []*sdlgoredis.SentinelDbState{},
1361                 },
1362         }
1363
1364         s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisMasterState, nil))
1365         s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisSlavesState, nil))
1366         s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState, errors.New("Some error")))
1367         ret, err := db.State()
1368         assert.NotNil(t, err)
1369         assert.Equal(t, expState, ret)
1370         r.AssertExpectations(t)
1371 }
1372
1373 func TestStateWithSingleMasterRedisSuccessfully(t *testing.T) {
1374         _, r, db := setupSingleEnv(true)
1375         redisInfo := "# Replication\r\n" +
1376                 "role:master\r\n" +
1377                 "connected_slaves:0\r\n" +
1378                 "min_slaves_good_slaves:0\r\n"
1379
1380         expState := &sdlgoredis.DbState{
1381                 MasterDbState: sdlgoredis.MasterDbState{
1382                         Fields: sdlgoredis.MasterDbStateFields{
1383                                 Role:  "master",
1384                                 Flags: "master",
1385                         },
1386                 },
1387         }
1388
1389         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, nil))
1390         ret, err := db.State()
1391         assert.Nil(t, err)
1392         assert.Equal(t, expState, ret)
1393         r.AssertExpectations(t)
1394 }
1395
1396 func TestStateWithSingleMasterRedisFailureInInfoCall(t *testing.T) {
1397         _, r, db := setupSingleEnv(true)
1398         redisInfo := ""
1399         expState := &sdlgoredis.DbState{}
1400
1401         r.On("Info", []string{"all"}).Return(redis.NewStringResult(redisInfo, errors.New("Some error")))
1402         ret, err := db.State()
1403         assert.NotNil(t, err)
1404         assert.Equal(t, expState, ret)
1405         r.AssertExpectations(t)
1406 }