141 lines
4.6 KiB
Go
141 lines
4.6 KiB
Go
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)
|
||
}
|
||
}
|