Moved all unit test files into a separate directory in preparation for splitting the project
This commit is contained in:
parent
28b96fd557
commit
ba5234f701
58 changed files with 0 additions and 853 deletions
466
Tests/Settings/ConfigurationFileStoreTest.cs
Normal file
466
Tests/Settings/ConfigurationFileStoreTest.cs
Normal file
|
@ -0,0 +1,466 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Settings {
|
||||
|
||||
/// <summary>Unit tests for the configuration file store</summary>
|
||||
[TestFixture]
|
||||
internal class ConfigurationFileStoreTest {
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that loading an empty file doesn't lead to an exception
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CanParseEmptyFile() {
|
||||
Assert.That(() => load(string.Empty), Throws.Nothing);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that categories can be parsed from a configuration file
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CanParseCategories() {
|
||||
string[] categoryNames = new string[] { "Category1", "Category 2" };
|
||||
string fileContents =
|
||||
"[" + categoryNames[0] + "]\r\n" +
|
||||
" [ " + categoryNames[1] + " ] \r\n";
|
||||
ConfigurationFileStore configurationFile = load(fileContents);
|
||||
|
||||
Assert.That(configurationFile.EnumerateCategories(), Is.EquivalentTo(categoryNames));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that malformed categories can be handled by the parser
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void MalformedCategoriesAreIgnored() {
|
||||
string fileContents =
|
||||
"[ Not a category\r\n" +
|
||||
" [";
|
||||
ConfigurationFileStore configurationFile = load(fileContents);
|
||||
|
||||
Assert.That(configurationFile.EnumerateCategories(), Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that empty lines in the configuration file have no meaning
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void EmptyLinesAreSkipped() {
|
||||
string fileContents =
|
||||
"\r\n" +
|
||||
" ";
|
||||
ConfigurationFileStore configurationFile = load(fileContents);
|
||||
Assert.That(configurationFile.EnumerateCategories(), Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that category definitions after a comment sign are ignored
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CommentedOutCategoriesAreIgnored() {
|
||||
string fileContents =
|
||||
"#[NotACategory]\r\n" +
|
||||
"; [ Also Not A Category ]\r\n";
|
||||
ConfigurationFileStore configurationFile = load(fileContents);
|
||||
Assert.That(configurationFile.EnumerateCategories(), Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that assignments without an option name are ignored by the parser
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void NamelessAssignmentsAreIgnored() {
|
||||
string fileContents =
|
||||
"=\r\n" +
|
||||
" = \r\n" +
|
||||
" = hello";
|
||||
ConfigurationFileStore configurationFile = load(fileContents);
|
||||
Assert.That(configurationFile.EnumerateCategories(), Is.Empty);
|
||||
Assert.That(configurationFile.EnumerateOptions(), Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that assignments without an option name are ignored by the parser
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OptionsCanHaveEmptyValues() {
|
||||
string fileContents =
|
||||
"a =\r\n" +
|
||||
"b = \r\n" +
|
||||
"c = ; hello";
|
||||
ConfigurationFileStore configurationFile = load(fileContents);
|
||||
Assert.That(configurationFile.EnumerateCategories(), Is.Empty);
|
||||
|
||||
var options = new List<OptionInfo>(configurationFile.EnumerateOptions());
|
||||
Assert.That(options.Count, Is.EqualTo(3));
|
||||
|
||||
for(int index = 0; index < options.Count; ++index) {
|
||||
Assert.That(
|
||||
configurationFile.Get<string>(null, options[index].Name), Is.Null.Or.Empty
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that values assigned to options can contain space charcters
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OptionValuesCanContainSpaces() {
|
||||
string fileContents =
|
||||
"test = hello world";
|
||||
ConfigurationFileStore configurationFile = load(fileContents);
|
||||
|
||||
Assert.That(configurationFile.Get<string>(null, "test"), Is.EqualTo("hello world"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that values enclosed in quotes can embed comment characters
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OptionValuesWithQuotesCanEmbedComments() {
|
||||
string fileContents =
|
||||
"test = \"This ; is # not a comment\" # but this is";
|
||||
ConfigurationFileStore configurationFile = load(fileContents);
|
||||
|
||||
Assert.That(
|
||||
configurationFile.Get<string>(null, "test"),
|
||||
Is.EqualTo("\"This ; is # not a comment\"")
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that values can end on a quote without causing trouble
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CommentsCanEndWithAQuote() {
|
||||
string fileContents =
|
||||
"test = \"This value ends with a quote\"";
|
||||
ConfigurationFileStore configurationFile = load(fileContents);
|
||||
|
||||
Assert.That(
|
||||
configurationFile.Get<string>(null, "test"),
|
||||
Is.EqualTo("\"This value ends with a quote\"")
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that values can forget the closing quote without causing trouble
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ClosingQuoteCanBeOmmitted() {
|
||||
string fileContents =
|
||||
"test = \"No closing quote";
|
||||
ConfigurationFileStore configurationFile = load(fileContents);
|
||||
|
||||
Assert.That(
|
||||
configurationFile.Get<string>(null, "test"),
|
||||
Is.EqualTo("\"No closing quote")
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that text placed after the closing quote will also be part of
|
||||
/// an option's value
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TextAfterClosingQuoteBecomesPartOfValue() {
|
||||
string fileContents =
|
||||
"test = \"Begins here\" end ends here";
|
||||
ConfigurationFileStore configurationFile = load(fileContents);
|
||||
|
||||
Assert.That(
|
||||
configurationFile.Get<string>(null, "test"),
|
||||
Is.EqualTo("\"Begins here\" end ends here")
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that text placed after the closing quote will also be part of
|
||||
/// an option's value
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OptionValuesCanBeChanged() {
|
||||
string fileContents = "test = 123 ; comment";
|
||||
ConfigurationFileStore configurationFile = load(fileContents);
|
||||
|
||||
configurationFile.Set(null, "test", "hello world");
|
||||
|
||||
Assert.That(
|
||||
save(configurationFile),
|
||||
Contains.Substring("hello world").And.ContainsSubstring("comment")
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that options can be added to the configuration file
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OptionsCanBeAdded() {
|
||||
var configurationFile = new ConfigurationFileStore();
|
||||
|
||||
configurationFile.Set<string>(null, "test", "123");
|
||||
Assert.That(configurationFile.Get<string>(null, "test"), Is.EqualTo("123"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that options can be added to the configuration file
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CategoriesCanBeAdded() {
|
||||
var configurationFile = new ConfigurationFileStore();
|
||||
|
||||
configurationFile.Set<string>("general", "sol", "42");
|
||||
|
||||
Assert.That(
|
||||
configurationFile.EnumerateCategories(), Is.EquivalentTo(new string[] { "general" })
|
||||
);
|
||||
Assert.That(save(configurationFile), Contains.Substring("[general]"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that accessing an option that doesn't exist throws an exception
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void AccessingNonExistingOptionThrowsException() {
|
||||
var configurationFile = new ConfigurationFileStore();
|
||||
|
||||
Assert.That(
|
||||
() => configurationFile.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 configurationFile = new ConfigurationFileStore();
|
||||
configurationFile.Set<string>(null, "test", "123");
|
||||
|
||||
Assert.That(
|
||||
() => configurationFile.Get<string>("doesn't exist", "test"),
|
||||
Throws.Exception.AssignableTo<KeyNotFoundException>()
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that it's possible to enumerate a category that doesn't exist
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void NonExistingCategoryCanBeEnumerated() {
|
||||
var configurationFile = new ConfigurationFileStore();
|
||||
|
||||
Assert.That(configurationFile.EnumerateOptions("doesn't exist"), Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that it's possible to create an option without a value
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ValuelessOptionsCanBeCreated() {
|
||||
var configurationFile = new ConfigurationFileStore();
|
||||
|
||||
configurationFile.Set<string>(null, "test", null);
|
||||
Assert.That(configurationFile.Get<string>(null, "test"), Is.Null.Or.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that it's possible to assign an empty value to an option
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OptionValueCanBeCleared() {
|
||||
string fileContents = "test = 123 ; comment";
|
||||
ConfigurationFileStore configurationFile = load(fileContents);
|
||||
|
||||
configurationFile.Set<string>(null, "test", null);
|
||||
Assert.That(configurationFile.Get<string>(null, "test"), Is.Null.Or.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that it's possible to remove options from the configuration file
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OptionsCanBeRemoved() {
|
||||
var configurationFile = new ConfigurationFileStore();
|
||||
configurationFile.Set<string>(null, "test", null);
|
||||
|
||||
Assert.That(configurationFile.Remove(null, "test"), Is.True);
|
||||
|
||||
string value;
|
||||
Assert.That(configurationFile.TryGet<string>(null, "test", out value), Is.False);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that options are removed from the configuration file correctly
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void RemovingOptionShiftsFollowingOptionsUp() {
|
||||
string fileContents =
|
||||
"first = 1\r\n" +
|
||||
"second = 2";
|
||||
ConfigurationFileStore configurationFile = load(fileContents);
|
||||
|
||||
Assert.That(configurationFile.Remove(null, "first"), Is.True);
|
||||
configurationFile.Set<string>(null, "second", "yay! first!");
|
||||
|
||||
Assert.That(save(configurationFile), Has.No.ContainsSubstring("1"));
|
||||
Assert.That(save(configurationFile), Contains.Substring("second"));
|
||||
Assert.That(save(configurationFile), Contains.Substring("yay! first!"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that it's not an error to remove an option from a non-existing category
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CanRemoveOptionFromNonExistingCategory() {
|
||||
var configurationFile = new ConfigurationFileStore();
|
||||
Assert.That(configurationFile.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 configurationFile = new ConfigurationFileStore();
|
||||
Assert.That(configurationFile.Remove(null, "first"), Is.False);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the configuration file store can identify various types of values
|
||||
/// </summary>
|
||||
[
|
||||
Test,
|
||||
TestCase("nothing=", typeof(string)),
|
||||
TestCase("text = world", typeof(string)),
|
||||
TestCase("short=9", typeof(int)),
|
||||
TestCase("integer = 123", typeof(int)),
|
||||
TestCase("integer = 123 ", typeof(int)),
|
||||
TestCase("string=x", typeof(string)),
|
||||
TestCase("string = 123s", typeof(string)),
|
||||
TestCase("float = 123.45", typeof(float)),
|
||||
TestCase("float = 123.45 ", typeof(float)),
|
||||
TestCase("boolean = true", typeof(bool)),
|
||||
TestCase("boolean = false", typeof(bool)),
|
||||
TestCase("boolean = yes", typeof(bool)),
|
||||
TestCase("boolean = no", typeof(bool))
|
||||
]
|
||||
public void OptionTypeCanBeIdentified(string assignment, Type expectedType) {
|
||||
ConfigurationFileStore configurationFile = load(assignment);
|
||||
|
||||
OptionInfo info;
|
||||
using(
|
||||
IEnumerator<OptionInfo> enumerator = configurationFile.EnumerateOptions().GetEnumerator()
|
||||
) {
|
||||
Assert.That(enumerator.MoveNext(), Is.True);
|
||||
info = enumerator.Current;
|
||||
Assert.That(enumerator.MoveNext(), Is.False);
|
||||
}
|
||||
|
||||
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>
|
||||
/// Verifies that attempting to cast a value to an incompatible data type causes
|
||||
/// a FormatException to be thrown
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ImpossibleCastCausesFormatException() {
|
||||
string fileContents = "fail = yesnomaybe";
|
||||
ConfigurationFileStore configurationFile = load(fileContents);
|
||||
|
||||
Assert.That(
|
||||
() => configurationFile.Get<bool>(null, "fail"),
|
||||
Throws.Exception.AssignableTo<FormatException>()
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that configuration files containing duplicate option names can not
|
||||
/// be used with the configuration file store
|
||||
/// </summary>
|
||||
[
|
||||
Test,
|
||||
TestCase("value = yes", true),
|
||||
TestCase("value = true", true),
|
||||
TestCase("value = no", false),
|
||||
TestCase("value = false", false)
|
||||
]
|
||||
public void BooleanLiteralsAreUnderstood(string fileContents, bool expectedValue) {
|
||||
ConfigurationFileStore configurationFile = load(fileContents);
|
||||
|
||||
if(expectedValue) {
|
||||
Assert.That(configurationFile.Get<bool>(null, "value"), Is.True);
|
||||
} else {
|
||||
Assert.That(configurationFile.Get<bool>(null, "value"), Is.False);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Loads a configuration file from a string</summary>
|
||||
/// <param name="fileContents">Contents of the configuration file</param>
|
||||
/// <returns>The configuration file loaded from the string</returns>
|
||||
private static ConfigurationFileStore load(string fileContents) {
|
||||
using(var reader = new StringReader(fileContents)) {
|
||||
return ConfigurationFileStore.Parse(reader);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Saves a configuration file into a string</summary>
|
||||
/// <param name="configurationFile">Configuration file that will be saved</param>
|
||||
/// <returns>Contents of the configuration file</returns>
|
||||
private static string save(ConfigurationFileStore configurationFile) {
|
||||
var builder = new StringBuilder();
|
||||
|
||||
using(var writer = new StringWriter(builder)) {
|
||||
configurationFile.Save(writer);
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Settings
|
||||
|
||||
#endif // UNITTEST
|
164
Tests/Settings/MemoryStoreTest.cs
Normal file
164
Tests/Settings/MemoryStoreTest.cs
Normal file
|
@ -0,0 +1,164 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Settings {
|
||||
|
||||
/// <summary>Unit tests for the memory settings store</summary>
|
||||
[TestFixture]
|
||||
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
|
||||
|
||||
#endif // UNITTEST
|
365
Tests/Settings/WindowsRegistryStoreTest.cs
Normal file
365
Tests/Settings/WindowsRegistryStoreTest.cs
Normal file
|
@ -0,0 +1,365 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if UNITTEST && WINDOWS
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Settings {
|
||||
|
||||
/// <summary>Unit tests for the windows registry settings store</summary>
|
||||
[TestFixture]
|
||||
internal class WindowsRegistryStoreTest {
|
||||
|
||||
#region class TestContext
|
||||
|
||||
/// <summary>Sets up a temporary registry key for the unit test</summary>
|
||||
private class TestContext : IDisposable {
|
||||
|
||||
/// <summary>Initializes a new test context</summary>
|
||||
public TestContext() {
|
||||
this.keyName = Guid.NewGuid().ToString();
|
||||
this.registryKey = Registry.CurrentUser.CreateSubKey(this.keyName);
|
||||
this.store = new WindowsRegistryStore(this.registryKey, writable: true);
|
||||
}
|
||||
|
||||
/// <summary>Immediately frees all resources owned by the test context</summary>
|
||||
public void Dispose() {
|
||||
if(this.store != null) {
|
||||
this.store.Dispose();
|
||||
this.store = null;
|
||||
this.registryKey = null;
|
||||
} else if(this.registryKey != null) {
|
||||
this.registryKey.Dispose();
|
||||
this.registryKey = null;
|
||||
}
|
||||
if(this.keyName != null) {
|
||||
Registry.CurrentUser.DeleteSubKeyTree(this.keyName);
|
||||
this.keyName = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Store created on a temporary registry key</summary>
|
||||
public WindowsRegistryStore Store {
|
||||
get { return this.store; }
|
||||
}
|
||||
|
||||
/// <summary>Name of the temporary registry key</summary>
|
||||
private string keyName;
|
||||
/// <summary>Registry key (ownership transfered to the store)</summary>
|
||||
private RegistryKey registryKey;
|
||||
/// <summary>Store that is accessing the registry key</summary>
|
||||
private WindowsRegistryStore store;
|
||||
|
||||
}
|
||||
|
||||
#endregion // class TestContext
|
||||
|
||||
/// <summary>Verifies that new instances of the registry store can be created</summary>
|
||||
[Test]
|
||||
public void CanBeCreated() {
|
||||
Assert.That(
|
||||
() => { using(var context = new TestContext()) { } }, Throws.Nothing
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that new instances of the registry store can be created</summary>
|
||||
[Test]
|
||||
public void RegistryHivesCanBeOpened() {
|
||||
Assert.That(
|
||||
() => {
|
||||
using(
|
||||
var store = new WindowsRegistryStore(
|
||||
RegistryHive.CurrentUser, "", writable: false
|
||||
)
|
||||
) { }
|
||||
},
|
||||
Throws.Nothing
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that booleans can be stored in the registry</summary>
|
||||
[Test]
|
||||
public void BooleansCanBeStored() {
|
||||
using(var context = new TestContext()) {
|
||||
context.Store.Set(null, "test", true);
|
||||
Assert.That(context.Store.Get<bool>(null, "test"), Is.True);
|
||||
|
||||
context.Store.Set(null, "test", false);
|
||||
Assert.That(context.Store.Get<bool>(null, "test"), Is.False);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that integers can be stored in the registry</summary>
|
||||
[Test]
|
||||
public void IntegersCanBeStored() {
|
||||
using(var context = new TestContext()) {
|
||||
context.Store.Set(null, "test", 123);
|
||||
Assert.That(context.Store.Get<int>(null, "test"), Is.EqualTo(123));
|
||||
|
||||
context.Store.Set(null, "test", 456);
|
||||
Assert.That(context.Store.Get<int>(null, "test"), Is.EqualTo(456));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that floats can be stored in the registry</summary>
|
||||
[Test]
|
||||
public void FloatsCanBeStored() {
|
||||
float testValue = float.Parse("123.456", CultureInfo.InvariantCulture);
|
||||
|
||||
using(var context = new TestContext()) {
|
||||
context.Store.Set(null, "test", testValue);
|
||||
Assert.That(context.Store.Get<float>(null, "test"), Is.EqualTo(testValue));
|
||||
|
||||
testValue = float.Parse("654.321", CultureInfo.InvariantCulture);
|
||||
|
||||
context.Store.Set(null, "test", testValue);
|
||||
Assert.That(context.Store.Get<float>(null, "test"), Is.EqualTo(testValue));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that strings can be stored in the registry</summary>
|
||||
[Test]
|
||||
public void StringsCanBeStored() {
|
||||
using(var context = new TestContext()) {
|
||||
context.Store.Set(null, "test", "hello world");
|
||||
Assert.That(context.Store.Get<string>(null, "test"), Is.EqualTo("hello world"));
|
||||
|
||||
context.Store.Set(null, "test", "world hello");
|
||||
Assert.That(context.Store.Get<string>(null, "test"), Is.EqualTo("world hello"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that long integers can be stored in the registry</summary>
|
||||
[Test]
|
||||
public void LongIntegersCanBeStored() {
|
||||
using(var context = new TestContext()) {
|
||||
context.Store.Set(null, "test", long.MaxValue);
|
||||
Assert.That(context.Store.Get<long>(null, "test"), Is.EqualTo(long.MaxValue));
|
||||
|
||||
context.Store.Set(null, "test", long.MinValue);
|
||||
Assert.That(context.Store.Get<long>(null, "test"), Is.EqualTo(long.MinValue));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that string arrays can be stored in the registry</summary>
|
||||
[Test]
|
||||
public void StringArraysCanBeStored() {
|
||||
string[] english = new string[] { "one", "two", "three" };
|
||||
string[] german = new string[] { "eins", "zwei", "drei" };
|
||||
|
||||
using(var context = new TestContext()) {
|
||||
context.Store.Set(null, "test", english);
|
||||
Assert.That(context.Store.Get<string[]>(null, "test"), Is.EquivalentTo(english));
|
||||
|
||||
context.Store.Set(null, "test", german);
|
||||
Assert.That(context.Store.Get<string[]>(null, "test"), Is.EquivalentTo(german));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that it's possible to enumerate a category that doesn't exist
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void NonExistingCategoryCanBeEnumerated() {
|
||||
using(var context = new TestContext()) {
|
||||
Assert.That(context.Store.EnumerateOptions("doesn't exist"), Is.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that byte arrays can be stored in the registry</summary>
|
||||
[Test]
|
||||
public void ByteArraysCanBeStored() {
|
||||
byte[] ascending = new byte[] { 1, 2, 3 };
|
||||
byte[] descending = new byte[] { 9, 8, 7 };
|
||||
|
||||
using(var context = new TestContext()) {
|
||||
context.Store.Set(null, "test", ascending);
|
||||
Assert.That(context.Store.Get<byte[]>(null, "test"), Is.EquivalentTo(ascending));
|
||||
|
||||
context.Store.Set(null, "test", descending);
|
||||
Assert.That(context.Store.Get<byte[]>(null, "test"), Is.EquivalentTo(descending));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that strings can be stored in the registry</summary>
|
||||
[Test]
|
||||
public void ValuesCanBeStoredInCategories() {
|
||||
using(var context = new TestContext()) {
|
||||
context.Store.Set("main", "test", "hello world");
|
||||
|
||||
string value;
|
||||
Assert.That(context.Store.TryGet<string>(null, "test", out value), Is.False);
|
||||
Assert.That(context.Store.Get<string>("main", "test"), Is.EqualTo("hello world"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the subkeys of a registry key can be enumerated</summary>
|
||||
[Test]
|
||||
public void CategoriesCanBeEnumerated() {
|
||||
string[] names = new string[] { "one", "two", "three" };
|
||||
|
||||
using(var context = new TestContext()) {
|
||||
context.Store.Set(names[0], "sol", 21);
|
||||
context.Store.Set(names[1], "sol", 42);
|
||||
context.Store.Set(names[2], "sol", 84);
|
||||
|
||||
Assert.That(context.Store.EnumerateCategories(), Is.EquivalentTo(names));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the values under a registry subkey can be enumerated</summary>
|
||||
[Test]
|
||||
public void OptionsInCategoryCanBeEnumerated() {
|
||||
string[] names = new string[] { "one", "two", "three" };
|
||||
|
||||
using(var context = new TestContext()) {
|
||||
context.Store.Set("test", names[0], 1);
|
||||
context.Store.Set("test", names[1], 2);
|
||||
context.Store.Set("test", names[2], 3);
|
||||
|
||||
var optionInfos = new List<OptionInfo>(context.Store.EnumerateOptions("test"));
|
||||
Assert.That(optionInfos.Count, Is.EqualTo(3));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the values under a registry key can be enumerated</summary>
|
||||
[Test]
|
||||
public void RootOptionsCanBeEnumerated() {
|
||||
string[] names = new string[] { "one", "two", "three" };
|
||||
|
||||
using(var context = new TestContext()) {
|
||||
context.Store.Set(null, names[0], 1);
|
||||
context.Store.Set(null, names[1], 2);
|
||||
context.Store.Set(null, names[2], 3);
|
||||
|
||||
var optionInfos = new List<OptionInfo>(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));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that accessing an option that doesn't exist throws an exception
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void AccessingNonExistingOptionThrowsException() {
|
||||
using(var context = new TestContext()) {
|
||||
Assert.That(
|
||||
() => context.Store.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() {
|
||||
using(var context = new TestContext()) {
|
||||
Assert.That(
|
||||
() => context.Store.Get<string>("doesn't exist", "test"),
|
||||
Throws.Exception.AssignableTo<KeyNotFoundException>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that values can be removed from a registry key
|
||||
/// </summary>
|
||||
[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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that values can be removed from the subkey of a registry key
|
||||
/// </summary>
|
||||
[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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that values can be removed from a non-existing subkey without
|
||||
/// causing an error
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void RemovingValueFromNonExistingCategoryCanBeHandled() {
|
||||
using(var context = new TestContext()) {
|
||||
Assert.That(context.Store.Remove("empty", "nothing"), Is.False);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the store identifies the types of values stored in
|
||||
/// a registry when they are enumerated
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ValueTypesAreIdentifiedWhenEnumerating() {
|
||||
Type[] types = new Type[] {
|
||||
typeof(int),
|
||||
typeof(long),
|
||||
typeof(byte[]),
|
||||
typeof(string),
|
||||
typeof(string[])
|
||||
};
|
||||
using(var context = new TestContext()) {
|
||||
context.Store.Set<int>(null, "0", 123);
|
||||
context.Store.Set<long>(null, "1", 456L);
|
||||
context.Store.Set<byte[]>(null, "2", new byte[] { 7, 8, 9 });
|
||||
context.Store.Set<string>(null, "3", "text");
|
||||
context.Store.Set<string[]>(null, "4", new string[] { "many", "words" });
|
||||
|
||||
var optionInfos = new List<OptionInfo>(context.Store.EnumerateOptions());
|
||||
for(int index = 0; index < optionInfos.Count; ++index) {
|
||||
int typeIndex = int.Parse(optionInfos[index].Name);
|
||||
Assert.That(optionInfos[index].OptionType, Is.EqualTo(types[typeIndex]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Settings
|
||||
|
||||
#endif // UNITTEST
|
Loading…
Add table
Add a link
Reference in a new issue