重置项目上下文与规范文档

This commit is contained in:
2026-08-07 16:18:07 +08:00
parent 6611ca5226
commit 79e2d9ff92
1900 changed files with 1552 additions and 348365 deletions

View File

@@ -1,115 +0,0 @@
package systemconfig_test
import (
"context"
stderrors "errors"
"sync"
"testing"
"time"
"github.com/break/junhong_cmp_fiber/internal/infrastructure/systemconfig"
"github.com/break/junhong_cmp_fiber/internal/model"
"github.com/break/junhong_cmp_fiber/internal/testutil"
"github.com/break/junhong_cmp_fiber/pkg/constants"
)
type unavailableCache struct{}
func (unavailableCache) Get(context.Context, string) (string, error) {
return "", stderrors.New("测试缓存不可用")
}
func (unavailableCache) Set(context.Context, string, string, time.Duration) error {
return stderrors.New("测试缓存不可用")
}
func (unavailableCache) Delete(context.Context, string) error {
return stderrors.New("测试缓存不可用")
}
type alertRecorder struct {
mu sync.Mutex
codes []string
}
func (r *alertRecorder) Warn(_ context.Context, code, _, _, _ string) {
r.mu.Lock()
defer r.mu.Unlock()
r.codes = append(r.codes, code)
}
func TestReaderUsesRedisHitAndFallsBackToPostgresOnMiss(t *testing.T) {
db := testutil.NewPostgresTransaction(t)
redisClient := testutil.NewRedisClient(t)
testutil.CreateTemporarySystemConfigTable(t, db)
registry := systemconfig.NewRegistry()
definition := systemconfig.Definition{
Key: "foundation.reader.limit", Module: "foundation", ValueType: constants.SystemConfigTypeInt,
DefaultValue: "10", Description: "读取器测试上限",
}
if err := registry.Register(definition); err != nil {
t.Fatalf("注册系统配置失败:%v", err)
}
if err := db.Create(&model.SystemConfig{
ConfigKey: definition.Key, ConfigValue: "20", ValueType: definition.ValueType,
Module: definition.Module, Description: definition.Description,
}).Error; err != nil {
t.Fatalf("准备数据库配置失败:%v", err)
}
cacheKey := constants.RedisSystemConfigKey(definition.Key)
t.Cleanup(func() { _ = redisClient.Del(context.Background(), cacheKey).Err() })
if err := redisClient.Set(context.Background(), cacheKey, "30", constants.SystemConfigCacheTTL).Err(); err != nil {
t.Fatalf("准备 Redis 缓存失败:%v", err)
}
reader := systemconfig.NewReader(db, registry, systemconfig.NewRedisCache(redisClient), nil)
value, err := reader.Get(context.Background(), definition.Key)
if err != nil || value != "30" {
t.Fatalf("Redis 命中结果错误:值=%q错误=%v", value, err)
}
if err := redisClient.Del(context.Background(), cacheKey).Err(); err != nil {
t.Fatalf("清理 Redis 缓存失败:%v", err)
}
value, err = reader.Get(context.Background(), definition.Key)
if err != nil || value != "20" {
t.Fatalf("Redis 未命中时未回退 PostgreSQL值=%q错误=%v", value, err)
}
cached, err := redisClient.Get(context.Background(), cacheKey).Result()
if err != nil || cached != "20" {
t.Fatalf("PostgreSQL 结果未回填 Redis值=%q错误=%v", cached, err)
}
ttl, err := redisClient.TTL(context.Background(), cacheKey).Result()
if err != nil || ttl <= 0 || ttl > constants.SystemConfigCacheTTL {
t.Fatalf("Redis 回填 TTL 不符合公共常量TTL=%s错误=%v", ttl, err)
}
}
func TestReaderFallsBackToPostgresWhenCacheIsUnavailable(t *testing.T) {
db := testutil.NewPostgresTransaction(t)
testutil.CreateTemporarySystemConfigTable(t, db)
registry := systemconfig.NewRegistry()
definition := systemconfig.Definition{
Key: "foundation.reader.fallback", Module: "foundation", ValueType: constants.SystemConfigTypeString,
DefaultValue: "default", Description: "缓存故障回退测试值",
}
if err := registry.Register(definition); err != nil {
t.Fatalf("注册系统配置失败:%v", err)
}
if err := db.Create(&model.SystemConfig{
ConfigKey: definition.Key, ConfigValue: "database", ValueType: definition.ValueType,
Module: definition.Module, Description: definition.Description,
}).Error; err != nil {
t.Fatalf("准备数据库配置失败:%v", err)
}
alerts := &alertRecorder{}
reader := systemconfig.NewReader(db, registry, unavailableCache{}, alerts)
value, err := reader.Get(context.Background(), definition.Key)
if err != nil || value != "database" {
t.Fatalf("缓存不可用时未回退 PostgreSQL值=%q错误=%v", value, err)
}
alerts.mu.Lock()
defer alerts.mu.Unlock()
if len(alerts.codes) < 2 || alerts.codes[0] != "SYSTEM_CONFIG_CACHE_READ_FAILED" {
t.Fatalf("缓存读写故障未产生安全告警:%v", alerts.codes)
}
}

View File

@@ -1,61 +0,0 @@
package systemconfig_test
import (
"testing"
"github.com/break/junhong_cmp_fiber/internal/infrastructure/systemconfig"
"github.com/break/junhong_cmp_fiber/pkg/constants"
)
func TestRegistryRejectsDuplicateTypeConflictAndInvalidDefault(t *testing.T) {
t.Parallel()
registry := systemconfig.NewRegistry()
definition := systemconfig.Definition{
Key: "foundation.example.limit", Module: "foundation", ValueType: constants.SystemConfigTypeInt,
DefaultValue: "10", Description: "示例限制",
}
if err := registry.Register(definition); err != nil {
t.Fatalf("注册合法配置失败:%v", err)
}
if err := registry.Register(definition); err == nil {
t.Fatal("重复 Key 必须被拒绝")
}
conflict := definition
conflict.ValueType = constants.SystemConfigTypeString
if err := registry.Register(conflict); err == nil {
t.Fatal("同 Key 类型冲突必须被拒绝")
}
invalid := definition
invalid.Key = "foundation.example.invalid"
invalid.DefaultValue = "not-int"
if err := registry.Register(invalid); err == nil {
t.Fatal("非法默认值必须在注册阶段失败")
}
}
func TestValidateValueSupportsFourControlledTypesAndBounds(t *testing.T) {
t.Parallel()
minimum, maximum := int64(1), int64(10)
cases := []systemconfig.Definition{
{Key: "a.b.string", Module: "a", ValueType: constants.SystemConfigTypeString, DefaultValue: "x", Description: "字符串"},
{Key: "a.b.int", Module: "a", ValueType: constants.SystemConfigTypeInt, DefaultValue: "5", Description: "整数", Min: &minimum, Max: &maximum},
{Key: "a.b.bool", Module: "a", ValueType: constants.SystemConfigTypeBool, DefaultValue: "true", Description: "布尔"},
{Key: "a.b.json", Module: "a", ValueType: constants.SystemConfigTypeJSON, DefaultValue: `{"enabled":true}`, Description: "JSON"},
}
for _, definition := range cases {
if err := systemconfig.ValidateValue(definition, definition.DefaultValue); err != nil {
t.Fatalf("合法 %s 值未通过:%v", definition.ValueType, err)
}
}
if err := systemconfig.ValidateValue(cases[1], "11"); err == nil {
t.Fatal("越界整数必须被拒绝")
}
if err := systemconfig.ValidateValue(cases[2], "yes"); err == nil {
t.Fatal("非法布尔值必须被拒绝")
}
if err := systemconfig.ValidateValue(cases[3], "{"); err == nil {
t.Fatal("非法 JSON 必须被拒绝")
}
}