diff --git a/Source/Settings/WindowsRegistryStore.Test.cs b/Source/Settings/WindowsRegistryStore.Test.cs index 0e4e116..7f4f2eb 100644 --- a/Source/Settings/WindowsRegistryStore.Test.cs +++ b/Source/Settings/WindowsRegistryStore.Test.cs @@ -18,15 +18,15 @@ License along with this library */ #endregion -#if UNITTEST +#if UNITTEST && WINDOWS using System; +using System.Collections.Generic; +using System.Globalization; + +using Microsoft.Win32; using NUnit.Framework; -using System.IO; -using Microsoft.Win32; -using System.Globalization; -using System.Collections.Generic; namespace Nuclex.Support.Settings { @@ -179,6 +179,76 @@ namespace Nuclex.Support.Settings { var optionInfos = new List(context.Store.EnumerateOptions(null)); Assert.That(optionInfos.Count, Is.EqualTo(3)); + + string[] actualNames = new string[] { + optionInfos[0].Name, optionInfos[1].Name, optionInfos[2].Name + }; + Assert.That(actualNames, Is.EquivalentTo(names)); + } + } + + /// + /// Verifies that accessing an option that doesn't exist throws an exception + /// + [Test] + public void AccessingNonExistingOptionThrowsException() { + using(var context = new TestContext()) { + Assert.That( + () => context.Store.Get(null, "doesn't exist"), + Throws.Exception.AssignableTo() + ); + } + } + + /// + /// Verifies that accessing a category that doesn't exist throws an exception + /// + [Test] + public void AccessingNonExistingCategoryThrowsException() { + using(var context = new TestContext()) { + Assert.That( + () => context.Store.Get("doesn't exist", "test"), + Throws.Exception.AssignableTo() + ); + } + } + + /// + /// Verifies that values can be removed from a registry key + /// + [Test] + public void ValuesCanBeRemovedFromRoot() { + using(var context = new TestContext()) { + context.Store.Set(null, "nothing", "short-lived"); + Assert.That(context.Store.Remove(null, "nothing"), Is.True); + Assert.That(context.Store.Remove(null, "nothing"), Is.False); + + Assert.That(context.Store.EnumerateOptions(), Is.Empty); + } + } + + /// + /// Verifies that values can be removed from the subkey of a registry key + /// + [Test] + public void ValuesCanBeRemovedFromCategory() { + using(var context = new TestContext()) { + context.Store.Set("limbo", "nothing", "short-lived"); + Assert.That(context.Store.Remove("limbo", "nothing"), Is.True); + Assert.That(context.Store.Remove("limbo", "nothing"), Is.False); + + Assert.That(context.Store.EnumerateOptions("limbo"), Is.Empty); + } + } + + /// + /// Verifies that values can be removed from a non-existing subkey without + /// causing an error + /// + [Test] + public void RemovingValueFromNonExistingCategoryCanBeHandled() { + using(var context = new TestContext()) { + Assert.That(context.Store.Remove("empty", "nothing"), Is.False); } } diff --git a/Source/Settings/WindowsRegistryStore.cs b/Source/Settings/WindowsRegistryStore.cs index 9781674..86204df 100644 --- a/Source/Settings/WindowsRegistryStore.cs +++ b/Source/Settings/WindowsRegistryStore.cs @@ -131,11 +131,11 @@ namespace Nuclex.Support.Settings { if(string.IsNullOrEmpty(category)) { return tryGetValueFromKey(this.rootKey, optionName, out value); } else { - RegistryKey categoryKey = this.rootKey.OpenSubKey(category, this.writable); - if(categoryKey == null) { - value = default(TValue); - return false; - } + RegistryKey categoryKey = this.rootKey.OpenSubKey(category, this.writable); + if(categoryKey == null) { + value = default(TValue); + return false; + } using(categoryKey) { return tryGetValueFromKey(categoryKey, optionName, out value); } @@ -151,16 +151,38 @@ namespace Nuclex.Support.Settings { if(string.IsNullOrEmpty(category)) { setValue(this.rootKey, optionName, value); } else { - RegistryKey categoryKey = this.rootKey.OpenSubKey(category, this.writable); - if(categoryKey == null) { - categoryKey = this.rootKey.CreateSubKey(category); - } + RegistryKey categoryKey = this.rootKey.OpenSubKey(category, this.writable); + if(categoryKey == null) { + categoryKey = this.rootKey.CreateSubKey(category); + } using(categoryKey) { setValue(categoryKey, optionName, value); } } } + /// Removes the option with the specified name + /// Category the option is found in. Can be null. + /// Name of the option that will be removed + /// True if the option was found and removed + public bool Remove(string category, string optionName) { + if(string.IsNullOrEmpty(category)) { + object value = this.rootKey.GetValue(optionName); + this.rootKey.DeleteValue(optionName, throwOnMissingValue: false); + return (value != null); + } else { + RegistryKey categoryKey = this.rootKey.OpenSubKey(category, this.writable); + if(categoryKey == null) { + return false; + } + using(categoryKey) { + object value = categoryKey.GetValue(optionName); + categoryKey.DeleteValue(optionName, throwOnMissingValue: false); + return (value != null); + } + } + } + /// Writes a setting to the registry /// /// @@ -187,14 +209,6 @@ namespace Nuclex.Support.Settings { } } - /// Removes the option with the specified name - /// Category the option is found in. Can be null. - /// Name of the option that will be removed - /// True if the option was found and removed - public bool Remove(string category, string optionName) { - throw new NotImplementedException(); - } - /// Tries to retrieve the value of a registry key if it exists /// Type of value the registry key is expected to have /// Registry key the value is stored under @@ -228,33 +242,7 @@ namespace Nuclex.Support.Settings { case RegistryValueKind.QWord: { return typeof(long); } case RegistryValueKind.MultiString: { return typeof(string[]); } case RegistryValueKind.ExpandString: - case RegistryValueKind.String: { - string value = (string)categoryKey.GetValue(optionName); - if(value.Length == 0) { - return typeof(string); - } - - // If there are at least two characters, it may be an integer with - // a sign in front of it - if(value.Length >= 2) { - int index = 0; - if(ParserHelper.SkipInteger(value, ref index)) { - if(index >= value.Length) { - return typeof(int); - } - if(value[index] == '.') { - return typeof(float); - } - } - } else { // If it's just a single character, it may be a number - if(char.IsNumber(value, 0)) { - return typeof(int); - } - } - - return typeof(string); - } - + case RegistryValueKind.String: { return typeof(string); } case RegistryValueKind.Unknown: case RegistryValueKind.None: default: { return typeof(string); }