diff --git a/resource/static/.gitignore b/resource/static/.gitignore deleted file mode 100644 index c96a04f..0000000 --- a/resource/static/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/resource/static/fonts/Vera.ttf b/resource/static/fonts/Vera.ttf new file mode 100644 index 0000000..58cd6b5 Binary files /dev/null and b/resource/static/fonts/Vera.ttf differ diff --git a/upload.zip b/upload.zip new file mode 100644 index 0000000..5a0b541 Binary files /dev/null and b/upload.zip differ diff --git a/utility/config/config_test.go b/utility/config/config_test.go deleted file mode 100644 index 612cc42..0000000 --- a/utility/config/config_test.go +++ /dev/null @@ -1,125 +0,0 @@ -package config - -import ( - "context" - "os" - "testing" - - "github.com/gogf/gf/v2/os/gcfg" -) - -// fakeBase 模拟文件适配器,返回固定配置树 -type fakeBase struct { - data map[string]any -} - -func (f *fakeBase) Available(ctx context.Context, resource ...string) bool { return true } - -func (f *fakeBase) Get(ctx context.Context, pattern string) (any, error) { - if pattern == "" || pattern == "." { - return f.data, nil - } - var cur any = f.data - for _, part := range splitPattern(pattern) { - m, ok := cur.(map[string]any) - if !ok { - return nil, nil - } - cur = m[part] - } - return cur, nil -} - -func (f *fakeBase) Data(ctx context.Context) (map[string]any, error) { return f.data, nil } - -func splitPattern(pattern string) []string { - var parts []string - start := 0 - for i := 0; i < len(pattern); i++ { - if pattern[i] == '.' { - parts = append(parts, pattern[start:i]) - start = i + 1 - } - } - return append(parts, pattern[start:]) -} - -// TestAdapterEnvFirst 覆盖优先级核心行为: -// - 设置 GF_ 环境变量 → 覆盖文件值(含 map 整节点逐叶叠加) -// - 未设置 → 回落文件值 -// - 空值环境变量 → 视为未设置,不清空文件值 -func TestAdapterEnvFirst(t *testing.T) { - ctx := context.Background() - base := &fakeBase{data: map[string]any{ - "database": map[string]any{ - "default": map[string]any{ - "type": "mysql", - "link": "file-link", - }, - }, - "jwt": map[string]any{"secret": "file-secret"}, - }} - a := &adapterEnvFirst{base: base} - - // 1. 未设置环境变量:文件值原样返回 - if v, _ := a.Get(ctx, "database.default.link"); v != "file-link" { - t.Fatalf("未设环境变量时应返回文件值,得到: %v", v) - } - - // 2. 标量覆盖 - os.Setenv("GF_JWT_SECRET", "env-secret") - defer os.Unsetenv("GF_JWT_SECRET") - if v, _ := a.Get(ctx, "jwt.secret"); v != "env-secret" { - t.Fatalf("环境变量应覆盖文件值,得到: %v", v) - } - - // 3. map 整节点逐叶叠加(gdb 读 database 整节点的场景) - os.Setenv("GF_DATABASE_DEFAULT_LINK", "env-link") - defer os.Unsetenv("GF_DATABASE_DEFAULT_LINK") - v, _ := a.Get(ctx, "database") - m, ok := v.(map[string]any) - if !ok { - t.Fatalf("database 节点应返回 map,得到: %T", v) - } - def := m["default"].(map[string]any) - if def["link"] != "env-link" { - t.Fatalf("整节点读取时 link 应被环境变量覆盖,得到: %v", def["link"]) - } - if def["type"] != "mysql" { - t.Fatalf("未覆盖的键应保持文件值,得到: %v", def["type"]) - } - - // 4. 空值环境变量视为未设置(不清空文件值) - os.Setenv("GF_DATABASE_DEFAULT_TYPE", "") - defer os.Unsetenv("GF_DATABASE_DEFAULT_TYPE") - if v, _ := a.Get(ctx, "database.default.type"); v != "mysql" { - t.Fatalf("空环境变量应视为未设置,得到: %v", v) - } - - // 5. Data 全量叠加 - data, _ := a.Data(ctx) - defData := data["database"].(map[string]any)["default"].(map[string]any) - if defData["link"] != "env-link" { - t.Fatalf("Data 应叠加环境变量覆盖,得到: %v", defData["link"]) - } -} - -// TestRegisterEnvOverride 注册后 g.Cfg() 读取链路获得覆盖能力 -func TestRegisterEnvOverride(t *testing.T) { - adapter, err := gcfg.NewAdapterContent(`database: - default: - link: file-link -`) - if err != nil { - t.Fatalf("构造内容适配器失败: %v", err) - } - gcfg.Instance().SetAdapter(adapter) - RegisterEnvOverride() - ctx := context.Background() - - os.Setenv("GF_DATABASE_DEFAULT_LINK", "env-link") - defer os.Unsetenv("GF_DATABASE_DEFAULT_LINK") - if v := gcfg.Instance().MustGet(ctx, "database.default.link").String(); v != "env-link" { - t.Fatalf("注册后 g.Cfg 读取应获得环境变量覆盖,得到: %v", v) - } -}