89 lines
5.7 KiB
C#
89 lines
5.7 KiB
C#
using game.PlayerDataStorage;
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
static partial class Tests
|
|
{
|
|
static async Task RunCollectionSchemaTests()
|
|
{
|
|
await Run("M09-two-formats-conflicts-empty-and-strict", () =>
|
|
{
|
|
var raw = new Dictionary<string,string> { ["FishingBoxData"] = "{\"FishingBoxOpenNum\":{\"1\":2,\"3\":4}}" };
|
|
var modern = new Dictionary<string,string> { ["bd"] = "1,2" };
|
|
var e = new PlayerKVSchemaDiagnostics();
|
|
var state = PlayerKVSaveSchema.DecodeFishingBox(raw,modern,e);
|
|
Check(state != null && state.Values.Count == 1 && state.Values[1] == 2, "new replaces whole map");
|
|
modern["bd"] = "";
|
|
Check(PlayerKVSaveSchema.DecodeFishingBox(raw,modern,new()).Values.Count == 0, "present empty replaces old");
|
|
modern["bd"] = "1,3"; e = new();
|
|
Check(PlayerKVSaveSchema.DecodeFishingBox(raw,modern,e) == null && e.Count(9,PlayerKVSchemaError.ConflictingRepresentations) == 1, "conflict rejected");
|
|
foreach (var bad in new[] { "1,2;", "1,2,3", "1,2;01,3", "1,2.0", "2147483648,0", "null" })
|
|
{
|
|
modern["bd"] = bad;
|
|
Check(PlayerKVSaveSchema.DecodeFishingBox(raw,modern,new()) == null, "bad compact never falls back");
|
|
}
|
|
modern["bd"] = "1,2";
|
|
foreach (var bad in new[] { "null", "{}", "{\"FishingBoxOpenNum\":null}", "{\"FishingBoxOpenNum\":{\"1\":2,\"01\":2}}",
|
|
"{\"FishingBoxOpenNum\":{\"1\":\"2\"}}", "{\"FishingBoxOpenNum\":{\"1\":2.0}}" })
|
|
{
|
|
raw["FishingBoxData"] = bad;
|
|
Check(PlayerKVSaveSchema.DecodeFishingBox(raw,modern,new()) == null, "bad old never hidden");
|
|
}
|
|
Check(PlayerKVSaveSchema.DecodeFishingBox(new Dictionary<string,string>(),new Dictionary<string,string>(),new()).Values.Count == 0,"missing empty");
|
|
return Task.CompletedTask;
|
|
});
|
|
await Run("M10-whole-guide-replacement-and-conflict", () =>
|
|
{
|
|
var raw = new Dictionary<string,string> {
|
|
["GuideSaveData"] = "{\"A\":{\"guideSubIndex\":2,\"isFinish\":true,\"groupName\":\"A\"},\"B\":{\"guideSubIndex\":3,\"isFinish\":false,\"groupName\":\"B\"}}",
|
|
["GuideSaveDataNew"] = "A|2|1"
|
|
};
|
|
var state = PlayerKVSaveSchema.DecodeGuides(raw,new());
|
|
Check(state.Values.Count == 1 && state.Values["A"].Index == 2 && state.Values["A"].Finished && state.Values["A"].Group == "A","new whole map selected");
|
|
foreach (var conflict in new[] { "A|3|1", "A|2|0" })
|
|
{
|
|
raw["GuideSaveDataNew"] = conflict; var e = new PlayerKVSchemaDiagnostics();
|
|
Check(PlayerKVSaveSchema.DecodeGuides(raw,e) == null && e.Count(10,PlayerKVSchemaError.ConflictingRepresentations) == 1,"common field conflict");
|
|
}
|
|
raw["GuideSaveDataNew"] = "";
|
|
Check(PlayerKVSaveSchema.DecodeGuides(raw,new()).Values.Count == 0,"new empty clears old groups");
|
|
foreach (var bad in new[] { "A|2|true", "A|2|2", "A|x|0", "A|2", "A|2|0;", "A|2|0;A|2|0" })
|
|
{
|
|
raw["GuideSaveDataNew"] = bad;
|
|
Check(PlayerKVSaveSchema.DecodeGuides(raw,new()) == null,"invalid compact rejected");
|
|
}
|
|
raw["GuideSaveDataNew"] = "A|2|1";
|
|
foreach (var bad in new[] { "null", "{\"A\":null}", "{\"A\":{\"guideSubIndex\":2,\"isFinish\":1,\"groupName\":\"A\"}}",
|
|
"{\"A\":{\"guideSubIndex\":2,\"isFinish\":true,\"groupName\":null}}" })
|
|
{
|
|
raw["GuideSaveData"] = bad;
|
|
Check(PlayerKVSaveSchema.DecodeGuides(raw,new()) == null,"invalid old not ignored");
|
|
}
|
|
raw["GuideSaveData"] = "{\"A\":{\"guideSubIndex\":2,\"isFinish\":true,\"groupName\":\"B\"}}";
|
|
Check(PlayerKVSaveSchema.DecodeGuides(raw,new()) == null,"groupName participates in comparison");
|
|
Check(PlayerKVSaveSchema.DecodeGuides(new Dictionary<string,string>(),new()).Values.Count == 0,"missing empty");
|
|
return Task.CompletedTask;
|
|
});
|
|
await Run("M12-nested-signin-all-fields-required", () =>
|
|
{
|
|
var valid = JObject.Parse("{\"index\":5,\"dailySignEvent\":{\"ID\":7,\"index\":2,\"lastID\":-1,\"time\":\"2026-09-23\"}}");
|
|
var raw = new Dictionary<string,string> { ["MonthlySignEvent"] = valid.ToString(Formatting.None) };
|
|
var state = PlayerKVSaveSchema.DecodeMonthlySign(raw,new());
|
|
Check(state.IsPresent && state.Index == 5 && state.DailyId == 7 && state.DailyIndex == 2 && state.LastId == -1 && state.Time == "2026-09-23","all fields decoded");
|
|
foreach (var path in new[] { "index", "dailySignEvent", "dailySignEvent.ID", "dailySignEvent.index", "dailySignEvent.lastID", "dailySignEvent.time" })
|
|
foreach (var bad in new JToken[] { JValue.CreateNull(), new JArray() })
|
|
{
|
|
var obj = (JObject)valid.DeepClone(); obj.SelectToken(path).Replace(bad);
|
|
raw["MonthlySignEvent"] = obj.ToString(Formatting.None);
|
|
Check(PlayerKVSaveSchema.DecodeMonthlySign(raw,new()) == null,"nested field null/shape rejected");
|
|
}
|
|
foreach (var bad in new[] { "null", "{}", "{\"index\":1}", "{\"index\":1,\"dailySignEvent\":{}}" })
|
|
{
|
|
raw["MonthlySignEvent"] = bad; Check(PlayerKVSaveSchema.DecodeMonthlySign(raw,new()) == null,"present malformed fails");
|
|
}
|
|
Check(!PlayerKVSaveSchema.DecodeMonthlySign(new Dictionary<string,string>(),new()).IsPresent,"missing explicit");
|
|
return Task.CompletedTask;
|
|
});
|
|
}
|
|
}
|