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
This commit is contained in:
Markus Ewald 2014-07-21 12:58:33 +00:00
parent 03ada146e5
commit d55ba52369
3 changed files with 190 additions and 4 deletions

View File

@ -305,7 +305,7 @@ namespace Nuclex.Support.Settings {
} }
/// <summary> /// <summary>
/// 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
/// </summary> /// </summary>
[Test] [Test]
public void OptionsCanBeRemoved() { public void OptionsCanBeRemoved() {
@ -313,6 +313,9 @@ namespace Nuclex.Support.Settings {
configurationFile.Set<string>(null, "test", null); configurationFile.Set<string>(null, "test", null);
Assert.That(configurationFile.Remove(null, "test"), Is.True); Assert.That(configurationFile.Remove(null, "test"), Is.True);
string value;
Assert.That(configurationFile.TryGet<string>(null, "test", out value), Is.False);
} }
/// <summary> /// <summary>
@ -385,6 +388,19 @@ namespace Nuclex.Support.Settings {
Assert.That(info.OptionType, Is.EqualTo(expectedType)); Assert.That(info.OptionType, Is.EqualTo(expectedType));
} }
/// <summary>
/// Verifies that configuration files containing duplicate option names can not
/// be used with the configuration file store
/// </summary>
[Test]
public void FilesWithDuplicateOptionNamesCannotBeProcessed() {
string fileContents =
"duplicate name = 1\r\n" +
"duplicate name = 2";
Assert.That(() => load(fileContents), Throws.Exception);
}
/// <summary>Loads a configuration file from a string</summary> /// <summary>Loads a configuration file from a string</summary>
/// <param name="fileContents">Contents of the configuration file</param> /// <param name="fileContents">Contents of the configuration file</param>
/// <returns>The configuration file loaded from the string</returns> /// <returns>The configuration file loaded from the string</returns>

View File

@ -21,6 +21,7 @@ License along with this library
#if UNITTEST #if UNITTEST
using System; using System;
using System.Collections.Generic;
using NUnit.Framework; using NUnit.Framework;
@ -29,6 +30,134 @@ namespace Nuclex.Support.Settings {
/// <summary>Unit tests for the memory settings store</summary> /// <summary>Unit tests for the memory settings store</summary>
[TestFixture] [TestFixture]
internal class MemoryStoreTest { internal class MemoryStoreTest {
/// <summary>Verifies that constructed a memory store throws an exception</summary>
[Test]
public void CanBeCreated() {
Assert.That(() => new MemoryStore(), Throws.Nothing);
}
/// <summary>
/// Verifies that it's possible to enumerate the options in a non-existing category
/// </summary>
[Test]
public void NonExistingCategoriesCanBeEnumerated() {
var memoryStore = new MemoryStore();
Assert.That(memoryStore.EnumerateOptions("doesn't exist"), Is.Empty);
}
/// <summary>
/// Verifies that accessing an option that doesn't exist throws an exception
/// </summary>
[Test]
public void AccessingNonExistingOptionThrowsException() {
var memoryStore = new MemoryStore();
Assert.That(
() => memoryStore.Get<string>(null, "doesn't exist"),
Throws.Exception.AssignableTo<KeyNotFoundException>()
);
}
/// <summary>
/// Verifies that accessing a category that doesn't exist throws an exception
/// </summary>
[Test]
public void AccessingNonExistingCategoryThrowsException() {
var memoryStore = new MemoryStore();
memoryStore.Set<string>(null, "test", "123");
Assert.That(
() => memoryStore.Get<string>("doesn't exist", "test"),
Throws.Exception.AssignableTo<KeyNotFoundException>()
);
}
/// <summary>
/// Verifies that settings can be stored in the memory store
/// </summary>
[Test]
public void SettingsCanBeAssignedAndRetrieved() {
var memoryStore = new MemoryStore();
memoryStore.Set<string>("general", "sol", "42");
Assert.That(memoryStore.Get<string>("general", "sol"), Is.EqualTo("42"));
}
/// <summary>
/// Verifies that it's possible to remove options from the memory store
/// </summary>
[Test]
public void OptionsCanBeRemoved() {
var memoryStore = new MemoryStore();
memoryStore.Set<string>(null, "test", null);
Assert.That(memoryStore.Remove(null, "test"), Is.True);
string value;
Assert.That(memoryStore.TryGet<string>(null, "test", out value), Is.False);
}
/// <summary>
/// Verifies that it's not an error to remove an option from a non-existing category
/// </summary>
[Test]
public void CanRemoveOptionFromNonExistingCategory() {
var memoryStore = new MemoryStore();
Assert.That(memoryStore.Remove("nothing", "first"), Is.False);
}
/// <summary>
/// Verifies that it's not an error to remove a non-existing option
/// </summary>
[Test]
public void CanRemoveNonExistingOption() {
var memoryStore = new MemoryStore();
Assert.That(memoryStore.Remove(null, "first"), Is.False);
}
/// <summary>
/// Verifies that the root category is not part of the enumerated categories
/// </summary>
[Test]
public void RootCategoryIsNotEnumerated() {
var memoryStore = new MemoryStore();
Assert.That(memoryStore.EnumerateCategories(), Is.Empty);
}
/// <summary>
/// Verifies that the root category is not part of the enumerated categories
/// </summary>
[Test]
public void OptionsInRootCategoryCanBeEnumerated() {
var memoryStore = new MemoryStore();
string[] optionNames = new string[] { "first", "second" };
memoryStore.Set<int>(null, optionNames[0], 1);
memoryStore.Set<int>(null, optionNames[1], 2);
var optionInfos = new List<OptionInfo>(memoryStore.EnumerateOptions());
Assert.That(optionInfos.Count, Is.EqualTo(2));
var enumeratedOptionNames = new List<string>() {
optionInfos[0].Name, optionInfos[1].Name
};
Assert.That(enumeratedOptionNames, Is.EquivalentTo(optionNames));
}
/// <summary>
/// Verifies that the root category is not part of the enumerated categories
/// </summary>
[Test]
public void CategoriesCanBeCreated() {
var memoryStore = new MemoryStore();
memoryStore.Set<string>(null, "not", "used");
memoryStore.Set<string>("test", "message", "hello world");
Assert.That(memoryStore.EnumerateCategories(), Is.EquivalentTo(new string[] { "test" }));
}
} }
} // namespace Nuclex.Support.Settings } // namespace Nuclex.Support.Settings

View File

@ -91,7 +91,17 @@ namespace Nuclex.Support.Settings {
/// parameter, false otherwise /// parameter, false otherwise
/// </returns> /// </returns>
public bool TryGet<TValue>(string category, string optionName, out TValue value) { public bool TryGet<TValue>(string category, string optionName, out TValue value) {
throw new NotImplementedException(); IDictionary<string, object> 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;
} }
/// <summary>Saves an option in the settings store</summary> /// <summary>Saves an option in the settings store</summary>
@ -100,7 +110,18 @@ namespace Nuclex.Support.Settings {
/// <param name="optionName">Name of the option that will be saved</param> /// <param name="optionName">Name of the option that will be saved</param>
/// <param name="value">The value under which the option will be saved</param> /// <param name="value">The value under which the option will be saved</param>
public void Set<TValue>(string category, string optionName, TValue value) { public void Set<TValue>(string category, string optionName, TValue value) {
throw new NotImplementedException(); IDictionary<string, object> targetCategory;
if(string.IsNullOrEmpty(category)) {
targetCategory = this.rootOptions;
} else if(!this.options.TryGetValue(category, out targetCategory)) {
targetCategory = new Dictionary<string, object>();
this.options.Add(category, targetCategory);
targetCategory.Add(optionName, value);
return;
}
targetCategory[optionName] = value;
} }
/// <summary>Removes the option with the specified name</summary> /// <summary>Removes the option with the specified name</summary>
@ -108,7 +129,27 @@ namespace Nuclex.Support.Settings {
/// <param name="optionName">Name of the option that will be removed</param> /// <param name="optionName">Name of the option that will be removed</param>
/// <returns>True if the option was found and removed</returns> /// <returns>True if the option was found and removed</returns>
public bool Remove(string category, string optionName) { public bool Remove(string category, string optionName) {
throw new NotImplementedException(); IDictionary<string, object> targetCategory = getCategoryByName(category);
if(targetCategory == null) {
return false;
}
return targetCategory.Remove(optionName);
}
/// <summary>Looks up a category by its name</summary>
/// <param name="name">Name of the category that will be looked up</param>
/// <returns>The category with the specified name if found, null otherwise</returns>
private IDictionary<string, object> getCategoryByName(string name) {
IDictionary<string, object> category;
if(string.IsNullOrEmpty(name)) {
category = this.rootOptions;
} else if(!this.options.TryGetValue(name, out category)) {
return null;
}
return category;
} }
/// <summary>Categories and the options stored in them</summary> /// <summary>Categories and the options stored in them</summary>