From 0c393e0eec5ee5b95a8c62e226d646f87bed0df2 Mon Sep 17 00:00:00 2001 From: NextTurn <45985406+NextTurn@users.noreply.github.com> Date: Mon, 26 Nov 2018 00:00:00 +0800 Subject: [PATCH] Don't print to console --- src/WinSW.Core/ServiceDescriptor.cs | 9 +- src/WinSW.Tests/DownloadConfigTests.cs | 24 +++-- .../Extensions/RunawayProcessKillerTest.cs | 89 +++++++++++-------- src/WinSW.Tests/ServiceDescriptorTests.cs | 34 ++++--- src/WinSW.Tests/Util/ConfigXmlBuilder.cs | 44 ++++----- src/WinSW.Tests/Util/FilesystemTestHelper.cs | 6 +- 6 files changed, 116 insertions(+), 90 deletions(-) diff --git a/src/WinSW.Core/ServiceDescriptor.cs b/src/WinSW.Core/ServiceDescriptor.cs index 81ae541..2e484ef 100644 --- a/src/WinSW.Core/ServiceDescriptor.cs +++ b/src/WinSW.Core/ServiceDescriptor.cs @@ -533,15 +533,16 @@ namespace WinSW { return (ServiceStartMode)Enum.Parse(typeof(ServiceStartMode), p, true); } - catch + catch (ArgumentException e) { - Console.WriteLine("Start mode in XML must be one of the following:"); + StringBuilder builder = new StringBuilder(); + builder.AppendLine("Start mode in XML must be one of the following:"); foreach (string sm in Enum.GetNames(typeof(ServiceStartMode))) { - Console.WriteLine(sm); + builder.AppendLine(sm); } - throw; + throw new InvalidDataException(builder.ToString(), e); } } } diff --git a/src/WinSW.Tests/DownloadConfigTests.cs b/src/WinSW.Tests/DownloadConfigTests.cs index 910aa31..d60b197 100644 --- a/src/WinSW.Tests/DownloadConfigTests.cs +++ b/src/WinSW.Tests/DownloadConfigTests.cs @@ -1,6 +1,7 @@ using System.IO; using WinSW.Tests.Util; using Xunit; +using Xunit.Abstractions; namespace WinSW.Tests { @@ -9,12 +10,19 @@ namespace WinSW.Tests private const string From = "https://www.nosuchhostexists.foo.myorg/foo.xml"; private const string To = "%BASE%\\foo.xml"; + private readonly ITestOutputHelper output; + + public DownloadConfigTests(ITestOutputHelper output) + { + this.output = output; + } + [Fact] public void Roundtrip_Defaults() { // Roundtrip data Download d = new Download(From, To); - var sd = ConfigXmlBuilder.Create() + var sd = ConfigXmlBuilder.Create(this.output) .WithDownload(d) .ToServiceDescriptor(true); var loaded = this.GetSingleEntry(sd); @@ -32,7 +40,7 @@ namespace WinSW.Tests { // Roundtrip data Download d = new Download(From, To, true, Download.AuthType.Basic, "aUser", "aPassword", true); - var sd = ConfigXmlBuilder.Create() + var sd = ConfigXmlBuilder.Create(this.output) .WithDownload(d) .ToServiceDescriptor(true); var loaded = this.GetSingleEntry(sd); @@ -50,7 +58,7 @@ namespace WinSW.Tests { // Roundtrip data Download d = new Download(From, To, false, Download.AuthType.Sspi); - var sd = ConfigXmlBuilder.Create() + var sd = ConfigXmlBuilder.Create(this.output) .WithDownload(d) .ToServiceDescriptor(true); var loaded = this.GetSingleEntry(sd); @@ -99,7 +107,7 @@ namespace WinSW.Tests { Download d = new Download(From, To, failOnError); - var sd = ConfigXmlBuilder.Create() + var sd = ConfigXmlBuilder.Create(this.output) .WithDownload(d) .ToServiceDescriptor(true); @@ -115,7 +123,7 @@ namespace WinSW.Tests [Fact] public void Download_FailOnError_Undefined() { - var sd = ConfigXmlBuilder.Create() + var sd = ConfigXmlBuilder.Create(this.output) .WithRawEntry("") .ToServiceDescriptor(true); @@ -130,7 +138,7 @@ namespace WinSW.Tests [InlineData("Sspi")] public void AuthType_Is_CaseInsensitive(string authType) { - var sd = ConfigXmlBuilder.Create() + var sd = ConfigXmlBuilder.Create(this.output) .WithRawEntry("") .ToServiceDescriptor(true); var loaded = this.GetSingleEntry(sd); @@ -141,7 +149,7 @@ namespace WinSW.Tests public void Should_Fail_On_Unsupported_AuthType() { // TODO: will need refactoring once all fields are being parsed on startup - var sd = ConfigXmlBuilder.Create() + var sd = ConfigXmlBuilder.Create(this.output) .WithRawEntry("") .ToServiceDescriptor(true); @@ -187,7 +195,7 @@ namespace WinSW.Tests private void AssertInitializationFails(Download download, string expectedMessagePart = null) { - var sd = ConfigXmlBuilder.Create() + var sd = ConfigXmlBuilder.Create(this.output) .WithDownload(download) .ToServiceDescriptor(true); diff --git a/src/WinSW.Tests/Extensions/RunawayProcessKillerTest.cs b/src/WinSW.Tests/Extensions/RunawayProcessKillerTest.cs index f84c032..ee19f06 100644 --- a/src/WinSW.Tests/Extensions/RunawayProcessKillerTest.cs +++ b/src/WinSW.Tests/Extensions/RunawayProcessKillerTest.cs @@ -6,6 +6,7 @@ using WinSW.Plugins.RunawayProcessKiller; using WinSW.Tests.Util; using WinSW.Util; using Xunit; +using Xunit.Abstractions; namespace WinSW.Tests.Extensions { @@ -15,8 +16,12 @@ namespace WinSW.Tests.Extensions private readonly string testExtension = GetExtensionClassNameWithAssembly(typeof(RunawayProcessKillerExtension)); - public RunawayProcessKillerExtensionTest() + private readonly ITestOutputHelper output; + + public RunawayProcessKillerExtensionTest(ITestOutputHelper output) { + this.output = output; + string seedXml = $@" SERVICE_NAME @@ -63,51 +68,57 @@ $@" var winswId = "myAppWithRunaway"; var extensionId = "runaway-process-killer"; var tmpDir = FilesystemTestHelper.CreateTmpDirectory(); - - // Spawn the test process - Process proc = new Process(); - var ps = proc.StartInfo; - ps.FileName = "cmd.exe"; - ps.Arguments = "/c pause"; - ps.UseShellExecute = false; - ps.RedirectStandardOutput = true; - ps.EnvironmentVariables[WinSWSystem.EnvVarNameServiceId] = winswId; - proc.Start(); - try { - // Generate extension and ensure that the roundtrip is correct - var pidfile = Path.Combine(tmpDir, "process.pid"); - var sd = ConfigXmlBuilder.Create(id: winswId) - .WithRunawayProcessKiller(new RunawayProcessKillerExtension(pidfile), extensionId) - .ToServiceDescriptor(); - WinSWExtensionManager manager = new WinSWExtensionManager(sd); - manager.LoadExtensions(); - var extension = manager.Extensions[extensionId] as RunawayProcessKillerExtension; - Assert.NotNull(extension); - Assert.Equal(pidfile, extension.Pidfile); + // Spawn the test process + Process proc = new Process(); + var ps = proc.StartInfo; + ps.FileName = "cmd.exe"; + ps.Arguments = "/c pause"; + ps.UseShellExecute = false; + ps.RedirectStandardOutput = true; + ps.EnvironmentVariables[WinSWSystem.EnvVarNameServiceId] = winswId; + proc.Start(); - // Inject PID - File.WriteAllText(pidfile, proc.Id.ToString()); + try + { + // Generate extension and ensure that the roundtrip is correct + var pidfile = Path.Combine(tmpDir, "process.pid"); + var sd = ConfigXmlBuilder.Create(this.output, id: winswId) + .WithRunawayProcessKiller(new RunawayProcessKillerExtension(pidfile), extensionId) + .ToServiceDescriptor(); + WinSWExtensionManager manager = new WinSWExtensionManager(sd); + manager.LoadExtensions(); + var extension = manager.Extensions[extensionId] as RunawayProcessKillerExtension; + Assert.NotNull(extension); + Assert.Equal(pidfile, extension.Pidfile); - // Try to terminate - Assert.False(proc.HasExited, "Process " + proc + " has exited before the RunawayProcessKiller extension invocation"); - _ = proc.StandardOutput.Read(); - extension.OnWrapperStarted(); - Assert.True(proc.HasExited, "Process " + proc + " should have been terminated by RunawayProcessKiller"); + // Inject PID + File.WriteAllText(pidfile, proc.Id.ToString()); + + // Try to terminate + Assert.False(proc.HasExited, "Process " + proc + " has exited before the RunawayProcessKiller extension invocation"); + _ = proc.StandardOutput.Read(); + extension.OnWrapperStarted(); + Assert.True(proc.HasExited, "Process " + proc + " should have been terminated by RunawayProcessKiller"); + } + finally + { + if (!proc.HasExited) + { + Console.Error.WriteLine("Test: Killing runaway process with ID=" + proc.Id); + ProcessHelper.StopProcessTree(proc, TimeSpan.FromMilliseconds(100)); + if (!proc.HasExited) + { + // The test is failed here anyway, but we add additional diagnostics info + Console.Error.WriteLine("Test: ProcessHelper failed to properly terminate process with ID=" + proc.Id); + } + } + } } finally { - if (!proc.HasExited) - { - Console.Error.WriteLine("Test: Killing runaway process with ID=" + proc.Id); - ProcessHelper.StopProcessTree(proc, TimeSpan.FromMilliseconds(100)); - if (!proc.HasExited) - { - // The test is failed here anyway, but we add additional diagnostics info - Console.Error.WriteLine("Test: ProcessHelper failed to properly terminate process with ID=" + proc.Id); - } - } + Directory.Delete(tmpDir, true); } } } diff --git a/src/WinSW.Tests/ServiceDescriptorTests.cs b/src/WinSW.Tests/ServiceDescriptorTests.cs index 2e5ab57..503bc7a 100644 --- a/src/WinSW.Tests/ServiceDescriptorTests.cs +++ b/src/WinSW.Tests/ServiceDescriptorTests.cs @@ -1,8 +1,10 @@ using System; using System.Diagnostics; +using System.IO; using System.ServiceProcess; using WinSW.Tests.Util; using Xunit; +using Xunit.Abstractions; namespace WinSW.Tests { @@ -14,10 +16,14 @@ namespace WinSW.Tests private const string Domain = "Domain"; private const string AllowServiceAccountLogonRight = "true"; + private readonly ITestOutputHelper output; + private ServiceDescriptor extendedServiceDescriptor; - public ServiceDescriptorTests() + public ServiceDescriptorTests(ITestOutputHelper output) { + this.output = output; + string seedXml = $@" service.exe @@ -65,7 +71,7 @@ $@" "; this.extendedServiceDescriptor = ServiceDescriptor.FromXml(seedXml); - Assert.Throws(() => this.extendedServiceDescriptor.StartMode); + _ = Assert.Throws(() => this.extendedServiceDescriptor.StartMode); } [Fact] @@ -304,7 +310,7 @@ $@" [Fact] public void VerifyWaitHint_FullXML() { - var sd = ConfigXmlBuilder.Create() + var sd = ConfigXmlBuilder.Create(this.output) .WithTag("waithint", "20 min") .ToServiceDescriptor(true); Assert.Equal(TimeSpan.FromMinutes(20), sd.WaitHint); @@ -316,7 +322,7 @@ $@" [Fact] public void VerifyWaitHint_XMLWithoutVersion() { - var sd = ConfigXmlBuilder.Create(printXMLVersion: false) + var sd = ConfigXmlBuilder.Create(this.output, printXmlVersion: false) .WithTag("waithint", "21 min") .ToServiceDescriptor(true); Assert.Equal(TimeSpan.FromMinutes(21), sd.WaitHint); @@ -325,7 +331,7 @@ $@" [Fact] public void VerifyWaitHint_XMLWithoutComment() { - var sd = ConfigXmlBuilder.Create(xmlComment: null) + var sd = ConfigXmlBuilder.Create(this.output, xmlComment: null) .WithTag("waithint", "22 min") .ToServiceDescriptor(true); Assert.Equal(TimeSpan.FromMinutes(22), sd.WaitHint); @@ -334,7 +340,7 @@ $@" [Fact] public void VerifyWaitHint_XMLWithoutVersionAndComment() { - var sd = ConfigXmlBuilder.Create(xmlComment: null, printXMLVersion: false) + var sd = ConfigXmlBuilder.Create(this.output, xmlComment: null, printXmlVersion: false) .WithTag("waithint", "23 min") .ToServiceDescriptor(true); Assert.Equal(TimeSpan.FromMinutes(23), sd.WaitHint); @@ -343,21 +349,21 @@ $@" [Fact] public void VerifySleepTime() { - var sd = ConfigXmlBuilder.Create().WithTag("sleeptime", "3 hrs").ToServiceDescriptor(true); + var sd = ConfigXmlBuilder.Create(this.output).WithTag("sleeptime", "3 hrs").ToServiceDescriptor(true); Assert.Equal(TimeSpan.FromHours(3), sd.SleepTime); } [Fact] public void VerifyResetFailureAfter() { - var sd = ConfigXmlBuilder.Create().WithTag("resetfailure", "75 sec").ToServiceDescriptor(true); + var sd = ConfigXmlBuilder.Create(this.output).WithTag("resetfailure", "75 sec").ToServiceDescriptor(true); Assert.Equal(TimeSpan.FromSeconds(75), sd.ResetFailureAfter); } [Fact] public void VerifyStopTimeout() { - var sd = ConfigXmlBuilder.Create().WithTag("stoptimeout", "35 secs").ToServiceDescriptor(true); + var sd = ConfigXmlBuilder.Create(this.output).WithTag("stoptimeout", "35 secs").ToServiceDescriptor(true); Assert.Equal(TimeSpan.FromSeconds(35), sd.StopTimeout); } @@ -367,14 +373,14 @@ $@" [Fact] public void Arguments_LegacyParam() { - var sd = ConfigXmlBuilder.Create().WithTag("arguments", "arg").ToServiceDescriptor(true); + var sd = ConfigXmlBuilder.Create(this.output).WithTag("arguments", "arg").ToServiceDescriptor(true); Assert.Equal("arg", sd.Arguments); } [Fact] public void Arguments_NewParam_Single() { - var sd = ConfigXmlBuilder.Create() + var sd = ConfigXmlBuilder.Create(this.output) .WithTag("argument", "--arg1=2") .ToServiceDescriptor(true); Assert.Equal(" --arg1=2", sd.Arguments); @@ -383,7 +389,7 @@ $@" [Fact] public void Arguments_NewParam_MultipleArgs() { - var sd = ConfigXmlBuilder.Create() + var sd = ConfigXmlBuilder.Create(this.output) .WithTag("argument", "--arg1=2") .WithTag("argument", "--arg2=123") .WithTag("argument", "--arg3=null") @@ -397,7 +403,7 @@ $@" [Fact] public void Arguments_Bothparam_Priorities() { - var sd = ConfigXmlBuilder.Create() + var sd = ConfigXmlBuilder.Create(this.output) .WithTag("arguments", "--arg1=2 --arg2=3") .WithTag("argument", "--arg2=123") .WithTag("argument", "--arg3=null") @@ -410,7 +416,7 @@ $@" [InlineData(false)] public void DelayedStart_RoundTrip(bool enabled) { - var bldr = ConfigXmlBuilder.Create(); + var bldr = ConfigXmlBuilder.Create(this.output); if (enabled) { bldr = bldr.WithDelayedAutoStart(); diff --git a/src/WinSW.Tests/Util/ConfigXmlBuilder.cs b/src/WinSW.Tests/Util/ConfigXmlBuilder.cs index 6f38519..35be9c9 100644 --- a/src/WinSW.Tests/Util/ConfigXmlBuilder.cs +++ b/src/WinSW.Tests/Util/ConfigXmlBuilder.cs @@ -1,8 +1,8 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Text; using WinSW.Plugins.RunawayProcessKiller; using WinSW.Tests.Extensions; +using Xunit.Abstractions; namespace WinSW.Tests.Util { @@ -23,35 +23,37 @@ namespace WinSW.Tests.Util public string XmlComment { get; set; } - public List ExtensionXmls { get; } + public List ExtensionXmls { get; } = new List(); - private readonly List configEntries; + private readonly List configEntries = new List(); - // TODO: Switch to the initializer? - private ConfigXmlBuilder() + private readonly ITestOutputHelper output; + + private ConfigXmlBuilder(ITestOutputHelper output) { - this.configEntries = new List(); - this.ExtensionXmls = new List(); + this.output = output; } public static ConfigXmlBuilder Create( + ITestOutputHelper output, string id = null, string name = null, string description = null, string executable = null, - bool printXMLVersion = true, + bool printXmlVersion = true, string xmlComment = "") { - var config = new ConfigXmlBuilder(); - config.Id = id ?? "myapp"; - config.Name = name ?? "MyApp Service"; - config.Description = description ?? "MyApp Service (powered by WinSW)"; - config.Executable = executable ?? "%BASE%\\myExecutable.exe"; - config.PrintXmlVersion = printXMLVersion; - config.XmlComment = (xmlComment != null && xmlComment.Length == 0) - ? "Just a sample configuration file generated by the test suite" - : xmlComment; - return config; + return new ConfigXmlBuilder(output) + { + Id = id ?? "myapp", + Name = name ?? "MyApp Service", + Description = description ?? "MyApp Service (powered by WinSW)", + Executable = executable ?? "%BASE%\\myExecutable.exe", + PrintXmlVersion = printXmlVersion, + XmlComment = (xmlComment != null && xmlComment.Length == 0) + ? "Just a sample configuration file generated by the test suite" + : xmlComment, + }; } public string ToXmlString(bool dumpConfig = false) @@ -95,8 +97,8 @@ namespace WinSW.Tests.Util string res = str.ToString(); if (dumpConfig) { - Console.Out.WriteLine("Produced config:"); - Console.Out.WriteLine(res); + this.output.WriteLine("Produced config:"); + this.output.WriteLine(res); } return res; diff --git a/src/WinSW.Tests/Util/FilesystemTestHelper.cs b/src/WinSW.Tests/Util/FilesystemTestHelper.cs index 11324c4..b81fc46 100644 --- a/src/WinSW.Tests/Util/FilesystemTestHelper.cs +++ b/src/WinSW.Tests/Util/FilesystemTestHelper.cs @@ -1,5 +1,4 @@ -using System; -using System.IO; +using System.IO; namespace WinSW.Tests.Util { @@ -12,8 +11,7 @@ namespace WinSW.Tests.Util public static string CreateTmpDirectory(string testName = null) { string tempDirectory = Path.Combine(Path.GetTempPath(), "winswTests_" + (testName ?? string.Empty) + Path.GetRandomFileName()); - Directory.CreateDirectory(tempDirectory); - Console.Out.WriteLine("Created the temporary directory: {0}", tempDirectory); + _ = Directory.CreateDirectory(tempDirectory); return tempDirectory; } }