From d55ba52369bce2a41b6f304cae109c102cc5be5b Mon Sep 17 00:00:00 2001 From: Markus Ewald Date: Mon, 21 Jul 2014 12:58:33 +0000 Subject: [PATCH] Fully implemented the memory store and added unit tests for it git-svn-id: file:///srv/devel/repo-conversion/nusu@308 d2e56fa2-650e-0410-a79f-9358c0239efd --- .../Settings/ConfigurationFileStore.Test.cs | 18 ++- Source/Settings/MemoryStore.Test.cs | 129 ++++++++++++++++++ Source/Settings/MemoryStore.cs | 47 ++++++- 3 files changed, 190 insertions(+), 4 deletions(-) diff --git a/Source/Settings/ConfigurationFileStore.Test.cs b/Source/Settings/ConfigurationFileStore.Test.cs index b1ae6a5..5b1cb23 100644 --- a/Source/Settings/ConfigurationFileStore.Test.cs +++ b/Source/Settings/ConfigurationFileStore.Test.cs @@ -305,7 +305,7 @@ namespace Nuclex.Support.Settings { } /// - /// Verifies that it's possible to assign an empty value to an option + /// Verifies that it's possible to remove options from the configuration file /// [Test] public void OptionsCanBeRemoved() { @@ -313,6 +313,9 @@ namespace Nuclex.Support.Settings { configurationFile.Set(null, "test", null); Assert.That(configurationFile.Remove(null, "test"), Is.True); + + string value; + Assert.That(configurationFile.TryGet(null, "test", out value), Is.False); } /// @@ -385,6 +388,19 @@ namespace Nuclex.Support.Settings { Assert.That(info.OptionType, Is.EqualTo(expectedType)); } + /// + /// Verifies that configuration files containing duplicate option names can not + /// be used with the configuration file store + /// + [Test] + public void FilesWithDuplicateOptionNamesCannotBeProcessed() { + string fileContents = + "duplicate name = 1\r\n" + + "duplicate name = 2"; + + Assert.That(() => load(fileContents), Throws.Exception); + } + /// Loads a configuration file from a string /// Contents of the configuration file /// The configuration file loaded from the string diff --git a/Source/Settings/MemoryStore.Test.cs b/Source/Settings/MemoryStore.Test.cs index 4be3be9..cde79ab 100644 --- a/Source/Settings/MemoryStore.Test.cs +++ b/Source/Settings/MemoryStore.Test.cs @@ -21,6 +21,7 @@ License along with this library #if UNITTEST using System; +using System.Collections.Generic; using NUnit.Framework; @@ -29,6 +30,134 @@ namespace Nuclex.Support.Settings { /// Unit tests for the memory settings store [TestFixture] internal class MemoryStoreTest { + + /// Verifies that constructed a memory store throws an exception + [Test] + public void CanBeCreated() { + Assert.That(() => new MemoryStore(), Throws.Nothing); + } + + /// + /// Verifies that it's possible to enumerate the options in a non-existing category + /// + [Test] + public void NonExistingCategoriesCanBeEnumerated() { + var memoryStore = new MemoryStore(); + Assert.That(memoryStore.EnumerateOptions("doesn't exist"), Is.Empty); + } + + /// + /// Verifies that accessing an option that doesn't exist throws an exception + /// + [Test] + public void AccessingNonExistingOptionThrowsException() { + var memoryStore = new MemoryStore(); + + Assert.That( + () => memoryStore.Get(null, "doesn't exist"), + Throws.Exception.AssignableTo() + ); + } + + /// + /// Verifies that accessing a category that doesn't exist throws an exception + /// + [Test] + public void AccessingNonExistingCategoryThrowsException() { + var memoryStore = new MemoryStore(); + memoryStore.Set(null, "test", "123"); + + Assert.That( + () => memoryStore.Get("doesn't exist", "test"), + Throws.Exception.AssignableTo() + ); + } + + /// + /// Verifies that settings can be stored in the memory store + /// + [Test] + public void SettingsCanBeAssignedAndRetrieved() { + var memoryStore = new MemoryStore(); + memoryStore.Set("general", "sol", "42"); + + Assert.That(memoryStore.Get("general", "sol"), Is.EqualTo("42")); + } + + /// + /// Verifies that it's possible to remove options from the memory store + /// + [Test] + public void OptionsCanBeRemoved() { + var memoryStore = new MemoryStore(); + memoryStore.Set(null, "test", null); + + Assert.That(memoryStore.Remove(null, "test"), Is.True); + + string value; + Assert.That(memoryStore.TryGet(null, "test", out value), Is.False); + } + + /// + /// Verifies that it's not an error to remove an option from a non-existing category + /// + [Test] + public void CanRemoveOptionFromNonExistingCategory() { + var memoryStore = new MemoryStore(); + Assert.That(memoryStore.Remove("nothing", "first"), Is.False); + } + + /// + /// Verifies that it's not an error to remove a non-existing option + /// + [Test] + public void CanRemoveNonExistingOption() { + var memoryStore = new MemoryStore(); + Assert.That(memoryStore.Remove(null, "first"), Is.False); + } + + /// + /// Verifies that the root category is not part of the enumerated categories + /// + [Test] + public void RootCategoryIsNotEnumerated() { + var memoryStore = new MemoryStore(); + Assert.That(memoryStore.EnumerateCategories(), Is.Empty); + } + + /// + /// Verifies that the root category is not part of the enumerated categories + /// + [Test] + public void OptionsInRootCategoryCanBeEnumerated() { + var memoryStore = new MemoryStore(); + + string[] optionNames = new string[] { "first", "second" }; + memoryStore.Set(null, optionNames[0], 1); + memoryStore.Set(null, optionNames[1], 2); + + var optionInfos = new List(memoryStore.EnumerateOptions()); + Assert.That(optionInfos.Count, Is.EqualTo(2)); + + var enumeratedOptionNames = new List() { + optionInfos[0].Name, optionInfos[1].Name + }; + Assert.That(enumeratedOptionNames, Is.EquivalentTo(optionNames)); + } + + /// + /// Verifies that the root category is not part of the enumerated categories + /// + [Test] + public void CategoriesCanBeCreated() { + var memoryStore = new MemoryStore(); + + memoryStore.Set(null, "not", "used"); + memoryStore.Set("test", "message", "hello world"); + + Assert.That(memoryStore.EnumerateCategories(), Is.EquivalentTo(new string[] { "test" })); + } + } } // namespace Nuclex.Support.Settings diff --git a/Source/Settings/MemoryStore.cs b/Source/Settings/MemoryStore.cs index a25518e..083373f 100644 --- a/Source/Settings/MemoryStore.cs +++ b/Source/Settings/MemoryStore.cs @@ -91,7 +91,17 @@ namespace Nuclex.Support.Settings { /// parameter, false otherwise /// public bool TryGet(string category, string optionName, out TValue value) { - throw new NotImplementedException(); + IDictionary categoryOptions = getCategoryByName(category); + if(categoryOptions != null) { + object valueAsObject; + if(categoryOptions.TryGetValue(optionName, out valueAsObject)) { + value = (TValue)Convert.ChangeType(valueAsObject, typeof(TValue)); + return true; + } + } + + value = default(TValue); + return false; } /// Saves an option in the settings store @@ -100,7 +110,18 @@ namespace Nuclex.Support.Settings { /// Name of the option that will be saved /// The value under which the option will be saved public void Set(string category, string optionName, TValue value) { - throw new NotImplementedException(); + IDictionary targetCategory; + + if(string.IsNullOrEmpty(category)) { + targetCategory = this.rootOptions; + } else if(!this.options.TryGetValue(category, out targetCategory)) { + targetCategory = new Dictionary(); + this.options.Add(category, targetCategory); + targetCategory.Add(optionName, value); + return; + } + + targetCategory[optionName] = value; } /// Removes the option with the specified name @@ -108,7 +129,27 @@ namespace Nuclex.Support.Settings { /// 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(); + IDictionary targetCategory = getCategoryByName(category); + if(targetCategory == null) { + return false; + } + + return targetCategory.Remove(optionName); + } + + /// Looks up a category by its name + /// Name of the category that will be looked up + /// The category with the specified name if found, null otherwise + private IDictionary getCategoryByName(string name) { + IDictionary category; + + if(string.IsNullOrEmpty(name)) { + category = this.rootOptions; + } else if(!this.options.TryGetValue(name, out category)) { + return null; + } + + return category; } /// Categories and the options stored in them