package service import ( "carrotskin/internal/model" "errors" ) // ============================================================================ // Repository Mocks // ============================================================================ // MockUserRepository 模拟UserRepository type MockUserRepository struct { users map[int64]*model.User // 用于模拟错误的标志 FailCreate bool FailFindByID bool FailFindByUsername bool FailFindByEmail bool FailUpdate bool } func NewMockUserRepository() *MockUserRepository { return &MockUserRepository{ users: make(map[int64]*model.User), } } func (m *MockUserRepository) Create(user *model.User) error { if m.FailCreate { return errors.New("mock create error") } if user.ID == 0 { user.ID = int64(len(m.users) + 1) } m.users[user.ID] = user return nil } func (m *MockUserRepository) FindByID(id int64) (*model.User, error) { if m.FailFindByID { return nil, errors.New("mock find error") } if user, ok := m.users[id]; ok { return user, nil } return nil, nil } func (m *MockUserRepository) FindByUsername(username string) (*model.User, error) { if m.FailFindByUsername { return nil, errors.New("mock find by username error") } for _, user := range m.users { if user.Username == username { return user, nil } } return nil, nil } func (m *MockUserRepository) FindByEmail(email string) (*model.User, error) { if m.FailFindByEmail { return nil, errors.New("mock find by email error") } for _, user := range m.users { if user.Email == email { return user, nil } } return nil, nil } func (m *MockUserRepository) Update(user *model.User) error { if m.FailUpdate { return errors.New("mock update error") } m.users[user.ID] = user return nil } func (m *MockUserRepository) UpdateFields(id int64, fields map[string]interface{}) error { if m.FailUpdate { return errors.New("mock update fields error") } _, ok := m.users[id] if !ok { return errors.New("user not found") } return nil } func (m *MockUserRepository) Delete(id int64) error { delete(m.users, id) return nil } func (m *MockUserRepository) CreateLoginLog(log *model.UserLoginLog) error { return nil } func (m *MockUserRepository) CreatePointLog(log *model.UserPointLog) error { return nil } func (m *MockUserRepository) UpdatePoints(userID int64, amount int, changeType, reason string) error { return nil } // MockProfileRepository 模拟ProfileRepository type MockProfileRepository struct { profiles map[string]*model.Profile userProfiles map[int64][]*model.Profile nextID int64 FailCreate bool FailFind bool FailUpdate bool FailDelete bool } func NewMockProfileRepository() *MockProfileRepository { return &MockProfileRepository{ profiles: make(map[string]*model.Profile), userProfiles: make(map[int64][]*model.Profile), nextID: 1, } } func (m *MockProfileRepository) Create(profile *model.Profile) error { if m.FailCreate { return errors.New("mock create error") } m.profiles[profile.UUID] = profile m.userProfiles[profile.UserID] = append(m.userProfiles[profile.UserID], profile) return nil } func (m *MockProfileRepository) FindByUUID(uuid string) (*model.Profile, error) { if m.FailFind { return nil, errors.New("mock find error") } if profile, ok := m.profiles[uuid]; ok { return profile, nil } return nil, errors.New("profile not found") } func (m *MockProfileRepository) FindByName(name string) (*model.Profile, error) { if m.FailFind { return nil, errors.New("mock find error") } for _, profile := range m.profiles { if profile.Name == name { return profile, nil } } return nil, nil } func (m *MockProfileRepository) FindByUserID(userID int64) ([]*model.Profile, error) { if m.FailFind { return nil, errors.New("mock find error") } return m.userProfiles[userID], nil } func (m *MockProfileRepository) Update(profile *model.Profile) error { if m.FailUpdate { return errors.New("mock update error") } m.profiles[profile.UUID] = profile return nil } func (m *MockProfileRepository) UpdateFields(uuid string, updates map[string]interface{}) error { if m.FailUpdate { return errors.New("mock update error") } return nil } func (m *MockProfileRepository) Delete(uuid string) error { if m.FailDelete { return errors.New("mock delete error") } delete(m.profiles, uuid) return nil } func (m *MockProfileRepository) CountByUserID(userID int64) (int64, error) { return int64(len(m.userProfiles[userID])), nil } func (m *MockProfileRepository) SetActive(uuid string, userID int64) error { return nil } func (m *MockProfileRepository) UpdateLastUsedAt(uuid string) error { return nil } func (m *MockProfileRepository) GetByNames(names []string) ([]*model.Profile, error) { var result []*model.Profile for _, name := range names { for _, profile := range m.profiles { if profile.Name == name { result = append(result, profile) } } } return result, nil } func (m *MockProfileRepository) GetKeyPair(profileId string) (*model.KeyPair, error) { return nil, nil } func (m *MockProfileRepository) UpdateKeyPair(profileId string, keyPair *model.KeyPair) error { return nil } // MockTextureRepository 模拟TextureRepository type MockTextureRepository struct { textures map[int64]*model.Texture favorites map[int64]map[int64]bool // userID -> textureID -> favorited nextID int64 FailCreate bool FailFind bool FailUpdate bool FailDelete bool } func NewMockTextureRepository() *MockTextureRepository { return &MockTextureRepository{ textures: make(map[int64]*model.Texture), favorites: make(map[int64]map[int64]bool), nextID: 1, } } func (m *MockTextureRepository) Create(texture *model.Texture) error { if m.FailCreate { return errors.New("mock create error") } if texture.ID == 0 { texture.ID = m.nextID m.nextID++ } m.textures[texture.ID] = texture return nil } func (m *MockTextureRepository) FindByID(id int64) (*model.Texture, error) { if m.FailFind { return nil, errors.New("mock find error") } if texture, ok := m.textures[id]; ok { return texture, nil } return nil, errors.New("texture not found") } func (m *MockTextureRepository) FindByHash(hash string) (*model.Texture, error) { if m.FailFind { return nil, errors.New("mock find error") } for _, texture := range m.textures { if texture.Hash == hash { return texture, nil } } return nil, nil } func (m *MockTextureRepository) FindByUploaderID(uploaderID int64, page, pageSize int) ([]*model.Texture, int64, error) { if m.FailFind { return nil, 0, errors.New("mock find error") } var result []*model.Texture for _, texture := range m.textures { if texture.UploaderID == uploaderID { result = append(result, texture) } } return result, int64(len(result)), nil } func (m *MockTextureRepository) Search(keyword string, textureType model.TextureType, publicOnly bool, page, pageSize int) ([]*model.Texture, int64, error) { if m.FailFind { return nil, 0, errors.New("mock find error") } var result []*model.Texture for _, texture := range m.textures { if publicOnly && !texture.IsPublic { continue } result = append(result, texture) } return result, int64(len(result)), nil } func (m *MockTextureRepository) Update(texture *model.Texture) error { if m.FailUpdate { return errors.New("mock update error") } m.textures[texture.ID] = texture return nil } func (m *MockTextureRepository) UpdateFields(id int64, fields map[string]interface{}) error { if m.FailUpdate { return errors.New("mock update error") } return nil } func (m *MockTextureRepository) Delete(id int64) error { if m.FailDelete { return errors.New("mock delete error") } delete(m.textures, id) return nil } func (m *MockTextureRepository) IncrementDownloadCount(id int64) error { if texture, ok := m.textures[id]; ok { texture.DownloadCount++ } return nil } func (m *MockTextureRepository) IncrementFavoriteCount(id int64) error { if texture, ok := m.textures[id]; ok { texture.FavoriteCount++ } return nil } func (m *MockTextureRepository) DecrementFavoriteCount(id int64) error { if texture, ok := m.textures[id]; ok && texture.FavoriteCount > 0 { texture.FavoriteCount-- } return nil } func (m *MockTextureRepository) CreateDownloadLog(log *model.TextureDownloadLog) error { return nil } func (m *MockTextureRepository) IsFavorited(userID, textureID int64) (bool, error) { if userFavs, ok := m.favorites[userID]; ok { return userFavs[textureID], nil } return false, nil } func (m *MockTextureRepository) AddFavorite(userID, textureID int64) error { if m.favorites[userID] == nil { m.favorites[userID] = make(map[int64]bool) } m.favorites[userID][textureID] = true return nil } func (m *MockTextureRepository) RemoveFavorite(userID, textureID int64) error { if userFavs, ok := m.favorites[userID]; ok { delete(userFavs, textureID) } return nil } func (m *MockTextureRepository) GetUserFavorites(userID int64, page, pageSize int) ([]*model.Texture, int64, error) { var result []*model.Texture if userFavs, ok := m.favorites[userID]; ok { for textureID := range userFavs { if texture, exists := m.textures[textureID]; exists { result = append(result, texture) } } } return result, int64(len(result)), nil } func (m *MockTextureRepository) CountByUploaderID(uploaderID int64) (int64, error) { var count int64 for _, texture := range m.textures { if texture.UploaderID == uploaderID { count++ } } return count, nil } // MockTokenRepository 模拟TokenRepository type MockTokenRepository struct { tokens map[string]*model.Token userTokens map[int64][]*model.Token FailCreate bool FailFind bool FailDelete bool } func NewMockTokenRepository() *MockTokenRepository { return &MockTokenRepository{ tokens: make(map[string]*model.Token), userTokens: make(map[int64][]*model.Token), } } func (m *MockTokenRepository) Create(token *model.Token) error { if m.FailCreate { return errors.New("mock create error") } m.tokens[token.AccessToken] = token m.userTokens[token.UserID] = append(m.userTokens[token.UserID], token) return nil } func (m *MockTokenRepository) FindByAccessToken(accessToken string) (*model.Token, error) { if m.FailFind { return nil, errors.New("mock find error") } if token, ok := m.tokens[accessToken]; ok { return token, nil } return nil, errors.New("token not found") } func (m *MockTokenRepository) GetByUserID(userId int64) ([]*model.Token, error) { if m.FailFind { return nil, errors.New("mock find error") } return m.userTokens[userId], nil } func (m *MockTokenRepository) GetUUIDByAccessToken(accessToken string) (string, error) { if m.FailFind { return "", errors.New("mock find error") } if token, ok := m.tokens[accessToken]; ok { return token.ProfileId, nil } return "", errors.New("token not found") } func (m *MockTokenRepository) GetUserIDByAccessToken(accessToken string) (int64, error) { if m.FailFind { return 0, errors.New("mock find error") } if token, ok := m.tokens[accessToken]; ok { return token.UserID, nil } return 0, errors.New("token not found") } func (m *MockTokenRepository) DeleteByAccessToken(accessToken string) error { if m.FailDelete { return errors.New("mock delete error") } delete(m.tokens, accessToken) return nil } func (m *MockTokenRepository) DeleteByUserID(userId int64) error { if m.FailDelete { return errors.New("mock delete error") } for _, token := range m.userTokens[userId] { delete(m.tokens, token.AccessToken) } m.userTokens[userId] = nil return nil } func (m *MockTokenRepository) BatchDelete(accessTokens []string) (int64, error) { if m.FailDelete { return 0, errors.New("mock delete error") } var count int64 for _, accessToken := range accessTokens { if _, ok := m.tokens[accessToken]; ok { delete(m.tokens, accessToken) count++ } } return count, nil } // MockSystemConfigRepository 模拟SystemConfigRepository type MockSystemConfigRepository struct { configs map[string]*model.SystemConfig } func NewMockSystemConfigRepository() *MockSystemConfigRepository { return &MockSystemConfigRepository{ configs: make(map[string]*model.SystemConfig), } } func (m *MockSystemConfigRepository) GetByKey(key string) (*model.SystemConfig, error) { if config, ok := m.configs[key]; ok { return config, nil } return nil, nil } func (m *MockSystemConfigRepository) GetPublic() ([]model.SystemConfig, error) { var result []model.SystemConfig for _, v := range m.configs { result = append(result, *v) } return result, nil } func (m *MockSystemConfigRepository) GetAll() ([]model.SystemConfig, error) { var result []model.SystemConfig for _, v := range m.configs { result = append(result, *v) } return result, nil } func (m *MockSystemConfigRepository) Update(config *model.SystemConfig) error { m.configs[config.Key] = config return nil } func (m *MockSystemConfigRepository) UpdateValue(key, value string) error { if config, ok := m.configs[key]; ok { config.Value = value return nil } return errors.New("config not found") } // ============================================================================ // Service Mocks // ============================================================================ // MockUserService 模拟UserService type MockUserService struct { users map[int64]*model.User maxProfilesPerUser int maxTexturesPerUser int FailRegister bool FailLogin bool FailGetByID bool FailUpdate bool } func NewMockUserService() *MockUserService { return &MockUserService{ users: make(map[int64]*model.User), maxProfilesPerUser: 5, maxTexturesPerUser: 50, } } func (m *MockUserService) Register(username, password, email, avatar string) (*model.User, string, error) { if m.FailRegister { return nil, "", errors.New("mock register error") } user := &model.User{ ID: int64(len(m.users) + 1), Username: username, Email: email, Avatar: avatar, Status: 1, } m.users[user.ID] = user return user, "mock-token", nil } func (m *MockUserService) Login(usernameOrEmail, password, ipAddress, userAgent string) (*model.User, string, error) { if m.FailLogin { return nil, "", errors.New("mock login error") } for _, user := range m.users { if user.Username == usernameOrEmail || user.Email == usernameOrEmail { return user, "mock-token", nil } } return nil, "", errors.New("user not found") } func (m *MockUserService) GetByID(id int64) (*model.User, error) { if m.FailGetByID { return nil, errors.New("mock get by id error") } if user, ok := m.users[id]; ok { return user, nil } return nil, nil } func (m *MockUserService) GetByEmail(email string) (*model.User, error) { for _, user := range m.users { if user.Email == email { return user, nil } } return nil, nil } func (m *MockUserService) UpdateInfo(user *model.User) error { if m.FailUpdate { return errors.New("mock update error") } m.users[user.ID] = user return nil } func (m *MockUserService) UpdateAvatar(userID int64, avatarURL string) error { if m.FailUpdate { return errors.New("mock update error") } if user, ok := m.users[userID]; ok { user.Avatar = avatarURL } return nil } func (m *MockUserService) ChangePassword(userID int64, oldPassword, newPassword string) error { return nil } func (m *MockUserService) ResetPassword(email, newPassword string) error { return nil } func (m *MockUserService) ChangeEmail(userID int64, newEmail string) error { if user, ok := m.users[userID]; ok { user.Email = newEmail } return nil } func (m *MockUserService) ValidateAvatarURL(avatarURL string) error { return nil } func (m *MockUserService) GetMaxProfilesPerUser() int { return m.maxProfilesPerUser } func (m *MockUserService) GetMaxTexturesPerUser() int { return m.maxTexturesPerUser } // MockProfileService 模拟ProfileService type MockProfileService struct { profiles map[string]*model.Profile FailCreate bool FailGet bool FailUpdate bool FailDelete bool } func NewMockProfileService() *MockProfileService { return &MockProfileService{ profiles: make(map[string]*model.Profile), } } func (m *MockProfileService) Create(userID int64, name string) (*model.Profile, error) { if m.FailCreate { return nil, errors.New("mock create error") } profile := &model.Profile{ UUID: "mock-uuid-" + name, UserID: userID, Name: name, } m.profiles[profile.UUID] = profile return profile, nil } func (m *MockProfileService) GetByUUID(uuid string) (*model.Profile, error) { if m.FailGet { return nil, errors.New("mock get error") } if profile, ok := m.profiles[uuid]; ok { return profile, nil } return nil, errors.New("profile not found") } func (m *MockProfileService) GetByUserID(userID int64) ([]*model.Profile, error) { if m.FailGet { return nil, errors.New("mock get error") } var result []*model.Profile for _, profile := range m.profiles { if profile.UserID == userID { result = append(result, profile) } } return result, nil } func (m *MockProfileService) Update(uuid string, userID int64, name *string, skinID, capeID *int64) (*model.Profile, error) { if m.FailUpdate { return nil, errors.New("mock update error") } if profile, ok := m.profiles[uuid]; ok { if name != nil { profile.Name = *name } if skinID != nil { profile.SkinID = skinID } if capeID != nil { profile.CapeID = capeID } return profile, nil } return nil, errors.New("profile not found") } func (m *MockProfileService) Delete(uuid string, userID int64) error { if m.FailDelete { return errors.New("mock delete error") } delete(m.profiles, uuid) return nil } func (m *MockProfileService) SetActive(uuid string, userID int64) error { return nil } func (m *MockProfileService) CheckLimit(userID int64, maxProfiles int) error { count := 0 for _, profile := range m.profiles { if profile.UserID == userID { count++ } } if count >= maxProfiles { return errors.New("达到档案数量上限") } return nil } func (m *MockProfileService) GetByNames(names []string) ([]*model.Profile, error) { var result []*model.Profile for _, name := range names { for _, profile := range m.profiles { if profile.Name == name { result = append(result, profile) } } } return result, nil } func (m *MockProfileService) GetByProfileName(name string) (*model.Profile, error) { for _, profile := range m.profiles { if profile.Name == name { return profile, nil } } return nil, errors.New("profile not found") } // MockTextureService 模拟TextureService type MockTextureService struct { textures map[int64]*model.Texture nextID int64 FailCreate bool FailGet bool FailUpdate bool FailDelete bool } func NewMockTextureService() *MockTextureService { return &MockTextureService{ textures: make(map[int64]*model.Texture), nextID: 1, } } func (m *MockTextureService) Create(uploaderID int64, name, description, textureType, url, hash string, size int, isPublic, isSlim bool) (*model.Texture, error) { if m.FailCreate { return nil, errors.New("mock create error") } texture := &model.Texture{ ID: m.nextID, UploaderID: uploaderID, Name: name, Description: description, URL: url, Hash: hash, Size: size, IsPublic: isPublic, IsSlim: isSlim, } m.textures[texture.ID] = texture m.nextID++ return texture, nil } func (m *MockTextureService) GetByID(id int64) (*model.Texture, error) { if m.FailGet { return nil, errors.New("mock get error") } if texture, ok := m.textures[id]; ok { return texture, nil } return nil, errors.New("texture not found") } func (m *MockTextureService) GetByUserID(uploaderID int64, page, pageSize int) ([]*model.Texture, int64, error) { if m.FailGet { return nil, 0, errors.New("mock get error") } var result []*model.Texture for _, texture := range m.textures { if texture.UploaderID == uploaderID { result = append(result, texture) } } return result, int64(len(result)), nil } func (m *MockTextureService) Search(keyword string, textureType model.TextureType, publicOnly bool, page, pageSize int) ([]*model.Texture, int64, error) { if m.FailGet { return nil, 0, errors.New("mock get error") } var result []*model.Texture for _, texture := range m.textures { if publicOnly && !texture.IsPublic { continue } result = append(result, texture) } return result, int64(len(result)), nil } func (m *MockTextureService) Update(textureID, uploaderID int64, name, description string, isPublic *bool) (*model.Texture, error) { if m.FailUpdate { return nil, errors.New("mock update error") } if texture, ok := m.textures[textureID]; ok { if name != "" { texture.Name = name } if description != "" { texture.Description = description } if isPublic != nil { texture.IsPublic = *isPublic } return texture, nil } return nil, errors.New("texture not found") } func (m *MockTextureService) Delete(textureID, uploaderID int64) error { if m.FailDelete { return errors.New("mock delete error") } delete(m.textures, textureID) return nil } func (m *MockTextureService) ToggleFavorite(userID, textureID int64) (bool, error) { return true, nil } func (m *MockTextureService) GetUserFavorites(userID int64, page, pageSize int) ([]*model.Texture, int64, error) { return nil, 0, nil } func (m *MockTextureService) CheckUploadLimit(uploaderID int64, maxTextures int) error { count := 0 for _, texture := range m.textures { if texture.UploaderID == uploaderID { count++ } } if count >= maxTextures { return errors.New("达到材质数量上限") } return nil } // MockTokenService 模拟TokenService type MockTokenService struct { tokens map[string]*model.Token FailCreate bool FailValidate bool FailRefresh bool } func NewMockTokenService() *MockTokenService { return &MockTokenService{ tokens: make(map[string]*model.Token), } } func (m *MockTokenService) Create(userID int64, uuid, clientToken string) (*model.Profile, []*model.Profile, string, string, error) { if m.FailCreate { return nil, nil, "", "", errors.New("mock create error") } accessToken := "mock-access-token" if clientToken == "" { clientToken = "mock-client-token" } token := &model.Token{ AccessToken: accessToken, ClientToken: clientToken, UserID: userID, ProfileId: uuid, Usable: true, } m.tokens[accessToken] = token return nil, nil, accessToken, clientToken, nil } func (m *MockTokenService) Validate(accessToken, clientToken string) bool { if m.FailValidate { return false } if token, ok := m.tokens[accessToken]; ok { if clientToken == "" || token.ClientToken == clientToken { return token.Usable } } return false } func (m *MockTokenService) Refresh(accessToken, clientToken, selectedProfileID string) (string, string, error) { if m.FailRefresh { return "", "", errors.New("mock refresh error") } return "new-access-token", clientToken, nil } func (m *MockTokenService) Invalidate(accessToken string) { delete(m.tokens, accessToken) } func (m *MockTokenService) InvalidateUserTokens(userID int64) { for key, token := range m.tokens { if token.UserID == userID { delete(m.tokens, key) } } } func (m *MockTokenService) GetUUIDByAccessToken(accessToken string) (string, error) { if token, ok := m.tokens[accessToken]; ok { return token.ProfileId, nil } return "", errors.New("token not found") } func (m *MockTokenService) GetUserIDByAccessToken(accessToken string) (int64, error) { if token, ok := m.tokens[accessToken]; ok { return token.UserID, nil } return 0, errors.New("token not found") }