Files
user-system/internal/service/auth_cache_invalidator_test.go
2026-05-30 21:29:24 +08:00

168 lines
6.6 KiB
Go

package service_test
import (
"context"
"strconv"
"testing"
"time"
"github.com/user-management-system/internal/cache"
"github.com/user-management-system/internal/domain"
"github.com/user-management-system/internal/repository"
"github.com/user-management-system/internal/service"
gormsqlite "gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type cacheInvalidatorHarness struct {
l1 *cache.L1Cache
}
func (h *cacheInvalidatorHarness) InvalidateUserState(userID int64) {
h.l1.Delete("user_state:" + strconv.FormatInt(userID, 10))
}
func (h *cacheInvalidatorHarness) InvalidateUserPerms(userID int64) {
h.l1.Delete("user_perms:" + strconv.FormatInt(userID, 10))
}
func setupCacheInvalidationDB(t *testing.T) *gorm.DB {
t.Helper()
db, err := gorm.Open(gormsqlite.New(gormsqlite.Config{
DriverName: "sqlite",
DSN: "file:cache_invalidation?mode=memory&cache=shared",
}), &gorm.Config{Logger: logger.Default.LogMode(logger.Silent)})
if err != nil {
t.Fatalf("open sqlite failed: %v", err)
}
if err := db.AutoMigrate(&domain.User{}, &domain.Role{}, &domain.UserRole{}, &domain.Permission{}, &domain.RolePermission{}); err != nil {
t.Fatalf("migrate failed: %v", err)
}
return db
}
func TestUserService_InvalidateStateCacheOnStatusChange(t *testing.T) {
db := setupCacheInvalidationDB(t)
userRepo := repository.NewUserRepository(db)
userRoleRepo := repository.NewUserRoleRepository(db)
roleRepo := repository.NewRoleRepository(db)
userSvc := service.NewUserService(userRepo, userRoleRepo, roleRepo, nil)
l1 := cache.NewL1Cache()
userSvc.SetAuthCacheInvalidator(&cacheInvalidatorHarness{l1: l1})
user := &domain.User{Username: "statecache", Password: "x", Status: domain.UserStatusActive}
if err := db.Create(user).Error; err != nil {
t.Fatalf("create user failed: %v", err)
}
l1.Set("user_state:"+strconv.FormatInt(user.ID, 10), "cached", time.Minute)
if err := userSvc.UpdateStatus(context.Background(), user.ID, domain.UserStatusInactive); err != nil {
t.Fatalf("UpdateStatus failed: %v", err)
}
if _, ok := l1.Get("user_state:" + strconv.FormatInt(user.ID, 10)); ok {
t.Fatal("expected user_state cache to be invalidated")
}
}
func TestUserService_InvalidatePermCacheOnAssignRoles(t *testing.T) {
db := setupCacheInvalidationDB(t)
userRepo := repository.NewUserRepository(db)
userRoleRepo := repository.NewUserRoleRepository(db)
roleRepo := repository.NewRoleRepository(db)
userSvc := service.NewUserService(userRepo, userRoleRepo, roleRepo, nil)
l1 := cache.NewL1Cache()
userSvc.SetAuthCacheInvalidator(&cacheInvalidatorHarness{l1: l1})
user := &domain.User{Username: "permcache", Password: "x", Status: domain.UserStatusActive}
role := &domain.Role{Name: "role1", Code: "role1", Status: domain.RoleStatusEnabled}
if err := db.Create(user).Error; err != nil {
t.Fatalf("create user failed: %v", err)
}
if err := db.Create(role).Error; err != nil {
t.Fatalf("create role failed: %v", err)
}
l1.Set("user_perms:"+strconv.FormatInt(user.ID, 10), "cached", time.Minute)
if err := userSvc.AssignRoles(context.Background(), user.ID, []int64{role.ID}); err != nil {
t.Fatalf("AssignRoles failed: %v", err)
}
if _, ok := l1.Get("user_perms:" + strconv.FormatInt(user.ID, 10)); ok {
t.Fatal("expected user_perms cache to be invalidated")
}
}
func TestRoleService_InvalidatePermCacheOnAssignPermissions(t *testing.T) {
db := setupCacheInvalidationDB(t)
roleRepo := repository.NewRoleRepository(db)
rolePermRepo := repository.NewRolePermissionRepository(db)
userRoleRepo := repository.NewUserRoleRepository(db)
roleSvc := service.NewRoleService(roleRepo, rolePermRepo)
roleSvc.SetUserRoleRepository(userRoleRepo)
l1 := cache.NewL1Cache()
roleSvc.SetAuthCacheInvalidator(&cacheInvalidatorHarness{l1: l1})
user := &domain.User{Username: "rolepermcache", Password: "x", Status: domain.UserStatusActive}
role := &domain.Role{Name: "role2", Code: "role2", Status: domain.RoleStatusEnabled}
perm := &domain.Permission{Name: "perm1", Code: "perm1", Type: domain.PermissionTypeMenu, Status: domain.PermissionStatusEnabled}
if err := db.Create(user).Error; err != nil {
t.Fatalf("create user failed: %v", err)
}
if err := db.Create(role).Error; err != nil {
t.Fatalf("create role failed: %v", err)
}
if err := db.Create(perm).Error; err != nil {
t.Fatalf("create permission failed: %v", err)
}
if err := db.Create(&domain.UserRole{UserID: user.ID, RoleID: role.ID}).Error; err != nil {
t.Fatalf("create user role failed: %v", err)
}
l1.Set("user_perms:"+strconv.FormatInt(user.ID, 10), "cached", time.Minute)
if err := roleSvc.AssignPermissions(context.Background(), role.ID, []int64{perm.ID}); err != nil {
t.Fatalf("AssignPermissions failed: %v", err)
}
if _, ok := l1.Get("user_perms:" + strconv.FormatInt(user.ID, 10)); ok {
t.Fatal("expected user_perms cache to be invalidated after role permission change")
}
}
func TestPermissionService_InvalidatePermCacheOnStatusChange(t *testing.T) {
db := setupCacheInvalidationDB(t)
permRepo := repository.NewPermissionRepository(db)
rolePermRepo := repository.NewRolePermissionRepository(db)
userRoleRepo := repository.NewUserRoleRepository(db)
permSvc := service.NewPermissionService(permRepo)
permSvc.SetRolePermissionRepository(rolePermRepo)
permSvc.SetUserRoleRepository(userRoleRepo)
l1 := cache.NewL1Cache()
permSvc.SetAuthCacheInvalidator(&cacheInvalidatorHarness{l1: l1})
user := &domain.User{Username: "permstatuscache", Password: "x", Status: domain.UserStatusActive}
role := &domain.Role{Name: "role3", Code: "role3", Status: domain.RoleStatusEnabled}
perm := &domain.Permission{Name: "perm2", Code: "perm2", Type: domain.PermissionTypeMenu, Status: domain.PermissionStatusEnabled}
if err := db.Create(user).Error; err != nil {
t.Fatalf("create user failed: %v", err)
}
if err := db.Create(role).Error; err != nil {
t.Fatalf("create role failed: %v", err)
}
if err := db.Create(perm).Error; err != nil {
t.Fatalf("create permission failed: %v", err)
}
if err := db.Create(&domain.UserRole{UserID: user.ID, RoleID: role.ID}).Error; err != nil {
t.Fatalf("create user role failed: %v", err)
}
if err := db.Create(&domain.RolePermission{RoleID: role.ID, PermissionID: perm.ID}).Error; err != nil {
t.Fatalf("create role permission failed: %v", err)
}
l1.Set("user_perms:"+strconv.FormatInt(user.ID, 10), "cached", time.Minute)
if err := permSvc.UpdatePermissionStatus(context.Background(), perm.ID, domain.PermissionStatusDisabled); err != nil {
t.Fatalf("UpdatePermissionStatus failed: %v", err)
}
if _, ok := l1.Get("user_perms:" + strconv.FormatInt(user.ID, 10)); ok {
t.Fatal("expected user_perms cache to be invalidated after permission status change")
}
}