using System; using System.Diagnostics; using System.IO; using System.Xml; using NUnit.Framework; using winsw; using winsw.Native; using winswTests.Util; using WMI; namespace winswTests { [TestFixture] public class ServiceDescriptorTests { private ServiceDescriptor _extendedServiceDescriptor; private const string ExpectedWorkingDirectory = @"Z:\Path\SubPath"; private const string Username = "User"; private const string Password = "Password"; private const string Domain = "Domain"; private const string AllowServiceAccountLogonRight = "true"; [SetUp] public void SetUp() { string seedXml = $@" service.exe Service The service. node.exe My Arguments rotate {Domain} {Username} {Password} {AllowServiceAccountLogonRight} {ExpectedWorkingDirectory} C:\logs "; _extendedServiceDescriptor = ServiceDescriptor.FromXML(seedXml); } [Test] public void DefaultStartMode() { Assert.That(_extendedServiceDescriptor.StartMode, Is.EqualTo(StartMode.Automatic)); } [Test] public void IncorrectStartMode() { string seedXml = $@" service.exe Service The service. node.exe My Arguments rotate rotate {Domain} {Username} {Password} {AllowServiceAccountLogonRight} {ExpectedWorkingDirectory} C:\logs "; _extendedServiceDescriptor = ServiceDescriptor.FromXML(seedXml); Assert.Throws(() => _ = _extendedServiceDescriptor.StartMode); } [Test] public void ChangedStartMode() { string seedXml = $@" service.exe Service The service. node.exe My Arguments manual rotate {Domain} {Username} {Password} {AllowServiceAccountLogonRight} {ExpectedWorkingDirectory} C:\logs "; _extendedServiceDescriptor = ServiceDescriptor.FromXML(seedXml); Assert.That(_extendedServiceDescriptor.StartMode, Is.EqualTo(StartMode.Manual)); } [Test] public void VerifyWorkingDirectory() { Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + _extendedServiceDescriptor.WorkingDirectory); Assert.That(_extendedServiceDescriptor.WorkingDirectory, Is.EqualTo(ExpectedWorkingDirectory)); } [Test] public void VerifyServiceLogonRight() { Assert.That(_extendedServiceDescriptor.AllowServiceAcountLogonRight, Is.EqualTo(true)); } [Test] public void VerifyUsername() { Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + _extendedServiceDescriptor.WorkingDirectory); Assert.That(_extendedServiceDescriptor.ServiceAccountUser, Is.EqualTo(Domain + "\\" + Username)); } [Test] public void VerifyPassword() { Debug.WriteLine("_extendedServiceDescriptor.WorkingDirectory :: " + _extendedServiceDescriptor.WorkingDirectory); Assert.That(_extendedServiceDescriptor.ServiceAccountPassword, Is.EqualTo(Password)); } [Test] public void Priority() { var sd = ServiceDescriptor.FromXML("testnormal"); Assert.That(sd.Priority, Is.EqualTo(ProcessPriorityClass.Normal)); sd = ServiceDescriptor.FromXML("testidle"); Assert.That(sd.Priority, Is.EqualTo(ProcessPriorityClass.Idle)); sd = ServiceDescriptor.FromXML("test"); Assert.That(sd.Priority, Is.EqualTo(ProcessPriorityClass.Normal)); } [Test] public void StopParentProcessFirstIsFalseByDefault() { Assert.False(_extendedServiceDescriptor.StopParentProcessFirst); } [Test] public void CanParseStopParentProcessFirst() { const string seedXml = "" + "true" + ""; var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); Assert.True(serviceDescriptor.StopParentProcessFirst); } [Test] public void CanParseStopTimeout() { const string seedXml = "" + "60sec" + ""; var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); Assert.That(serviceDescriptor.StopTimeout, Is.EqualTo(TimeSpan.FromSeconds(60))); } [Test] public void CanParseStopTimeoutFromMinutes() { const string seedXml = "" + "10min" + ""; var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); Assert.That(serviceDescriptor.StopTimeout, Is.EqualTo(TimeSpan.FromMinutes(10))); } [Test] public void CanParseLogname() { const string seedXml = "" + "MyTestApp" + ""; var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); Assert.That(serviceDescriptor.LogName, Is.EqualTo("MyTestApp")); } [Test] public void CanParseOutfileDisabled() { const string seedXml = "" + "true" + ""; var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); Assert.That(serviceDescriptor.OutFileDisabled, Is.EqualTo(true)); } [Test] public void CanParseErrfileDisabled() { const string seedXml = "" + "true" + ""; var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); Assert.That(serviceDescriptor.ErrFileDisabled, Is.EqualTo(true)); } [Test] public void CanParseOutfilePattern() { const string seedXml = "" + ".out.test.log" + ""; var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); Assert.That(serviceDescriptor.OutFilePattern, Is.EqualTo(".out.test.log")); } [Test] public void CanParseErrfilePattern() { const string seedXml = "" + ".err.test.log" + ""; var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); Assert.That(serviceDescriptor.ErrFilePattern, Is.EqualTo(".err.test.log")); } [Test] public void LogModeRollBySize() { const string seedXml = "" + "c:\\" + "" + "112" + "113" + "" + ""; var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); serviceDescriptor.BaseName = "service"; var logHandler = serviceDescriptor.LogHandler as SizeBasedRollingLogAppender; Assert.NotNull(logHandler); Assert.That(logHandler.SizeTheshold, Is.EqualTo(112 * 1024)); Assert.That(logHandler.FilesToKeep, Is.EqualTo(113)); } [Test] public void LogModeRollByTime() { const string seedXml = "" + "c:\\" + "" + "7" + "log pattern" + "" + ""; var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); serviceDescriptor.BaseName = "service"; var logHandler = serviceDescriptor.LogHandler as TimeBasedRollingLogAppender; Assert.NotNull(logHandler); Assert.That(logHandler.Period, Is.EqualTo(7)); Assert.That(logHandler.Pattern, Is.EqualTo("log pattern")); } [Test] public void LogModeRollBySizeTime() { const string seedXml = "" + "c:\\" + "" + "10240" + "yyyy-MM-dd" + "00:00:00" + "" + ""; var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); serviceDescriptor.BaseName = "service"; var logHandler = serviceDescriptor.LogHandler as RollingSizeTimeLogAppender; Assert.NotNull(logHandler); Assert.That(logHandler.SizeTheshold, Is.EqualTo(10240 * 1024)); Assert.That(logHandler.FilePattern, Is.EqualTo("yyyy-MM-dd")); Assert.That(logHandler.AutoRollAtTime, Is.EqualTo((TimeSpan?)new TimeSpan(0, 0, 0))); } [Test] public void VerifyServiceLogonRightGraceful() { const string seedXml = "" + "" + "" + Domain + "" + "" + Username + "" + "" + Password + "" + "true1" + "" + ""; var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); Assert.That(serviceDescriptor.AllowServiceAcountLogonRight, Is.EqualTo(false)); } [Test] public void VerifyServiceLogonRightOmitted() { const string seedXml = "" + "" + "" + Domain + "" + "" + Username + "" + "" + Password + "" + "" + ""; var serviceDescriptor = ServiceDescriptor.FromXML(seedXml); Assert.That(serviceDescriptor.AllowServiceAcountLogonRight, Is.EqualTo(false)); } [Test] public void VerifyWaitHint_FullXML() { var sd = ConfigXmlBuilder.create() .WithTag("waithint", "20 min") .ToServiceDescriptor(true); Assert.That(sd.WaitHint, Is.EqualTo(TimeSpan.FromMinutes(20))); } /// /// Test for https://github.com/kohsuke/winsw/issues/159 /// [Test] public void VerifyWaitHint_XMLWithoutVersion() { var sd = ConfigXmlBuilder.create(printXMLVersion: false) .WithTag("waithint", "21 min") .ToServiceDescriptor(true); Assert.That(sd.WaitHint, Is.EqualTo(TimeSpan.FromMinutes(21))); } [Test] public void VerifyWaitHint_XMLWithoutComment() { var sd = ConfigXmlBuilder.create(xmlComment: null) .WithTag("waithint", "22 min") .ToServiceDescriptor(true); Assert.That(sd.WaitHint, Is.EqualTo(TimeSpan.FromMinutes(22))); } [Test] public void VerifyWaitHint_XMLWithoutVersionAndComment() { var sd = ConfigXmlBuilder.create(xmlComment: null, printXMLVersion: false) .WithTag("waithint", "23 min") .ToServiceDescriptor(true); Assert.That(sd.WaitHint, Is.EqualTo(TimeSpan.FromMinutes(23))); } [Test] public void VerifySleepTime() { var sd = ConfigXmlBuilder.create().WithTag("sleeptime", "3 hrs").ToServiceDescriptor(true); Assert.That(sd.SleepTime, Is.EqualTo(TimeSpan.FromHours(3))); } [Test] public void VerifyResetFailureAfter() { var sd = ConfigXmlBuilder.create().WithTag("resetfailure", "75 sec").ToServiceDescriptor(true); Assert.That(sd.ResetFailureAfter, Is.EqualTo(TimeSpan.FromSeconds(75))); } [Test] public void VerifyStopTimeout() { var sd = ConfigXmlBuilder.create().WithTag("stoptimeout", "35 secs").ToServiceDescriptor(true); Assert.That(sd.StopTimeout, Is.EqualTo(TimeSpan.FromSeconds(35))); } /// /// https://github.com/kohsuke/winsw/issues/178 /// [Test] public void Arguments_LegacyParam() { var sd = ConfigXmlBuilder.create().WithTag("arguments", "arg").ToServiceDescriptor(true); Assert.That(sd.Arguments, Is.EqualTo("arg")); } [Test] public void Arguments_NewParam_Single() { var sd = ConfigXmlBuilder.create() .WithTag("argument", "--arg1=2") .ToServiceDescriptor(true); Assert.That(sd.Arguments, Is.EqualTo(" --arg1=2")); } [Test] public void Arguments_NewParam_MultipleArgs() { var sd = ConfigXmlBuilder.create() .WithTag("argument", "--arg1=2") .WithTag("argument", "--arg2=123") .WithTag("argument", "--arg3=null") .ToServiceDescriptor(true); Assert.That(sd.Arguments, Is.EqualTo(" --arg1=2 --arg2=123 --arg3=null")); } /// /// Ensures that the new single-argument field has a higher priority. /// [Test] public void Arguments_Bothparam_Priorities() { var sd = ConfigXmlBuilder.create() .WithTag("arguments", "--arg1=2 --arg2=3") .WithTag("argument", "--arg2=123") .WithTag("argument", "--arg3=null") .ToServiceDescriptor(true); Assert.That(sd.Arguments, Is.EqualTo(" --arg2=123 --arg3=null")); } [TestCase(true)] [TestCase(false)] public void DelayedStart_RoundTrip(bool enabled) { var bldr = ConfigXmlBuilder.create(); if (enabled) { bldr = bldr.WithDelayedAutoStart(); } var sd = bldr.ToServiceDescriptor(); Assert.That(sd.DelayedAutoStart, Is.EqualTo(enabled)); } [Test] public void ValidateAndLoadXmlSchemaTest() { const string seedXml = @" myapp appname app description jenkins "; var dom = new XmlDocument(); dom.LoadXml(seedXml); var serviceDescriptor = new ServiceDescriptor(dom); var reader = XmlReader.Create(new StringReader(seedXml)); Assert.That(() => serviceDescriptor.ValidateAndLoadXmlSchema(reader), Throws.TypeOf()); } } }