test(upserver): 归档存档迁移与玩法闭环回归工具

This commit is contained in:
Liubing\LB
2026-09-28 18:16:14 +08:00
parent c4ae02def9
commit a6f5e107f8
232 changed files with 12903 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
using game.PlayerDataStorage;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
static partial class Tests
{
static async Task RunBuffTriggerSchemaTests()
{
await Run("M06-four-buff-shapes-strict-and-missing", () =>
{
const string value="{\"SortID\":1,\"sourceID\":2,\"buffID\":3,\"isEnd\":false,\"buffEndTime\":\"2026-09-24T00:00:00.0000000Z\"}";
var raw=new Dictionary<string,string> { ["BuffDataList"]="{\"7\":"+value+"}",["TargetBuffDataList"]="["+value+"]",
["FishDailyBuff"]=value,["GlobalBuffDataList"]="{\"7\":"+value+"}" };
var state=PlayerKVSaveSchema.DecodeBuffs(raw,SchemaSnapshot(),new());
foreach(var item in new[] { state.Map[7],state.Target[0],state.Daily,state.Global[7] })
Check(item.SortID==1 && item.sourceID==2 && item.buffID==3 && !item.isEnd && item.buffEndTime.Day==24,"all saved buff fields");
var absent=PlayerKVSaveSchema.DecodeBuffs(new Dictionary<string,string>(),SchemaSnapshot(),new());
Check(absent.Map.Count==0 && absent.Target.Count==0 && absent.Global.Count==0 && absent.Daily==null,"all missing defaults");
foreach(var key in raw.Keys)
foreach(var bad in new[] { "null","{\"7\":null}","[null]","{}" })
{
// Empty maps are valid only for map containers.
if(bad=="{}" && (key=="BuffDataList" || key=="GlobalBuffDataList")) continue;
Check(PlayerKVSaveSchema.DecodeBuffs(new Dictionary<string,string>(raw) { [key]=bad },SchemaSnapshot(),new())==null,"bad present container fails");
}
foreach(var property in JObject.Parse(value).Properties())
{
var bad=JObject.Parse(value); bad[property.Name]=JValue.CreateNull();
Check(PlayerKVSaveSchema.DecodeBuffs(new Dictionary<string,string> { ["FishDailyBuff"]=bad.ToString(Formatting.None) },SchemaSnapshot(),new())==null,"all required buff fields");
}
Check(PlayerKVSaveSchema.DecodeBuffs(new Dictionary<string,string> { ["BuffDataList"]="{\"7\":"+value+",\"07\":"+value+"}" },SchemaSnapshot(),new())==null,"normalized duplicate rejected");
var allBad=new Dictionary<string,string>(raw); foreach(var key in raw.Keys) allBad[key]="null";
var errors=new PlayerKVSchemaDiagnostics(); Check(PlayerKVSaveSchema.DecodeBuffs(allBad,SchemaSnapshot(),errors)==null && errors.TotalErrors==4,"all bad keys counted");
return Task.CompletedTask;
});
await Run("M13-trigger-gift-fixed-shapes", () =>
{
var raw=new Dictionary<string,string> {
["TriggerPackDataList"]="[{\"ID\":1,\"index\":2,\"lastID\":3,\"vipLevel\":4,\"mapID\":5,\"time\":\"2026-09-24\"}]",
["GiftVIPDData"]="{\"A\":{\"oldVipLevel\":1,\"curVipLevel\":2,\"timer\":3}}",
["FixedTimeShopDic"]="{\"7\":{\"id\":8,\"endTime\":\"2026-09-24\"}}"
};
var state=PlayerKVSaveSchema.DecodeTriggers(raw,new()); var pack=state.Packs[0];
Check(pack.ID==1 && pack.index==2 && pack.lastID==3 && pack.vipLevel==4 && pack.mapID==5 && pack.time=="2026-09-24","pack fields");
Check(state.Gifts["A"].oldVipLevel==1 && state.Gifts["A"].curVipLevel==2 && state.Gifts["A"].timer==3 &&
state.Fixed[7].id==8 && state.Fixed[7].endTime=="2026-09-24","gift and fixed fields");
foreach(var key in raw.Keys)
foreach(var bad in new[] { "null","[null]","{\"7\":null}","{\"A\":{}}" })
Check(PlayerKVSaveSchema.DecodeTriggers(new Dictionary<string,string>(raw) { [key]=bad },new())==null,"invalid container or nested fails");
var missing=PlayerKVSaveSchema.DecodeTriggers(new Dictionary<string,string>(),new());
Check(missing.Packs.Count==0 && missing.Gifts.Count==0 && missing.Fixed.Count==0,"missing all empty");
var allBad=new Dictionary<string,string>(raw); foreach(var key in raw.Keys) allBad[key]="null";
var e=new PlayerKVSchemaDiagnostics(); Check(PlayerKVSaveSchema.DecodeTriggers(allBad,e)==null && e.TotalErrors==3,"all keys counted");
return Task.CompletedTask;
});
}
}