| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 |
- #nullable enable
- using System.Collections.Concurrent;
- using System.Reflection;
- using System.Text.Json;
- namespace UnitTests.ConfigurationTests;
- public class ConfigPropertyTests
- {
- [Fact]
- public void Apply_PropertyValueIsAppliedToStatic_String_Property ()
- {
- // Arrange
- TestConfiguration.Reset ();
- var propertyInfo = typeof (TestConfiguration).GetProperty (nameof (TestConfiguration.TestStringProperty));
- var configProperty = new ConfigProperty
- {
- PropertyInfo = propertyInfo,
- PropertyValue = "UpdatedValue"
- };
- // Act
- var result = configProperty.Apply ();
- // Assert
- Assert.Equal (1, TestConfiguration.TestStringPropertySetCount);
- Assert.True (result);
- Assert.Equal ("UpdatedValue", TestConfiguration.TestStringProperty);
- TestConfiguration.Reset ();
- }
- [Fact]
- public void Apply_PropertyValueIsAppliedToStatic_Key_Property ()
- {
- // Arrange
- TestConfiguration.Reset ();
- var propertyInfo = typeof (TestConfiguration).GetProperty (nameof (TestConfiguration.TestKeyProperty));
- var configProperty = new ConfigProperty
- {
- PropertyInfo = propertyInfo,
- PropertyValue = Key.Q.WithCtrl
- };
- // Act
- var result = configProperty.Apply ();
- // Assert
- Assert.Equal (1, TestConfiguration.TestKeyPropertySetCount);
- Assert.True (result);
- Assert.Equal (Key.Q.WithCtrl, TestConfiguration.TestKeyProperty);
- TestConfiguration.Reset ();
- }
- [Fact]
- public void RetrieveValue_GetsCurrentValueOfStaticProperty ()
- {
- // Arrange
- TestConfiguration.TestStringProperty = "CurrentValue";
- var propertyInfo = typeof (TestConfiguration).GetProperty (nameof (TestConfiguration.TestStringProperty));
- var configProperty = new ConfigProperty
- {
- PropertyInfo = propertyInfo
- };
- // Act
- var value = configProperty.UpdateToCurrentValue ();
- // Assert
- Assert.Equal ("CurrentValue", value);
- Assert.Equal ("CurrentValue", configProperty.PropertyValue);
- }
- [Fact]
- public void DeepCloneFrom_Updates_String_Property_Value ()
- {
- // Arrange
- TestConfiguration.Reset ();
- var propertyInfo = typeof (TestConfiguration).GetProperty (nameof (TestConfiguration.TestStringProperty));
- var configProperty = new ConfigProperty
- {
- PropertyInfo = propertyInfo,
- PropertyValue = "InitialValue"
- };
- // Act
- var updatedValue = configProperty.UpdateFrom ("NewValue");
- // Assert
- Assert.Equal (0, TestConfiguration.TestStringPropertySetCount);
- Assert.Equal ("NewValue", updatedValue);
- Assert.Equal ("NewValue", configProperty.PropertyValue);
- TestConfiguration.Reset ();
- }
- //[Fact]
- //public void UpdateValueFrom_InvalidType_ThrowsArgumentException()
- //{
- // // Arrange
- // var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestStringProperty));
- // var configProperty = new ConfigProperty
- // {
- // PropertyInfo = propertyInfo
- // };
- // // Act & Assert
- // Assert.Throws<ArgumentException>(() => configProperty.UpdateValueFrom(123));
- //}
- [Fact]
- public void Apply_TargetInvocationException_ThrowsJsonException ()
- {
- // Arrange
- var propertyInfo = typeof (TestConfiguration).GetProperty (nameof (TestConfiguration.TestStringProperty));
- var configProperty = new ConfigProperty
- {
- PropertyInfo = propertyInfo,
- PropertyValue = null // This will cause ArgumentNullException in the set accessor
- };
- // Act & Assert
- var exception = Assert.Throws<JsonException> (() => configProperty.Apply ());
- }
- [Fact]
- public void GetJsonPropertyName_ReturnsJsonPropertyNameAttributeValue ()
- {
- // Arrange
- var propertyInfo = typeof (TestConfiguration).GetProperty (nameof (TestConfiguration.TestStringProperty));
- // Act
- var jsonPropertyName = ConfigProperty.GetJsonPropertyName (propertyInfo!);
- // Assert
- Assert.Equal ("TestStringProperty", jsonPropertyName);
- }
- [Fact]
- public void UpdateFrom_NullSource_ReturnsExistingValue()
- {
- // Arrange
- TestConfiguration.TestStringProperty = "CurrentValue";
- var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestStringProperty));
- var configProperty = new ConfigProperty
- {
- PropertyInfo = propertyInfo,
- PropertyValue = "ExistingValue"
- };
- // Act
- var result = configProperty.UpdateFrom(null);
- // Assert
- Assert.Equal("ExistingValue", result);
- Assert.Equal("ExistingValue", configProperty.PropertyValue);
- }
- [Fact]
- public void UpdateFrom_InvalidType_ThrowsArgumentException()
- {
- // Arrange
- var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestStringProperty));
- var configProperty = new ConfigProperty
- {
- PropertyInfo = propertyInfo,
- PropertyValue = "ExistingValue"
- };
- // Act & Assert
- Assert.Throws<ArgumentException>(() => configProperty.UpdateFrom(123));
- }
- [Fact]
- public void UpdateFrom_ConfigPropertySource_CopiesValue()
- {
- // Arrange
- var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestStringProperty));
- var configProperty = new ConfigProperty
- {
- PropertyInfo = propertyInfo,
- PropertyValue = "ExistingValue"
- };
- var sourceConfigProperty = new ConfigProperty
- {
- PropertyValue = "SourceValue",
- HasValue = true
- };
- // Act
- var result = configProperty.UpdateFrom(sourceConfigProperty);
- // Assert
- Assert.Equal("SourceValue", result);
- Assert.Equal("SourceValue", configProperty.PropertyValue);
- }
- [Fact]
- public void UpdateFrom_ConfigPropertySource_WithoutValue_KeepsExistingValue()
- {
- // Arrange
- var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestStringProperty));
- var configProperty = new ConfigProperty
- {
- PropertyInfo = propertyInfo,
- PropertyValue = "ExistingValue"
- };
- var sourceConfigProperty = new ConfigProperty
- {
- HasValue = false
- };
- // Act
- var result = configProperty.UpdateFrom(sourceConfigProperty);
- // Assert
- Assert.Equal("ExistingValue", result);
- Assert.Equal("ExistingValue", configProperty.PropertyValue);
- }
- [Fact]
- public void UpdateFrom_ConcurrentDictionaryOfThemeScopes_UpdatesValues()
- {
- // Arrange
- var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestDictionaryProperty));
- // Create a destination dictionary
- var destinationDict = new ConcurrentDictionary<string, ThemeScope>(StringComparer.InvariantCultureIgnoreCase);
- destinationDict.TryAdd("theme1", new ThemeScope());
- var configProperty = new ConfigProperty
- {
- PropertyInfo = propertyInfo,
- PropertyValue = destinationDict
- };
- // Create a source dictionary with one matching key and one new key
- var sourceDict = new ConcurrentDictionary<string, ThemeScope>(StringComparer.InvariantCultureIgnoreCase);
- var sourceTheme1 = new ThemeScope();
- var sourceTheme2 = new ThemeScope();
- // Add a property to sourceTheme1 to verify it gets updated
- var keyProperty = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestKeyProperty));
- if (sourceTheme1.TryAdd("TestKey", new ConfigProperty { PropertyInfo = keyProperty, PropertyValue = Key.A.WithCtrl, HasValue = true }))
- {
- // Successfully added
- }
- sourceDict.TryAdd("theme1", sourceTheme1);
- sourceDict.TryAdd("theme2", sourceTheme2);
- // Act
- var result = configProperty.UpdateFrom(sourceDict);
- // Assert
- var resultDict = result as ConcurrentDictionary<string, ThemeScope>;
- Assert.NotNull(resultDict);
- Assert.Equal(2, resultDict.Count);
- Assert.True(resultDict.ContainsKey("theme1"));
- Assert.True(resultDict.ContainsKey("theme2"));
- // Verify the theme1 was updated with the property
- Assert.True(resultDict["theme1"].ContainsKey("TestKey"));
- Assert.Equal(Key.A.WithCtrl, resultDict["theme1"]["TestKey"].PropertyValue);
- }
- [Fact]
- public void UpdateFrom_ConcurrentDictionaryOfConfigProperties_UpdatesValues()
- {
- // Arrange
- var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestConfigDictionaryProperty));
- // Create a destination dictionary
- var destinationDict = new ConcurrentDictionary<string, ConfigProperty>(StringComparer.InvariantCultureIgnoreCase);
- destinationDict.TryAdd("prop1", new ConfigProperty { PropertyValue = "Original", HasValue = true });
- var configProperty = new ConfigProperty
- {
- PropertyInfo = propertyInfo,
- PropertyValue = destinationDict
- };
- // Create a source dictionary with one matching key and one new key
- var sourceDict = new ConcurrentDictionary<string, ConfigProperty>(StringComparer.InvariantCultureIgnoreCase);
- sourceDict.TryAdd("prop1", new ConfigProperty { PropertyValue = "Updated", HasValue = true });
- sourceDict.TryAdd("prop2", new ConfigProperty { PropertyValue = "New", HasValue = true });
- // Act
- var result = configProperty.UpdateFrom(sourceDict);
- // Assert
- var resultDict = result as ConcurrentDictionary<string, ConfigProperty>;
- Assert.NotNull(resultDict);
- Assert.Equal(2, resultDict.Count);
- Assert.True(resultDict.ContainsKey("prop1"));
- Assert.True(resultDict.ContainsKey("prop2"));
- Assert.Equal("Updated", resultDict["prop1"].PropertyValue);
- Assert.Equal("New", resultDict["prop2"].PropertyValue);
- }
- [Fact]
- public void UpdateFrom_DictionaryOfConfigProperties_UpdatesValues()
- {
- // Arrange
- var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestConfigDictionaryProperty));
- // Create a destination dictionary
- var destinationDict = new Dictionary<string, ConfigProperty>(StringComparer.InvariantCultureIgnoreCase);
- destinationDict.Add("prop1", new ConfigProperty { PropertyValue = "Original", HasValue = true });
- var configProperty = new ConfigProperty
- {
- PropertyInfo = propertyInfo,
- PropertyValue = destinationDict
- };
- // Create a source dictionary with one matching key and one new key
- var sourceDict = new Dictionary<string, ConfigProperty>(StringComparer.InvariantCultureIgnoreCase);
- sourceDict.Add("prop1", new ConfigProperty { PropertyValue = "Updated", HasValue = true });
- sourceDict.Add("prop2", new ConfigProperty { PropertyValue = "New", HasValue = true });
- // Act
- var result = configProperty.UpdateFrom(sourceDict);
- // Assert
- var resultDict = result as Dictionary<string, ConfigProperty>;
- Assert.NotNull(resultDict);
- Assert.Equal(2, resultDict.Count);
- Assert.True(resultDict.ContainsKey("prop1"));
- Assert.True(resultDict.ContainsKey("prop2"));
- Assert.Equal("Updated", resultDict["prop1"].PropertyValue);
- Assert.Equal("New", resultDict["prop2"].PropertyValue);
- }
- [Fact]
- public void PropertyValue_SetWhenImmutable_ThrowsException()
- {
- // Arrange
- var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestStringProperty));
- var configProperty = new ConfigProperty
- {
- PropertyInfo = propertyInfo,
- Immutable = true
- };
- // Act & Assert
- var exception = Assert.Throws<InvalidOperationException>(() => configProperty.PropertyValue = "New Value");
- Assert.Contains("immutable", exception.Message);
- }
- [Fact]
- public void CreateWithAttributeInfo_ReturnsConfigPropertyWithCorrectValues()
- {
- // Arrange
- var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestStringProperty));
- // Act
- var configProperty = ConfigProperty.CreateImmutableWithAttributeInfo(propertyInfo!);
- // Assert
- Assert.Equal(propertyInfo, configProperty.PropertyInfo);
- Assert.False(configProperty.OmitClassName);
- Assert.True(configProperty.Immutable);
- Assert.Null(configProperty.PropertyValue);
- Assert.False(configProperty.HasValue);
- }
- [Fact]
- public void HasConfigurationPropertyAttribute_ReturnsTrue_ForDecoratedProperty()
- {
- // Arrange
- var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestStringProperty));
- // Act
- var result = ConfigProperty.HasConfigurationPropertyAttribute(propertyInfo!);
- // Assert
- Assert.True(result);
- }
- [Fact]
- public void HasConfigurationPropertyAttribute_ReturnsFalse_ForNonDecoratedProperty()
- {
- // Arrange
- var propertyInfo = typeof(TestConfiguration).GetProperty(nameof(TestConfiguration.TestStringPropertySetCount));
- // Act
- var result = ConfigProperty.HasConfigurationPropertyAttribute(propertyInfo!);
- // Assert
- Assert.False(result);
- }
- public class TestConfiguration
- {
- private static string _testStringProperty = "Default";
- public static int TestStringPropertySetCount { get; set; }
- [ConfigurationProperty]
- public static string TestStringProperty
- {
- get => _testStringProperty;
- set
- {
- TestStringPropertySetCount++;
- _testStringProperty = value ?? throw new ArgumentNullException (nameof (value));
- }
- }
- private static Key _testKeyProperty = Key.Esc;
- public static int TestKeyPropertySetCount { get; set; }
- [ConfigurationProperty]
- public static Key TestKeyProperty
- {
- get => _testKeyProperty;
- set
- {
- TestKeyPropertySetCount++;
- _testKeyProperty = value ?? throw new ArgumentNullException (nameof (value));
- }
- }
- // Add these new properties for testing dictionaries
- [ConfigurationProperty]
- public static ConcurrentDictionary<string, ThemeScope>? TestDictionaryProperty { get; set; }
- [ConfigurationProperty]
- public static Dictionary<string, ConfigProperty>? TestRegularDictionaryProperty { get; set; }
- [ConfigurationProperty]
- public static ConcurrentDictionary<string, ConfigProperty>? TestConfigDictionaryProperty { get; set; }
- [ConfigurationProperty]
- public static Scheme? TestSchemeProperty { get; set; }
- public static void Reset ()
- {
- TestStringPropertySetCount = 0;
- TestKeyPropertySetCount = 0;
- TestDictionaryProperty = null;
- TestRegularDictionaryProperty = null;
- TestConfigDictionaryProperty = null;
- TestSchemeProperty = null;
- }
- }
- [Fact]
- public void UpdateFrom_SchemeSource_UpdatesValue ()
- {
- // Arrange
- PropertyInfo? propertyInfo = typeof (TestConfiguration).GetProperty (nameof (TestConfiguration.TestSchemeProperty));
- Scheme sourceScheme = new (new Attribute (Color.Red, Color.Blue, TextStyle.Bold));
- var configProperty = new ConfigProperty
- {
- PropertyInfo = propertyInfo!,
- PropertyValue = new Scheme (new Attribute (Color.White, Color.Black, TextStyle.None))
- };
- // Act
- object? result = configProperty.UpdateFrom (sourceScheme);
- // Assert
- Assert.Equal (sourceScheme, result);
- Assert.Equal (sourceScheme, configProperty.PropertyValue);
- Assert.NotSame (sourceScheme, configProperty.PropertyValue); // Prove it's a clone, not a ref
- }
- }
|