|
|
@ -425,7 +425,7 @@ func TestEvalChannelUpgrade(t *testing.T) { |
|
|
} |
|
|
} |
|
|
for _, c := range cases { |
|
|
for _, c := range cases { |
|
|
t.Run(c.name, func(t *testing.T) { |
|
|
t.Run(c.name, func(t *testing.T) { |
|
|
need, force, reviewing := evalChannelUpgrade(c.cfg, c.client) |
|
|
need, force, reviewing := evalChannelUpgrade(c.cfg, nil, comm.ChannelChinaXiaomi, c.client, "https://dl/app.apk") |
|
|
if need != c.need || force != c.force || reviewing != c.reviewing { |
|
|
if need != c.need || force != c.force || reviewing != c.reviewing { |
|
|
t.Fatalf("client=%q 得到 need=%v force=%v reviewing=%v,期望 need=%v force=%v reviewing=%v", |
|
|
t.Fatalf("client=%q 得到 need=%v force=%v reviewing=%v,期望 need=%v force=%v reviewing=%v", |
|
|
c.client, need, force, reviewing, c.need, c.force, c.reviewing) |
|
|
c.client, need, force, reviewing, c.need, c.force, c.reviewing) |
|
|
@ -437,7 +437,7 @@ func TestEvalChannelUpgrade(t *testing.T) { |
|
|
// 运营把最低支持版本填得比线上版本还高时,不能出现「必须更新但没有更新可用」这种客户端无解的组合。
|
|
|
// 运营把最低支持版本填得比线上版本还高时,不能出现「必须更新但没有更新可用」这种客户端无解的组合。
|
|
|
func TestEvalChannelUpgradeForceImpliesNeed(t *testing.T) { |
|
|
func TestEvalChannelUpgradeForceImpliesNeed(t *testing.T) { |
|
|
cfg := &comm.AppRelease{Version: "1.0.0", MinVersion: "2.0.0", ForceUpdate: true} |
|
|
cfg := &comm.AppRelease{Version: "1.0.0", MinVersion: "2.0.0", ForceUpdate: true} |
|
|
need, force, _ := evalChannelUpgrade(cfg, "1.5.0") |
|
|
need, force, _ := evalChannelUpgrade(cfg, nil, comm.ChannelChinaXiaomi, "1.5.0", "https://dl/app.apk") |
|
|
if !force { |
|
|
if !force { |
|
|
t.Fatal("低于最低支持版本应强更") |
|
|
t.Fatal("低于最低支持版本应强更") |
|
|
} |
|
|
} |
|
|
@ -448,11 +448,42 @@ func TestEvalChannelUpgradeForceImpliesNeed(t *testing.T) { |
|
|
|
|
|
|
|
|
// 后台还没配发版信息时 model 层给的是 nil,这里确认 nil 不会 panic 也不会误判。
|
|
|
// 后台还没配发版信息时 model 层给的是 nil,这里确认 nil 不会 panic 也不会误判。
|
|
|
func TestEvalChannelUpgradeNilSafe(t *testing.T) { |
|
|
func TestEvalChannelUpgradeNilSafe(t *testing.T) { |
|
|
if need, force, reviewing := evalChannelUpgrade(nil, "1.0.0"); need || force || reviewing { |
|
|
if need, force, reviewing := evalChannelUpgrade(nil, nil, comm.ChannelChinaXiaomi, "1.0.0", "https://dl/app.apk"); need || force || reviewing { |
|
|
t.Fatal("nil 配置必须全 false") |
|
|
t.Fatal("nil 配置必须全 false") |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 2026-09-23 口径:版本号按平台分、渠道未上架不推、没地址不提示。每条都是线上会直接踩到的组合。
|
|
|
|
|
|
func TestEvalChannelUpgradePlatformStatusAddress(t *testing.T) { |
|
|
|
|
|
rel := &comm.AppRelease{Version: "1.0.3", IosVersion: "1.0.2", ForceUpdate: true} |
|
|
|
|
|
apk := "https://dl/app.apk" |
|
|
|
|
|
|
|
|
|
|
|
// iOS 渠道读 ios_version:Android 已发 1.0.3、iOS 商店还是 1.0.2 时,iOS 的 1.0.2 用户不该被提示
|
|
|
|
|
|
if need, _, _ := evalChannelUpgrade(rel, nil, comm.ChannelGlobalApple, "1.0.2", "https://apps.apple.com/x"); need { |
|
|
|
|
|
t.Fatal("iOS 客户端已是 iOS 线上版本,不该提示更新(不能拿 Android 的版本号判)") |
|
|
|
|
|
} |
|
|
|
|
|
if need, force, _ := evalChannelUpgrade(rel, nil, comm.ChannelChinaXiaomi, "1.0.2", apk); !need || !force { |
|
|
|
|
|
t.Fatal("Android 1.0.2 低于 Android 线上 1.0.3,且最低版本留空 = 线上版本,应强更") |
|
|
|
|
|
} |
|
|
|
|
|
// 最低版本留空 = 线上版本:填了最低版本后,介于两者之间的只推荐不强制
|
|
|
|
|
|
withMin := &comm.AppRelease{Version: "1.0.3", MinVersion: "1.0.1", ForceUpdate: true} |
|
|
|
|
|
if need, force, _ := evalChannelUpgrade(withMin, nil, comm.ChannelChinaXiaomi, "1.0.2", apk); !need || force { |
|
|
|
|
|
t.Fatal("高于最低版本、低于线上版本:只推荐不强制") |
|
|
|
|
|
} |
|
|
|
|
|
// 渠道审核中:商店里还是旧包,推荐更新不推;强更不受影响
|
|
|
|
|
|
reviewing := &comm.ChannelApp{Channel: comm.ChannelChinaXiaomi, Status: comm.ChannelStatusReviewing, Address: "https://xiaomi/store"} |
|
|
|
|
|
if need, _, _ := evalChannelUpgrade(withMin, reviewing, comm.ChannelChinaXiaomi, "1.0.2", apk); need { |
|
|
|
|
|
t.Fatal("渠道审核中时不该推送推荐更新") |
|
|
|
|
|
} |
|
|
|
|
|
if need, force, _ := evalChannelUpgrade(withMin, reviewing, comm.ChannelChinaXiaomi, "1.0.0", apk); !need || !force { |
|
|
|
|
|
t.Fatal("渠道审核中也挡不住强更(地址已由回退链换成官方包)") |
|
|
|
|
|
} |
|
|
|
|
|
// 没有任何可去的地址:两种更新都不提示,强更也不例外
|
|
|
|
|
|
if need, force, _ := evalChannelUpgrade(rel, nil, comm.ChannelChinaXiaomi, "1.0.0", ""); need || force { |
|
|
|
|
|
t.Fatal("没有下载地址时不该提示任何更新,否则弹出一个点了没反应又关不掉的框") |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
// ---------------------------------------------------------------------------
|
|
|
// ⑤ 老客户端兼容字段
|
|
|
// ⑤ 老客户端兼容字段
|
|
|
// ---------------------------------------------------------------------------
|
|
|
// ---------------------------------------------------------------------------
|
|
|
@ -838,7 +869,7 @@ func TestToPbChannelAppSurvivesMissingChannelRow(t *testing.T) { |
|
|
Address: "https://default/app.apk", |
|
|
Address: "https://default/app.apk", |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
got := toPbChannelApp(comm.ChannelChinaHonor, nil, rel, "1.0.1") |
|
|
got := toPbChannelApp(comm.ChannelChinaHonor, nil, rel, "1.0.1", "") |
|
|
if got == nil { |
|
|
if got == nil { |
|
|
t.Fatal("渠道行缺失但发版配置存在时必须照常下发,否则应用级开关会被渠道行卡死") |
|
|
t.Fatal("渠道行缺失但发版配置存在时必须照常下发,否则应用级开关会被渠道行卡死") |
|
|
} |
|
|
} |
|
|
@ -863,7 +894,7 @@ func TestToPbChannelAppSurvivesMissingRelease(t *testing.T) { |
|
|
Channel: comm.ChannelChinaXiaomi, Address: "https://xiaomi/store", |
|
|
Channel: comm.ChannelChinaXiaomi, Address: "https://xiaomi/store", |
|
|
PayChannels: "wxpay", AllowSkipDeviceBinding: true, Status: comm.ChannelStatusOnline, |
|
|
PayChannels: "wxpay", AllowSkipDeviceBinding: true, Status: comm.ChannelStatusOnline, |
|
|
} |
|
|
} |
|
|
got := toPbChannelApp(comm.ChannelChinaXiaomi, ch, nil, "1.0.1") |
|
|
got := toPbChannelApp(comm.ChannelChinaXiaomi, ch, nil, "1.0.1", "") |
|
|
if got == nil { |
|
|
if got == nil { |
|
|
t.Fatal("发版配置未配时仍应下发渠道信息") |
|
|
t.Fatal("发版配置未配时仍应下发渠道信息") |
|
|
} |
|
|
} |
|
|
@ -881,15 +912,44 @@ func TestToPbChannelAppSurvivesMissingRelease(t *testing.T) { |
|
|
// 渠道地址优先于应用默认地址:各商店链接不同,一套地址会把用户引到别家商店。
|
|
|
// 渠道地址优先于应用默认地址:各商店链接不同,一套地址会把用户引到别家商店。
|
|
|
func TestToPbChannelAppAddressPrecedence(t *testing.T) { |
|
|
func TestToPbChannelAppAddressPrecedence(t *testing.T) { |
|
|
rel := &comm.AppRelease{Address: "https://default/app.apk"} |
|
|
rel := &comm.AppRelease{Address: "https://default/app.apk"} |
|
|
ch := &comm.ChannelApp{Channel: comm.ChannelChinaHuawei, Address: "https://huawei/store"} |
|
|
ch := &comm.ChannelApp{Channel: comm.ChannelChinaHuawei, Address: "https://huawei/store", Status: comm.ChannelStatusOnline} |
|
|
if got := toPbChannelApp(comm.ChannelChinaHuawei, ch, rel, "1.0.1"); got.Address != "https://huawei/store" { |
|
|
if got := toPbChannelApp(comm.ChannelChinaHuawei, ch, rel, "1.0.1", "https://official/app.apk"); got.Address != "https://huawei/store" { |
|
|
t.Fatalf("渠道地址应覆盖应用默认地址,实际 %q", got.Address) |
|
|
t.Fatalf("渠道地址应覆盖官方渠道与应用默认地址,实际 %q", got.Address) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 回退链(2026-09-23):Android 渠道 → 官方渠道(100) → 默认地址;未上架的渠道地址视同没有;iOS 只认自己的商店链接。
|
|
|
|
|
|
func TestToPbChannelAppAddressFallbackChain(t *testing.T) { |
|
|
|
|
|
rel := &comm.AppRelease{Address: "https://default/app.apk", Version: "1.0.3", IosVersion: "1.0.2", MinVersion: "1.0.1"} |
|
|
|
|
|
// 渠道没填地址 → 官方渠道
|
|
|
|
|
|
if got := toPbChannelApp(comm.ChannelChinaXiaomi, nil, rel, "1.0.1", "https://official/app.apk"); got.Address != "https://official/app.apk" { |
|
|
|
|
|
t.Fatalf("渠道缺失时应先回退官方渠道地址,实际 %q", got.Address) |
|
|
|
|
|
} |
|
|
|
|
|
// 官方渠道也没有 → 默认地址
|
|
|
|
|
|
if got := toPbChannelApp(comm.ChannelChinaXiaomi, nil, rel, "1.0.1", ""); got.Address != "https://default/app.apk" { |
|
|
|
|
|
t.Fatalf("官方渠道也没有时应回退默认地址,实际 %q", got.Address) |
|
|
|
|
|
} |
|
|
|
|
|
// 渠道审核中:它的商店链接视同没有
|
|
|
|
|
|
reviewing := &comm.ChannelApp{Channel: comm.ChannelChinaXiaomi, Address: "https://xiaomi/store", Status: comm.ChannelStatusReviewing} |
|
|
|
|
|
if got := toPbChannelApp(comm.ChannelChinaXiaomi, reviewing, rel, "1.0.1", "https://official/app.apk"); got.Address != "https://official/app.apk" { |
|
|
|
|
|
t.Fatalf("渠道未上架时不该用它的地址,实际 %q", got.Address) |
|
|
|
|
|
} |
|
|
|
|
|
// iOS:没填 App Store 链接就是空,绝不能回退到 apk
|
|
|
|
|
|
if got := toPbChannelApp(comm.ChannelGlobalApple, nil, rel, "1.0.1", "https://official/app.apk"); got.Address != "" { |
|
|
|
|
|
t.Fatalf("iOS 没有商店链接时地址必须为空,实际 %q", got.Address) |
|
|
|
|
|
} |
|
|
|
|
|
// iOS 的版本号来自 ios_version / ios_min_version(留空 = 线上版本)
|
|
|
|
|
|
if got := toPbChannelApp(comm.ChannelGlobalApple, nil, rel, "1.0.1", ""); got.Version != "1.0.2" || got.Minversion != "1.0.2" { |
|
|
|
|
|
t.Fatalf("iOS 渠道应下发 iOS 那套版本号,实际 version=%q min=%q", got.Version, got.Minversion) |
|
|
|
|
|
} |
|
|
|
|
|
if got := toPbChannelApp(comm.ChannelChinaXiaomi, nil, rel, "1.0.1", ""); got.Version != "1.0.3" || got.Minversion != "1.0.1" { |
|
|
|
|
|
t.Fatalf("Android 渠道应下发 Android 那套版本号,实际 version=%q min=%q", got.Version, got.Minversion) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 两张表都没配才返回 nil。
|
|
|
// 两张表都没配才返回 nil。
|
|
|
func TestToPbChannelAppBothNil(t *testing.T) { |
|
|
func TestToPbChannelAppBothNil(t *testing.T) { |
|
|
if got := toPbChannelApp(comm.ChannelChinaXiaomi, nil, nil, "1.0.1"); got != nil { |
|
|
if got := toPbChannelApp(comm.ChannelChinaXiaomi, nil, nil, "1.0.1", ""); got != nil { |
|
|
t.Fatalf("两边都没配时应返回 nil,实际 %+v", got) |
|
|
t.Fatalf("两边都没配时应返回 nil,实际 %+v", got) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|