package cli import ( "context" "errors" "os" "path/filepath" "testing" "git.pcux.cn/xuans/Scert/backend/internal/config" ) func TestLoadServeConfigFailsClosed(t *testing.T) { root := t.TempDir() path := filepath.Join(root, "conf", "scert.json") defaults := config.Default(root) cfg, err := loadServeConfig(path, defaults) if err != nil || cfg.SetupReady || cfg.Paths.Config != filepath.Dir(path) { t.Fatalf("缺失配置应进入初始化:%v", err) } if _, err := os.Stat(path); !os.IsNotExist(err) { t.Fatal("仅加载不应保存默认配置") } if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil { t.Fatal(err) } for _, data := range []string{"{", "null", "{}", `{"setup_ready":true}`, "[]", ""} { if err := os.WriteFile(path, []byte(data), 0o600); err != nil { t.Fatal(err) } if _, err := loadServeConfig(path, defaults); err == nil { t.Fatalf("损坏配置被降级成初始化:%q", data) } } if _, err := loadServeConfig(root, defaults); err == nil { t.Fatal("目录不应被视为缺失配置") } } func TestServeLifecycle(t *testing.T) { for _, name := range []string{"missing", "ready", "cancel", "bootstrap-error", "reload-error", "not-ready", "path-changed", "web-disabled", "bootstrap-web-disabled", "application-error"} { t.Run(name, func(t *testing.T) { cfg := config.Default(t.TempDir()) cfg.SetupReady = name == "ready" || name == "web-disabled" || name == "application-error" cfg.Web.Enabled = name != "web-disabled" ctx, cancel := context.WithCancel(context.Background()) defer cancel() bootstrapCalls, reloadCalls, appCalls := 0, 0, 0 err := serveLifecycle(ctx, cfg, func() (config.Config, error) { reloadCalls++ if name == "reload-error" { return config.Config{}, errors.New("test") } next := cfg next.SetupReady = name != "not-ready" if name == "bootstrap-web-disabled" { next.Web.Enabled = false } if name == "path-changed" { next.Paths.Data += "-changed" } return next, nil }, func(context.Context, config.Config) (bool, error) { bootstrapCalls++ if name == "bootstrap-error" { return false, errors.New("test") } if name == "cancel" { cancel() return false, nil } return true, nil }, func(_ context.Context, ready config.Config) (bool, error) { appCalls++ if !ready.SetupReady { t.Fatal("未初始化时构造业务应用") } if (name == "web-disabled" || name == "bootstrap-web-disabled") && ready.Web.Enabled { t.Fatal("关闭静态页面的配置不能被启动流程覆盖") } if name == "application-error" { return false, errors.New("test") } return false, nil }) wantError := name != "missing" && name != "ready" && name != "cancel" && name != "web-disabled" && name != "bootstrap-web-disabled" if (err != nil) != wantError { t.Fatalf("错误边界不符:%v", err) } wantApp := 0 if name == "missing" || name == "ready" || name == "application-error" || name == "web-disabled" || name == "bootstrap-web-disabled" { wantApp = 1 } if appCalls != wantApp { t.Fatalf("业务启动次数:%d", appCalls) } if cfg.SetupReady && (bootstrapCalls != 0 || reloadCalls != 0) { t.Fatal("已完成配置进入初始化") } if !cfg.SetupReady && bootstrapCalls != 1 { t.Fatal("初始化未运行一次") } }) } } func TestBootstrapFirewallModeFlagOverridesEnvironment(t *testing.T) { for _, test := range []struct { name string environment string flag string want string }{ {name: "environment", environment: "external", want: "external"}, {name: "flag", environment: "external", flag: "auto", want: "auto"}, {name: "external-flag", environment: "auto", flag: "external", want: "external"}, {name: "invalid-environment", environment: "invalid", want: "invalid"}, } { t.Run(test.name, func(t *testing.T) { t.Setenv("SCERT_BOOTSTRAP_FIREWALL_MODE", test.environment) command := newServeCommand() if test.flag != "" { if err := command.ParseFlags([]string{"--bootstrap-firewall-mode", test.flag}); err != nil { t.Fatal(err) } } value, err := command.Flags().GetString("bootstrap-firewall-mode") if err != nil { t.Fatal(err) } if got := bootstrapFirewallMode(command, value); got != test.want { t.Fatalf("本机策略优先级错误:得到 %q,期望 %q", got, test.want) } }) } }