213 lines
6.5 KiB
C#
213 lines
6.5 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Cysharp.Threading.Tasks;
|
|
using NUnit.Framework;
|
|
using UnityEngine;
|
|
using UnityEngine.TestTools;
|
|
|
|
namespace ShrinkDataSaver.Tests
|
|
{
|
|
[TestFixture]
|
|
public class ShrinkSettingsTests
|
|
{
|
|
private MockStorageProvider _storage;
|
|
private ShrinkDataSaverSettings _settings;
|
|
|
|
[SetUp]
|
|
public void SetUp()
|
|
{
|
|
_storage = new MockStorageProvider();
|
|
_settings = ScriptableObject.CreateInstance<ShrinkDataSaverSettings>();
|
|
ShrinkDataSaverSettings.Instance = _settings;
|
|
ShrinkSettings.ResetForTesting();
|
|
ShrinkSettings.Initialize(_storage, "settings.json");
|
|
}
|
|
|
|
[TearDown]
|
|
public void TearDown()
|
|
{
|
|
ShrinkSettings.ResetForTesting();
|
|
if (_settings != null) Object.DestroyImmediate(_settings);
|
|
}
|
|
|
|
// ── Get / Set ──
|
|
|
|
[Test]
|
|
public void Set_Get_String()
|
|
{
|
|
ShrinkSettings.Set("name", "Alice");
|
|
Assert.AreEqual("Alice", ShrinkSettings.Get<string>("name"));
|
|
}
|
|
|
|
[Test]
|
|
public void Set_Get_Int()
|
|
{
|
|
ShrinkSettings.Set("score", 42);
|
|
Assert.AreEqual(42, ShrinkSettings.Get<int>("score"));
|
|
}
|
|
|
|
[Test]
|
|
public void Set_Get_Float()
|
|
{
|
|
ShrinkSettings.Set("volume", 0.75f);
|
|
Assert.AreEqual(0.75f, ShrinkSettings.Get<float>("volume"), 0.001f);
|
|
}
|
|
|
|
[Test]
|
|
public void Set_Get_Bool()
|
|
{
|
|
ShrinkSettings.Set("muted", true);
|
|
Assert.IsTrue(ShrinkSettings.Get<bool>("muted"));
|
|
}
|
|
|
|
[Test]
|
|
public void Set_Get_ComplexObject()
|
|
{
|
|
var data = new Dictionary<string, int> { { "a", 1 }, { "b", 2 } };
|
|
ShrinkSettings.Set("map", data);
|
|
var restored = ShrinkSettings.Get<Dictionary<string, int>>("map");
|
|
|
|
Assert.AreEqual(1, restored["a"]);
|
|
Assert.AreEqual(2, restored["b"]);
|
|
}
|
|
|
|
[Test]
|
|
public void Get_NonExistentKey_ReturnsDefault()
|
|
{
|
|
Assert.AreEqual(0, ShrinkSettings.Get<int>("missing"));
|
|
Assert.IsNull(ShrinkSettings.Get<string>("missing"));
|
|
Assert.AreEqual(99, ShrinkSettings.Get("missing", 99));
|
|
}
|
|
|
|
// ── Has / Remove ──
|
|
|
|
[Test]
|
|
public void Has_ExistingKey_ReturnsTrue()
|
|
{
|
|
ShrinkSettings.Set("key", "value");
|
|
Assert.IsTrue(ShrinkSettings.Has("key"));
|
|
}
|
|
|
|
[Test]
|
|
public void Has_NonExistentKey_ReturnsFalse()
|
|
{
|
|
Assert.IsFalse(ShrinkSettings.Has("ghost"));
|
|
}
|
|
|
|
[Test]
|
|
public void Remove_ExistingKey()
|
|
{
|
|
ShrinkSettings.Set("temp", 123);
|
|
Assert.IsTrue(ShrinkSettings.Has("temp"));
|
|
|
|
ShrinkSettings.Remove("temp");
|
|
Assert.IsFalse(ShrinkSettings.Has("temp"));
|
|
}
|
|
|
|
[Test]
|
|
public void Remove_NonExistentKey_NoError()
|
|
{
|
|
Assert.DoesNotThrow(() => ShrinkSettings.Remove("ghost"));
|
|
}
|
|
|
|
// ── GetAllRaw ──
|
|
|
|
[Test]
|
|
public void GetAllRaw_ReturnsAllSettings()
|
|
{
|
|
ShrinkSettings.Set("a", 1);
|
|
ShrinkSettings.Set("b", "two");
|
|
ShrinkSettings.Set("c", true);
|
|
|
|
var all = ShrinkSettings.GetAllRaw();
|
|
Assert.AreEqual(3, all.Count);
|
|
Assert.IsTrue(all.ContainsKey("a"));
|
|
Assert.IsTrue(all.ContainsKey("b"));
|
|
Assert.IsTrue(all.ContainsKey("c"));
|
|
}
|
|
|
|
// ── 事件 ──
|
|
|
|
[Test]
|
|
public void OnChanged_FiredOnSet()
|
|
{
|
|
string receivedKey = null;
|
|
object receivedValue = null;
|
|
ShrinkSettings.OnChanged += (k, v) => { receivedKey = k; receivedValue = v; };
|
|
|
|
ShrinkSettings.Set("volume", 0.5f);
|
|
|
|
Assert.AreEqual("volume", receivedKey);
|
|
}
|
|
|
|
[Test]
|
|
public void OnChanged_FiredOnRemove()
|
|
{
|
|
ShrinkSettings.Set("temp", "data");
|
|
|
|
string removedKey = null;
|
|
ShrinkSettings.OnChanged += (k, v) => { removedKey = k; };
|
|
|
|
ShrinkSettings.Remove("temp");
|
|
Assert.AreEqual("temp", removedKey);
|
|
}
|
|
|
|
// ── 持久化 ──
|
|
|
|
[UnityTest]
|
|
public IEnumerator SaveAsync_LoadAsync_RoundTrip() => UniTask.ToCoroutine(async () =>
|
|
{
|
|
ShrinkSettings.Set("persist_str", "hello");
|
|
ShrinkSettings.Set("persist_int", 42);
|
|
await ShrinkSettings.SaveAsync();
|
|
|
|
// 重置内存数据后重新加载
|
|
ShrinkSettings.ResetForTesting();
|
|
ShrinkSettings.Initialize(_storage, "settings.json");
|
|
|
|
await ShrinkSettings.LoadAsync();
|
|
|
|
Assert.AreEqual("hello", ShrinkSettings.Get<string>("persist_str"));
|
|
Assert.AreEqual(42, ShrinkSettings.Get<int>("persist_int"));
|
|
});
|
|
|
|
[UnityTest]
|
|
public IEnumerator LoadAsync_EmptyStorage_GivesCleanState() => UniTask.ToCoroutine(async () =>
|
|
{
|
|
await ShrinkSettings.LoadAsync();
|
|
Assert.AreEqual(0, ShrinkSettings.GetAllRaw().Count);
|
|
});
|
|
|
|
[UnityTest]
|
|
public IEnumerator LoadAsync_FallsBackToBackup_WhenPrimaryCorrupted() => UniTask.ToCoroutine(async () =>
|
|
{
|
|
ShrinkSettings.Set("lang", "zh_cn");
|
|
await ShrinkSettings.SaveAsync();
|
|
|
|
var backupBytes = await _storage.ReadAsync("settings.json");
|
|
await _storage.WriteAsync("settings.json.bak1", backupBytes);
|
|
// 用无法解析的字节模拟主文件损坏:结构合法但字段不符的 JSON 无法与“合法空设置”区分
|
|
await _storage.WriteAsync("settings.json", System.Text.Encoding.UTF8.GetBytes("{ \"lang\": \"zh_cn\" , broken"));
|
|
|
|
ShrinkSettings.ResetForTesting();
|
|
ShrinkSettings.Initialize(_storage, "settings.json");
|
|
|
|
await ShrinkSettings.LoadAsync();
|
|
|
|
Assert.AreEqual("zh_cn", ShrinkSettings.Get<string>("lang"));
|
|
var repairedPrimary = await _storage.ReadAsync("settings.json");
|
|
CollectionAssert.AreEqual(backupBytes, repairedPrimary);
|
|
});
|
|
|
|
// ── Overwrite ──
|
|
|
|
[Test]
|
|
public void Set_OverwriteExistingKey()
|
|
{
|
|
ShrinkSettings.Set("key", "first");
|
|
ShrinkSettings.Set("key", "second");
|
|
Assert.AreEqual("second", ShrinkSettings.Get<string>("key"));
|
|
}
|
|
}
|
|
}
|