From 3c5d67e287043ec2cd93cf8fc0be136b8cd2cd83 Mon Sep 17 00:00:00 2001 From: NextTurn <45985406+nxtn@users.noreply.github.com> Date: Sun, 13 Sep 2020 00:00:00 +0800 Subject: [PATCH] Merge shared directory mapping into core --- src/WinSW.Core/Configuration/ServiceConfig.cs | 6 +- .../Configuration/XmlServiceConfig.cs | 29 ++++- src/WinSW.Core/LogAppenders.cs | 2 +- .../Logging/IServiceEventLog.cs | 0 .../Logging/WrapperServiceEventLogProvider.cs | 0 src/WinSW.Core/Native/Libraries.cs | 1 + src/WinSW.Core/Native/NetworkApis.cs | 31 +++++ src/WinSW.Core/Native/ResourceApis.cs | 4 +- src/{WinSW => WinSW.Core}/ServiceMessages.cs | 0 src/WinSW.Core/SharedDirectoryMapper.cs | 50 ++++++++ src/WinSW.Core/SharedDirectoryMapperConfig.cs | 15 +++ src/{WinSW => WinSW.Core}/WrapperService.cs | 40 ++++-- src/WinSW.Plugins/SharedDirectoryMapper.cs | 121 ------------------ .../SharedDirectoryMapperConfig.cs | 32 ----- src/WinSW.Tests/DownloadTests.cs | 2 +- .../Extensions/ExtensionTestBase.cs | 21 --- .../SharedDirectoryMapperConfigTest.cs | 58 --------- src/WinSW.Tests/ServiceConfigTests.cs | 21 +++ .../SharedDirectoryMapperTests.cs | 41 +++--- src/WinSW.Tests/Util/ConfigXmlBuilder.cs | 2 +- src/WinSW/Program.cs | 2 +- 21 files changed, 201 insertions(+), 277 deletions(-) rename src/{WinSW => WinSW.Core}/Logging/IServiceEventLog.cs (100%) rename src/{WinSW => WinSW.Core}/Logging/WrapperServiceEventLogProvider.cs (100%) create mode 100644 src/WinSW.Core/Native/NetworkApis.cs rename src/{WinSW => WinSW.Core}/ServiceMessages.cs (100%) create mode 100644 src/WinSW.Core/SharedDirectoryMapper.cs create mode 100644 src/WinSW.Core/SharedDirectoryMapperConfig.cs rename src/{WinSW => WinSW.Core}/WrapperService.cs (94%) delete mode 100644 src/WinSW.Plugins/SharedDirectoryMapper.cs delete mode 100644 src/WinSW.Plugins/SharedDirectoryMapperConfig.cs delete mode 100644 src/WinSW.Tests/Extensions/ExtensionTestBase.cs delete mode 100644 src/WinSW.Tests/Extensions/SharedDirectoryMapperConfigTest.cs rename src/WinSW.Tests/{Extensions => }/SharedDirectoryMapperTests.cs (74%) diff --git a/src/WinSW.Core/Configuration/ServiceConfig.cs b/src/WinSW.Core/Configuration/ServiceConfig.cs index 4ee0447..b9ed843 100644 --- a/src/WinSW.Core/Configuration/ServiceConfig.cs +++ b/src/WinSW.Core/Configuration/ServiceConfig.cs @@ -77,13 +77,15 @@ namespace WinSW.Configuration public virtual string ErrFilePattern => ".err.log"; // Environment - public virtual List Downloads => new List(0); + public virtual List Downloads => new(0); - public virtual Dictionary EnvironmentVariables => new Dictionary(0); + public virtual Dictionary EnvironmentVariables => new(0); // Misc public virtual bool BeepOnShutdown => false; + public virtual List SharedDirectories => new(0); + // Extensions public virtual XmlNode? ExtensionsConfiguration => null; } diff --git a/src/WinSW.Core/Configuration/XmlServiceConfig.cs b/src/WinSW.Core/Configuration/XmlServiceConfig.cs index 94be8d9..07021a5 100644 --- a/src/WinSW.Core/Configuration/XmlServiceConfig.cs +++ b/src/WinSW.Core/Configuration/XmlServiceConfig.cs @@ -18,7 +18,7 @@ namespace WinSW /// public class XmlServiceConfig : ServiceConfig { - protected readonly XmlDocument dom = new XmlDocument(); + protected readonly XmlDocument dom = new(); private readonly XmlNode root; private readonly Dictionary environmentVariables; @@ -145,7 +145,7 @@ namespace WinSW return value is null ? defaultValue : ParseTimeSpan(value); } - private static readonly Dictionary Suffix = new Dictionary + private static readonly Dictionary Suffix = new() { { "ms", 1 }, { "sec", 1000L }, @@ -581,6 +581,31 @@ namespace WinSW public bool AutoRefresh => this.SingleBoolElementOrDefault("autoRefresh", true); + public override List SharedDirectories + { + get + { + var mapNodes = this.root.SelectSingleNode("sharedDirectoryMapping")?.SelectNodes("map"); + if (mapNodes is null) + { + return new(); + } + + var result = new List(mapNodes.Count); + for (int i = 0; i < mapNodes.Count; i++) + { + if (mapNodes[i] is XmlElement mapElement) + { + string label = XmlHelper.SingleAttribute(mapElement, "label"); + string uncPath = XmlHelper.SingleAttribute(mapElement, "uncpath"); + result.Add(new(label, uncPath)); + } + } + + return result; + } + } + private Dictionary LoadEnvironmentVariables() { var nodeList = this.root.SelectNodes("env")!; diff --git a/src/WinSW.Core/LogAppenders.cs b/src/WinSW.Core/LogAppenders.cs index 936e601..59fe4d4 100644 --- a/src/WinSW.Core/LogAppenders.cs +++ b/src/WinSW.Core/LogAppenders.cs @@ -419,7 +419,7 @@ namespace WinSW private async Task CopyStreamWithRotationAsync(StreamReader reader, string extension) { // lock required as the timer thread and the thread that will write to the stream could try and access the file stream at the same time - object? fileLock = new object(); + object? fileLock = new(); string? baseDirectory = Path.GetDirectoryName(this.BaseLogFileName)!; string? baseFileName = Path.GetFileName(this.BaseLogFileName); diff --git a/src/WinSW/Logging/IServiceEventLog.cs b/src/WinSW.Core/Logging/IServiceEventLog.cs similarity index 100% rename from src/WinSW/Logging/IServiceEventLog.cs rename to src/WinSW.Core/Logging/IServiceEventLog.cs diff --git a/src/WinSW/Logging/WrapperServiceEventLogProvider.cs b/src/WinSW.Core/Logging/WrapperServiceEventLogProvider.cs similarity index 100% rename from src/WinSW/Logging/WrapperServiceEventLogProvider.cs rename to src/WinSW.Core/Logging/WrapperServiceEventLogProvider.cs diff --git a/src/WinSW.Core/Native/Libraries.cs b/src/WinSW.Core/Native/Libraries.cs index 5ca8e5c..ef9669a 100644 --- a/src/WinSW.Core/Native/Libraries.cs +++ b/src/WinSW.Core/Native/Libraries.cs @@ -5,6 +5,7 @@ internal const string Advapi32 = "advapi32.dll"; internal const string CredUI = "credui.dll"; internal const string Kernel32 = "kernel32.dll"; + internal const string Mpr = "mpr.dll"; internal const string NtDll = "ntdll.dll"; } } diff --git a/src/WinSW.Core/Native/NetworkApis.cs b/src/WinSW.Core/Native/NetworkApis.cs new file mode 100644 index 0000000..9d0a2a9 --- /dev/null +++ b/src/WinSW.Core/Native/NetworkApis.cs @@ -0,0 +1,31 @@ +#pragma warning disable SA1310 // Field names should not contain underscore + +using System.Runtime.InteropServices; +using static WinSW.Native.Libraries; + +namespace WinSW.Native +{ + internal static class NetworkApis + { + internal const uint RESOURCETYPE_DISK = 0x00000001; + + [DllImport(Mpr, SetLastError = true, CharSet = CharSet.Unicode)] + internal static extern int WNetAddConnection2W(in NETRESOURCEW netResource, string? password = null, string? userName = null, uint flags = 0); + + [DllImport(Mpr, SetLastError = true, CharSet = CharSet.Unicode)] + internal static extern int WNetCancelConnection2W(string name, uint flags = 0, bool force = false); + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct NETRESOURCEW + { + public uint Scope; + public uint Type; + public uint DisplayType; + public uint Usage; + public string LocalName; + public string RemoteName; + public string Comment; + public string Provider; + } + } +} diff --git a/src/WinSW.Core/Native/ResourceApis.cs b/src/WinSW.Core/Native/ResourceApis.cs index 8df76f4..5bf6cd2 100644 --- a/src/WinSW.Core/Native/ResourceApis.cs +++ b/src/WinSW.Core/Native/ResourceApis.cs @@ -7,9 +7,9 @@ namespace WinSW.Native { internal static class ResourceApis { - internal static readonly IntPtr VS_VERSION_INFO = new IntPtr(1); + internal static readonly IntPtr VS_VERSION_INFO = new(1); - internal static readonly IntPtr RT_VERSION = new IntPtr(16); + internal static readonly IntPtr RT_VERSION = new(16); [DllImport(Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Unicode)] internal static extern IntPtr BeginUpdateResourceW(string fileName, bool deleteExistingResources); diff --git a/src/WinSW/ServiceMessages.cs b/src/WinSW.Core/ServiceMessages.cs similarity index 100% rename from src/WinSW/ServiceMessages.cs rename to src/WinSW.Core/ServiceMessages.cs diff --git a/src/WinSW.Core/SharedDirectoryMapper.cs b/src/WinSW.Core/SharedDirectoryMapper.cs new file mode 100644 index 0000000..eca1bd7 --- /dev/null +++ b/src/WinSW.Core/SharedDirectoryMapper.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using WinSW.Native; +using static WinSW.Native.NetworkApis; + +namespace WinSW +{ + public sealed class SharedDirectoryMapper + { + private readonly List entries; + + public SharedDirectoryMapper(List entries) + { + this.entries = entries; + } + + public void Map() + { + foreach (var config in this.entries) + { + string label = config.Label; + string uncPath = config.UncPath; + + int error = WNetAddConnection2W(new() + { + Type = RESOURCETYPE_DISK, + LocalName = label, + RemoteName = uncPath, + }); + if (error != 0) + { + Throw.Command.Win32Exception(error, $"Failed to map {label}."); + } + } + } + + public void Unmap() + { + foreach (var config in this.entries) + { + string label = config.Label; + + int error = WNetCancelConnection2W(label); + if (error != 0) + { + Throw.Command.Win32Exception(error, $"Failed to unmap {label}."); + } + } + } + } +} diff --git a/src/WinSW.Core/SharedDirectoryMapperConfig.cs b/src/WinSW.Core/SharedDirectoryMapperConfig.cs new file mode 100644 index 0000000..55848fa --- /dev/null +++ b/src/WinSW.Core/SharedDirectoryMapperConfig.cs @@ -0,0 +1,15 @@ +namespace WinSW +{ + public sealed class SharedDirectoryMapperConfig + { + public string Label { get; } + + public string UncPath { get; } + + public SharedDirectoryMapperConfig(string driveLabel, string directoryUncPath) + { + this.Label = driveLabel; + this.UncPath = directoryUncPath; + } + } +} diff --git a/src/WinSW/WrapperService.cs b/src/WinSW.Core/WrapperService.cs similarity index 94% rename from src/WinSW/WrapperService.cs rename to src/WinSW.Core/WrapperService.cs index 6b81abe..4f18c2a 100644 --- a/src/WinSW/WrapperService.cs +++ b/src/WinSW.Core/WrapperService.cs @@ -17,9 +17,9 @@ namespace WinSW { public sealed class WrapperService : ServiceBase, IEventLogger, IServiceEventLog { - internal static readonly WrapperServiceEventLogProvider eventLogProvider = new WrapperServiceEventLogProvider(); + internal static readonly WrapperServiceEventLogProvider EventLogProvider = new(); - private static readonly int additionalStopTimeout = 1_000; + private static readonly int AdditionalStopTimeout = 1_000; private static readonly ILog Log = LogManager.GetLogger(typeof(WrapperService)); @@ -31,6 +31,8 @@ namespace WinSW internal WinSWExtensionManager ExtensionManager { get; } + private SharedDirectoryMapper? sharedDirectoryMapper; + private bool shuttingdown; /// @@ -51,7 +53,7 @@ namespace WinSW this.ExtensionManager = new WinSWExtensionManager(config); // Register the event log provider - eventLogProvider.Service = this; + EventLogProvider.Service = this; if (config.Preshutdown) { @@ -297,6 +299,13 @@ namespace WinSW throw new AggregateException(exceptions); } + var sharedDirectories = this.config.SharedDirectories; + if (sharedDirectories.Count > 0) + { + this.sharedDirectoryMapper = new(sharedDirectories); + this.sharedDirectoryMapper.Map(); + } + var prestart = this.config.Prestart; string? prestartExecutable = prestart.Executable; if (prestartExecutable != null) @@ -306,7 +315,7 @@ namespace WinSW using var process = this.StartProcess(prestartExecutable, prestart.Arguments, prestart.CreateLogHandler()); this.WaitForProcessToExit(process); this.LogExited($"Pre-start process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode); - process.StopDescendants(additionalStopTimeout); + process.StopDescendants(AdditionalStopTimeout); } catch (Exception e) { @@ -335,7 +344,7 @@ namespace WinSW using var process = StartProcessLocked(); this.WaitForProcessToExit(process); this.LogExited($"Post-start process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode); - process.StopDescendants(additionalStopTimeout); + process.StopDescendants(AdditionalStopTimeout); this.startingProcess = null; Process StartProcessLocked() @@ -367,7 +376,7 @@ namespace WinSW using var process = StartProcessLocked(prestopExecutable, prestop.Arguments, prestop.CreateLogHandler()); this.WaitForProcessToExit(process); this.LogExited($"Pre-stop process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode); - process.StopDescendants(additionalStopTimeout); + process.StopDescendants(AdditionalStopTimeout); this.stoppingProcess = null; } catch (Exception e) @@ -408,7 +417,7 @@ namespace WinSW Log.Debug("WaitForProcessToExit " + this.process.Id + "+" + stopProcess.Id); this.WaitForProcessToExit(stopProcess); - stopProcess.StopDescendants(additionalStopTimeout); + stopProcess.StopDescendants(AdditionalStopTimeout); this.stoppingProcess = null; this.WaitForProcessToExit(this.process); @@ -429,8 +438,8 @@ namespace WinSW { using var process = StartProcessLocked(poststopExecutable, poststop.Arguments, poststop.CreateLogHandler()); this.WaitForProcessToExit(process); - this.LogExited($"Post-Stop process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode); - process.StopDescendants(additionalStopTimeout); + this.LogExited($"Post-stop process '{process.Format()}' exited with code {process.ExitCode}.", process.ExitCode); + process.StopDescendants(AdditionalStopTimeout); this.stoppingProcess = null; } catch (Exception e) @@ -439,6 +448,15 @@ namespace WinSW } } + try + { + this.sharedDirectoryMapper?.Unmap(); + } + catch (Exception e) + { + Log.Error(e); + } + // Stop extensions this.ExtensionManager.FireBeforeWrapperStopped(); @@ -513,8 +531,8 @@ namespace WinSW process.StopDescendants(this.config.StopTimeoutInMs); - this.startingProcess?.StopTree(additionalStopTimeout); - this.stoppingProcess?.StopTree(additionalStopTimeout); + this.startingProcess?.StopTree(AdditionalStopTimeout); + this.stoppingProcess?.StopTree(AdditionalStopTimeout); // if we finished orderly, report that to SCM. // by not reporting unclean shutdown, we let Windows SCM to decide if it wants to diff --git a/src/WinSW.Plugins/SharedDirectoryMapper.cs b/src/WinSW.Plugins/SharedDirectoryMapper.cs deleted file mode 100644 index bf8f29f..0000000 --- a/src/WinSW.Plugins/SharedDirectoryMapper.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel; -using System.Runtime.InteropServices; -using System.Xml; -using log4net; -using WinSW.Extensions; -using WinSW.Util; -using static WinSW.Plugins.SharedDirectoryMapper.SharedDirectoryMapper.Native; - -namespace WinSW.Plugins.SharedDirectoryMapper -{ - public class SharedDirectoryMapper : AbstractWinSWExtension - { - private readonly List entries = new List(); - - public override string DisplayName => "Shared Directory Mapper"; - - private static readonly ILog Logger = LogManager.GetLogger(typeof(SharedDirectoryMapper)); - - public SharedDirectoryMapper() - { - } - - public SharedDirectoryMapper(bool enableMapping, string directoryUNC, string driveLabel) - { - var config = new SharedDirectoryMapperConfig(enableMapping, driveLabel, directoryUNC); - this.entries.Add(config); - } - - public override void Configure(XmlServiceConfig config, XmlNode node) - { - var mapNodes = XmlHelper.SingleNode(node, "mapping", false)!.SelectNodes("map"); - if (mapNodes != null) - { - for (int i = 0; i < mapNodes.Count; i++) - { - if (mapNodes[i] is XmlElement mapElement) - { - this.entries.Add(SharedDirectoryMapperConfig.FromXml(mapElement)); - } - } - } - } - - public override void OnWrapperStarted() - { - foreach (var config in this.entries) - { - string label = config.Label; - string uncPath = config.UNCPath; - if (config.EnableMapping) - { - Logger.Info(this.DisplayName + ": Mapping shared directory " + uncPath + " to " + label); - - int error = WNetAddConnection2(new NETRESOURCE - { - Type = RESOURCETYPE_DISK, - LocalName = label, - RemoteName = uncPath, - }); - if (error != 0) - { - this.ThrowExtensionException(error, $"Mapping of {label} failed."); - } - } - else - { - Logger.Warn(this.DisplayName + ": Mapping of " + label + " is disabled"); - } - } - } - - public override void BeforeWrapperStopped() - { - foreach (var config in this.entries) - { - string label = config.Label; - if (config.EnableMapping) - { - int error = WNetCancelConnection2(label); - if (error != 0) - { - this.ThrowExtensionException(error, $"Unmapping of {label} failed."); - } - } - } - } - - private void ThrowExtensionException(int error, string message) - { - var inner = new Win32Exception(error); - throw new ExtensionException(this.Descriptor.Id, $"{this.DisplayName}: {message} {inner.Message}", inner); - } - - internal static class Native - { - internal const uint RESOURCETYPE_DISK = 0x00000001; - - private const string MprLibraryName = "mpr.dll"; - - [DllImport(MprLibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "WNetAddConnection2W")] - internal static extern int WNetAddConnection2(in NETRESOURCE netResource, string? password = null, string? userName = null, uint flags = 0); - - [DllImport(MprLibraryName, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "WNetCancelConnection2W")] - internal static extern int WNetCancelConnection2(string name, uint flags = 0, bool force = false); - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal struct NETRESOURCE - { - public uint Scope; - public uint Type; - public uint DisplayType; - public uint Usage; - public string LocalName; - public string RemoteName; - public string Comment; - public string Provider; - } - } - } -} diff --git a/src/WinSW.Plugins/SharedDirectoryMapperConfig.cs b/src/WinSW.Plugins/SharedDirectoryMapperConfig.cs deleted file mode 100644 index 15e622d..0000000 --- a/src/WinSW.Plugins/SharedDirectoryMapperConfig.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Xml; -using WinSW.Util; - -namespace WinSW.Plugins.SharedDirectoryMapper -{ - /// - /// Stores configuration entries for SharedDirectoryMapper extension. - /// - public class SharedDirectoryMapperConfig - { - public bool EnableMapping { get; } - - public string Label { get; } - - public string UNCPath { get; } - - public SharedDirectoryMapperConfig(bool enableMapping, string label, string uncPath) - { - this.EnableMapping = enableMapping; - this.Label = label; - this.UNCPath = uncPath; - } - - public static SharedDirectoryMapperConfig FromXml(XmlElement node) - { - bool enableMapping = XmlHelper.SingleAttribute(node, "enabled", true); - string label = XmlHelper.SingleAttribute(node, "label"); - string uncPath = XmlHelper.SingleAttribute(node, "uncpath"); - return new SharedDirectoryMapperConfig(enableMapping, label, uncPath); - } - } -} diff --git a/src/WinSW.Tests/DownloadTests.cs b/src/WinSW.Tests/DownloadTests.cs index 3906a72..880370e 100644 --- a/src/WinSW.Tests/DownloadTests.cs +++ b/src/WinSW.Tests/DownloadTests.cs @@ -11,7 +11,7 @@ namespace WinSW.Tests { public class DownloadTests : IDisposable { - private readonly HttpListener globalListener = new HttpListener(); + private readonly HttpListener globalListener = new(); private readonly byte[] contents = { 0x57, 0x69, 0x6e, 0x53, 0x57 }; diff --git a/src/WinSW.Tests/Extensions/ExtensionTestBase.cs b/src/WinSW.Tests/Extensions/ExtensionTestBase.cs deleted file mode 100644 index b6a6365..0000000 --- a/src/WinSW.Tests/Extensions/ExtensionTestBase.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; - -namespace WinSW.Tests.Extensions -{ - /// - /// Base class for testing of WinSW Extensions. - /// - public class ExtensionTestBase - { - /// - /// Defines the name of the extension to be passed in the configuration. - /// This name should point to assembly in tests, because we do not merge extension DLLs for testing purposes. - /// - /// Type of the extension - /// String for Type locator, which includes class and assembly names - public static string GetExtensionClassNameWithAssembly(Type type) - { - return type.ToString() + ", " + type.Assembly; - } - } -} diff --git a/src/WinSW.Tests/Extensions/SharedDirectoryMapperConfigTest.cs b/src/WinSW.Tests/Extensions/SharedDirectoryMapperConfigTest.cs deleted file mode 100644 index 9ec72d2..0000000 --- a/src/WinSW.Tests/Extensions/SharedDirectoryMapperConfigTest.cs +++ /dev/null @@ -1,58 +0,0 @@ -using WinSW.Extensions; -using WinSW.Plugins.SharedDirectoryMapper; -using Xunit; - -namespace WinSW.Tests.Extensions -{ - public class SharedDirectoryMapperConfigTest : ExtensionTestBase - { - private readonly XmlServiceConfig serviceConfig; - - private readonly string testExtension = GetExtensionClassNameWithAssembly(typeof(SharedDirectoryMapper)); - - public SharedDirectoryMapperConfigTest() - { - string seedXml = -$@" - SERVICE_NAME - Jenkins Slave - This service runs a slave for Jenkins continuous integration system. - C:\Program Files\Java\jre7\bin\java.exe - -Xrs -jar \""%BASE%\slave.jar\"" -jnlpUrl ... - - - - - - - - - - - - - - - -"; - this.serviceConfig = XmlServiceConfig.FromXml(seedXml); - } - - [Fact] - public void LoadExtensions() - { - var manager = new WinSWExtensionManager(this.serviceConfig); - manager.LoadExtensions(); - Assert.Equal(2, manager.Extensions.Count); - } - - [Fact] - public void StartStopExtension() - { - var manager = new WinSWExtensionManager(this.serviceConfig); - manager.LoadExtensions(); - manager.FireOnWrapperStarted(); - manager.FireBeforeWrapperStopped(); - } - } -} diff --git a/src/WinSW.Tests/ServiceConfigTests.cs b/src/WinSW.Tests/ServiceConfigTests.cs index ff043be..9aab38b 100644 --- a/src/WinSW.Tests/ServiceConfigTests.cs +++ b/src/WinSW.Tests/ServiceConfigTests.cs @@ -420,5 +420,26 @@ $@" Assert.Equal(expected.StderrPath, actual.StderrPath); } } + + [Fact] + public void SharedDirectoryMapping() + { + string seedXml = +@" + + + + +"; + + var config = XmlServiceConfig.FromXml(seedXml); + + var sharedDirectories = config.SharedDirectories; + Assert.Equal(2, sharedDirectories.Count); + Assert.Equal("N:", sharedDirectories[0].Label); + Assert.Equal(@"\\UNC", sharedDirectories[0].UncPath); + Assert.Equal("M:", sharedDirectories[1].Label); + Assert.Equal(@"\\UNC2", sharedDirectories[1].UncPath); + } } } diff --git a/src/WinSW.Tests/Extensions/SharedDirectoryMapperTests.cs b/src/WinSW.Tests/SharedDirectoryMapperTests.cs similarity index 74% rename from src/WinSW.Tests/Extensions/SharedDirectoryMapperTests.cs rename to src/WinSW.Tests/SharedDirectoryMapperTests.cs index ac99e2d..f712834 100644 --- a/src/WinSW.Tests/Extensions/SharedDirectoryMapperTests.cs +++ b/src/WinSW.Tests/SharedDirectoryMapperTests.cs @@ -3,52 +3,45 @@ using System; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using WinSW.Plugins.SharedDirectoryMapper; using Xunit; namespace WinSW.Tests.Extensions { - // TODO: Assert.Throws public class SharedDirectoryMapperTests { + private static SharedDirectoryMapper CreateMapper(string driveLabel, string directoryUncPath) + { + return new(new(1) + { + new(driveLabel, directoryUncPath), + }); + } + [ElevatedFact] public void TestMap() { using var data = TestData.Create(); const string label = "W:"; - var mapper = new SharedDirectoryMapper(true, $@"\\{Environment.MachineName}\{data.name}", label); + var mapper = CreateMapper(label, $@"\\{Environment.MachineName}\{data.name}"); - mapper.OnWrapperStarted(); + mapper.Map(); Assert.True(Directory.Exists($@"{label}\")); - mapper.BeforeWrapperStopped(); + mapper.Unmap(); Assert.False(Directory.Exists($@"{label}\")); } - [ElevatedFact] - public void TestDisableMapping() - { - using var data = TestData.Create(); - - const string label = "W:"; - var mapper = new SharedDirectoryMapper(enableMapping: false, $@"\\{Environment.MachineName}\{data.name}", label); - - mapper.OnWrapperStarted(); - Assert.False(Directory.Exists($@"{label}\")); - mapper.BeforeWrapperStopped(); - } - [ElevatedFact] public void TestMap_PathEndsWithSlash_Throws() { using var data = TestData.Create(); const string label = "W:"; - var mapper = new SharedDirectoryMapper(true, $@"\\{Environment.MachineName}\{data.name}\", label); + var mapper = CreateMapper(label, $@"\\{Environment.MachineName}\{data.name}\"); - _ = Assert.ThrowsAny(() => mapper.OnWrapperStarted()); + _ = Assert.ThrowsAny(() => mapper.Map()); Assert.False(Directory.Exists($@"{label}\")); - _ = Assert.ThrowsAny(() => mapper.BeforeWrapperStopped()); + _ = Assert.ThrowsAny(() => mapper.Unmap()); } [ElevatedFact] @@ -57,11 +50,11 @@ namespace WinSW.Tests.Extensions using var data = TestData.Create(); const string label = "W"; - var mapper = new SharedDirectoryMapper(true, $@"\\{Environment.MachineName}\{data.name}", label); + var mapper = CreateMapper(label, $@"\\{Environment.MachineName}\{data.name}"); - _ = Assert.ThrowsAny(() => mapper.OnWrapperStarted()); + _ = Assert.ThrowsAny(() => mapper.Map()); Assert.False(Directory.Exists($@"{label}\")); - _ = Assert.ThrowsAny(() => mapper.BeforeWrapperStopped()); + _ = Assert.ThrowsAny(() => mapper.Unmap()); } private readonly ref struct TestData diff --git a/src/WinSW.Tests/Util/ConfigXmlBuilder.cs b/src/WinSW.Tests/Util/ConfigXmlBuilder.cs index b107aed..8e2cecd 100644 --- a/src/WinSW.Tests/Util/ConfigXmlBuilder.cs +++ b/src/WinSW.Tests/Util/ConfigXmlBuilder.cs @@ -23,7 +23,7 @@ namespace WinSW.Tests.Util public List ExtensionXmls { get; } = new List(); - private readonly List configEntries = new List(); + private readonly List configEntries = new(); private readonly ITestOutputHelper output; diff --git a/src/WinSW/Program.cs b/src/WinSW/Program.cs index 6ddaf0a..c395a78 100644 --- a/src/WinSW/Program.cs +++ b/src/WinSW/Program.cs @@ -1099,7 +1099,7 @@ namespace WinSW } else { - var eventLogAppender = new ServiceEventLogAppender(WrapperService.eventLogProvider) + var eventLogAppender = new ServiceEventLogAppender(WrapperService.EventLogProvider) { Name = "Wrapper event log", Threshold = eventLogLevel,