using System; using Newtonsoft.Json.Linq; using NUnit.Framework; using UnityEngine; using UnityEngine.TestTools; namespace ShrinkDataSaver.Tests { [TestFixture] public class MigrationChainTests { [SetUp] public void SetUp() => MigrationChain.Clear(); [TearDown] public void TearDown() => MigrationChain.Clear(); [Test] public void Register_ValidVersions_Succeeds() { Assert.DoesNotThrow(() => MigrationChain.Register(1, 2, data => data)); } [Test] public void Register_InvalidRange_Throws() { Assert.Throws(() => MigrationChain.Register(2, 1, data => data)); Assert.Throws(() => MigrationChain.Register(1, 1, data => data)); } [Test] public void Apply_SingleMigration() { MigrationChain.Register(1, 2, data => { data["newField"] = "added"; return data; }); var input = new JObject { ["existing"] = "value" }; var (result, version) = MigrationChain.Apply(input, 1, 2); Assert.AreEqual(2, version); Assert.AreEqual("value", result["existing"].ToString()); Assert.AreEqual("added", result["newField"].ToString()); } [Test] public void Apply_ChainMigration_1To3() { MigrationChain.Register(1, 2, data => { data["coins"] = data["gold"]; data.Remove("gold"); return data; }); MigrationChain.Register(2, 3, data => { data["version3Field"] = 42; return data; }); var input = new JObject { ["gold"] = 100 }; var (result, version) = MigrationChain.Apply(input, 1, 3); Assert.AreEqual(3, version); Assert.AreEqual(100, result["coins"].Value()); Assert.IsFalse(result.ContainsKey("gold")); Assert.AreEqual(42, result["version3Field"].Value()); } [Test] public void Apply_MissingStep_StopsEarly() { MigrationChain.Register(1, 2, data => data); // 缺少 2→3 的迁移 var input = new JObject { ["data"] = "test" }; var (result, version) = MigrationChain.Apply(input, 1, 3); // 应该停在 v2,因为没有 2→3 的迁移 Assert.AreEqual(2, version); } [Test] public void Apply_FailedMigration_Rollback() { MigrationChain.Register(1, 2, data => { data["step1"] = "done"; return data; }); MigrationChain.Register(2, 3, data => { throw new Exception("Migration failed!"); }); var input = new JObject { ["original"] = "data" }; LogAssert.Expect(LogType.Error, "[ShrinkDataSaver] 迁移 v2 → v3 失败: Migration failed!,已回滚至 v1"); var (result, version) = MigrationChain.Apply(input, 1, 3); // 应该回滚到 v1 的备份数据 Assert.AreEqual(1, version); Assert.AreEqual("data", result["original"].ToString()); // 回滚意味着 step1 的修改不会存在 Assert.IsFalse(result.ContainsKey("step1")); } [Test] public void Apply_NoMigrationNeeded_ReturnsSameData() { var input = new JObject { ["data"] = "unchanged" }; var (result, version) = MigrationChain.Apply(input, 3, 3); Assert.AreEqual(3, version); Assert.AreEqual("unchanged", result["data"].ToString()); } } }