- PanelUpdateInfo 增 displayCurrentVersion/displayLatestVersion/ displayUpdateAvailable:V 系按个位进位段比较,大于当前才算新版; 原 currentVersion/latestVersion/updateAvailable 语义不动(节点页 与传统节点继续用) - 稳定渠道自更新改 Go 原生路径:查最新 tag→按架构下载发行资产→ sha256 旁车校验→原子换名(旧二进制留 .bak)→写既有状态文件 (与 update.sh 同形状,前端轮询协议不变)→脱离进程 systemctl restart 本单元(单元名 XUI_SERVICE_NAME 覆盖 / /proc/self/cgroup 解析 / 回退 x-ui);dev 渠道保留 update.sh 原路径 - 仅 systemd 环境启用(/run/systemd/system 存在或 XUI_SELFUPDATE_SYSTEMD=1 沙箱钩子),否则报错提示手动更新 - 单测:显示版本比较、cgroup 单元名解析、状态文件往返、systemd 门拦截
66 lines
2.2 KiB
Go
66 lines
2.2 KiB
Go
package panel
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// Item 20: the stable channel compares V-series display versions with
|
|
// the segment rule; the native self-update is systemd-gated and records
|
|
// its outcome in the shared update status file.
|
|
|
|
func TestDisplayUpdateFields(t *testing.T) {
|
|
// The test binary runs the default display version V1.0.0.
|
|
if disp, avail := displayUpdateFields("V1.0.1"); disp != "V1.0.1" || !avail {
|
|
t.Fatalf("V1.0.1 vs V1.0.0 = %q, %v; want V1.0.1, true", disp, avail)
|
|
}
|
|
if disp, avail := displayUpdateFields("V1.0.0"); disp != "V1.0.0" || avail {
|
|
t.Fatalf("V1.0.0 vs V1.0.0 = %q, %v; want V1.0.0, false", disp, avail)
|
|
}
|
|
if disp, avail := displayUpdateFields("3.7.0-agent.1"); disp != "" || avail {
|
|
t.Fatalf("legacy tag = %q, %v; want empty, false", disp, avail)
|
|
}
|
|
if _, avail := displayUpdateFields("V1.0.9"); !avail {
|
|
t.Fatal("V1.0.9 must be newer than V1.0.0")
|
|
}
|
|
}
|
|
|
|
func TestServiceUnitFromCgroup(t *testing.T) {
|
|
content := "0::/system.slice/x-ui.service\n"
|
|
if got := serviceUnitFromCgroup(content); got != "x-ui" {
|
|
t.Fatalf("unit = %q, want x-ui", got)
|
|
}
|
|
if got := serviceUnitFromCgroup("0::/user.slice/session-3.scope\n"); got != "" {
|
|
t.Fatalf("unit = %q, want empty", got)
|
|
}
|
|
if got := serviceUnitFromCgroup(""); got != "" {
|
|
t.Fatalf("unit = %q, want empty", got)
|
|
}
|
|
}
|
|
|
|
func TestNativeUpdateStatusRoundtrip(t *testing.T) {
|
|
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
|
writeUpdateStatus(424242, updateStateSuccess, 0)
|
|
st := (&PanelService{}).GetUpdateStatus()
|
|
if st.RunID != "424242" || st.State != updateStateSuccess || st.ExitCode != 0 {
|
|
t.Fatalf("status roundtrip = %+v", st)
|
|
}
|
|
writeUpdateStatus(424243, updateStateFailed, 1)
|
|
st = (&PanelService{}).GetUpdateStatus()
|
|
if st.RunID != "424243" || st.State != updateStateFailed || st.ExitCode != 1 {
|
|
t.Fatalf("status roundtrip = %+v", st)
|
|
}
|
|
}
|
|
|
|
func TestStartUpdateStableRequiresSystemd(t *testing.T) {
|
|
// Force the gate closed regardless of the host running the test.
|
|
orig := nativeSystemdAvailable
|
|
nativeSystemdAvailable = func() bool { return false }
|
|
t.Cleanup(func() { nativeSystemdAvailable = orig })
|
|
|
|
_, err := (&PanelService{}).startNativeUpdate()
|
|
if err == nil || !strings.Contains(err.Error(), "systemd") {
|
|
t.Fatalf("want systemd gate error, got %v", err)
|
|
}
|
|
}
|