github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/modules/access_key/zz_access_key_test.go (about)

     1  package access_key_test
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"encoding/base64"
     7  	"runtime"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/agiledragon/gomonkey/v2"
    13  	"github.com/golang/mock/gomock"
    14  	. "github.com/onsi/gomega"
    15  	"github.com/pkg/errors"
    16  
    17  	base "github.com/machinefi/w3bstream/pkg/depends/base/types"
    18  	confid "github.com/machinefi/w3bstream/pkg/depends/conf/id"
    19  	"github.com/machinefi/w3bstream/pkg/depends/kit/httptransport"
    20  	"github.com/machinefi/w3bstream/pkg/depends/kit/httptransport/httpx"
    21  	"github.com/machinefi/w3bstream/pkg/depends/kit/kit"
    22  	"github.com/machinefi/w3bstream/pkg/depends/kit/sqlx/builder"
    23  	"github.com/machinefi/w3bstream/pkg/depends/kit/sqlx/datatypes"
    24  	"github.com/machinefi/w3bstream/pkg/depends/x/contextx"
    25  	"github.com/machinefi/w3bstream/pkg/enums"
    26  	"github.com/machinefi/w3bstream/pkg/errors/status"
    27  	"github.com/machinefi/w3bstream/pkg/models"
    28  	"github.com/machinefi/w3bstream/pkg/modules/access_key"
    29  	mock_sqlx "github.com/machinefi/w3bstream/pkg/test/mock_depends_kit_sqlx"
    30  	"github.com/machinefi/w3bstream/pkg/test/patch_models"
    31  	"github.com/machinefi/w3bstream/pkg/types"
    32  )
    33  
    34  func TestAccessKeyContext(t *testing.T) {
    35  	kctx := access_key.NewDefaultAccessKeyContext()
    36  	target := &access_key.AccessKeyContext{}
    37  
    38  	key, err := kctx.MarshalText()
    39  	NewWithT(t).Expect(err).To(BeNil())
    40  	t.Logf(string(key))
    41  
    42  	err = target.UnmarshalText(key)
    43  	NewWithT(t).Expect(err).To(BeNil())
    44  
    45  	NewWithT(t).Expect(kctx.Equal(target)).To(BeTrue())
    46  
    47  	cases := []*struct {
    48  		name string
    49  		key  string
    50  		err  error
    51  	}{
    52  		{
    53  			name: "#Failed#InvalidPartCountOrPrefix",
    54  			key:  "invalid_key",
    55  			err:  access_key.ErrInvalidPrefixOrPartCount,
    56  		},
    57  		{
    58  			name: "#Failed#Base64DecodeFailed",
    59  			key:  "w3b_YWJjZA=====",
    60  			err:  access_key.ErrBase64DecodeFailed,
    61  		},
    62  		{
    63  			name: "#Failed#InvalidContentsPartCount",
    64  			key:  "w3b_" + base64.RawURLEncoding.EncodeToString([]byte("1xxx")),
    65  			err:  access_key.ErrInvalidContentsPartCount,
    66  		},
    67  		{
    68  			name: "#Failed#ParseVersionFailed",
    69  			key:  "w3b_" + base64.RawURLEncoding.EncodeToString([]byte("b_100_xxx")),
    70  			err:  access_key.ErrParseVersionFailed,
    71  		},
    72  		{
    73  			name: "#Failed#ParseGenTsFailed",
    74  			key:  "w3b_" + base64.RawURLEncoding.EncodeToString([]byte("1_aaa_xxx")),
    75  			err:  access_key.ErrParseGenTsFailed,
    76  		},
    77  		{
    78  			name: "#Failed#InvalidVersion",
    79  			key:  "w3b_" + base64.RawURLEncoding.EncodeToString([]byte("2_100_xxx")),
    80  			err:  access_key.ErrInvalidVersion,
    81  		},
    82  		{
    83  			name: "#Success",
    84  			key:  "w3b_" + base64.StdEncoding.EncodeToString([]byte("1_100_xxx")),
    85  		},
    86  	}
    87  
    88  	for _, c := range cases {
    89  		t.Run(c.name, func(t *testing.T) {
    90  			k := &access_key.AccessKeyContext{}
    91  			err = k.UnmarshalText([]byte(c.key))
    92  			if c.err != nil {
    93  				NewWithT(t).Expect(strings.Contains(err.Error(), c.err.Error())).To(BeTrue())
    94  			} else {
    95  				NewWithT(t).Expect(err).To(BeNil())
    96  			}
    97  		})
    98  	}
    99  }
   100  
   101  func TestCondArgs(t *testing.T) {
   102  	args := &access_key.CondArgs{}
   103  	t.Log(builder.ResolveExpr(args.Condition()).Query())
   104  	args = &access_key.CondArgs{
   105  		AccountID:      100,
   106  		Names:          []string{"test"},
   107  		ExpiredAtBegin: types.Timestamp{Time: time.Now().Add(-time.Hour)},
   108  		ExpiredAtEnd:   types.Timestamp{Time: time.Now().Add(time.Hour)},
   109  		IdentityIDs:    types.SFIDs{1, 2, 3},
   110  		IdentityTypes:  []enums.AccessKeyIdentityType{1, 2},
   111  	}
   112  	t.Log(builder.ResolveExpr(args.Condition()).Query())
   113  }
   114  
   115  func TestTimeParseAndFormat(t *testing.T) {
   116  	formatAndParse := func(layout string) (error, bool) {
   117  		ts := time.Now().UTC()
   118  		_ts, err := time.ParseInLocation(layout, ts.Format(layout), time.UTC)
   119  		return err, ts.Equal(_ts)
   120  	}
   121  
   122  	for _, layout := range []string{time.RFC3339, time.RFC3339Nano} {
   123  		err, equal := formatAndParse(layout)
   124  		t.Logf("layout: %s err: %v, equal: %v", layout, err, equal)
   125  	}
   126  }
   127  
   128  var (
   129  	RootRouter1 *kit.Router
   130  	RootRouter2 *kit.Router
   131  	RootRouter3 *kit.Router
   132  )
   133  
   134  type MockGet struct{ httpx.MethodGet }
   135  
   136  func (*MockGet) Output(_ context.Context) (interface{}, error) { return nil, nil }
   137  
   138  type MockPos struct{ httpx.MethodPost }
   139  
   140  func (*MockPos) Output(_ context.Context) (interface{}, error) { return nil, nil }
   141  
   142  func (*MockPos) OperatorAttr() enums.ApiOperatorAttr { return enums.API_OPERATOR_ATTR__COMMON }
   143  
   144  type MockPatch struct{ httpx.MethodPatch }
   145  
   146  func (*MockPatch) Output(_ context.Context) (interface{}, error) { return nil, nil }
   147  
   148  func init() {
   149  	RootRouter1 = kit.NewRouter(httptransport.Group("mock1"))
   150  	RootRouter2 = kit.NewRouter(httptransport.Group("mock2"))
   151  	RootRouter3 = kit.NewRouter(httptransport.Group("mock3"))
   152  
   153  	type MockGetMock1Group struct{ MockGet }
   154  	type MockPosMock1Group struct{ MockPos }
   155  	type MockGetMock2Group struct{ MockGet }
   156  	type MockPosMock2Group struct{ MockPos }
   157  	type MockGetMock3Group struct{ MockGet }
   158  	type MockPosMock3Group struct{ MockPos }
   159  
   160  	RootRouter1.Register(kit.NewRouter(&MockGetMock1Group{}))
   161  	RootRouter1.Register(kit.NewRouter(&MockPosMock1Group{}))
   162  	RootRouter2.Register(kit.NewRouter(&MockGetMock2Group{}))
   163  	RootRouter2.Register(kit.NewRouter(&MockPosMock2Group{}))
   164  	RootRouter3.Register(kit.NewRouter(&MockGetMock3Group{}))
   165  	RootRouter3.Register(kit.NewRouter(&MockPosMock3Group{}))
   166  
   167  	access_key.RouterRegister(RootRouter1, "mock1", "mock group operator")
   168  	access_key.RouterRegister(RootRouter2, "mock2", "mock group operator")
   169  	access_key.RouterRegister(RootRouter3, "mock3", "mock group operator")
   170  }
   171  
   172  func TestRouterRegister(t *testing.T) {
   173  	t.Run("#GroupAlreadyRegistered", func(t *testing.T) {
   174  		defer func() {
   175  			err := recover()
   176  			t.Log(err)
   177  			NewWithT(t).Expect(strings.Contains(err.(error).Error(), "group already registered"))
   178  		}()
   179  		access_key.RouterRegister(RootRouter1, "mock1", "mock group operator")
   180  	})
   181  
   182  	t.Run("#IgnoredMethod", func(t *testing.T) {
   183  		RootRouter4 := kit.NewRouter(httptransport.Group("mock4"))
   184  		RootRouter4.Register(kit.NewRouter(&MockPatch{}))
   185  		access_key.RouterRegister(RootRouter4, "mock4", "mock group operator")
   186  	})
   187  	t.Run("#", func(t *testing.T) {
   188  		RootRouter5 := kit.NewRouter(httptransport.Group("mock5"))
   189  		type MockPosMock3Group struct{ MockPos } // operator MockPosMock3Group has registered in init func
   190  		RootRouter5.Register(kit.NewRouter(&MockPosMock3Group{}))
   191  		defer func() {
   192  			err := recover()
   193  			t.Log(err)
   194  			NewWithT(t).Expect(strings.Contains(err.(error).Error(), "operator id already registered in group"))
   195  		}()
   196  		access_key.RouterRegister(RootRouter5, "mock5", "mock group operator")
   197  	})
   198  }
   199  
   200  func TestOperatorGroupMetaList(t *testing.T) {
   201  	metas := access_key.OperatorGroupMetaList()
   202  	NewWithT(t).Expect(len(metas)).To(Equal(4))
   203  	NewWithT(t).Expect(metas[0].Name).To(Equal("mock1"))
   204  	NewWithT(t).Expect(metas[1].Name).To(Equal("mock2"))
   205  	NewWithT(t).Expect(metas[2].Name).To(Equal("mock3"))
   206  }
   207  
   208  func TestAccessKey(t *testing.T) {
   209  	ctl := gomock.NewController(t)
   210  	defer ctl.Finish()
   211  
   212  	d := &struct {
   213  		*mock_sqlx.MockDBExecutor
   214  		*mock_sqlx.MockTxExecutor
   215  	}{
   216  		MockDBExecutor: mock_sqlx.NewMockDBExecutor(ctl),
   217  		MockTxExecutor: mock_sqlx.NewMockTxExecutor(ctl),
   218  	}
   219  	idg := confid.MustNewSFIDGenerator()
   220  	acc := &models.Account{
   221  		RelAccount: models.RelAccount{AccountID: idg.MustGenSFID()},
   222  	}
   223  
   224  	ctx := contextx.WithContextCompose(
   225  		types.WithMgrDBExecutorContext(d),
   226  		confid.WithSFIDGeneratorContext(idg),
   227  		types.WithAccountContext(acc),
   228  	)(context.Background())
   229  
   230  	d.MockDBExecutor.EXPECT().T(gomock.Any()).Return(&builder.Table{}).AnyTimes()
   231  	d.MockTxExecutor.EXPECT().IsTx().Return(true).AnyTimes()
   232  	d.MockDBExecutor.EXPECT().Context().Return(ctx).AnyTimes()
   233  
   234  	errFrom := func(from string) error { return errors.New(from) }
   235  
   236  	t.Run("Create", func(t *testing.T) {
   237  		pub := &models.Publisher{
   238  			RelPublisher: models.RelPublisher{PublisherID: idg.MustGenSFID()},
   239  		}
   240  
   241  		t.Run("#Success", func(t *testing.T) {
   242  			cases := []*struct {
   243  				name string
   244  				req  *access_key.CreateReq
   245  			}{
   246  				{
   247  					name: "#NoExpiration",
   248  					req: &access_key.CreateReq{
   249  						CreateReqBase: access_key.CreateReqBase{
   250  							Name:           "test",
   251  							ExpirationDays: 0,
   252  							Privileges: access_key.GroupAccessPrivileges{
   253  								{Name: "mock1", Perm: enums.ACCESS_PERMISSION__NO_ACCESS},
   254  								{Name: "mock2", Perm: enums.ACCESS_PERMISSION__READONLY},
   255  								{Name: "mock3", Perm: enums.ACCESS_PERMISSION__READ_WRITE},
   256  								{Name: "not_exists"},
   257  							},
   258  						},
   259  					},
   260  				},
   261  				{
   262  					name: "#HasExpiration",
   263  					req: &access_key.CreateReq{
   264  						CreateReqBase: access_key.CreateReqBase{
   265  							Name:           "test",
   266  							ExpirationDays: 30,
   267  							Privileges: access_key.GroupAccessPrivileges{
   268  								{Name: "mock1", Perm: enums.ACCESS_PERMISSION__NO_ACCESS},
   269  								{Name: "mock2", Perm: enums.ACCESS_PERMISSION__READONLY},
   270  								{Name: "mock3", Perm: enums.ACCESS_PERMISSION__READ_WRITE},
   271  							},
   272  						},
   273  					},
   274  				},
   275  			}
   276  			for _, c := range cases {
   277  				t.Run(c.name, func(t *testing.T) {
   278  					d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(mock_sqlx.ErrNotFound).Times(1)
   279  					d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, nil).Times(1)
   280  					_, err := access_key.Create(ctx, c.req)
   281  					NewWithT(t).Expect(err).To(BeNil())
   282  				})
   283  			}
   284  			t.Run("CreateForPublisher", func(t *testing.T) {
   285  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(mock_sqlx.ErrNotFound).Times(1)
   286  				d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, nil).Times(1)
   287  				_, err := access_key.Create(ctx, &access_key.CreateReq{
   288  					IdentityID:   pub.PublisherID,
   289  					IdentityType: enums.ACCESS_KEY_IDENTITY_TYPE__PUBLISHER,
   290  				})
   291  				NewWithT(t).Expect(err).To(BeNil())
   292  			})
   293  		})
   294  		t.Run("#Failed", func(t *testing.T) {
   295  			t.Run("#InvalidAccessKeyIdentityType", func(t *testing.T) {
   296  				_, err := access_key.Create(ctx, &access_key.CreateReq{
   297  					IdentityID:   0,
   298  					IdentityType: enums.AccessKeyIdentityType(100),
   299  				})
   300  				mock_sqlx.ExpectError(t, err, status.InvalidAccessKeyIdentityType)
   301  			})
   302  			t.Run("#FetchByRandDatbaseError", func(t *testing.T) {
   303  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(nil).Times(1)
   304  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(mock_sqlx.ErrDatabase).Times(1)
   305  				_, err := access_key.Create(ctx, &access_key.CreateReq{
   306  					CreateReqBase: access_key.CreateReqBase{
   307  						Privileges: access_key.GroupAccessPrivileges{
   308  							{Name: "mock1", Perm: enums.ACCESS_PERMISSION__READONLY},
   309  							{Name: "mock2", Perm: enums.ACCESS_PERMISSION__READ_WRITE},
   310  							{Name: "mock3", Perm: enums.AccessPermission(10)},
   311  						},
   312  					},
   313  				})
   314  				mock_sqlx.ExpectError(t, err, status.DatabaseError)
   315  			})
   316  			t.Run("#CreateAccessKeyConflict", func(t *testing.T) {
   317  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(mock_sqlx.ErrNotFound).Times(1)
   318  				d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, mock_sqlx.ErrConflict).Times(1)
   319  				_, err := access_key.Create(ctx, &access_key.CreateReq{})
   320  				mock_sqlx.ExpectError(t, err, status.AccessKeyNameConflict)
   321  			})
   322  			t.Run("#CreateAccessKeyNameDatabaseError", func(t *testing.T) {
   323  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(mock_sqlx.ErrNotFound).Times(1)
   324  				d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, mock_sqlx.ErrDatabase).Times(1)
   325  				_, err := access_key.Create(ctx, &access_key.CreateReq{})
   326  				mock_sqlx.ExpectError(t, err, status.DatabaseError)
   327  			})
   328  		})
   329  	})
   330  
   331  	t.Run("#Update", func(t *testing.T) {
   332  		patch := gomonkey.NewPatches()
   333  		defer patch.Reset()
   334  
   335  		t.Run("#Failed", func(t *testing.T) {
   336  			t.Run("#FetchByAccountIDAndNameFailed", func(t *testing.T) {
   337  				t.Run("#AccessKeyNotFound", func(t *testing.T) {
   338  					d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(mock_sqlx.ErrNotFound).Times(1)
   339  					_, err := access_key.UpdateByName(ctx, "any_name", &access_key.UpdateReq{})
   340  					mock_sqlx.ExpectError(t, err, status.AccessKeyNotFound)
   341  				})
   342  				t.Run("#DatabaseError", func(t *testing.T) {
   343  					d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(errFrom(t.Name())).Times(1)
   344  					_, err := access_key.UpdateByName(ctx, "any_name", &access_key.UpdateReq{})
   345  					mock_sqlx.ExpectError(t, err, status.DatabaseError, t.Name())
   346  				})
   347  			})
   348  			req := &access_key.UpdateReq{
   349  				ExpirationDays: 10,
   350  				Desc:           "desc",
   351  			}
   352  			if runtime.GOOS == `darwin` {
   353  				return
   354  			}
   355  			patch = patch_models.AccessKeyFetchByAccountIDAndName(patch, &models.AccessKey{
   356  				AccessKeyInfo: models.AccessKeyInfo{
   357  					ExpiredAt: base.Timestamp{Time: time.Now()},
   358  					LastUsed:  base.Timestamp{Time: time.Now()},
   359  				},
   360  			}, nil)
   361  			t.Run("#UpdateFailed", func(t *testing.T) {
   362  				d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(sql.Result(nil), errFrom(t.Name())).Times(1)
   363  				_, err := access_key.UpdateByName(ctx, "any_name", req)
   364  				mock_sqlx.ExpectError(t, err, status.DatabaseError, t.Name())
   365  			})
   366  		})
   367  		t.Run("#Success", func(t *testing.T) {
   368  			if runtime.GOOS == `darwin` {
   369  				return
   370  			}
   371  			d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(sql.Result(nil), nil).Times(1)
   372  			_, err := access_key.UpdateByName(ctx, "any_name", &access_key.UpdateReq{
   373  				ExpirationDays: 10,
   374  			})
   375  			NewWithT(t).Expect(err).To(BeNil())
   376  		})
   377  	})
   378  
   379  	t.Run("#DeleteByName", func(t *testing.T) {
   380  		t.Run("#Success", func(t *testing.T) {
   381  			d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, nil).MaxTimes(1)
   382  
   383  			err := access_key.DeleteByName(ctx, "any_name")
   384  			NewWithT(t).Expect(err).To(BeNil())
   385  		})
   386  
   387  		t.Run("#Failed", func(t *testing.T) {
   388  			t.Run("#AccountKeyNotFound", func(t *testing.T) {
   389  				d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, mock_sqlx.ErrNotFound).MaxTimes(1)
   390  
   391  				err := access_key.DeleteByName(ctx, "any")
   392  				mock_sqlx.ExpectError(t, err, status.AccessKeyNotFound)
   393  			})
   394  			t.Run("#DatabaseError", func(t *testing.T) {
   395  				d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, errFrom(t.Name())).MaxTimes(1)
   396  
   397  				err := access_key.DeleteByName(ctx, "any")
   398  				mock_sqlx.ExpectError(t, err, status.DatabaseError, t.Name())
   399  			})
   400  		})
   401  	})
   402  
   403  	t.Run("#GetByName", func(t *testing.T) {
   404  		t.Run("#Failed", func(t *testing.T) {
   405  			t.Run("#NotFoundError", func(t *testing.T) {
   406  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(mock_sqlx.ErrNotFound).Times(1)
   407  				_, err := access_key.GetByName(ctx, "any_name")
   408  				mock_sqlx.ExpectError(t, err, status.AccessKeyNotFound)
   409  			})
   410  			t.Run("#DatabaseError", func(t *testing.T) {
   411  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(errFrom(t.Name())).Times(1)
   412  				_, err := access_key.GetByName(ctx, "any_name")
   413  				mock_sqlx.ExpectError(t, err, status.DatabaseError, t.Name())
   414  			})
   415  		})
   416  		t.Run("#Success", func(t *testing.T) {
   417  			if runtime.GOOS == `darwin` {
   418  				return
   419  			}
   420  			patch := patch_models.AccessKeyFetchByAccountIDAndName(gomonkey.NewPatches(), &models.AccessKey{
   421  				AccessKeyInfo: models.AccessKeyInfo{
   422  					ExpiredAt: base.Timestamp{Time: time.Now()},
   423  					LastUsed:  base.Timestamp{Time: time.Now()},
   424  					Privileges: models.GroupAccessPrivileges{
   425  						"mock1": enums.ACCESS_PERMISSION__READONLY,
   426  					},
   427  				},
   428  			}, nil)
   429  			defer patch.Reset()
   430  			_, err := access_key.GetByName(ctx, "any_name")
   431  			NewWithT(t).Expect(err).To(BeNil())
   432  		})
   433  	})
   434  
   435  	t.Run("#Validate", func(t *testing.T) {
   436  		kctx := access_key.NewAccessKeyContext(1)
   437  
   438  		id := idg.MustGenSFID()
   439  		m := &models.AccessKey{
   440  			RelAccount: models.RelAccount{AccountID: id},
   441  			AccessKeyInfo: models.AccessKeyInfo{
   442  				IdentityID:   id,
   443  				IdentityType: enums.ACCESS_KEY_IDENTITY_TYPE__ACCOUNT,
   444  				Name:         "test",
   445  				Rand:         kctx.Rand,
   446  				ExpiredAt:    base.Timestamp{Time: kctx.GenTS.UTC().Add(2 * time.Second)},
   447  				Privileges:   models.GroupAccessPrivileges{"mock1": enums.ACCESS_PERMISSION__READONLY},
   448  			},
   449  			OperationTimesWithDeleted: datatypes.OperationTimesWithDeleted{
   450  				OperationTimes: datatypes.OperationTimes{
   451  					CreatedAt: base.Timestamp{Time: kctx.GenTS.UTC()},
   452  				},
   453  			},
   454  		}
   455  		key, _ := kctx.MarshalText()
   456  		ctx := httptransport.ContextWithRouteMetaID(ctx, "MockGetMock1Group")
   457  
   458  		t.Run("#Success", func(t *testing.T) {
   459  			if runtime.GOOS == `darwin` {
   460  				return
   461  			}
   462  			patch := patch_models.AccessKeyFetchByRand(gomonkey.NewPatches(), m, nil)
   463  			defer patch.Reset()
   464  			d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, nil).Times(1)
   465  
   466  			idAny, err, canBeValidated := access_key.Validate(ctx, string(key))
   467  			if err != nil {
   468  				t.Log(err)
   469  			}
   470  
   471  			NewWithT(t).Expect(canBeValidated).To(BeTrue())
   472  			NewWithT(t).Expect(err).To(BeNil())
   473  
   474  			idVal, ok := idAny.(*models.AccessKey)
   475  			NewWithT(t).Expect(ok).To(BeTrue())
   476  			NewWithT(t).Expect(idVal.IdentityID).To(Equal(id))
   477  		})
   478  
   479  		patch := gomonkey.NewPatches()
   480  		defer patch.Reset()
   481  
   482  		t.Run("#Failed", func(t *testing.T) {
   483  			t.Run("#AccessKeyContextUnmarshalFailed", func(t *testing.T) {
   484  				t.Run("#CanbeValidated", func(t *testing.T) {
   485  					_, err, canbe := access_key.Validate(ctx, "invalid_key")
   486  					NewWithT(t).Expect(err).NotTo(BeNil())
   487  					NewWithT(t).Expect(canbe).To(BeFalse())
   488  				})
   489  				t.Run("#CannotBeValidated", func(t *testing.T) {
   490  					key := "w3b_xxxx"
   491  					_, err, canbe := access_key.Validate(ctx, key)
   492  					NewWithT(t).Expect(err).NotTo(BeNil())
   493  					NewWithT(t).Expect(canbe).To(BeTrue())
   494  				})
   495  			})
   496  			t.Run("#FetchByRandFailed", func(t *testing.T) {
   497  				t.Run("#AccessKeyNotFound", func(t *testing.T) {
   498  					d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(mock_sqlx.ErrNotFound).Times(1)
   499  					_, err, _ := access_key.Validate(ctx, string(key))
   500  					mock_sqlx.ExpectError(t, err, status.AccessKeyNotFound)
   501  				})
   502  				t.Run("#DatabaseError", func(t *testing.T) {
   503  					d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(mock_sqlx.ErrDatabase).Times(1)
   504  					_, err, _ := access_key.Validate(ctx, string(key))
   505  					mock_sqlx.ExpectError(t, err, status.DatabaseError)
   506  				})
   507  			})
   508  
   509  			if runtime.GOOS == `darwin` {
   510  				return
   511  			}
   512  
   513  			t.Run("#GenTsNotMatch", func(t *testing.T) {
   514  				overwrite := *m
   515  				overwrite.CreatedAt.Time = overwrite.CreatedAt.Add(time.Second)
   516  				patch = patch_models.AccessKeyFetchByRand(patch, &overwrite, nil)
   517  				_, err, _ := access_key.Validate(ctx, string(key))
   518  				mock_sqlx.ExpectError(t, err, status.InvalidAccessKey)
   519  			})
   520  
   521  			patch = patch_models.AccessKeyFetchByRand(patch, m, nil)
   522  			t.Run("#AccessKeyPermissionDenied", func(t *testing.T) {
   523  				t.Run("#OperatorIDNotRegistered", func(t *testing.T) {
   524  					ctx := httptransport.ContextWithRouteMetaID(ctx, "NotEqualMockOperatorID")
   525  					_, err, _ := access_key.Validate(ctx, string(key))
   526  					mock_sqlx.ExpectError(t, err, status.AccessKeyPermissionDenied)
   527  					t.Log(err)
   528  				})
   529  				t.Run("#NoGroupPermission", func(t *testing.T) {
   530  					ctx := httptransport.ContextWithRouteMetaID(ctx, "MockGetMock2Group")
   531  					_, err, _ := access_key.Validate(ctx, string(key))
   532  					mock_sqlx.ExpectError(t, err, status.AccessKeyPermissionDenied)
   533  					t.Log(err)
   534  				})
   535  				t.Run("#NoOperatorPermission", func(t *testing.T) {
   536  					ctx := httptransport.ContextWithRouteMetaID(ctx, "MockPosMock1Group")
   537  					_, err, _ := access_key.Validate(ctx, string(key))
   538  					mock_sqlx.ExpectError(t, err, status.AccessKeyPermissionDenied)
   539  					t.Log(err)
   540  				})
   541  			})
   542  
   543  			t.Run("#UpdateLastUsedFailed", func(t *testing.T) {
   544  				d.MockDBExecutor.EXPECT().Exec(gomock.Any()).Return(nil, errFrom(t.Name())).Times(1)
   545  				_, err, _ := access_key.Validate(ctx, string(key))
   546  				NewWithT(t).Expect(err).To(BeNil())
   547  			})
   548  
   549  			t.Run("#AccessKeyExpired", func(t *testing.T) {
   550  				time.Sleep(3 * time.Second)
   551  				_, err, _ := access_key.Validate(ctx, string(key))
   552  				mock_sqlx.ExpectError(t, err, status.AccessKeyExpired)
   553  			})
   554  		})
   555  
   556  	})
   557  
   558  	t.Run("#List", func(t *testing.T) {
   559  		if runtime.GOOS == `darwin` {
   560  			return
   561  		}
   562  		patch := gomonkey.NewPatches()
   563  		defer patch.Reset()
   564  
   565  		t.Run("#Failed", func(t *testing.T) {
   566  			t.Run("#ListFailed", func(t *testing.T) {
   567  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(errFrom(t.Name())).Times(1)
   568  				_, err := access_key.List(ctx, &access_key.ListReq{})
   569  				mock_sqlx.ExpectError(t, err, status.DatabaseError, t.Name())
   570  			})
   571  			t.Run("#CountFailed", func(t *testing.T) {
   572  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(nil).Times(1)
   573  				d.MockDBExecutor.EXPECT().QueryAndScan(gomock.Any(), gomock.Any()).Return(errFrom(t.Name())).Times(1)
   574  				_, err := access_key.List(ctx, &access_key.ListReq{})
   575  				mock_sqlx.ExpectError(t, err, status.DatabaseError, t.Name())
   576  			})
   577  		})
   578  
   579  		result := []models.AccessKey{
   580  			{},
   581  			{
   582  				AccessKeyInfo: models.AccessKeyInfo{
   583  					ExpiredAt: base.Timestamp{Time: time.Now()},
   584  					LastUsed:  base.Timestamp{Time: time.Now()},
   585  				},
   586  			},
   587  		}
   588  
   589  		patch = patch_models.AccessKeyList(patch, result, nil)
   590  		patch = patch_models.AccessKeyCount(patch, 2, nil)
   591  		t.Run("#Success", func(t *testing.T) {
   592  			rsp, err := access_key.List(ctx, &access_key.ListReq{})
   593  			NewWithT(t).Expect(err).To(BeNil())
   594  			NewWithT(t).Expect(rsp.Total).To(Equal(int64(2)))
   595  			NewWithT(t).Expect(len(rsp.Data)).To(Equal(2))
   596  		})
   597  	})
   598  }