Scert/backend/internal/cli/root_test.go

141 lines
4.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package cli
import (
"bytes"
"context"
"errors"
"os"
"path/filepath"
"strings"
"testing"
"git.pcux.cn/xuans/Scert/backend/internal/buildinfo"
"git.pcux.cn/xuans/Scert/backend/internal/config"
"git.pcux.cn/xuans/Scert/backend/internal/firewall"
)
type cliFakeFirewallManager struct {
result firewall.Result
openErr error
rollbackErr error
openedPort int
rollbackCall bool
}
func (f *cliFakeFirewallManager) OpenTCP(_ context.Context, port int) (firewall.Result, error) {
f.openedPort = port
if f.result.Port == 0 {
f.result.Port = port
}
return f.result, f.openErr
}
func (f *cliFakeFirewallManager) Rollback(_ context.Context, _ firewall.Result) error {
f.rollbackCall = true
return f.rollbackErr
}
func TestHelpIsLocalizedAndHasNoDuplicateCommands(t *testing.T) {
configPath = ""
baseDir = ""
root := newRootCommand()
var output bytes.Buffer
root.SetOut(&output)
root.SetErr(&output)
root.SetArgs([]string{"help"})
if err := root.Execute(); err != nil {
t.Fatalf("执行帮助命令失败:%v", err)
}
text := output.String()
for _, expected := range []string{"用法:", "可用命令:", "参数:"} {
if !strings.Contains(text, expected) {
t.Fatalf("帮助缺少中文标题 %q:%s", expected, text)
}
}
for _, unexpected := range []string{"Available Commands:", "Usage:", "Flags:", "completion"} {
if strings.Contains(text, unexpected) {
t.Fatalf("帮助仍包含未本地化或禁用内容 %q:%s", unexpected, text)
}
}
if strings.Count(text, "\n help ") != 1 {
t.Fatalf("help 命令数量不正确:%s", text)
}
}
func TestHelpSupportsSubcommand(t *testing.T) {
root := newRootCommand()
var output bytes.Buffer
root.SetOut(&output)
root.SetErr(&output)
root.SetArgs([]string{"help", "domain"})
if err := root.Execute(); err != nil {
t.Fatalf("查看子命令帮助失败:%v", err)
}
text := output.String()
if !strings.Contains(text, "管理托管域名") || !strings.Contains(text, "添加托管域名") {
t.Fatalf("子命令帮助内容不正确:%s", text)
}
}
func TestCommandStatusUsesApplicationVersion(t *testing.T) {
cfg := config.Default(t.TempDir())
status := commandStatus(cfg)
if status["version"] != buildinfo.Version || status["config_version"] != config.CurrentVersion {
t.Fatalf("状态版本字段不正确:%+v", status)
}
}
func TestSaveSetupWithFirewallOpensOnlyMainPort(t *testing.T) {
cfg := config.Default(t.TempDir())
cfg.Server.Port = 8443
cfg.Admin.ResetServicePort = 8091
manager := &cliFakeFirewallManager{result: firewall.Result{
Backend: "windows", RuleName: "Scert Web TCP 8443", Created: true, Message: "已创建测试规则",
}}
path := filepath.Join(t.TempDir(), "config", "scert.json")
result, err := saveSetupWithFirewall(context.Background(), cfg, path, manager)
if err != nil {
t.Fatalf("保存初始化配置失败:%v", err)
}
if manager.openedPort != 8443 || manager.rollbackCall || !result.Created {
t.Fatalf("CLI 防火墙事务不正确:port=%d rollback=%t result=%+v", manager.openedPort, manager.rollbackCall, result)
}
if _, err := os.Stat(path); err != nil {
t.Fatalf("初始化配置未保存:%v", err)
}
}
func TestSaveSetupWithFirewallRollsBackNewRuleOnSaveFailure(t *testing.T) {
baseDir := t.TempDir()
blockedParent := filepath.Join(baseDir, "blocked")
if err := os.WriteFile(blockedParent, []byte("占位"), 0o600); err != nil {
t.Fatalf("创建阻塞路径失败:%v", err)
}
manager := &cliFakeFirewallManager{result: firewall.Result{
Backend: "ufw", RuleName: "Scert Web TCP 8080", Port: 8080, Created: true,
}}
_, err := saveSetupWithFirewall(context.Background(), config.Default(baseDir), filepath.Join(blockedParent, "scert.json"), manager)
if err == nil {
t.Fatal("配置保存失败应返回错误")
}
if !manager.rollbackCall {
t.Fatal("配置保存失败时应回滚本次新建的防火墙规则")
}
}
func TestSaveSetupWithFirewallReportsRollbackFailure(t *testing.T) {
baseDir := t.TempDir()
blockedParent := filepath.Join(baseDir, "blocked")
if err := os.WriteFile(blockedParent, []byte("占位"), 0o600); err != nil {
t.Fatalf("创建阻塞路径失败:%v", err)
}
manager := &cliFakeFirewallManager{
result: firewall.Result{Backend: "ufw", RuleName: "Scert Web TCP 8080", Port: 8080, Created: true},
rollbackErr: errors.New("rollback denied"),
}
_, err := saveSetupWithFirewall(context.Background(), config.Default(baseDir), filepath.Join(blockedParent, "scert.json"), manager)
if err == nil || !strings.Contains(err.Error(), "手动检查本机防火墙") {
t.Fatalf("防火墙回滚失败应返回明确错误:%v", err)
}
}