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