M2(领域层): ConfigManager/VersionResolver/ResourceManager/AppDataInjector/StartupOrchestrator
T-M2-05 ConfigManager:本地 rawfile/app_config.json(§4.2 实测值)、远程 URL 拼装('-'→'/'+.txt+?a=ts 禁缓存)、
长度<30 走 showmessage 阻断、二级 url 二次请求(语义待真机校验)、产出版本决策
T-M2-06 VersionResolver:纯函数,agentlist/gamelist 两棵树 + agent→channel→market→game 后层覆盖 +
两树取更高 version(§4.4)。单测 8 用例全通过,覆盖率 81.8%(≥80%)
T-M2-07 ResourceManager:沙箱路径规范、内置包拷贝解压、version.xml 解析(@ohos.xml)、远程 zip 下载/删旧/解压、版本比较
T-M2-09 AppDataInjector:加载前写 <gameDir>/app_data.js(§6 全局变量同名同义,JSON.stringify 安全字面量)
T-M2-11 StartupOrchestrator:INIT→…→ENTER_HALL 状态机,远程失败降级本地、showmessage 阻断、weburl 空/非空入口规则
配套:module.json5 声明 ohos.permission.INTERNET + reason_internet 字符串
devecocli build 通过;scripts/test.sh 单测全通过(修复 PermissionRequestResult 顶层导入)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -46,6 +46,16 @@
|
||||
}
|
||||
],
|
||||
}
|
||||
],
|
||||
"requestPermissions": [
|
||||
{
|
||||
"name": "ohos.permission.INTERNET",
|
||||
"reason": "$string:reason_internet",
|
||||
"usedScene": {
|
||||
"abilities": ["EntryAbility"],
|
||||
"when": "inuse"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,10 @@
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "label"
|
||||
},
|
||||
{
|
||||
"name": "reason_internet",
|
||||
"value": "用于下载游戏资源与获取远程配置"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"agent": "veRa0qrBf0df2K1G4de2tgfmVxB2jxpv",
|
||||
"channel": "FtJf073aa0d6rI1xD8J1Y42fINTm0ziK",
|
||||
"gamedir": "FtJf073aa0d6rI1xD8J1Y42fINTm0ziK",
|
||||
"gamestart": "gamehall",
|
||||
"appversion": "49",
|
||||
"market": "3",
|
||||
"gameid": "",
|
||||
"weburl": "",
|
||||
"gameconfig": "tsgames.daoqi88.cn-config_test-update_jsonv2_test",
|
||||
"other": "",
|
||||
"tuiguang": ""
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
import localUnitTest from './LocalUnit.test';
|
||||
import bridgeTest from './Bridge.test';
|
||||
import versionResolverTest from './VersionResolver.test';
|
||||
|
||||
export default function testsuite() {
|
||||
localUnitTest();
|
||||
bridgeTest();
|
||||
versionResolverTest();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
import { describe, it, expect } from '@ohos/hypium';
|
||||
import { VersionResolver, RemoteConfig, MatchKeys, VersionDecision } from 'domain_resource';
|
||||
|
||||
/**
|
||||
* 分层版本决策单测(T-M2-06,契约 §4.4)。纯函数,构造典型多层样例验证后层覆盖、
|
||||
* 两棵树取更高 version、showmessage 阻断。
|
||||
*/
|
||||
export default function versionResolverTest() {
|
||||
const keys: MatchKeys = { agentid: 'A1', channelid: 'C1', marketid: 'M1', gameid: 'G1' };
|
||||
|
||||
describe('VersionResolver', () => {
|
||||
it('empty_config_zero_decision', 0, () => {
|
||||
const d: VersionDecision = VersionResolver.resolve({}, keys);
|
||||
expect(d.gameVersion).assertEqual(0);
|
||||
expect(d.appVersion).assertEqual(0);
|
||||
expect(d.showmessage).assertEqual('');
|
||||
expect(d.gameDownload).assertEqual('');
|
||||
});
|
||||
|
||||
it('agent_tree_deeper_overrides', 0, () => {
|
||||
// 代理树:agent 设 game_version=10,market 覆盖为 20(深层覆盖浅层)
|
||||
const remote: RemoteConfig = {
|
||||
agentlist: [{
|
||||
agentid: 'A1', game_version: '10', game_download: 'a_url', game_size: '100',
|
||||
channellist: [{
|
||||
channelid: 'C1',
|
||||
marketlist: [{ marketid: 'M1', game_version: '20', game_download: 'm_url' }],
|
||||
}],
|
||||
}],
|
||||
};
|
||||
const d: VersionDecision = VersionResolver.resolve(remote, keys);
|
||||
expect(d.gameVersion).assertEqual(20);
|
||||
expect(d.gameDownload).assertEqual('m_url');
|
||||
});
|
||||
|
||||
it('market_game_level_overrides', 0, () => {
|
||||
// market.gamelist 中 gameid 命中,覆盖到最深
|
||||
const remote: RemoteConfig = {
|
||||
agentlist: [{
|
||||
agentid: 'A1',
|
||||
channellist: [{
|
||||
channelid: 'C1',
|
||||
marketlist: [{
|
||||
marketid: 'M1', game_version: '20',
|
||||
gamelist: [{ gameid: 'G1', game_version: '30', game_download: 'g_url' }],
|
||||
}],
|
||||
}],
|
||||
}],
|
||||
};
|
||||
const d: VersionDecision = VersionResolver.resolve(remote, keys);
|
||||
expect(d.gameVersion).assertEqual(30);
|
||||
expect(d.gameDownload).assertEqual('g_url');
|
||||
});
|
||||
|
||||
it('two_trees_take_higher_version', 0, () => {
|
||||
// 代理树 game_version=20,游戏树 game_version=25 → 取 25 及其下载地址
|
||||
const remote: RemoteConfig = {
|
||||
agentlist: [{ agentid: 'A1', game_version: '20', game_download: 'agent_url' }],
|
||||
gamelist: [{
|
||||
gameid: 'G1',
|
||||
agentlist: [{ agentid: 'A1', game_version: '25', game_download: 'game_url' }],
|
||||
}],
|
||||
};
|
||||
const d: VersionDecision = VersionResolver.resolve(remote, keys);
|
||||
expect(d.gameVersion).assertEqual(25);
|
||||
expect(d.gameDownload).assertEqual('game_url');
|
||||
});
|
||||
|
||||
it('app_and_game_independent_winners', 0, () => {
|
||||
// app 升级取代理树(app_version=49),game 升级取游戏树(game_version=30)
|
||||
const remote: RemoteConfig = {
|
||||
agentlist: [{ agentid: 'A1', app_version: '49', app_download: 'apk_url', game_version: '10' }],
|
||||
gamelist: [{
|
||||
gameid: 'G1',
|
||||
agentlist: [{ agentid: 'A1', app_version: '40', game_version: '30', game_download: 'g_url' }],
|
||||
}],
|
||||
};
|
||||
const d: VersionDecision = VersionResolver.resolve(remote, keys);
|
||||
expect(d.appVersion).assertEqual(49);
|
||||
expect(d.appDownload).assertEqual('apk_url');
|
||||
expect(d.gameVersion).assertEqual(30);
|
||||
expect(d.gameDownload).assertEqual('g_url');
|
||||
});
|
||||
|
||||
it('no_match_returns_empty', 0, () => {
|
||||
const remote: RemoteConfig = {
|
||||
agentlist: [{ agentid: 'OTHER', game_version: '99', game_download: 'x' }],
|
||||
};
|
||||
const d: VersionDecision = VersionResolver.resolve(remote, keys);
|
||||
expect(d.gameVersion).assertEqual(0);
|
||||
expect(d.gameDownload).assertEqual('');
|
||||
});
|
||||
|
||||
it('showmessage_from_layer_or_top', 0, () => {
|
||||
const top: RemoteConfig = { showmessage: '停服维护公告' };
|
||||
expect(VersionResolver.resolve(top, keys).showmessage).assertEqual('停服维护公告');
|
||||
const layer: RemoteConfig = {
|
||||
agentlist: [{ agentid: 'A1', showmessage: '代理层公告' }],
|
||||
};
|
||||
expect(VersionResolver.resolve(layer, keys).showmessage).assertEqual('代理层公告');
|
||||
});
|
||||
|
||||
it('empty_string_does_not_override', 0, () => {
|
||||
// 深层空串不应覆盖浅层非空值
|
||||
const remote: RemoteConfig = {
|
||||
agentlist: [{
|
||||
agentid: 'A1', game_download: 'keep', game_version: '10',
|
||||
channellist: [{ channelid: 'C1', game_download: '' }],
|
||||
}],
|
||||
};
|
||||
const d: VersionDecision = VersionResolver.resolve(remote, keys);
|
||||
expect(d.gameDownload).assertEqual('keep');
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user