using System.IO; using GFramework.Core.Configuration; using NUnit.Framework; namespace GFramework.Core.Tests.Configuration; /// /// ConfigurationManager 功能测试类 /// [TestFixture] public class ConfigurationManagerTests { [SetUp] public void SetUp() { _configManager = new ConfigurationManager(); } [TearDown] public void TearDown() { _configManager.Clear(); } private ConfigurationManager _configManager = null!; [Test] public void SetConfig_And_GetConfig_Should_Work() { _configManager.SetConfig("test.key", 42); var value = _configManager.GetConfig("test.key"); Assert.That(value, Is.EqualTo(42)); } [Test] public void GetConfig_With_DefaultValue_Should_Return_DefaultValue_When_Key_Not_Exists() { var value = _configManager.GetConfig("nonexistent.key", 100); Assert.That(value, Is.EqualTo(100)); } [Test] public void GetConfig_Should_Return_Default_When_Key_Not_Exists() { var value = _configManager.GetConfig("nonexistent.key"); Assert.That(value, Is.EqualTo(0)); } [Test] public void HasConfig_Should_Return_True_When_Key_Exists() { _configManager.SetConfig("test.key", "value"); Assert.That(_configManager.HasConfig("test.key"), Is.True); } [Test] public void HasConfig_Should_Return_False_When_Key_Not_Exists() { Assert.That(_configManager.HasConfig("nonexistent.key"), Is.False); } [Test] public void RemoveConfig_Should_Remove_Existing_Key() { _configManager.SetConfig("test.key", "value"); var removed = _configManager.RemoveConfig("test.key"); Assert.That(removed, Is.True); Assert.That(_configManager.HasConfig("test.key"), Is.False); } [Test] public void RemoveConfig_Should_Return_False_When_Key_Not_Exists() { var removed = _configManager.RemoveConfig("nonexistent.key"); Assert.That(removed, Is.False); } [Test] public void Clear_Should_Remove_All_Configs() { _configManager.SetConfig("key1", "value1"); _configManager.SetConfig("key2", "value2"); _configManager.Clear(); Assert.That(_configManager.Count, Is.EqualTo(0)); } [Test] public void Count_Should_Return_Correct_Number() { _configManager.SetConfig("key1", "value1"); _configManager.SetConfig("key2", "value2"); _configManager.SetConfig("key3", "value3"); Assert.That(_configManager.Count, Is.EqualTo(3)); } [Test] public void GetAllKeys_Should_Return_All_Keys() { _configManager.SetConfig("key1", "value1"); _configManager.SetConfig("key2", "value2"); var keys = _configManager.GetAllKeys().ToList(); Assert.That(keys, Has.Count.EqualTo(2)); Assert.That(keys, Contains.Item("key1")); Assert.That(keys, Contains.Item("key2")); } [Test] public void GetConfig_Should_Support_Different_Types() { _configManager.SetConfig("int.key", 42); _configManager.SetConfig("string.key", "hello"); _configManager.SetConfig("bool.key", true); _configManager.SetConfig("double.key", 3.14); Assert.That(_configManager.GetConfig("int.key"), Is.EqualTo(42)); Assert.That(_configManager.GetConfig("string.key"), Is.EqualTo("hello")); Assert.That(_configManager.GetConfig("bool.key"), Is.True); Assert.That(_configManager.GetConfig("double.key"), Is.EqualTo(3.14).Within(0.001)); } [Test] public void WatchConfig_Should_Trigger_When_Config_Changes() { var callCount = 0; var receivedValue = 0; _configManager.WatchConfig("test.key", value => { callCount++; receivedValue = value; }); _configManager.SetConfig("test.key", 42); Assert.That(callCount, Is.EqualTo(1)); Assert.That(receivedValue, Is.EqualTo(42)); } [Test] public void WatchConfig_Should_Not_Trigger_When_Value_Not_Changed() { _configManager.SetConfig("test.key", 42); var callCount = 0; _configManager.WatchConfig("test.key", _ => callCount++); _configManager.SetConfig("test.key", 42); Assert.That(callCount, Is.EqualTo(0)); } [Test] public void UnRegister_Should_Stop_Watching() { var callCount = 0; var unRegister = _configManager.WatchConfig("test.key", _ => callCount++); _configManager.SetConfig("test.key", 42); Assert.That(callCount, Is.EqualTo(1)); unRegister.UnRegister(); _configManager.SetConfig("test.key", 100); Assert.That(callCount, Is.EqualTo(1)); } [Test] public void Multiple_Watchers_Should_All_Be_Triggered() { var count1 = 0; var count2 = 0; _configManager.WatchConfig("test.key", _ => count1++); _configManager.WatchConfig("test.key", _ => count2++); _configManager.SetConfig("test.key", 42); Assert.That(count1, Is.EqualTo(1)); Assert.That(count2, Is.EqualTo(1)); } [Test] public void SaveToJson_And_LoadFromJson_Should_Work() { _configManager.SetConfig("key1", "value1"); _configManager.SetConfig("key2", 42); var json = _configManager.SaveToJson(); var newManager = new ConfigurationManager(); newManager.LoadFromJson(json); Assert.That(newManager.GetConfig("key1"), Is.EqualTo("value1")); Assert.That(newManager.GetConfig("key2"), Is.EqualTo(42)); } [Test] public void SaveToFile_And_LoadFromFile_Should_Work() { var tempFile = Path.GetTempFileName(); try { _configManager.SetConfig("key1", "value1"); _configManager.SetConfig("key2", 42); _configManager.SaveToFile(tempFile); var newManager = new ConfigurationManager(); newManager.LoadFromFile(tempFile); Assert.That(newManager.GetConfig("key1"), Is.EqualTo("value1")); Assert.That(newManager.GetConfig("key2"), Is.EqualTo(42)); } finally { if (File.Exists(tempFile)) { File.Delete(tempFile); } } } [Test] public void LoadFromFile_Should_Throw_When_File_Not_Exists() { Assert.Throws(() => { _configManager.LoadFromFile("nonexistent.json"); }); } [Test] public void SetConfig_Should_Throw_When_Key_Is_Null_Or_Empty() { Assert.Throws(() => _configManager.SetConfig(null!, "value")); Assert.Throws(() => _configManager.SetConfig("", "value")); Assert.Throws(() => _configManager.SetConfig(" ", "value")); } [Test] public void GetConfig_Should_Throw_When_Key_Is_Null_Or_Empty() { Assert.Throws(() => _configManager.GetConfig(null!)); Assert.Throws(() => _configManager.GetConfig("")); Assert.Throws(() => _configManager.GetConfig(" ")); } [Test] public void WatchConfig_Should_Throw_When_Parameters_Invalid() { Assert.Throws(() => _configManager.WatchConfig(null!, _ => { })); Assert.Throws(() => _configManager.WatchConfig("key", null!)); } [Test] public void Concurrent_SetConfig_Should_Be_Thread_Safe() { const int threadCount = 10; const int iterationsPerThread = 100; var tasks = new Task[threadCount]; var exceptions = new List(); for (var i = 0; i < threadCount; i++) { var threadId = i; tasks[i] = Task.Run(() => { try { for (var j = 0; j < iterationsPerThread; j++) { _configManager.SetConfig($"key.{threadId}", j); } } catch (Exception ex) { lock (exceptions) { exceptions.Add(ex); } } }); } Task.WaitAll(tasks); Assert.That(exceptions, Is.Empty); } [Test] public void Concurrent_GetConfig_And_SetConfig_Should_Be_Thread_Safe() { const int threadCount = 5; var tasks = new Task[threadCount]; var exceptions = new List(); for (var i = 0; i < threadCount; i++) { tasks[i] = Task.Run(() => { try { for (var j = 0; j < 100; j++) { if (j % 2 == 0) { _configManager.SetConfig("shared.key", j); } else { _configManager.GetConfig("shared.key"); } } } catch (Exception ex) { lock (exceptions) { exceptions.Add(ex); } } }); } Task.WaitAll(tasks); Assert.That(exceptions, Is.Empty); } [Test] public void Concurrent_WatchConfig_Should_Be_Thread_Safe() { const int threadCount = 10; var tasks = new Task[threadCount]; var exceptions = new List(); var callCounts = new int[threadCount]; for (var i = 0; i < threadCount; i++) { var threadId = i; tasks[i] = Task.Run(() => { try { _configManager.WatchConfig("test.key", _ => { Interlocked.Increment(ref callCounts[threadId]); }); } catch (Exception ex) { lock (exceptions) { exceptions.Add(ex); } } }); } Task.WaitAll(tasks); _configManager.SetConfig("test.key", 42); Assert.That(exceptions, Is.Empty); Assert.That(callCounts.Sum(), Is.EqualTo(threadCount)); } }