uscheduler/src/MaksIT.UScheduler.Tests/ConfigurationFileServiceTests.cs

323 lines
12 KiB
C#

using MaksIT.UScheduler.Shared;
using MaksIT.UScheduler.Shared.Helpers;
namespace MaksIT.UScheduler.Tests;
public class ConfigurationFileServiceTests {
[Fact]
public void Default_path_is_shared_programdata() {
var service = new ConfigurationFileService();
Assert.Equal(UserSettingsPath.GetShared(ConfigurationFileService.ProductFolder), service.FilePath);
}
[Fact]
public void Save_to_new_file_writes_only_configuration() {
var path = Path.Combine(Path.GetTempPath(), $"uscheduler-{Guid.NewGuid():N}.json");
try {
var service = new ConfigurationFileService(path);
service.Save(new Configuration {
LogDir = @"C:\MaksIT\Logs",
ScriptsDir = @"C:\MaksIT\Scripts"
});
var json = File.ReadAllText(path);
Assert.Contains("\"Configuration\"", json, StringComparison.Ordinal);
Assert.DoesNotContain("\"Logging\"", json, StringComparison.Ordinal);
Assert.Contains("C:\\\\MaksIT\\\\Logs", json, StringComparison.Ordinal);
var reloaded = new ConfigurationFileService(path);
Assert.Equal(@"C:\MaksIT\Logs", reloaded.Current.LogDir);
Assert.Equal(@"C:\MaksIT\Scripts", reloaded.Current.ScriptsDir);
}
finally {
if (File.Exists(path))
File.Delete(path);
}
}
[Fact]
public void Copies_seed_configuration_without_logging() {
var dir = Path.Combine(Path.GetTempPath(), $"uscheduler-{Guid.NewGuid():N}");
Directory.CreateDirectory(dir);
var seed = Path.Combine(dir, "appsettings.json");
var user = Path.Combine(dir, "settings.json");
File.WriteAllText(seed, """
{
"Logging": { "LogLevel": { "Default": "Information" } },
"Configuration": {
"LogDir": "C:\\MaksIT\\Logs",
"ScriptsDir": "C:\\MaksIT\\Scripts",
"Powershell": [ { "Path": "File-Sync\\file-sync.ps1", "Disabled": true } ]
}
}
""");
try {
var service = new ConfigurationFileService(user, seed);
Assert.True(File.Exists(user));
Assert.Equal(@"C:\MaksIT\Logs", service.Current.LogDir);
Assert.Single(service.Current.Powershell);
var json = File.ReadAllText(user);
Assert.Contains("\"Configuration\"", json, StringComparison.Ordinal);
Assert.DoesNotContain("\"Logging\"", json, StringComparison.Ordinal);
}
finally {
Directory.Delete(dir, true);
}
}
[Fact]
public void Logging_only_seed_does_not_create_user_file() {
var dir = Path.Combine(Path.GetTempPath(), $"uscheduler-{Guid.NewGuid():N}");
Directory.CreateDirectory(dir);
var seed = Path.Combine(dir, "appsettings.json");
var user = Path.Combine(dir, "settings.json");
File.WriteAllText(seed, """
{
"Logging": { "LogLevel": { "Default": "Information" } }
}
""");
try {
var service = new ConfigurationFileService(user, seed);
Assert.False(File.Exists(user));
Assert.Equal(HostPaths.DefaultLogDirectory, service.Current.LogDir);
}
finally {
Directory.Delete(dir, true);
}
}
[Fact]
public void Save_round_trips_powershell_entries() {
var path = Path.Combine(Path.GetTempPath(), $"uscheduler-{Guid.NewGuid():N}.json");
try {
var service = new ConfigurationFileService(path);
service.Save(new Configuration {
Powershell = [
new PowershellScript {
Path = @"File-Sync\file-sync.ps1",
Name = "File Sync",
Disabled = true,
IsSigned = false
}
]
});
var reloaded = new ConfigurationFileService(path);
Assert.Single(reloaded.Current.Powershell);
Assert.Equal(@"File-Sync\file-sync.ps1", reloaded.Current.Powershell[0].Path);
Assert.True(reloaded.Current.Powershell[0].Disabled);
Assert.False(reloaded.Current.Powershell[0].IsSigned);
}
finally {
if (File.Exists(path))
File.Delete(path);
}
}
}
public class HostPathsTests {
[Fact]
public void Windows_defaults_use_maksit_data_root() {
if (!OperatingSystem.IsWindows())
return;
Assert.Equal(@"C:\MaksIT\Scripts", HostPaths.DefaultScriptsDirectory);
Assert.Equal(@"C:\MaksIT\Logs", HostPaths.DefaultLogDirectory);
Assert.Equal(@"C:\MaksIT", HostPaths.DefaultDataRoot);
Assert.EndsWith(
Path.Combine("MaksIT", "UScheduler"),
HostPaths.DefaultInstallDirectory,
StringComparison.OrdinalIgnoreCase);
Assert.Equal(
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "MaksIT", "UScheduler"),
HostPaths.DefaultInstallDirectory);
}
[Fact]
public void DetectServiceBinPath_finds_worker_next_to_ui() {
var root = Path.Combine(Path.GetTempPath(), $"uscheduler-detect-{Guid.NewGuid():N}");
Directory.CreateDirectory(root);
var exeName = HostServiceManager.GetExecutableFileName();
File.WriteAllBytes(Path.Combine(root, exeName), [0]);
try {
Assert.Equal(Path.GetFullPath(root), HostPaths.FindWorkerDirectory(root));
}
finally {
Directory.Delete(root, true);
}
}
[Fact]
public void Shared_settings_are_under_programdata() {
if (!OperatingSystem.IsWindows())
return;
var path = UserSettingsPath.GetShared("UScheduler");
Assert.Contains("MaksIT", path, StringComparison.OrdinalIgnoreCase);
Assert.Contains("UScheduler", path, StringComparison.OrdinalIgnoreCase);
Assert.EndsWith("settings.json", path, StringComparison.OrdinalIgnoreCase);
Assert.Equal(
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "MaksIT", "UScheduler", "settings.json"),
path);
}
[Fact]
public void Per_user_settings_are_under_appdata() {
var path = UserSettingsPath.Get("UScheduler");
Assert.Equal(
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "MaksIT", "UScheduler", "settings.json"),
path);
}
[Fact]
public void FindPortableRoot_returns_null_without_marker() {
var root = Path.Combine(Path.GetTempPath(), $"uscheduler-no-portable-{Guid.NewGuid():N}");
Directory.CreateDirectory(root);
try {
Assert.Null(HostPaths.FindPortableRoot(root));
Assert.False(HostPaths.IsPortableLayout(root));
}
finally {
Directory.Delete(root, true);
}
}
[Fact]
public void FindPortableRoot_finds_marker_in_start_directory() {
var root = Path.Combine(Path.GetTempPath(), $"uscheduler-portable-{Guid.NewGuid():N}");
Directory.CreateDirectory(root);
File.WriteAllText(Path.Combine(root, HostPaths.PortableMarkerFileName), HostPaths.PortableMarkerContent);
try {
Assert.Equal(Path.GetFullPath(root), HostPaths.FindPortableRoot(root));
Assert.True(HostPaths.IsPortableLayout(root));
Assert.Equal(
Path.GetFullPath(Path.Combine(root, "Data", "settings.json")),
Path.GetFullPath(HostPaths.ResolveSharedSettingsFile(root)));
Assert.Equal(
Path.GetFullPath(Path.Combine(root, "Data", "ui-settings.json")),
Path.GetFullPath(HostPaths.ResolveUiSettingsFile(root)));
}
finally {
Directory.Delete(root, true);
}
}
[Fact]
public void FindPortableRoot_walks_up_to_parent_marker() {
var root = Path.Combine(Path.GetTempPath(), $"uscheduler-portable-parent-{Guid.NewGuid():N}");
var worker = Path.Combine(root, "MaksIT.UScheduler");
Directory.CreateDirectory(worker);
File.WriteAllText(Path.Combine(root, HostPaths.PortableMarkerFileName), HostPaths.PortableMarkerContent);
try {
Assert.Equal(Path.GetFullPath(root), HostPaths.FindPortableRoot(worker));
}
finally {
Directory.Delete(root, true);
}
}
[Fact]
public void ApplyPortableDefaults_replaces_machine_wide_paths() {
var root = Path.Combine(Path.GetTempPath(), $"uscheduler-portable-defaults-{Guid.NewGuid():N}");
Directory.CreateDirectory(root);
File.WriteAllText(Path.Combine(root, HostPaths.PortableMarkerFileName), HostPaths.PortableMarkerContent);
try {
var config = new Configuration {
LogDir = HostPaths.DefaultLogDirectory,
ScriptsDir = HostPaths.DefaultScriptsDirectory
};
HostPaths.ApplyPortableDefaults(config, root);
Assert.Equal(Path.GetFullPath(Path.Combine(root, "Logs")), Path.GetFullPath(config.LogDir));
Assert.Equal(Path.GetFullPath(Path.Combine(root, "Scripts")), Path.GetFullPath(config.ScriptsDir));
}
finally {
Directory.Delete(root, true);
}
}
[Fact]
public void Copies_seed_into_portable_data_folder_with_local_paths() {
var root = Path.Combine(Path.GetTempPath(), $"uscheduler-portable-seed-{Guid.NewGuid():N}");
var data = Path.Combine(root, "Data");
Directory.CreateDirectory(data);
File.WriteAllText(Path.Combine(root, HostPaths.PortableMarkerFileName), HostPaths.PortableMarkerContent);
var seed = Path.Combine(root, "appsettings.json");
var user = Path.Combine(data, "settings.json");
var defaultLog = HostPaths.DefaultLogDirectory.Replace("\\", "\\\\", StringComparison.Ordinal);
var defaultScripts = HostPaths.DefaultScriptsDirectory.Replace("\\", "\\\\", StringComparison.Ordinal);
File.WriteAllText(seed, $$"""
{
"Logging": { "LogLevel": { "Default": "Information" } },
"Configuration": {
"LogDir": "{{defaultLog}}",
"ScriptsDir": "{{defaultScripts}}",
"Powershell": [ { "Path": "File-Sync\\file-sync.ps1", "Disabled": true } ]
}
}
""");
try {
var service = new ConfigurationFileService(user, seed);
Assert.True(File.Exists(user));
Assert.Equal(Path.GetFullPath(Path.Combine(root, "Logs")), Path.GetFullPath(service.Current.LogDir));
Assert.Equal(Path.GetFullPath(Path.Combine(root, "Scripts")), Path.GetFullPath(service.Current.ScriptsDir));
Assert.Single(service.Current.Powershell);
}
finally {
Directory.Delete(root, true);
}
}
[Fact]
public void FindBundledScriptsDirectory_finds_scripts_next_to_start() {
var root = Path.Combine(Path.GetTempPath(), $"uscheduler-bundled-{Guid.NewGuid():N}");
var start = Path.Combine(root, "install");
var scripts = Path.Combine(start, "Scripts");
Directory.CreateDirectory(Path.Combine(scripts, "Native-Sync"));
File.WriteAllText(Path.Combine(scripts, "Native-Sync", "native-sync.ps1"), "seed");
try {
var found = HostPaths.FindBundledScriptsDirectory(start);
Assert.Equal(Path.GetFullPath(scripts), found is null ? null : Path.GetFullPath(found));
}
finally {
Directory.Delete(root, true);
}
}
[Fact]
public void FindBundledScriptsDirectory_finds_sibling_scripts_folder() {
var root = Path.Combine(Path.GetTempPath(), $"uscheduler-sibling-{Guid.NewGuid():N}");
var start = Path.Combine(root, "MaksIT.UScheduler");
var scripts = Path.Combine(root, "Scripts");
Directory.CreateDirectory(start);
Directory.CreateDirectory(Path.Combine(scripts, "File-Sync"));
try {
var found = HostPaths.FindBundledScriptsDirectory(start);
Assert.Equal(Path.GetFullPath(scripts), found is null ? null : Path.GetFullPath(found));
}
finally {
Directory.Delete(root, true);
}
}
[Fact]
public void ResolveScriptPath_uses_scripts_dir() {
var dir = Path.Combine(Path.GetTempPath(), $"uscheduler-scripts-{Guid.NewGuid():N}");
Directory.CreateDirectory(dir);
try {
var config = new Configuration { ScriptsDir = dir };
var resolved = config.ResolveScriptPath(Path.Combine("File-Sync", "file-sync.ps1"));
Assert.Equal(Path.GetFullPath(Path.Combine(dir, "File-Sync", "file-sync.ps1")), resolved);
}
finally {
Directory.Delete(dir, true);
}
}
}