Files
HomeAgent/cmd/homed-upgrade/main_test.go
JianFeeeee 02022bc13d feat(ota): kernelupgrade 抽成独立包 + 插件仓库迁移脚本
## 1. internal/kernelupgrade:抽包(避免两份实现漂移)

原来 641 行全在 cmd/homed-upgrade 的 main 包里。内核侧的 kernel_update
工具要复用同一套逻辑,而 main 包不可被 import —— 照抄一份的后果是
"CLI 能升级、agent 调用却把机器搞坏"。

导出:ReadBinVersion / CompareVersions / ParseSemver / CmpSemver /
ProbePluginCompat / ExtractPkg / FindFile / DoUpgrade / WaitHealthy 等。
CLI 变薄壳(只留 flag 解析与 fail 输出)。

★ 顺带修一个真实 bug(判据抓到):ParseSemver 原来只挡 len<2,
于是 "1.4" 漏过去、缺失的 patch 被零值填成 1.4.0 —— 会让
「1.4 → 1.4.0」被判成完全相同(进而说"无需升级"),而两者内容未必相同。
现在要求恰好三段。

## 2. scripts/migrate-plugins-to-org.sh:插件迁成独立仓库

为什么迁:插件散在 SDK 仓 example/ 下有三个问题 ——
  ① 插件版本与 SDK 版本绑死(一次 SDK 发版把所有插件都带上)
  ② 插件作者不能单独为自己的插件发版
  ③ plugin_update 需要"仓库地址 → 拉源码 → 编译",而 example/ 是
     别人的仓库,不是插件自己的仓库

脚本纪律:
· 默认 --dry-run,不碰 GitHub
· 产物不入库(dist/build/rawfile/node_modules/*.hmap 全排除)——
  实测源码 3MB、产物 1.9G,后者进了仓库就再也删不干净
· 幂等:仓库已存在(422)则跳过创建,重跑安全
· 自动给 plg.json 补 repo 字段,使 plugin_update 能定位仓库
· 用 tar 管道而非 rsync:后者在最小化系统里常常没有(本机实测就没有)

执行结果:26 个插件全部迁移(25 Go + 1 Lua),仓库名与插件名同名。
2026-10-26 00:06:59 +08:00

114 lines
4.3 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 main
import (
"strings"
"testing"
"github.com/JianFeeeee/HologramAgent/internal/kernelupgrade"
)
// ── 版本比较的判据 ────────────────────────────────────────────
//
// 这些是 OTA 敢不敢按 -apply 的依据。判错一次就可能把新版换成旧版,
// 或让"内容其实没变"被当成升级成功。
func TestCompareVersions(t *testing.T) {
cases := []struct {
name string
cur *kernelupgrade.BinVersion
nv *kernelupgrade.BinVersion
wantSub string // 结论文案必须包含的片段
}{
{
name: "正常升级",
cur: &kernelupgrade.BinVersion{Version: "1.3.0", Commit: "aaa"},
nv: &kernelupgrade.BinVersion{Version: "1.4.0", Commit: "bbb"},
wantSub: "可升级",
},
{
name: "降级必须显式警告",
cur: &kernelupgrade.BinVersion{Version: "1.4.0", Commit: "aaa"},
nv: &kernelupgrade.BinVersion{Version: "1.3.0", Commit: "bbb"},
wantSub: "降级",
},
{
name: "同版本同 commit = 无需升级",
cur: &kernelupgrade.BinVersion{Version: "1.4.0", Commit: "aaa"},
nv: &kernelupgrade.BinVersion{Version: "1.4.0", Commit: "aaa"},
wantSub: "完全相同",
},
{
// ★ 这条最容易被忽略:版本号没变但内容变了(同版本重发)。
// 不报出来会让用户以为"升级了其实没升"或反之。
name: "同版本不同 commit 必须点明",
cur: &kernelupgrade.BinVersion{Version: "1.4.0", Commit: "aaa"},
nv: &kernelupgrade.BinVersion{Version: "1.4.0", Commit: "bbb"},
wantSub: "同版本重发",
},
{
// 非标准形态(1.4.0dev):走字符串回退,不能说"降级"
name: "非标准版本号走字符串比较",
cur: &kernelupgrade.BinVersion{Version: "1.4.0", Commit: "aaa"},
nv: &kernelupgrade.BinVersion{Version: "1.4.0dev", Commit: "bbb"},
wantSub: "commit 不同",
},
}
for _, c := range cases {
got := kernelupgrade.CompareVersions(c.cur, c.nv)
if !strings.Contains(got, c.wantSub) {
t.Errorf("%s: 结论应含 %q,实际 %q", c.name, c.wantSub, got)
}
}
}
// 判据:读不到当前版本时**不能**阻断(第一次升级必然撞到)。
//
// 这是实测踩到的:线上内核是加 --version 之前的版本,第一次探测必然失败。
// 若此时直接退出,所有用户第一次升级都要人工介入。
func TestCompareVersions_UnknownCurrentDoesNotBlock(t *testing.T) {
got := kernelupgrade.CompareVersions(nil, &kernelupgrade.BinVersion{Version: "1.4.0", Commit: "bbb"})
if strings.Contains(got, "❌") {
t.Errorf("当前版本未知不应判失败,实际: %s", got)
}
if !strings.Contains(got, "跳过比较") {
t.Errorf("应说明跳过比较,实际: %s", got)
}
}
// ── 版本解析 ─────────────────────────────────────────────────
func TestParseSemver(t *testing.T) {
// 只测**可观察行为**(返回 nil 与否),不探私有字段 ——
// 跨包断言内部字段会把重构锁死,而"解析对不对"最终要由
// CompareVersions 的行为体现(上面那组用例已覆盖)。
if kernelupgrade.ParseSemver("1.4.0") == nil {
t.Error("1.4.0 应能解析")
}
// dev 后缀不算正式语义版本(否则 1.4.0dev 会被当成 1.4.0 比大小)
if v := kernelupgrade.ParseSemver("1.4.0dev"); v != nil {
t.Errorf("1.4.0dev 应回退字符串比较,实际解析成 %+v", v)
}
// 不完整串同样不算
for _, bad := range []string{"", "1", "1.4", "v1.4.0", "1.4.x"} {
if v := kernelupgrade.ParseSemver(bad); v != nil {
t.Errorf("%q 不应被解析成语义版本,实际 %+v", bad, v)
}
}
}
// ── waiter 兜底解析 ──────────────────────────────────────────
func TestFirstSemverLike(t *testing.T) {
// waiter 的真实输出形态
line := "waiter 1.4.0 (commit 98850e1, built 2026-10-17T09:20:25Z)"
if got := kernelupgrade.FirstSemverLike(line); got != "1.4.0" {
t.Errorf("应从 waiter 输出取到 1.4.0,实际 %q", got)
}
// 不能把日期当版本号
if got := kernelupgrade.FirstSemverLike("built 2026-10-17"); got != "" {
t.Errorf("日期不应被识别为版本号,实际 %q", got)
}
}