204 lines
7.9 KiB
C#
204 lines
7.9 KiB
C#
using System.Collections.Generic;
|
||
using NUnit.Framework;
|
||
using Newtonsoft.Json;
|
||
using BaseGames.Core.Save;
|
||
|
||
namespace BaseGames.Tests.EditMode
|
||
{
|
||
/// <summary>
|
||
/// 存档系统单元测试(EditMode,纯 C# 逻辑,无 MonoBehaviour 依赖)。
|
||
/// 覆盖:SaveMigrator 迁移链、SaveData 序列化/反序列化往返、字段完整性。
|
||
/// </summary>
|
||
[TestFixture]
|
||
public class SaveSystemTests
|
||
{
|
||
// ── SaveMigrator · 边界输入 ──────────────────────────────────────────
|
||
|
||
[Test]
|
||
public void Migrate_NullInput_ReturnsNull()
|
||
{
|
||
var result = SaveMigrator.Migrate(null);
|
||
Assert.IsNull(result, "null 输入应安全返回 null");
|
||
}
|
||
|
||
[Test]
|
||
public void Migrate_NullMeta_ReturnsSameObject()
|
||
{
|
||
var data = new SaveData { Meta = null };
|
||
var result = SaveMigrator.Migrate(data);
|
||
Assert.AreSame(data, result, "Meta 为 null 时应返回原对象");
|
||
}
|
||
|
||
// ── SaveMigrator · 版本迁移 ──────────────────────────────────────────
|
||
|
||
[Test]
|
||
public void Migrate_EmptyVersion_MigratesTo_2_1()
|
||
{
|
||
var data = new SaveData();
|
||
data.Meta.Version = "";
|
||
var result = SaveMigrator.Migrate(data);
|
||
Assert.AreEqual(SaveMigrator.CurrentVersion, result.Meta.Version);
|
||
}
|
||
|
||
[Test]
|
||
public void Migrate_OldVersion_FillsMissingSubObjects()
|
||
{
|
||
var data = new SaveData();
|
||
data.Meta.Version = "1.0";
|
||
data.Tutorial = null;
|
||
data.Settings = null;
|
||
data.EventChains = null;
|
||
data.ChallengeRooms = null;
|
||
|
||
var result = SaveMigrator.Migrate(data);
|
||
|
||
Assert.IsNotNull(result.Tutorial, "迁移后 Tutorial 不应为 null");
|
||
Assert.IsNotNull(result.Settings, "迁移后 Settings 不应为 null");
|
||
Assert.IsNotNull(result.EventChains, "迁移后 EventChains 不应为 null");
|
||
Assert.IsNotNull(result.ChallengeRooms, "迁移后 ChallengeRooms 不应为 null");
|
||
Assert.IsNull(result.NGPlus, "迁移后 NGPlus 应为 null(非 NG+ 模式)");
|
||
}
|
||
|
||
[Test]
|
||
public void Migrate_OldVersion_DeathShade_RemainsNull()
|
||
{
|
||
var data = new SaveData();
|
||
data.Meta.Version = "1.0";
|
||
data.Player.DeathShade = null;
|
||
|
||
var result = SaveMigrator.Migrate(data);
|
||
|
||
Assert.IsNull(result.Player.DeathShade,
|
||
"无遗骸时 DeathShade 应保持 null,由 DeathShadeManager 按需创建");
|
||
}
|
||
|
||
[Test]
|
||
public void Migrate_Version2_0_FillsMapPins()
|
||
{
|
||
var data = new SaveData();
|
||
data.Meta.Version = "2.0";
|
||
data.Map.Pins = null;
|
||
|
||
var result = SaveMigrator.Migrate(data);
|
||
|
||
Assert.IsNotNull(result.Map.Pins, "从 2.0 迁移后 Map.Pins 不应为 null");
|
||
Assert.IsEmpty(result.Map.Pins, "Map.Pins 应初始化为空列表");
|
||
}
|
||
|
||
[Test]
|
||
public void Migrate_CurrentVersion_NoChange()
|
||
{
|
||
var data = new SaveData();
|
||
data.Meta.Version = SaveMigrator.CurrentVersion;
|
||
var result = SaveMigrator.Migrate(data);
|
||
Assert.AreEqual(SaveMigrator.CurrentVersion, result.Meta.Version);
|
||
}
|
||
|
||
// ── SaveData · JSON 序列化往返 ───────────────────────────────────────
|
||
|
||
[Test]
|
||
public void SaveData_SerializeDeserialize_PreservesPlayerData()
|
||
{
|
||
var original = new SaveData();
|
||
original.Player.CurrentHP = 55;
|
||
original.Player.MaxHP = 100;
|
||
original.Player.CurrentLingZhu = 1234;
|
||
original.Player.Scene = "TestRoom";
|
||
|
||
string json = JsonConvert.SerializeObject(original, Formatting.None);
|
||
var restored = JsonConvert.DeserializeObject<SaveData>(json);
|
||
|
||
Assert.AreEqual(original.Player.CurrentHP, restored.Player.CurrentHP);
|
||
Assert.AreEqual(original.Player.MaxHP, restored.Player.MaxHP);
|
||
Assert.AreEqual(original.Player.CurrentLingZhu, restored.Player.CurrentLingZhu);
|
||
Assert.AreEqual(original.Player.Scene, restored.Player.Scene);
|
||
}
|
||
|
||
[Test]
|
||
public void SaveData_SerializeDeserialize_PreservesAbilityFlags()
|
||
{
|
||
var original = new SaveData();
|
||
original.Player.AbilityFlags = 0xDEADBEEFu;
|
||
|
||
string json = JsonConvert.SerializeObject(original, Formatting.None);
|
||
var restored = JsonConvert.DeserializeObject<SaveData>(json);
|
||
|
||
Assert.AreEqual(original.Player.AbilityFlags, restored.Player.AbilityFlags,
|
||
"AbilityFlags uint 不应因符号扩展而错误");
|
||
}
|
||
|
||
[Test]
|
||
public void SaveData_SerializeDeserialize_NGPlusNull_StaysNull()
|
||
{
|
||
var original = new SaveData();
|
||
original.NGPlus = null;
|
||
|
||
string json = JsonConvert.SerializeObject(original, Formatting.None);
|
||
var restored = JsonConvert.DeserializeObject<SaveData>(json);
|
||
|
||
Assert.IsNull(restored.NGPlus, "NGPlus null 应序列化/反序列化保持 null");
|
||
}
|
||
|
||
[Test]
|
||
public void SaveData_SerializeDeserialize_MetaVersionPreserved()
|
||
{
|
||
var original = new SaveData();
|
||
original.Meta.Version = SaveMigrator.CurrentVersion;
|
||
original.Meta.SlotIndex = 2;
|
||
original.Meta.SaveCount = 42;
|
||
|
||
string json = JsonConvert.SerializeObject(original, Formatting.None);
|
||
var restored = JsonConvert.DeserializeObject<SaveData>(json);
|
||
|
||
Assert.AreEqual(SaveMigrator.CurrentVersion, restored.Meta.Version);
|
||
Assert.AreEqual(2, restored.Meta.SlotIndex);
|
||
Assert.AreEqual(42, restored.Meta.SaveCount);
|
||
}
|
||
|
||
[Test]
|
||
public void SaveData_ExtensionData_PreservesUnknownFields()
|
||
{
|
||
// 模拟未来版本存档包含当前版本未知的字段
|
||
string futureJson = @"{
|
||
""Meta"": { ""Version"": ""3.0"", ""SlotIndex"": 0 },
|
||
""Player"": { ""CurrentHP"": 80 },
|
||
""FutureFeature"": { ""SomeValue"": 123 }
|
||
}";
|
||
|
||
var restored = JsonConvert.DeserializeObject<SaveData>(futureJson);
|
||
|
||
Assert.IsNotNull(restored);
|
||
Assert.AreEqual(80, restored.Player.CurrentHP);
|
||
Assert.IsTrue(restored.ExtensionData.ContainsKey("FutureFeature"),
|
||
"ExtensionData 应保留未知字段,确保向前兼容");
|
||
}
|
||
|
||
// ── SaveMeta · Checksum 字段 ─────────────────────────────────────────
|
||
|
||
[Test]
|
||
public void SaveMeta_Checksum_DefaultIsNull()
|
||
{
|
||
var meta = new SaveMeta();
|
||
Assert.IsNull(meta.Checksum, "新建 SaveMeta 的 Checksum 默认应为 null");
|
||
}
|
||
|
||
[Test]
|
||
public void SaveData_Serialize_WithNullChecksum_NotThrow()
|
||
{
|
||
var data = new SaveData();
|
||
data.Meta.Checksum = null;
|
||
Assert.DoesNotThrow(
|
||
() => JsonConvert.SerializeObject(data, Formatting.None));
|
||
}
|
||
|
||
// ── SaveMeta · IsSteelSoul ────────────────────────────────────────────
|
||
|
||
[Test]
|
||
public void SaveMeta_IsSteelSoul_DefaultIsFalse()
|
||
{
|
||
var meta = new SaveMeta();
|
||
Assert.IsFalse(meta.IsSteelSoul, "IsSteelSoul 默认应为 false");
|
||
}
|
||
}
|
||
}
|