Don't print to console

pull/581/head
NextTurn 2018-11-26 00:00:00 +08:00 committed by Next Turn
parent bbb3cd578c
commit 0c393e0eec
6 changed files with 116 additions and 90 deletions

View File

@ -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);
}
}
}

View File

@ -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("<download from=\"http://www.nosuchhostexists.foo.myorg/foo.xml\" to=\"%BASE%\\foo.xml\"/>")
.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("<download from=\"http://www.nosuchhostexists.foo.myorg/foo.xml\" to=\"%BASE%\\foo.xml\" auth=\"" + authType + "\"/>")
.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("<download from=\"http://www.nosuchhostexists.foo.myorg/foo.xml\" to=\"%BASE%\\foo.xml\" auth=\"digest\"/>")
.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);

View File

@ -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>
<id>SERVICE_NAME</id>
@ -63,51 +68,57 @@ $@"<service>
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);
}
}
}

View File

@ -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>
<id>service.exe</id>
@ -65,7 +71,7 @@ $@"<service>
</service>";
this.extendedServiceDescriptor = ServiceDescriptor.FromXml(seedXml);
Assert.Throws<ArgumentException>(() => this.extendedServiceDescriptor.StartMode);
_ = Assert.Throws<InvalidDataException>(() => this.extendedServiceDescriptor.StartMode);
}
[Fact]
@ -304,7 +310,7 @@ $@"<service>
[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 @@ $@"<service>
[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 @@ $@"<service>
[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 @@ $@"<service>
[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 @@ $@"<service>
[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 @@ $@"<service>
[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 @@ $@"<service>
[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 @@ $@"<service>
[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 @@ $@"<service>
[InlineData(false)]
public void DelayedStart_RoundTrip(bool enabled)
{
var bldr = ConfigXmlBuilder.Create();
var bldr = ConfigXmlBuilder.Create(this.output);
if (enabled)
{
bldr = bldr.WithDelayedAutoStart();

View File

@ -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<string> ExtensionXmls { get; }
public List<string> ExtensionXmls { get; } = new List<string>();
private readonly List<string> configEntries;
private readonly List<string> configEntries = new List<string>();
// TODO: Switch to the initializer?
private ConfigXmlBuilder()
private readonly ITestOutputHelper output;
private ConfigXmlBuilder(ITestOutputHelper output)
{
this.configEntries = new List<string>();
this.ExtensionXmls = new List<string>();
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;

View File

@ -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;
}
}