github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/lorry/engines/redis/manager_test.go (about)

     1  /*
     2  Copyright (C) 2022-2023 ApeCloud Co., Ltd
     3  
     4  This file is part of KubeBlocks project
     5  
     6  This program is free software: you can redistribute it and/or modify
     7  it under the terms of the GNU Affero General Public License as published by
     8  the Free Software Foundation, either version 3 of the License, or
     9  (at your option) any later version.
    10  
    11  This program is distributed in the hope that it will be useful
    12  but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  GNU Affero General Public License for more details.
    15  
    16  You should have received a copy of the GNU Affero General Public License
    17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18  */
    19  
    20  package redis
    21  
    22  import (
    23  	. "github.com/onsi/ginkgo/v2"
    24  	. "github.com/onsi/gomega"
    25  	"github.com/spf13/viper"
    26  
    27  	"github.com/1aal/kubeblocks/pkg/lorry/engines"
    28  )
    29  
    30  const (
    31  // testData  = `{"data":"data"}`
    32  // testKey   = "test"
    33  // redisHost = "127.0.0.1:6379"
    34  
    35  // userName = "kiminonawa"
    36  // password = "moss"
    37  // roleName = util.ReadWriteRole
    38  )
    39  
    40  var _ = Describe("Redis DBManager", func() {
    41  	// Set up relevant viper config variables
    42  	viper.Set("KB_SERVICE_USER", "testuser")
    43  	viper.Set("KB_SERVICE_PASSWORD", "testpassword")
    44  	Context("new db manager", func() {
    45  		It("with rigth configurations", func() {
    46  			properties := engines.Properties{
    47  				"url": "127.0.0.1",
    48  			}
    49  			dbManger, err := NewManager(properties)
    50  			Expect(err).Should(Succeed())
    51  			Expect(dbManger).ShouldNot(BeNil())
    52  		})
    53  
    54  		It("with wrong configurations", func() {
    55  			properties := engines.Properties{
    56  				"poolSize": "wrong-number",
    57  			}
    58  			dbManger, err := NewManager(properties)
    59  			Expect(err).Should(HaveOccurred())
    60  			Expect(dbManger).Should(BeNil())
    61  		})
    62  	})
    63  })
    64  
    65  // func TestRedisInit(t *testing.T) {
    66  // 	r, _ := mockRedisOps(t)
    67  // 	defer r.Close()
    68  // 	// make sure operations are inited
    69  // 	assert.NotNil(t, r.client)
    70  // 	assert.NotNil(t, r.OperationsMap[util.ListUsersOp])
    71  // 	assert.NotNil(t, r.OperationsMap[util.CreateUserOp])
    72  // 	assert.NotNil(t, r.OperationsMap[util.DeleteUserOp])
    73  // 	assert.NotNil(t, r.OperationsMap[util.DescribeUserOp])
    74  // 	assert.NotNil(t, r.OperationsMap[util.GrantUserRoleOp])
    75  // 	assert.NotNil(t, r.OperationsMap[util.RevokeUserRoleOp])
    76  // }
    77  // func TestRedisInvokeCreate(t *testing.T) {
    78  // 	r, mock := mockRedisOps(t)
    79  // 	defer r.Close()
    80  //
    81  // 	result := OpsResult{}
    82  // 	request := &ProbeRequest{
    83  // 		Data:      []byte(testData),
    84  // 		Metadata:  map[string]string{"key": testKey},
    85  // 		Operation: util.CreateOperation,
    86  // 	}
    87  // 	// mock expectation
    88  // 	mock.ExpectDo("SET", testKey, testData).SetVal("ok")
    89  //
    90  // 	// invoke
    91  // 	bindingRes, err := r.Invoke(context.TODO(), request)
    92  // 	assert.Equal(t, nil, err)
    93  // 	assert.NotNil(t, bindingRes)
    94  // 	assert.NotNil(t, bindingRes.Data)
    95  //
    96  // 	err = json.Unmarshal(bindingRes.Data, &result)
    97  // 	assert.Nil(t, err)
    98  // 	assert.Equal(t, util.RespEveSucc, result[util.RespFieldEvent], result[util.RespFieldMessage])
    99  // }
   100  //
   101  // func TestRedisInvokeGet(t *testing.T) {
   102  // 	r, mock := mockRedisOps(t)
   103  // 	defer r.Close()
   104  //
   105  // 	opsResult := OpsResult{}
   106  // 	request := &ProbeRequest{
   107  // 		Metadata:  map[string]string{"key": testKey},
   108  // 		Operation: util.GetOperation,
   109  // 	}
   110  // 	// mock expectation, set to nil
   111  // 	mock.ExpectDo("GET", testKey).RedisNil()
   112  // 	mock.ExpectDo("GET", testKey).SetVal(testData)
   113  //
   114  // 	// invoke create
   115  // 	bindingRes, err := r.Invoke(context.TODO(), request)
   116  // 	assert.Nil(t, err)
   117  // 	assert.NotNil(t, bindingRes)
   118  // 	assert.NotNil(t, bindingRes.Data)
   119  // 	err = json.Unmarshal(bindingRes.Data, &opsResult)
   120  // 	assert.Nil(t, err)
   121  // 	assert.Equal(t, util.RespEveFail, opsResult[util.RespFieldEvent])
   122  //
   123  // 	// invoke one more time
   124  // 	bindingRes, err = r.Invoke(context.TODO(), request)
   125  // 	assert.Nil(t, err)
   126  // 	assert.NotNil(t, bindingRes.Data)
   127  // 	err = json.Unmarshal(bindingRes.Data, &opsResult)
   128  // 	assert.Nil(t, err)
   129  // 	assert.Equal(t, util.RespEveSucc, opsResult[util.RespFieldEvent])
   130  // 	var o1 interface{}
   131  // 	_ = json.Unmarshal([]byte(opsResult[util.RespFieldMessage].(string)), &o1)
   132  // 	assert.Equal(t, testData, o1)
   133  // }
   134  //
   135  // func TestRedisInvokeDelete(t *testing.T) {
   136  // 	r, mock := mockRedisOps(t)
   137  // 	defer r.Close()
   138  //
   139  // 	opsResult := OpsResult{}
   140  // 	request := &ProbeRequest{
   141  // 		Metadata:  map[string]string{"key": testKey},
   142  // 		Operation: util.DeleteOperation,
   143  // 	}
   144  // 	// mock expectation, set to err
   145  // 	mock.ExpectDo("DEL", testKey).SetVal("ok")
   146  //
   147  // 	// invoke delete
   148  // 	bindingRes, err := r.Invoke(context.TODO(), request)
   149  // 	assert.Nil(t, err)
   150  // 	assert.NotNil(t, bindingRes)
   151  // 	assert.NotNil(t, bindingRes.Data)
   152  // 	err = json.Unmarshal(bindingRes.Data, &opsResult)
   153  // 	assert.Nil(t, err)
   154  // 	assert.Equal(t, util.RespEveSucc, opsResult[util.RespFieldEvent])
   155  // }
   156  //
   157  // func TestRedisGetRoles(t *testing.T) {
   158  // 	r, mock := mockRedisOps(t)
   159  // 	defer r.Close()
   160  //
   161  // 	opsResult := OpsResult{}
   162  // 	request := &ProbeRequest{
   163  // 		Operation: util.GetRoleOperation,
   164  // 	}
   165  //
   166  // 	// mock expectation, set to err
   167  // 	mock.ExpectInfo("Replication").SetVal("role:master\r\nconnected_slaves:1")
   168  // 	mock.ExpectInfo("Replication").SetVal("role:slave\r\nmaster_port:6379")
   169  // 	// invoke request
   170  // 	bindingRes, err := r.Invoke(context.TODO(), request)
   171  // 	assert.Nil(t, err)
   172  // 	assert.NotNil(t, bindingRes)
   173  // 	assert.NotNil(t, bindingRes.Data)
   174  // 	err = json.Unmarshal(bindingRes.Data, &opsResult)
   175  // 	assert.Nil(t, err)
   176  // 	assert.Equal(t, util.RespEveSucc, opsResult[util.RespFieldEvent])
   177  // 	assert.Equal(t, PRIMARY, opsResult["role"])
   178  //
   179  // 	// invoke one more time
   180  // 	bindingRes, err = r.Invoke(context.TODO(), request)
   181  // 	assert.Nil(t, err)
   182  // 	err = json.Unmarshal(bindingRes.Data, &opsResult)
   183  // 	assert.Nil(t, err)
   184  // 	assert.Equal(t, util.RespEveSucc, opsResult[util.RespFieldEvent])
   185  // 	assert.Equal(t, SECONDARY, opsResult["role"])
   186  // }
   187  //
   188  // func TestRedisAccounts(t *testing.T) {
   189  // 	// prepare
   190  // 	r, mock := mockRedisOps(t)
   191  // 	defer r.Close()
   192  //
   193  // 	ctx := context.TODO()
   194  // 	// list accounts
   195  // 	t.Run("List Accounts", func(t *testing.T) {
   196  // 		mock.ExpectDo("ACL", "USERS").SetVal([]string{"ape", "default", "kbadmin"})
   197  //
   198  // 		response, err := r.Invoke(ctx, &ProbeRequest{
   199  // 			Operation: util.ListUsersOp,
   200  // 		})
   201  //
   202  // 		assert.Nil(t, err)
   203  // 		assert.NotNil(t, response)
   204  // 		assert.NotNil(t, response.Data)
   205  // 		// parse result
   206  // 		opsResult := OpsResult{}
   207  // 		_ = json.Unmarshal(response.Data, &opsResult)
   208  // 		assert.Equal(t, util.RespEveSucc, opsResult[util.RespFieldEvent], opsResult[util.RespFieldMessage])
   209  //
   210  // 		users := make([]util.UserInfo, 0)
   211  // 		err = json.Unmarshal([]byte(opsResult[util.RespFieldMessage].(string)), &users)
   212  // 		assert.Nil(t, err)
   213  // 		assert.NotEmpty(t, users)
   214  // 		user := users[0]
   215  // 		assert.Equal(t, "ape", user.UserName)
   216  // 		mock.ClearExpect()
   217  // 	})
   218  //
   219  // 	// create accounts
   220  // 	t.Run("Create Accounts", func(t *testing.T) {
   221  //
   222  // 		var (
   223  // 			err       error
   224  // 			opsResult = OpsResult{}
   225  // 			response  *ProbeResponse
   226  // 			request   = &ProbeRequest{
   227  // 				Operation: util.CreateUserOp,
   228  // 			}
   229  // 		)
   230  //
   231  // 		testCases := []redisTestCase{
   232  // 			{
   233  // 				testName:      "emptymeta",
   234  // 				testMetaData:  map[string]string{},
   235  // 				expectEveType: util.RespEveFail,
   236  // 				expectEveMsg:  ErrNoUserName.Error(),
   237  // 			},
   238  // 			{
   239  // 				testName:      "nousername",
   240  // 				testMetaData:  map[string]string{"password": "moli"},
   241  // 				expectEveType: util.RespEveFail,
   242  // 				expectEveMsg:  ErrNoUserName.Error(),
   243  // 			},
   244  // 			{
   245  // 				testName:      "nopasswd",
   246  // 				testMetaData:  map[string]string{"userName": "namae"},
   247  // 				expectEveType: util.RespEveFail,
   248  // 				expectEveMsg:  ErrNoPassword.Error(),
   249  // 			},
   250  // 			{
   251  // 				testName: "validInput",
   252  // 				testMetaData: map[string]string{
   253  // 					"userName": userName,
   254  // 					"password": password,
   255  // 				},
   256  // 				expectEveType: util.RespEveSucc,
   257  // 				expectEveMsg:  fmt.Sprintf("created user: %s", userName),
   258  // 			},
   259  // 		}
   260  // 		// mock a user
   261  // 		mock.ExpectDo("ACL", "SETUSER", userName, ">"+password).SetVal("ok")
   262  //
   263  // 		for _, accTest := range testCases {
   264  // 			request.Metadata = accTest.testMetaData
   265  // 			response, err = r.Invoke(ctx, request)
   266  // 			assert.Nil(t, err)
   267  // 			assert.NotNil(t, response.Data)
   268  // 			err = json.Unmarshal(response.Data, &opsResult)
   269  // 			assert.Nil(t, err)
   270  // 			assert.Equal(t, accTest.expectEveType, opsResult[util.RespFieldEvent], opsResult[util.RespFieldMessage])
   271  // 			assert.Contains(t, opsResult[util.RespFieldMessage], accTest.expectEveMsg)
   272  // 		}
   273  // 		mock.ClearExpect()
   274  // 	})
   275  // 	// grant and revoke role
   276  // 	t.Run("Grant Accounts", func(t *testing.T) {
   277  //
   278  // 		var (
   279  // 			err       error
   280  // 			opsResult = OpsResult{}
   281  // 			response  *ProbeResponse
   282  // 		)
   283  //
   284  // 		testCases := []redisTestCase{
   285  // 			{
   286  // 				testName:      "emptymeta",
   287  // 				testMetaData:  map[string]string{},
   288  // 				expectEveType: util.RespEveFail,
   289  // 				expectEveMsg:  ErrNoUserName.Error(),
   290  // 			},
   291  // 			{
   292  // 				testName:      "nousername",
   293  // 				testMetaData:  map[string]string{"password": "moli"},
   294  // 				expectEveType: util.RespEveFail,
   295  // 				expectEveMsg:  ErrNoUserName.Error(),
   296  // 			},
   297  // 			{
   298  // 				testName:      "norolename",
   299  // 				testMetaData:  map[string]string{"userName": "namae"},
   300  // 				expectEveType: util.RespEveFail,
   301  // 				expectEveMsg:  ErrNoRoleName.Error(),
   302  // 			},
   303  // 			{
   304  // 				testName:      "invalidRoleName",
   305  // 				testMetaData:  map[string]string{"userName": "namae", "roleName": "superman"},
   306  // 				expectEveType: util.RespEveFail,
   307  // 				expectEveMsg:  ErrInvalidRoleName.Error(),
   308  // 			},
   309  // 			{
   310  // 				testName: "validInput",
   311  // 				testMetaData: map[string]string{
   312  // 					"userName": userName,
   313  // 					"roleName": (string)(roleName),
   314  // 				},
   315  // 				expectEveType: util.RespEveSucc,
   316  // 			},
   317  // 		}
   318  //
   319  // 		for _, ops := range []util.OperationKind{util.GrantUserRoleOp, util.RevokeUserRoleOp} {
   320  // 			// mock exepctation
   321  // 			args := tokenizeCmd2Args(fmt.Sprintf("ACL SETUSER %s %s", userName, r.role2Priv(ops, (string)(roleName))))
   322  // 			mock.ExpectDo(args...).SetVal("ok")
   323  //
   324  // 			request := &ProbeRequest{
   325  // 				Operation: ops,
   326  // 			}
   327  // 			for _, accTest := range testCases {
   328  // 				request.Metadata = accTest.testMetaData
   329  // 				response, err = r.Invoke(ctx, request)
   330  // 				assert.Nil(t, err)
   331  // 				assert.NotNil(t, response.Data)
   332  // 				err = json.Unmarshal(response.Data, &opsResult)
   333  // 				assert.Nil(t, err)
   334  // 				assert.Equal(t, accTest.expectEveType, opsResult[util.RespFieldEvent], opsResult[util.RespFieldMessage])
   335  // 				if len(accTest.expectEveMsg) > 0 {
   336  // 					assert.Contains(t, accTest.expectEveMsg, opsResult[util.RespFieldMessage])
   337  // 				}
   338  // 			}
   339  // 		}
   340  // 		mock.ClearExpect()
   341  // 	})
   342  //
   343  // 	// desc accounts
   344  // 	t.Run("Desc Accounts", func(t *testing.T) {
   345  // 		var (
   346  // 			err       error
   347  // 			opsResult = OpsResult{}
   348  // 			response  *ProbeResponse
   349  // 			request   = &ProbeRequest{
   350  // 				Operation: util.DescribeUserOp,
   351  // 			}
   352  // 			// mock a user, describing it as an array of interface{}
   353  // 			userInfo = []interface{}{
   354  // 				"flags",
   355  // 				[]interface{}{"on"},
   356  // 				"passwords",
   357  // 				[]interface{}{"mock-password"},
   358  // 				"commands",
   359  // 				"+@all",
   360  // 				"keys",
   361  // 				"~*",
   362  // 				"channels",
   363  // 				"",
   364  // 				"selectors",
   365  // 				[]interface{}{},
   366  // 			}
   367  //
   368  // 			userInfoMap = map[string]interface{}{
   369  // 				"flags":     []interface{}{"on"},
   370  // 				"passwords": []interface{}{"mock-password"},
   371  // 				"commands":  "+@all",
   372  // 				"keys":      "~*",
   373  // 				"channels":  "",
   374  // 				"selectors": []interface{}{},
   375  // 			}
   376  // 		)
   377  //
   378  // 		testCases := []redisTestCase{
   379  // 			{
   380  // 				testName:      "emptymeta",
   381  // 				testMetaData:  map[string]string{},
   382  // 				expectEveType: util.RespEveFail,
   383  // 				expectEveMsg:  ErrNoUserName.Error(),
   384  // 			},
   385  // 			{
   386  // 				testName:      "nousername",
   387  // 				testMetaData:  map[string]string{"password": "moli"},
   388  // 				expectEveType: util.RespEveFail,
   389  // 				expectEveMsg:  ErrNoUserName.Error(),
   390  // 			},
   391  // 			{
   392  // 				testName: "validInputButNil",
   393  // 				testMetaData: map[string]string{
   394  // 					"userName": userName,
   395  // 				},
   396  // 				expectEveType: util.RespEveFail,
   397  // 				expectEveMsg:  "redis: nil",
   398  // 			},
   399  // 			{
   400  // 				testName: "validInput",
   401  // 				testMetaData: map[string]string{
   402  // 					"userName": userName,
   403  // 				},
   404  // 				expectEveType: util.RespEveSucc,
   405  // 			},
   406  // 			{
   407  // 				testName: "validInputAsMap",
   408  // 				testMetaData: map[string]string{
   409  // 					"userName": userName,
   410  // 				},
   411  // 				expectEveType: util.RespEveSucc,
   412  // 			},
   413  // 		}
   414  //
   415  // 		mock.ExpectDo("ACL", "GETUSER", userName).RedisNil()
   416  // 		mock.ExpectDo("ACL", "GETUSER", userName).SetVal(userInfo)
   417  // 		mock.ExpectDo("ACL", "GETUSER", userName).SetVal(userInfoMap)
   418  //
   419  // 		for _, accTest := range testCases {
   420  // 			request.Metadata = accTest.testMetaData
   421  // 			response, err = r.Invoke(ctx, request)
   422  // 			assert.Nil(t, err)
   423  // 			assert.NotNil(t, response.Data)
   424  // 			err = json.Unmarshal(response.Data, &opsResult)
   425  // 			assert.Nil(t, err)
   426  // 			assert.Equal(t, accTest.expectEveType, opsResult[util.RespFieldEvent], opsResult[util.RespFieldMessage])
   427  // 			if len(accTest.expectEveMsg) > 0 {
   428  // 				assert.Contains(t, opsResult[util.RespFieldMessage], accTest.expectEveMsg)
   429  // 			}
   430  // 			if util.RespEveSucc == opsResult[util.RespFieldEvent] {
   431  // 				// parse user info
   432  // 				users := make([]util.UserInfo, 0)
   433  // 				err = json.Unmarshal([]byte(opsResult[util.RespFieldMessage].(string)), &users)
   434  // 				assert.Nil(t, err)
   435  // 				assert.Len(t, users, 1)
   436  // 				user := users[0]
   437  // 				assert.Equal(t, userName, user.UserName)
   438  // 				assert.True(t, util.SuperUserRole.EqualTo(user.RoleName))
   439  // 			}
   440  // 		}
   441  // 		mock.ClearExpect()
   442  // 	})
   443  // 	// delete accounts
   444  // 	t.Run("Delete Accounts", func(t *testing.T) {
   445  //
   446  // 		var (
   447  // 			err       error
   448  // 			opsResult = OpsResult{}
   449  // 			response  *ProbeResponse
   450  // 			request   = &ProbeRequest{
   451  // 				Operation: util.DeleteUserOp,
   452  // 			}
   453  // 		)
   454  //
   455  // 		testCases := []redisTestCase{
   456  // 			{
   457  // 				testName:      "emptymeta",
   458  // 				testMetaData:  map[string]string{},
   459  // 				expectEveType: util.RespEveFail,
   460  // 				expectEveMsg:  ErrNoUserName.Error(),
   461  // 			},
   462  // 			{
   463  // 				testName:      "nousername",
   464  // 				testMetaData:  map[string]string{"password": "moli"},
   465  // 				expectEveType: util.RespEveFail,
   466  // 				expectEveMsg:  ErrNoUserName.Error(),
   467  // 			},
   468  // 			{
   469  // 				testName: "validInput",
   470  // 				testMetaData: map[string]string{
   471  // 					"userName": userName,
   472  // 				},
   473  // 				expectEveType: util.RespEveSucc,
   474  // 				expectEveMsg:  fmt.Sprintf("deleted user: %s", userName),
   475  // 			},
   476  // 		}
   477  // 		// mock a user
   478  // 		mock.ExpectDo("ACL", "DELUSER", userName).SetVal("ok")
   479  //
   480  // 		for _, accTest := range testCases {
   481  // 			request.Metadata = accTest.testMetaData
   482  // 			response, err = r.Invoke(ctx, request)
   483  // 			assert.Nil(t, err)
   484  // 			assert.NotNil(t, response.Data)
   485  // 			err = json.Unmarshal(response.Data, &opsResult)
   486  // 			assert.Nil(t, err)
   487  // 			assert.Equal(t, accTest.expectEveType, opsResult[util.RespFieldEvent], opsResult[util.RespFieldMessage])
   488  // 			assert.Contains(t, opsResult[util.RespFieldMessage], accTest.expectEveMsg)
   489  // 		}
   490  // 		mock.ClearExpect()
   491  // 	})
   492  //
   493  // 	t.Run("RoleName Conversion", func(t *testing.T) {
   494  // 		type roleTestCase struct {
   495  // 			roleName   util.RoleType
   496  // 			redisPrivs string
   497  // 		}
   498  // 		grantTestCases := []roleTestCase{
   499  // 			{
   500  // 				util.SuperUserRole,
   501  // 				"+@all allkeys",
   502  // 			},
   503  // 			{
   504  // 				util.ReadWriteRole,
   505  // 				"-@all +@write +@read allkeys",
   506  // 			},
   507  // 			{
   508  // 				util.ReadOnlyRole,
   509  // 				"-@all +@read allkeys",
   510  // 			},
   511  // 		}
   512  // 		for _, test := range grantTestCases {
   513  // 			cmd := r.role2Priv(util.GrantUserRoleOp, (string)(test.roleName))
   514  // 			assert.Equal(t, test.redisPrivs, cmd)
   515  //
   516  // 			// allkeys -> ~*
   517  // 			cmd = strings.Replace(cmd, "allkeys", "~*", 1)
   518  // 			inferredRole := r.priv2Role(cmd)
   519  // 			assert.Equal(t, test.roleName, inferredRole)
   520  // 		}
   521  //
   522  // 		revokeTestCases := []roleTestCase{
   523  // 			{
   524  // 				util.SuperUserRole,
   525  // 				"-@all allkeys",
   526  // 			},
   527  // 			{
   528  // 				util.ReadWriteRole,
   529  // 				"-@all -@write -@read allkeys",
   530  // 			},
   531  // 			{
   532  // 				util.ReadOnlyRole,
   533  // 				"-@all -@read allkeys",
   534  // 			},
   535  // 		}
   536  // 		for _, test := range revokeTestCases {
   537  // 			cmd := r.role2Priv(util.RevokeUserRoleOp, (string)(test.roleName))
   538  // 			assert.Equal(t, test.redisPrivs, cmd)
   539  // 		}
   540  // 	})
   541  // 	// list accounts
   542  // 	t.Run("List System Accounts", func(t *testing.T) {
   543  // 		mock.ExpectDo("ACL", "USERS").SetVal([]string{"ape", "default", "kbadmin"})
   544  //
   545  // 		response, err := r.Invoke(ctx, &ProbeRequest{
   546  // 			Operation: util.ListSystemAccountsOp,
   547  // 		})
   548  //
   549  // 		assert.Nil(t, err)
   550  // 		assert.NotNil(t, response)
   551  // 		assert.NotNil(t, response.Data)
   552  // 		// parse result
   553  // 		opsResult := OpsResult{}
   554  // 		_ = json.Unmarshal(response.Data, &opsResult)
   555  // 		assert.Equal(t, util.RespEveSucc, opsResult[util.RespFieldEvent], opsResult[util.RespFieldMessage])
   556  //
   557  // 		users := []string{}
   558  // 		err = json.Unmarshal([]byte(opsResult[util.RespFieldMessage].(string)), &users)
   559  // 		assert.Nil(t, err)
   560  // 		assert.NotEmpty(t, users)
   561  // 		assert.Len(t, users, 2)
   562  // 		assert.Contains(t, users, "kbadmin")
   563  // 		assert.Contains(t, users, "default")
   564  // 		mock.ClearExpect()
   565  // 	})
   566  // }
   567  //
   568  // func mockRedisOps(t *testing.T) (*Redis, redismock.ClientMock) {
   569  // 	client, mock := redismock.NewClientMock()
   570  // 	viper.SetDefault("KB_ROLECHECK_DELAY", "0")
   571  //
   572  // 	if client == nil || mock == nil {
   573  // 		t.Fatalf("failed to mock a redis client")
   574  // 		return nil, nil
   575  // 	}
   576  // 	r := &Redis{}
   577  // 	development, _ := zap.NewDevelopment()
   578  // 	r.Logger = zapr.NewLogger(development)
   579  // 	r.client = client
   580  // 	r.ctx, r.cancel = context.WithCancel(context.Background())
   581  // 	_ = r.Init(nil)
   582  // 	r.DBPort = 6379
   583  // 	return r, mock
   584  // }
   585  //