#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 WINDOWS using System; using System.Collections.Generic; using System.Globalization; using Microsoft.Win32; using NUnit.Framework; namespace Nuclex.Support.Settings { /// Unit tests for the windows registry settings store [TestFixture] internal class WindowsRegistryStoreTest { #region class TestContext /// Sets up a temporary registry key for the unit test private class TestContext : IDisposable { /// Initializes a new test context public TestContext() { this.keyName = Guid.NewGuid().ToString(); this.registryKey = Registry.CurrentUser.CreateSubKey(this.keyName); this.store = new WindowsRegistryStore(this.registryKey, writable: true); } /// Immediately frees all resources owned by the test context 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; } } /// Store created on a temporary registry key public WindowsRegistryStore Store { get { return this.store; } } /// Name of the temporary registry key private string keyName; /// Registry key (ownership transfered to the store) private RegistryKey registryKey; /// Store that is accessing the registry key private WindowsRegistryStore store; } #endregion // class TestContext /// Verifies that new instances of the registry store can be created [Test] public void CanBeCreated() { Assert.That( () => { using(var context = new TestContext()) { } }, Throws.Nothing ); } /// Verifies that new instances of the registry store can be created [Test] public void RegistryHivesCanBeOpened() { Assert.That( () => { using( var store = new WindowsRegistryStore( RegistryHive.CurrentUser, "", writable: false ) ) { } }, Throws.Nothing ); } /// Verifies that booleans can be stored in the registry [Test] public void BooleansCanBeStored() { using(var context = new TestContext()) { context.Store.Set(null, "test", true); Assert.That(context.Store.Get(null, "test"), Is.True); context.Store.Set(null, "test", false); Assert.That(context.Store.Get(null, "test"), Is.False); } } /// Verifies that integers can be stored in the registry [Test] public void IntegersCanBeStored() { using(var context = new TestContext()) { context.Store.Set(null, "test", 123); Assert.That(context.Store.Get(null, "test"), Is.EqualTo(123)); context.Store.Set(null, "test", 456); Assert.That(context.Store.Get(null, "test"), Is.EqualTo(456)); } } /// Verifies that floats can be stored in the registry [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(null, "test"), Is.EqualTo(testValue)); testValue = float.Parse("654.321", CultureInfo.InvariantCulture); context.Store.Set(null, "test", testValue); Assert.That(context.Store.Get(null, "test"), Is.EqualTo(testValue)); } } /// Verifies that strings can be stored in the registry [Test] public void StringsCanBeStored() { using(var context = new TestContext()) { context.Store.Set(null, "test", "hello world"); Assert.That(context.Store.Get(null, "test"), Is.EqualTo("hello world")); context.Store.Set(null, "test", "world hello"); Assert.That(context.Store.Get(null, "test"), Is.EqualTo("world hello")); } } /// Verifies that long integers can be stored in the registry [Test] public void LongIntegersCanBeStored() { using(var context = new TestContext()) { context.Store.Set(null, "test", long.MaxValue); Assert.That(context.Store.Get(null, "test"), Is.EqualTo(long.MaxValue)); context.Store.Set(null, "test", long.MinValue); Assert.That(context.Store.Get(null, "test"), Is.EqualTo(long.MinValue)); } } /// Verifies that string arrays can be stored in the registry [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(null, "test"), Is.EquivalentTo(english)); context.Store.Set(null, "test", german); Assert.That(context.Store.Get(null, "test"), Is.EquivalentTo(german)); } } /// /// Verifies that it's possible to enumerate a category that doesn't exist /// [Test] public void NonExistingCategoryCanBeEnumerated() { using(var context = new TestContext()) { Assert.That(context.Store.EnumerateOptions("doesn't exist"), Is.Empty); } } /// Verifies that byte arrays can be stored in the registry [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(null, "test"), Is.EquivalentTo(ascending)); context.Store.Set(null, "test", descending); Assert.That(context.Store.Get(null, "test"), Is.EquivalentTo(descending)); } } /// Verifies that strings can be stored in the registry [Test] public void ValuesCanBeStoredInCategories() { using(var context = new TestContext()) { context.Store.Set("main", "test", "hello world"); string value; Assert.That(context.Store.TryGet(null, "test", out value), Is.False); Assert.That(context.Store.Get("main", "test"), Is.EqualTo("hello world")); } } /// Verifies that the subkeys of a registry key can be enumerated [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)); } } /// Verifies that the values under a registry subkey can be enumerated [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(context.Store.EnumerateOptions("test")); Assert.That(optionInfos.Count, Is.EqualTo(3)); } } /// Verifies that the values under a registry key can be enumerated [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(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); } } /// /// Verifies that the store identifies the types of values stored in /// a registry when they are enumerated /// [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(null, "0", 123); context.Store.Set(null, "1", 456L); context.Store.Set(null, "2", new byte[] { 7, 8, 9 }); context.Store.Set(null, "3", "text"); context.Store.Set(null, "4", new string[] { "many", "words" }); var optionInfos = new List(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 // WINDOWS