2
0
mirror of https://github.com/hirschmann/nbfc synced 2025-08-31 22:25:16 +00:00

Add tests for ConfigManager

This commit is contained in:
Stefan Hirschmann
2017-06-09 23:33:07 +02:00
parent e7f6aaf1cd
commit f313787d23
6 changed files with 415 additions and 56 deletions

View File

@@ -1,7 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO; using System.IO.Abstractions;
using System.Linq; using System.Linq;
using System.Xml.Serialization; using System.Xml.Serialization;
@@ -14,18 +14,19 @@ namespace StagWare.Configurations
private const string DefaultFileExtension = ".xml"; private const string DefaultFileExtension = ".xml";
// Use Windows specific invalid filename chars on all platforms // Use Windows specific invalid filename chars on all platforms
private static readonly char[] InvalidChars = new byte[] private static readonly char[] InvalidChars = new byte[]
{ {
34, 60, 62, 124, 0, 1, 2, 3, 4, 5, 34, 60, 62, 124, 0, 1, 2, 3, 4, 5,
6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 58, 42, 63, 92, 47 26, 27, 28, 29, 30, 31, 58, 42, 63, 92, 47
}.Select(x => (char)x).ToArray(); }.Select(x => (char)x).ToArray();
#endregion #endregion
#region Private Fields #region Private Fields
private IFileSystem fs;
private Dictionary<string, Lazy<T>> configs; private Dictionary<string, Lazy<T>> configs;
private XmlSerializer serializer; private XmlSerializer serializer;
private string configDirPath; private string configDirPath;
@@ -56,27 +57,36 @@ namespace StagWare.Configurations
#region Constructors #region Constructors
public ConfigManager(string configsDirPath) public ConfigManager(string configsDirPath)
: this(configsDirPath, DefaultFileExtension) : this(configsDirPath, DefaultFileExtension, new FileSystem())
{ {
} }
public ConfigManager(string configsDirPath, string configFileExtension) public ConfigManager(string configsDirPath, string configFileExtension)
: this(configsDirPath, configFileExtension, new FileSystem())
{ {
this.configDirPath = configsDirPath; }
this.configFileExtension = configFileExtension;
public ConfigManager(string configsDirPath, string configFileExtension, IFileSystem fs)
{
this.fs = fs
?? throw new ArgumentNullException(nameof(fs));
this.configDirPath = configsDirPath
?? throw new ArgumentNullException(nameof(configsDirPath));
this.configFileExtension = configFileExtension
?? throw new ArgumentNullException(nameof(configFileExtension));
this.serializer = new XmlSerializer(typeof(T)); this.serializer = new XmlSerializer(typeof(T));
if (!Directory.Exists(configsDirPath)) if (!fs.Directory.Exists(configsDirPath))
{ {
Directory.CreateDirectory(configsDirPath); fs.Directory.CreateDirectory(configsDirPath);
} }
string[] files = Directory.GetFiles(configsDirPath); string[] files = fs.Directory.GetFiles(configsDirPath);
this.configs = new Dictionary<string, Lazy<T>>(files.Length); this.configs = new Dictionary<string, Lazy<T>>(files.Length);
foreach (string path in files) foreach (string path in files)
{ {
string key = Path.GetFileNameWithoutExtension(path); string key = fs.Path.GetFileNameWithoutExtension(path);
if (!this.configs.ContainsKey(key)) if (!this.configs.ContainsKey(key))
{ {
@@ -86,31 +96,6 @@ namespace StagWare.Configurations
} }
} }
#region Helper Methods
private static T LoadConfig(string path, XmlSerializer serializer)
{
try
{
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
object cfg = serializer.Deserialize(stream);
if (cfg != null)
{
return (T)cfg;
}
}
}
catch
{
}
return default(T);
}
#endregion
#endregion #endregion
#region Public Methods #region Public Methods
@@ -119,7 +104,7 @@ namespace StagWare.Configurations
{ {
if (Contains(configName)) if (Contains(configName))
{ {
return (T)configs[configName].Value.Clone(); return (T)configs[configName]?.Value?.Clone();
} }
else else
{ {
@@ -129,7 +114,7 @@ namespace StagWare.Configurations
public virtual bool ConfigFileExists(string configName) public virtual bool ConfigFileExists(string configName)
{ {
return File.Exists(GetConfigFilePath(configName)); return fs.File.Exists(GetConfigFilePath(configName));
} }
public virtual bool Contains(string configName) public virtual bool Contains(string configName)
@@ -146,29 +131,29 @@ namespace StagWare.Configurations
{ {
if (config == null) if (config == null)
{ {
throw new ArgumentNullException("config"); throw new ArgumentNullException(nameof(config));
} }
if (string.IsNullOrWhiteSpace(configName)) if (string.IsNullOrWhiteSpace(configName))
{ {
throw new ArgumentException("The config name may not be null or consist only of whitespace.", "configName"); throw new ArgumentException("The config name may not be null or consist only of whitespace.", nameof(configName));
} }
if (configName.IndexOfAny(InvalidChars) != -1) if (configName.IndexOfAny(InvalidChars) != -1)
{ {
throw new ArgumentException("The config name may not contain invalid characters", "configName"); throw new ArgumentException("The config name may not contain invalid characters", nameof(configName));
} }
string path = GetConfigFilePath(configName); string path = GetConfigFilePath(configName);
if (Contains(configName) || File.Exists(path)) if (Contains(configName) || fs.File.Exists(path))
{ {
throw new ArgumentException("A config with this name already exists", "configName"); throw new ArgumentException("A config with this name already exists", nameof(configName));
} }
var clone = (T)config.Clone(); var clone = (T)config.Clone();
using (var stream = new FileStream(path, FileMode.Create)) using (var stream = fs.File.Open(path, System.IO.FileMode.Create))
{ {
this.serializer.Serialize(stream, clone); this.serializer.Serialize(stream, clone);
} }
@@ -187,19 +172,17 @@ namespace StagWare.Configurations
this.configs.Remove(configName); this.configs.Remove(configName);
} }
if (File.Exists(path)) if (fs.File.Exists(path))
{ {
File.Delete(path); fs.File.Delete(path);
} }
} }
public virtual void UpdateConfig(string configName, T newConfig) public virtual void UpdateConfig(string configName, T newConfig)
{ {
#region Exceptions
if (newConfig == null) if (newConfig == null)
{ {
throw new ArgumentNullException("newConfig"); throw new ArgumentNullException(nameof(newConfig));
} }
if (!Contains(configName)) if (!Contains(configName))
@@ -207,11 +190,9 @@ namespace StagWare.Configurations
throw new KeyNotFoundException(); throw new KeyNotFoundException();
} }
#endregion
var clone = (T)newConfig.Clone(); var clone = (T)newConfig.Clone();
using (var stream = new FileStream(GetConfigFilePath(configName), FileMode.Create)) using (var stream = fs.File.Open(GetConfigFilePath(configName), System.IO.FileMode.Create))
{ {
serializer.Serialize(stream, clone); serializer.Serialize(stream, clone);
} }
@@ -223,9 +204,30 @@ namespace StagWare.Configurations
#region Private Methods #region Private Methods
private T LoadConfig(string path, XmlSerializer serializer)
{
try
{
using (var stream = fs.File.Open(path, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
object cfg = serializer.Deserialize(stream);
if (cfg != null)
{
return (T)cfg;
}
}
}
catch
{
}
return default(T);
}
private string GetConfigFilePath(string fileNameWithoutExt) private string GetConfigFilePath(string fileNameWithoutExt)
{ {
return Path.Combine(this.configDirPath, fileNameWithoutExt + this.configFileExtension); return fs.Path.Combine(this.configDirPath, fileNameWithoutExt + this.configFileExtension);
} }
#endregion #endregion

View File

@@ -36,6 +36,9 @@
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.IO.Abstractions, Version=2.0.0.144, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.IO.Abstractions.2.0.0.144\lib\net40\System.IO.Abstractions.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
@@ -62,6 +65,9 @@
<Name>StagWare.BiosInfo</Name> <Name>StagWare.BiosInfo</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="System.IO.Abstractions" version="2.0.0.144" targetFramework="net45" />
</packages>

View File

@@ -0,0 +1,342 @@
using StagWare.Configurations;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions.TestingHelpers;
using System.Linq;
using Xunit;
namespace StagWare.FanControl.Configurations.Tests
{
public class ConfigManagerTests
{
public class Constructor
{
[Fact]
public void ThrowsIfConfigsDirIsNull()
{
Assert.Throws<ArgumentNullException>(
() => new ConfigManager<FanControlConfigV2>(null, ".xml", new MockFileSystem()));
}
[Fact]
public void ThrowsIfConfigsFileExtensionIsNull()
{
string dir = Environment.CurrentDirectory;
Assert.Throws<ArgumentNullException>(
() => new ConfigManager<FanControlConfigV2>(dir, null, new MockFileSystem()));
}
}
public class GetConfig
{
[Fact]
public void ReturnsExistingConfigs()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
int filesCount = 100;
for (int i = 0; i < filesCount; i++)
{
cfgMan.AddConfig(new FanControlConfigV2(), i.ToString());
}
for (int i = 0; i < filesCount; i++)
{
Assert.True(cfgMan.GetConfig(i.ToString()) != null, $"Config {i} should exist but doesn't");
}
}
[Fact]
public void ReturnsNullIfConfigDoesNotExist()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
int filesCount = 100;
for (int i = 0; i < filesCount; i++)
{
Assert.True(cfgMan.GetConfig(i.ToString()) == null, $"Config {i} shouldn't exist but exists");
}
}
[Fact]
public void ReturnsNullIfIdIsNull()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
Assert.Null(cfgMan.GetConfig(null));
}
}
public class ConfigFileExists
{
[Fact]
public void ReturnsTrueIfExists()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
int filesCount = 100;
for (int i = 0; i < filesCount; i++)
{
cfgMan.AddConfig(new FanControlConfigV2(), i.ToString());
}
for (int i = 0; i < filesCount; i++)
{
Assert.True(cfgMan.ConfigFileExists(i.ToString()), $"Config {i} should exist but doesn't");
}
}
[Fact]
public void ReturnsFalseIfNotExisting()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
int filesCount = 100;
for (int i = 0; i < filesCount; i++)
{
Assert.False(cfgMan.ConfigFileExists(i.ToString()), $"Config {i} shouldn't exist but exists");
}
}
[Fact]
public void ReturnsFalseIfIdIsNull()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
Assert.False(cfgMan.ConfigFileExists(null));
}
}
public class Contains
{
[Fact]
public void ReturnsTrueIfExists()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
int filesCount = 100;
for (int i = 0; i < filesCount; i++)
{
cfgMan.AddConfig(new FanControlConfigV2(), i.ToString());
}
for (int i = 0; i < filesCount; i++)
{
Assert.True(cfgMan.Contains(i.ToString()), $"Config {i} should exist but doesn't");
}
}
[Fact]
public void ReturnsFalseIfNotExisting()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
int filesCount = 100;
for (int i = 0; i < filesCount; i++)
{
Assert.False(cfgMan.Contains(i.ToString()), $"Config {i} shouldn't exist but exists");
}
}
[Fact]
public void ReturnsFalseIfIdIsNull()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
Assert.False(cfgMan.Contains(null));
}
}
public class AddConfig
{
[Fact]
public void AddsValidConfigs()
{
string extension = ".xml";
var fs = new MockFileSystem();
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, extension, fs);
int filesCount = 100;
for (int i = 0; i < filesCount; i++)
{
cfgMan.AddConfig(new FanControlConfigV2(), i.ToString());
}
for (int i = 0; i < filesCount; i++)
{
string path = Path.Combine(
Environment.CurrentDirectory, i.ToString() + extension);
Assert.True(fs.FileExists(path), $"Config {i} should exist but doesn't");
}
}
[Fact]
public void ThrowsOnDuplicates()
{
string cfgName = "foo";
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
cfgMan.AddConfig(new FanControlConfigV2(), cfgName);
Assert.Throws<ArgumentException>(
() => cfgMan.AddConfig(new FanControlConfigV2(), cfgName));
}
[Fact]
public void ThrowsIfConfigIsNull()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
Assert.Throws<ArgumentNullException>(
() => cfgMan.AddConfig(null, "foo"));
}
[Fact]
public void ThrowsIfIdIsNull()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
Assert.Throws<ArgumentException>(
() => cfgMan.AddConfig(new FanControlConfigV2(), null));
}
[Fact]
public void ThrowsIfIdContainsInvalidFileNameChars()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
string id = "foo" + Path.GetInvalidFileNameChars().First();
Assert.Throws<ArgumentException>(
() => cfgMan.AddConfig(new FanControlConfigV2(), id));
}
}
public class RemoveConfig
{
[Fact]
public void RemovesConfigs()
{
string extension = ".xml";
var fs = new MockFileSystem();
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, extension, fs);
int filesCount = 100;
for (int i = 0; i < filesCount; i++)
{
cfgMan.AddConfig(new FanControlConfigV2(), i.ToString());
}
for (int i = 0; i < filesCount; i += 2)
{
string path = Path.Combine(
Environment.CurrentDirectory, i.ToString() + extension);
cfgMan.RemoveConfig(i.ToString());
Assert.False(fs.FileExists(path), $"Config {i} shouldn't exist but exists");
}
}
[Fact]
public void DoesNothingIfNotExisting()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
for (int i = 0; i < 100; i++)
{
cfgMan.RemoveConfig(i.ToString());
}
}
[Fact]
public void ThrowsIfIdIsNull()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
Assert.Throws<ArgumentNullException>(() => cfgMan.RemoveConfig(null));
}
}
public class UpdateConfig
{
[Fact]
public void UpdatesExistingConfigs()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
string id = "foo";
var cfg = new FanControlConfigV2();
cfgMan.AddConfig(cfg, id);
cfg.Author = "bar";
cfgMan.UpdateConfig(id, cfg);
var updatedCfg = cfgMan.GetConfig(id);
Assert.True(updatedCfg.Author == cfg.Author);
}
[Fact]
public void ThrowsIfIdNotExisting()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
Assert.Throws<KeyNotFoundException>(
() => cfgMan.UpdateConfig("foo", new FanControlConfigV2()));
}
[Fact]
public void ThrowsIfIdIsNull()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
Assert.Throws<KeyNotFoundException>(
() => cfgMan.UpdateConfig(null, new FanControlConfigV2()));
}
[Fact]
public void ThrowsIfConfigIsNull()
{
var cfgMan = new ConfigManager<FanControlConfigV2>(
Environment.CurrentDirectory, ".xml", new MockFileSystem());
cfgMan.AddConfig(new FanControlConfigV2(), "foo");
Assert.Throws<ArgumentNullException>(
() => cfgMan.UpdateConfig("foo", null));
}
}
}
}

View File

@@ -38,6 +38,9 @@
<Reference Include="System.IO.Abstractions, Version=2.0.0.144, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="System.IO.Abstractions, Version=2.0.0.144, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.IO.Abstractions.2.0.0.144\lib\net40\System.IO.Abstractions.dll</HintPath> <HintPath>..\..\packages\System.IO.Abstractions.2.0.0.144\lib\net40\System.IO.Abstractions.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.IO.Abstractions.TestingHelpers, Version=2.0.0.143, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.IO.Abstractions.TestingHelpers.2.0.0.143\lib\net40\System.IO.Abstractions.TestingHelpers.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
@@ -58,6 +61,7 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ConfigManagerTests.cs" />
<Compile Include="ConfigsTests.cs" /> <Compile Include="ConfigsTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>

View File

@@ -2,6 +2,7 @@
<packages> <packages>
<package id="FakeItEasy" version="3.3.2" targetFramework="net452" /> <package id="FakeItEasy" version="3.3.2" targetFramework="net452" />
<package id="System.IO.Abstractions" version="2.0.0.144" targetFramework="net452" /> <package id="System.IO.Abstractions" version="2.0.0.144" targetFramework="net452" />
<package id="System.IO.Abstractions.TestingHelpers" version="2.0.0.143" targetFramework="net452" />
<package id="xunit" version="2.2.0" targetFramework="net452" /> <package id="xunit" version="2.2.0" targetFramework="net452" />
<package id="xunit.abstractions" version="2.0.1" targetFramework="net452" /> <package id="xunit.abstractions" version="2.0.1" targetFramework="net452" />
<package id="xunit.assert" version="2.2.0" targetFramework="net452" /> <package id="xunit.assert" version="2.2.0" targetFramework="net452" />