mirror of https://github.com/winsw/winsw
Simplify syntax
parent
466b5264e1
commit
941e67d08c
|
@ -91,8 +91,7 @@ namespace winsw
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var tr = new StreamReader(file, Encoding.UTF8))
|
using var tr = new StreamReader(file, Encoding.UTF8);
|
||||||
{
|
|
||||||
string? line;
|
string? line;
|
||||||
while ((line = tr.ReadLine()) != null)
|
while ((line = tr.ReadLine()) != null)
|
||||||
{
|
{
|
||||||
|
@ -107,7 +106,6 @@ namespace winsw
|
||||||
CopyFile(tokens[0], tokens[1]);
|
CopyFile(tokens[0], tokens[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
File.Delete(file);
|
File.Delete(file);
|
||||||
|
@ -186,7 +184,7 @@ namespace winsw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnStart(string[] _)
|
protected override void OnStart(string[] args)
|
||||||
{
|
{
|
||||||
_envs = _descriptor.EnvironmentVariables;
|
_envs = _descriptor.EnvironmentVariables;
|
||||||
// TODO: Disabled according to security concerns in https://github.com/kohsuke/winsw/issues/54
|
// TODO: Disabled according to security concerns in https://github.com/kohsuke/winsw/issues/54
|
||||||
|
@ -490,11 +488,11 @@ namespace winsw
|
||||||
bool isCLIMode = _args.Length > 0;
|
bool isCLIMode = _args.Length > 0;
|
||||||
|
|
||||||
// If descriptor is not specified, initialize the new one (and load configs from there)
|
// If descriptor is not specified, initialize the new one (and load configs from there)
|
||||||
var d = descriptor ?? new ServiceDescriptor();
|
descriptor ??= new ServiceDescriptor();
|
||||||
|
|
||||||
// Configure the wrapper-internal logging.
|
// Configure the wrapper-internal logging.
|
||||||
// STDIN and STDOUT of the child process will be handled independently.
|
// STDIN and STDOUT of the child process will be handled independently.
|
||||||
InitLoggers(d, isCLIMode);
|
InitLoggers(descriptor, isCLIMode);
|
||||||
|
|
||||||
if (isCLIMode) // CLI mode, in-service mode otherwise
|
if (isCLIMode) // CLI mode, in-service mode otherwise
|
||||||
{
|
{
|
||||||
|
@ -502,7 +500,7 @@ namespace winsw
|
||||||
|
|
||||||
// Get service info for the future use
|
// Get service info for the future use
|
||||||
Win32Services svc = new WmiRoot().GetCollection<Win32Services>();
|
Win32Services svc = new WmiRoot().GetCollection<Win32Services>();
|
||||||
Win32Service s = svc.Select(d.Id);
|
Win32Service s = svc.Select(descriptor.Id);
|
||||||
|
|
||||||
var args = new List<string>(Array.AsReadOnly(_args));
|
var args = new List<string>(Array.AsReadOnly(_args));
|
||||||
if (args[0] == "/redirect")
|
if (args[0] == "/redirect")
|
||||||
|
@ -530,14 +528,14 @@ namespace winsw
|
||||||
args[0] = args[0].ToLower();
|
args[0] = args[0].ToLower();
|
||||||
if (args[0] == "install")
|
if (args[0] == "install")
|
||||||
{
|
{
|
||||||
Log.Info("Installing the service with id '" + d.Id + "'");
|
Log.Info("Installing the service with id '" + descriptor.Id + "'");
|
||||||
|
|
||||||
// Check if the service exists
|
// Check if the service exists
|
||||||
if (s != null)
|
if (s != null)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Service with id '" + d.Id + "' already exists");
|
Console.WriteLine("Service with id '" + descriptor.Id + "' already exists");
|
||||||
Console.WriteLine("To install the service, delete the existing one or change service Id in the configuration file");
|
Console.WriteLine("To install the service, delete the existing one or change service Id in the configuration file");
|
||||||
throw new Exception("Installation failure: Service with id '" + d.Id + "' already exists");
|
throw new Exception("Installation failure: Service with id '" + descriptor.Id + "' already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
string? username = null;
|
string? username = null;
|
||||||
|
@ -561,11 +559,11 @@ namespace winsw
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (d.HasServiceAccount())
|
if (descriptor.HasServiceAccount())
|
||||||
{
|
{
|
||||||
username = d.ServiceAccountUser;
|
username = descriptor.ServiceAccountUser;
|
||||||
password = d.ServiceAccountPassword;
|
password = descriptor.ServiceAccountPassword;
|
||||||
setallowlogonasaserviceright = d.AllowServiceAcountLogonRight;
|
setallowlogonasaserviceright = descriptor.AllowServiceAcountLogonRight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,16 +573,16 @@ namespace winsw
|
||||||
}
|
}
|
||||||
|
|
||||||
svc.Create(
|
svc.Create(
|
||||||
d.Id,
|
descriptor.Id,
|
||||||
d.Caption,
|
descriptor.Caption,
|
||||||
"\"" + d.ExecutablePath + "\"",
|
"\"" + descriptor.ExecutablePath + "\"",
|
||||||
ServiceType.OwnProcess,
|
ServiceType.OwnProcess,
|
||||||
ErrorControl.UserNotified,
|
ErrorControl.UserNotified,
|
||||||
d.StartMode,
|
descriptor.StartMode,
|
||||||
d.Interactive,
|
descriptor.Interactive,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
d.ServiceDependencies);
|
descriptor.ServiceDependencies);
|
||||||
|
|
||||||
// update the description
|
// update the description
|
||||||
/* Somehow this doesn't work, even though it doesn't report an error
|
/* Somehow this doesn't work, even though it doesn't report an error
|
||||||
|
@ -594,17 +592,20 @@ namespace winsw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// so using a classic method to set the description. Ugly.
|
// so using a classic method to set the description. Ugly.
|
||||||
Registry.LocalMachine.OpenSubKey("System").OpenSubKey("CurrentControlSet").OpenSubKey("Services")
|
Registry.LocalMachine
|
||||||
.OpenSubKey(d.Id, true).SetValue("Description", d.Description);
|
.OpenSubKey("System")
|
||||||
|
.OpenSubKey("CurrentControlSet")
|
||||||
|
.OpenSubKey("Services")
|
||||||
|
.OpenSubKey(descriptor.Id, true)
|
||||||
|
.SetValue("Description", descriptor.Description);
|
||||||
|
|
||||||
var actions = d.FailureActions;
|
var actions = descriptor.FailureActions;
|
||||||
var isDelayedAutoStart = d.StartMode == StartMode.Automatic && d.DelayedAutoStart;
|
var isDelayedAutoStart = descriptor.StartMode == StartMode.Automatic && descriptor.DelayedAutoStart;
|
||||||
if (actions.Count > 0 || isDelayedAutoStart)
|
if (actions.Count > 0 || isDelayedAutoStart)
|
||||||
{
|
{
|
||||||
using (ServiceManager scm = new ServiceManager())
|
using ServiceManager scm = new ServiceManager();
|
||||||
{
|
using Service sc = scm.Open(descriptor.Id);
|
||||||
using (Service sc = scm.Open(d.Id))
|
|
||||||
{
|
|
||||||
// Delayed auto start
|
// Delayed auto start
|
||||||
if (isDelayedAutoStart)
|
if (isDelayedAutoStart)
|
||||||
{
|
{
|
||||||
|
@ -614,9 +615,7 @@ namespace winsw
|
||||||
// Set the failure actions
|
// Set the failure actions
|
||||||
if (actions.Count > 0)
|
if (actions.Count > 0)
|
||||||
{
|
{
|
||||||
sc.ChangeConfig(d.ResetFailureAfter, actions);
|
sc.ChangeConfig(descriptor.ResetFailureAfter, actions);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -625,10 +624,10 @@ namespace winsw
|
||||||
|
|
||||||
if (args[0] == "uninstall")
|
if (args[0] == "uninstall")
|
||||||
{
|
{
|
||||||
Log.Info("Uninstalling the service with id '" + d.Id + "'");
|
Log.Info("Uninstalling the service with id '" + descriptor.Id + "'");
|
||||||
if (s == null)
|
if (s == null)
|
||||||
{
|
{
|
||||||
Log.Warn("The service with id '" + d.Id + "' does not exist. Nothing to uninstall");
|
Log.Warn("The service with id '" + descriptor.Id + "' does not exist. Nothing to uninstall");
|
||||||
return; // there's no such service, so consider it already uninstalled
|
return; // there's no such service, so consider it already uninstalled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,7 +635,7 @@ namespace winsw
|
||||||
{
|
{
|
||||||
// We could fail the opeartion here, but it would be an incompatible change.
|
// We could fail the opeartion here, but it would be an incompatible change.
|
||||||
// So it is just a warning
|
// So it is just a warning
|
||||||
Log.Warn("The service with id '" + d.Id + "' is running. It may be impossible to uninstall it");
|
Log.Warn("The service with id '" + descriptor.Id + "' is running. It may be impossible to uninstall it");
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -647,7 +646,7 @@ namespace winsw
|
||||||
{
|
{
|
||||||
if (e.ErrorCode == ReturnValue.ServiceMarkedForDeletion)
|
if (e.ErrorCode == ReturnValue.ServiceMarkedForDeletion)
|
||||||
{
|
{
|
||||||
Log.Error("Failed to uninstall the service with id '" + d.Id + "'"
|
Log.Error("Failed to uninstall the service with id '" + descriptor.Id + "'"
|
||||||
+ ". It has been marked for deletion.");
|
+ ". It has been marked for deletion.");
|
||||||
|
|
||||||
// TODO: change the default behavior to Error?
|
// TODO: change the default behavior to Error?
|
||||||
|
@ -655,7 +654,7 @@ namespace winsw
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log.Fatal("Failed to uninstall the service with id '" + d.Id + "'. WMI Error code is '" + e.ErrorCode + "'");
|
Log.Fatal("Failed to uninstall the service with id '" + descriptor.Id + "'. WMI Error code is '" + e.ErrorCode + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
throw e;
|
throw e;
|
||||||
|
@ -666,7 +665,7 @@ namespace winsw
|
||||||
|
|
||||||
if (args[0] == "start")
|
if (args[0] == "start")
|
||||||
{
|
{
|
||||||
Log.Info("Starting the service with id '" + d.Id + "'");
|
Log.Info("Starting the service with id '" + descriptor.Id + "'");
|
||||||
if (s == null)
|
if (s == null)
|
||||||
ThrowNoSuchService();
|
ThrowNoSuchService();
|
||||||
|
|
||||||
|
@ -676,7 +675,7 @@ namespace winsw
|
||||||
|
|
||||||
if (args[0] == "stop")
|
if (args[0] == "stop")
|
||||||
{
|
{
|
||||||
Log.Info("Stopping the service with id '" + d.Id + "'");
|
Log.Info("Stopping the service with id '" + descriptor.Id + "'");
|
||||||
if (s == null)
|
if (s == null)
|
||||||
ThrowNoSuchService();
|
ThrowNoSuchService();
|
||||||
|
|
||||||
|
@ -686,7 +685,7 @@ namespace winsw
|
||||||
|
|
||||||
if (args[0] == "restart")
|
if (args[0] == "restart")
|
||||||
{
|
{
|
||||||
Log.Info("Restarting the service with id '" + d.Id + "'");
|
Log.Info("Restarting the service with id '" + descriptor.Id + "'");
|
||||||
if (s == null)
|
if (s == null)
|
||||||
ThrowNoSuchService();
|
ThrowNoSuchService();
|
||||||
|
|
||||||
|
@ -696,7 +695,7 @@ namespace winsw
|
||||||
while (s.Started)
|
while (s.Started)
|
||||||
{
|
{
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
s = svc.Select(d.Id);
|
s = svc.Select(descriptor.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
s.StartService();
|
s.StartService();
|
||||||
|
@ -705,12 +704,12 @@ namespace winsw
|
||||||
|
|
||||||
if (args[0] == "restart!")
|
if (args[0] == "restart!")
|
||||||
{
|
{
|
||||||
Log.Info("Restarting the service with id '" + d.Id + "'");
|
Log.Info("Restarting the service with id '" + descriptor.Id + "'");
|
||||||
|
|
||||||
// run restart from another process group. see README.md for why this is useful.
|
// run restart from another process group. see README.md for why this is useful.
|
||||||
|
|
||||||
STARTUPINFO si = default;
|
STARTUPINFO si = default;
|
||||||
bool result = Kernel32.CreateProcess(null, d.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero, false, 0x200/*CREATE_NEW_PROCESS_GROUP*/, IntPtr.Zero, null, ref si, out _);
|
bool result = Kernel32.CreateProcess(null, descriptor.ExecutablePath + " restart", IntPtr.Zero, IntPtr.Zero, false, 0x200/*CREATE_NEW_PROCESS_GROUP*/, IntPtr.Zero, null, ref si, out _);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
throw new Exception("Failed to invoke restart: " + Marshal.GetLastWin32Error());
|
throw new Exception("Failed to invoke restart: " + Marshal.GetLastWin32Error());
|
||||||
|
@ -721,7 +720,7 @@ namespace winsw
|
||||||
|
|
||||||
if (args[0] == "status")
|
if (args[0] == "status")
|
||||||
{
|
{
|
||||||
Log.Debug("User requested the status of the process with id '" + d.Id + "'");
|
Log.Debug("User requested the status of the process with id '" + descriptor.Id + "'");
|
||||||
if (s == null)
|
if (s == null)
|
||||||
Console.WriteLine("NonExistent");
|
Console.WriteLine("NonExistent");
|
||||||
else if (s.Started)
|
else if (s.Started)
|
||||||
|
@ -734,7 +733,7 @@ namespace winsw
|
||||||
|
|
||||||
if (args[0] == "test")
|
if (args[0] == "test")
|
||||||
{
|
{
|
||||||
WrapperService wsvc = new WrapperService(d);
|
WrapperService wsvc = new WrapperService(descriptor);
|
||||||
wsvc.OnStart(args.ToArray());
|
wsvc.OnStart(args.ToArray());
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
wsvc.OnStop();
|
wsvc.OnStop();
|
||||||
|
@ -743,7 +742,7 @@ namespace winsw
|
||||||
|
|
||||||
if (args[0] == "testwait")
|
if (args[0] == "testwait")
|
||||||
{
|
{
|
||||||
WrapperService wsvc = new WrapperService(d);
|
WrapperService wsvc = new WrapperService(descriptor);
|
||||||
wsvc.OnStart(args.ToArray());
|
wsvc.OnStart(args.ToArray());
|
||||||
Console.WriteLine("Press any key to stop the service...");
|
Console.WriteLine("Press any key to stop the service...");
|
||||||
Console.Read();
|
Console.Read();
|
||||||
|
@ -773,7 +772,7 @@ namespace winsw
|
||||||
Log.Info("Starting ServiceWrapper in the service mode");
|
Log.Info("Starting ServiceWrapper in the service mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
Run(new WrapperService(d));
|
Run(new WrapperService(descriptor));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void InitLoggers(ServiceDescriptor d, bool enableCLILogging)
|
private static void InitLoggers(ServiceDescriptor d, bool enableCLILogging)
|
||||||
|
@ -839,10 +838,9 @@ namespace winsw
|
||||||
private static string ReadPassword()
|
private static string ReadPassword()
|
||||||
{
|
{
|
||||||
StringBuilder buf = new StringBuilder();
|
StringBuilder buf = new StringBuilder();
|
||||||
ConsoleKeyInfo key;
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
key = Console.ReadKey(true);
|
ConsoleKeyInfo key = Console.ReadKey(true);
|
||||||
if (key.Key == ConsoleKey.Enter)
|
if (key.Key == ConsoleKey.Enter)
|
||||||
{
|
{
|
||||||
return buf.ToString();
|
return buf.ToString();
|
||||||
|
@ -870,7 +868,7 @@ namespace winsw
|
||||||
printAvailableCommandsInfo();
|
printAvailableCommandsInfo();
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
Console.WriteLine("Extra options:");
|
Console.WriteLine("Extra options:");
|
||||||
Console.WriteLine("- '/redirect' - redirect the wrapper's STDOUT and STDERR to the specified file");
|
Console.WriteLine(" /redirect redirect the wrapper's STDOUT and STDERR to the specified file");
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
printVersion();
|
printVersion();
|
||||||
Console.WriteLine("More info: https://github.com/kohsuke/winsw");
|
Console.WriteLine("More info: https://github.com/kohsuke/winsw");
|
||||||
|
@ -880,18 +878,19 @@ namespace winsw
|
||||||
// TODO: Rework to enum in winsw-2.0
|
// TODO: Rework to enum in winsw-2.0
|
||||||
private static void printAvailableCommandsInfo()
|
private static void printAvailableCommandsInfo()
|
||||||
{
|
{
|
||||||
Console.WriteLine("Available commands:");
|
Console.WriteLine(
|
||||||
Console.WriteLine("- 'install' - install the service to Windows Service Controller");
|
@"Available commands:
|
||||||
Console.WriteLine("- 'uninstall' - uninstall the service");
|
install install the service to Windows Service Controller
|
||||||
Console.WriteLine("- 'start' - start the service (must be installed before)");
|
uninstall uninstall the service
|
||||||
Console.WriteLine("- 'stop' - stop the service");
|
start start the service (must be installed before)
|
||||||
Console.WriteLine("- 'restart' - restart the service");
|
stop stop the service
|
||||||
Console.WriteLine("- 'restart!' - self-restart (can be called from child processes)");
|
restart restart the service
|
||||||
Console.WriteLine("- 'status' - check the current status of the service");
|
restart! self-restart (can be called from child processes)
|
||||||
Console.WriteLine("- 'test' - check if the service can be started and then stopped");
|
status check the current status of the service
|
||||||
Console.WriteLine("- 'testwait' - starts the service and waits until a key is pressed then stops the service");
|
test check if the service can be started and then stopped
|
||||||
Console.WriteLine("- 'version' - print the version info");
|
testwait starts the service and waits until a key is pressed then stops the service
|
||||||
Console.WriteLine("- 'help' - print the help info (aliases: -h,--help,-?,/?)");
|
version print the version info
|
||||||
|
help print the help info (aliases: -h,--help,-?,/?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void printVersion()
|
private static void printVersion()
|
||||||
|
|
|
@ -439,9 +439,9 @@ namespace winsw
|
||||||
// Next day so check if file can be zipped
|
// Next day so check if file can be zipped
|
||||||
ZipFiles(baseDirectory, extension, baseFileName);
|
ZipFiles(baseDirectory, extension, baseFileName);
|
||||||
}
|
}
|
||||||
catch (Exception et)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
EventLogger.LogEvent(string.Format("Failed to to trigger auto roll at time event due to: {0}", et.Message));
|
EventLogger.LogEvent($"Failed to to trigger auto roll at time event due to: {ex.Message}");
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -503,7 +503,7 @@ namespace winsw
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
EventLogger.LogEvent(string.Format("Failed to roll size time log: {0}", e.Message));
|
EventLogger.LogEvent($"Failed to roll size time log: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -635,12 +635,12 @@ namespace winsw
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new IOException(string.Format("File {0} does not follow the pattern provided", f));
|
throw new IOException($"File {f} does not follow the pattern provided");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
throw new IOException(string.Format("Failed to process file {0} due to error {1}", f, e.Message), e);
|
throw new IOException($"Failed to process file {f} due to error {e.Message}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -245,7 +245,6 @@ namespace winsw.Native
|
||||||
|
|
||||||
// initialize an unicode-string for the privilege name
|
// initialize an unicode-string for the privilege name
|
||||||
LSA_UNICODE_STRING[] userRights = new LSA_UNICODE_STRING[1];
|
LSA_UNICODE_STRING[] userRights = new LSA_UNICODE_STRING[1];
|
||||||
userRights[0] = default;
|
|
||||||
userRights[0].Buffer = Marshal.StringToHGlobalUni(privilegeName);
|
userRights[0].Buffer = Marshal.StringToHGlobalUni(privilegeName);
|
||||||
userRights[0].Length = (ushort)(privilegeName.Length * UnicodeEncoding.CharSize);
|
userRights[0].Length = (ushort)(privilegeName.Length * UnicodeEncoding.CharSize);
|
||||||
userRights[0].MaximumLength = (ushort)((privilegeName.Length + 1) * UnicodeEncoding.CharSize);
|
userRights[0].MaximumLength = (ushort)((privilegeName.Length + 1) * UnicodeEncoding.CharSize);
|
||||||
|
|
|
@ -64,35 +64,30 @@ namespace winsw
|
||||||
return PeriodicityType.ERRONEOUS;
|
return PeriodicityType.ERRONEOUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DateTime nextTriggeringTime(DateTime input, long increment)
|
private DateTime nextTriggeringTime(DateTime input, long increment) => periodicityType switch
|
||||||
{
|
{
|
||||||
DateTime output;
|
PeriodicityType.TOP_OF_MILLISECOND =>
|
||||||
switch (periodicityType)
|
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second, input.Millisecond)
|
||||||
{
|
.AddMilliseconds(increment),
|
||||||
case PeriodicityType.TOP_OF_MILLISECOND:
|
|
||||||
output = new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second, input.Millisecond);
|
PeriodicityType.TOP_OF_SECOND =>
|
||||||
output = output.AddMilliseconds(increment);
|
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second)
|
||||||
return output;
|
.AddSeconds(increment),
|
||||||
case PeriodicityType.TOP_OF_SECOND:
|
|
||||||
output = new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second);
|
PeriodicityType.TOP_OF_MINUTE =>
|
||||||
output = output.AddSeconds(increment);
|
new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, 0)
|
||||||
return output;
|
.AddMinutes(increment),
|
||||||
case PeriodicityType.TOP_OF_MINUTE:
|
|
||||||
output = new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, 0);
|
PeriodicityType.TOP_OF_HOUR =>
|
||||||
output = output.AddMinutes(increment);
|
new DateTime(input.Year, input.Month, input.Day, input.Hour, 0, 0)
|
||||||
return output;
|
.AddHours(increment),
|
||||||
case PeriodicityType.TOP_OF_HOUR:
|
|
||||||
output = new DateTime(input.Year, input.Month, input.Day, input.Hour, 0, 0);
|
PeriodicityType.TOP_OF_DAY =>
|
||||||
output = output.AddHours(increment);
|
new DateTime(input.Year, input.Month, input.Day)
|
||||||
return output;
|
.AddDays(increment),
|
||||||
case PeriodicityType.TOP_OF_DAY:
|
|
||||||
output = new DateTime(input.Year, input.Month, input.Day);
|
_ => throw new Exception("invalid periodicity type: " + periodicityType),
|
||||||
output = output.AddDays(increment);
|
};
|
||||||
return output;
|
|
||||||
default:
|
|
||||||
throw new Exception("invalid periodicity type: " + periodicityType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PeriodicityType periodicityType { get; set; }
|
public PeriodicityType periodicityType { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using log4net;
|
using log4net;
|
||||||
using winsw.Extensions;
|
using winsw.Extensions;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System.Xml;
|
||||||
using System.Xml;
|
|
||||||
using winsw.Util;
|
using winsw.Util;
|
||||||
|
|
||||||
namespace winsw.Plugins.SharedDirectoryMapper
|
namespace winsw.Plugins.SharedDirectoryMapper
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System.Diagnostics;
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace winsw.Plugins.SharedDirectoryMapper
|
namespace winsw.Plugins.SharedDirectoryMapper
|
||||||
{
|
{
|
||||||
|
|
|
@ -144,10 +144,7 @@ namespace winswTests
|
||||||
.WithRawEntry("<download from=\"http://www.nosuchhostexists.foo.myorg/foo.xml\" to=\"%BASE%\\foo.xml\" auth=\"digest\"/>")
|
.WithRawEntry("<download from=\"http://www.nosuchhostexists.foo.myorg/foo.xml\" to=\"%BASE%\\foo.xml\" auth=\"digest\"/>")
|
||||||
.ToServiceDescriptor(true);
|
.ToServiceDescriptor(true);
|
||||||
|
|
||||||
ExceptionHelper.assertFails("Cannot parse <auth> Enum value from string 'digest'", typeof(InvalidDataException), () =>
|
ExceptionHelper.AssertFails("Cannot parse <auth> Enum value from string 'digest'", typeof(InvalidDataException), () => _ = GetSingleEntry(sd));
|
||||||
{
|
|
||||||
var d = GetSingleEntry(sd);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Download GetSingleEntry(ServiceDescriptor sd)
|
private Download GetSingleEntry(ServiceDescriptor sd)
|
||||||
|
@ -163,10 +160,7 @@ namespace winswTests
|
||||||
.WithDownload(download)
|
.WithDownload(download)
|
||||||
.ToServiceDescriptor(true);
|
.ToServiceDescriptor(true);
|
||||||
|
|
||||||
ExceptionHelper.assertFails(expectedMessagePart, expectedExceptionType ?? typeof(InvalidDataException), () =>
|
ExceptionHelper.AssertFails(expectedMessagePart, expectedExceptionType ?? typeof(InvalidDataException), () => _ = GetSingleEntry(sd));
|
||||||
{
|
|
||||||
var d = GetSingleEntry(sd);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,27 +16,27 @@ namespace winswTests.Extensions
|
||||||
{
|
{
|
||||||
ServiceDescriptor _testServiceDescriptor;
|
ServiceDescriptor _testServiceDescriptor;
|
||||||
|
|
||||||
string testExtension = GetExtensionClassNameWithAssembly(typeof(RunawayProcessKillerExtension));
|
readonly string testExtension = GetExtensionClassNameWithAssembly(typeof(RunawayProcessKillerExtension));
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp()
|
public void SetUp()
|
||||||
{
|
{
|
||||||
string seedXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
|
string seedXml =
|
||||||
+ "<service> "
|
$@"<service>
|
||||||
+ " <id>SERVICE_NAME</id> "
|
<id>SERVICE_NAME</id>
|
||||||
+ " <name>Jenkins Slave</name> "
|
<name>Jenkins Slave</name>
|
||||||
+ " <description>This service runs a slave for Jenkins continuous integration system.</description> "
|
<description>This service runs a slave for Jenkins continuous integration system.</description>
|
||||||
+ " <executable>C:\\Program Files\\Java\\jre7\\bin\\java.exe</executable> "
|
<executable>C:\Program Files\Java\jre7\bin\java.exe</executable>
|
||||||
+ " <arguments>-Xrs -jar \\\"%BASE%\\slave.jar\\\" -jnlpUrl ...</arguments> "
|
<arguments>-Xrs -jar \""%BASE%\slave.jar\"" -jnlpUrl ...</arguments>
|
||||||
+ " <logmode>rotate</logmode> "
|
<logmode>rotate</logmode>
|
||||||
+ " <extensions> "
|
<extensions>
|
||||||
+ " <extension enabled=\"true\" className=\"" + testExtension + "\" id=\"killRunawayProcess\"> "
|
<extension enabled=""true"" className=""{testExtension}"" id=""killRunawayProcess"">
|
||||||
+ " <pidfile>foo/bar/pid.txt</pidfile>"
|
<pidfile>foo/bar/pid.txt</pidfile>
|
||||||
+ " <stopTimeout>5000</stopTimeout> "
|
<stopTimeout>5000</stopTimeout>
|
||||||
+ " <stopParentFirst>true</stopParentFirst>"
|
<stopParentFirst>true</stopParentFirst>
|
||||||
+ " </extension> "
|
</extension>
|
||||||
+ " </extensions> "
|
</extensions>
|
||||||
+ "</service>";
|
</service>";
|
||||||
_testServiceDescriptor = ServiceDescriptor.FromXML(seedXml);
|
_testServiceDescriptor = ServiceDescriptor.FromXML(seedXml);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,34 +10,34 @@ namespace winswTests.Extensions
|
||||||
{
|
{
|
||||||
ServiceDescriptor _testServiceDescriptor;
|
ServiceDescriptor _testServiceDescriptor;
|
||||||
|
|
||||||
string testExtension = GetExtensionClassNameWithAssembly(typeof(SharedDirectoryMapper));
|
readonly string testExtension = GetExtensionClassNameWithAssembly(typeof(SharedDirectoryMapper));
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp()
|
public void SetUp()
|
||||||
{
|
{
|
||||||
string seedXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
|
string seedXml =
|
||||||
+ "<service> "
|
$@"<service>
|
||||||
+ " <id>SERVICE_NAME</id> "
|
<id>SERVICE_NAME</id>
|
||||||
+ " <name>Jenkins Slave</name> "
|
<name>Jenkins Slave</name>
|
||||||
+ " <description>This service runs a slave for Jenkins continuous integration system.</description> "
|
<description>This service runs a slave for Jenkins continuous integration system.</description>
|
||||||
+ " <executable>C:\\Program Files\\Java\\jre7\\bin\\java.exe</executable> "
|
<executable>C:\Program Files\Java\jre7\bin\java.exe</executable>
|
||||||
+ " <arguments>-Xrs -jar \\\"%BASE%\\slave.jar\\\" -jnlpUrl ...</arguments> "
|
<arguments>-Xrs -jar \""%BASE%\slave.jar\"" -jnlpUrl ...</arguments>
|
||||||
+ " <logmode>rotate</logmode> "
|
<logmode>rotate</logmode>
|
||||||
+ " <extensions> "
|
<extensions>
|
||||||
+ " <extension enabled=\"true\" className=\"" + testExtension + "\" id=\"mapNetworDirs\"> "
|
<extension enabled=""true"" className=""{testExtension}"" id=""mapNetworDirs"">
|
||||||
+ " <mapping> "
|
<mapping>
|
||||||
+ " <map enabled=\"false\" label=\"N:\" uncpath=\"\\\\UNC\"/> "
|
<map enabled=""false"" label=""N:"" uncpath=""\\UNC""/>
|
||||||
+ " <map enabled=\"false\" label=\"M:\" uncpath=\"\\\\UNC2\"/> "
|
<map enabled=""false"" label=""M:"" uncpath=""\\UNC2""/>
|
||||||
+ " </mapping> "
|
</mapping>
|
||||||
+ " </extension> "
|
</extension>
|
||||||
+ " <extension enabled=\"true\" className=\"" + testExtension + "\" id=\"mapNetworDirs2\"> "
|
<extension enabled=""true"" className=""{testExtension}"" id=""mapNetworDirs2"">
|
||||||
+ " <mapping> "
|
<mapping>
|
||||||
+ " <map enabled=\"false\" label=\"X:\" uncpath=\"\\\\UNC\"/> "
|
<map enabled=""false"" label=""X:"" uncpath=""\\UNC""/>
|
||||||
+ " <map enabled=\"false\" label=\"Y:\" uncpath=\"\\\\UNC2\"/> "
|
<map enabled=""false"" label=""Y:"" uncpath=""\\UNC2""/>
|
||||||
+ " </mapping> "
|
</mapping>
|
||||||
+ " </extension> "
|
</extension>
|
||||||
+ " </extensions> "
|
</extensions>
|
||||||
+ "</service>";
|
</service>";
|
||||||
_testServiceDescriptor = ServiceDescriptor.FromXML(seedXml);
|
_testServiceDescriptor = ServiceDescriptor.FromXML(seedXml);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,24 +21,23 @@ namespace winswTests
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp()
|
public void SetUp()
|
||||||
{
|
{
|
||||||
const string seedXml = "<service>"
|
string seedXml =
|
||||||
+ "<id>service.exe</id>"
|
$@"<service>
|
||||||
+ "<name>Service</name>"
|
<id>service.exe</id>
|
||||||
+ "<description>The service.</description>"
|
<name>Service</name>
|
||||||
+ "<executable>node.exe</executable>"
|
<description>The service.</description>
|
||||||
+ "<arguments>My Arguments</arguments>"
|
<executable>node.exe</executable>
|
||||||
+ "<logmode>rotate</logmode>"
|
<arguments>My Arguments</arguments>
|
||||||
+ "<serviceaccount>"
|
<logmode>rotate</logmode>
|
||||||
+ "<domain>" + Domain + "</domain>"
|
<serviceaccount>
|
||||||
+ "<user>" + Username + "</user>"
|
<domain>{Domain}</domain>
|
||||||
+ "<password>" + Password + "</password>"
|
<user>{Username}</user>
|
||||||
+ "<allowservicelogon>" + AllowServiceAccountLogonRight + "</allowservicelogon>"
|
<password>{Password}</password>
|
||||||
+ "</serviceaccount>"
|
<allowservicelogon>{AllowServiceAccountLogonRight}</allowservicelogon>
|
||||||
+ "<workingdirectory>"
|
</serviceaccount>
|
||||||
+ ExpectedWorkingDirectory
|
<workingdirectory>{ExpectedWorkingDirectory}</workingdirectory>
|
||||||
+ "</workingdirectory>"
|
<logpath>C:\logs</logpath>
|
||||||
+ @"<logpath>C:\logs</logpath>"
|
</service>";
|
||||||
+ "</service>";
|
|
||||||
_extendedServiceDescriptor = ServiceDescriptor.FromXML(seedXml);
|
_extendedServiceDescriptor = ServiceDescriptor.FromXML(seedXml);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,54 +50,52 @@ namespace winswTests
|
||||||
[Test]
|
[Test]
|
||||||
public void IncorrectStartMode()
|
public void IncorrectStartMode()
|
||||||
{
|
{
|
||||||
const string SeedXml = "<service>"
|
string seedXml =
|
||||||
+ "<id>service.exe</id>"
|
$@"<service>
|
||||||
+ "<name>Service</name>"
|
<id>service.exe</id>
|
||||||
+ "<description>The service.</description>"
|
<name>Service</name>
|
||||||
+ "<executable>node.exe</executable>"
|
<description>The service.</description>
|
||||||
+ "<arguments>My Arguments</arguments>"
|
<executable>node.exe</executable>
|
||||||
+ "<startmode>rotate</startmode>"
|
<arguments>My Arguments</arguments>
|
||||||
+ "<logmode>rotate</logmode>"
|
<startmode>rotate</startmode>
|
||||||
+ "<serviceaccount>"
|
<logmode>rotate</logmode>
|
||||||
+ "<domain>" + Domain + "</domain>"
|
<serviceaccount>
|
||||||
+ "<user>" + Username + "</user>"
|
<domain>{Domain}</domain>
|
||||||
+ "<password>" + Password + "</password>"
|
<user>{Username}</user>
|
||||||
+ "<allowservicelogon>" + AllowServiceAccountLogonRight + "</allowservicelogon>"
|
<password>{Password}</password>
|
||||||
+ "</serviceaccount>"
|
<allowservicelogon>{AllowServiceAccountLogonRight}</allowservicelogon>
|
||||||
+ "<workingdirectory>"
|
</serviceaccount>
|
||||||
+ ExpectedWorkingDirectory
|
<workingdirectory>{ExpectedWorkingDirectory}</workingdirectory>
|
||||||
+ "</workingdirectory>"
|
<logpath>C:\logs</logpath>
|
||||||
+ @"<logpath>C:\logs</logpath>"
|
</service>";
|
||||||
+ "</service>";
|
|
||||||
|
|
||||||
_extendedServiceDescriptor = ServiceDescriptor.FromXML(SeedXml);
|
_extendedServiceDescriptor = ServiceDescriptor.FromXML(seedXml);
|
||||||
Assert.Throws(typeof(ArgumentException), () => _ = _extendedServiceDescriptor.StartMode);
|
Assert.Throws<ArgumentException>(() => _ = _extendedServiceDescriptor.StartMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ChangedStartMode()
|
public void ChangedStartMode()
|
||||||
{
|
{
|
||||||
const string SeedXml = "<service>"
|
string seedXml =
|
||||||
+ "<id>service.exe</id>"
|
$@"<service>
|
||||||
+ "<name>Service</name>"
|
<id>service.exe</id>
|
||||||
+ "<description>The service.</description>"
|
<name>Service</name>
|
||||||
+ "<executable>node.exe</executable>"
|
<description>The service.</description>
|
||||||
+ "<arguments>My Arguments</arguments>"
|
<executable>node.exe</executable>
|
||||||
+ "<startmode>manual</startmode>"
|
<arguments>My Arguments</arguments>
|
||||||
+ "<logmode>rotate</logmode>"
|
<startmode>manual</startmode>
|
||||||
+ "<serviceaccount>"
|
<logmode>rotate</logmode>
|
||||||
+ "<domain>" + Domain + "</domain>"
|
<serviceaccount>
|
||||||
+ "<user>" + Username + "</user>"
|
<domain>{Domain}</domain>
|
||||||
+ "<password>" + Password + "</password>"
|
<user>{Username}</user>
|
||||||
+ "<allowservicelogon>" + AllowServiceAccountLogonRight + "</allowservicelogon>"
|
<password>{Password}</password>
|
||||||
+ "</serviceaccount>"
|
<allowservicelogon>{AllowServiceAccountLogonRight}</allowservicelogon>
|
||||||
+ "<workingdirectory>"
|
</serviceaccount>
|
||||||
+ ExpectedWorkingDirectory
|
<workingdirectory>{ExpectedWorkingDirectory}</workingdirectory>
|
||||||
+ "</workingdirectory>"
|
<logpath>C:\logs</logpath>
|
||||||
+ @"<logpath>C:\logs</logpath>"
|
</service>";
|
||||||
+ "</service>";
|
|
||||||
|
|
||||||
_extendedServiceDescriptor = ServiceDescriptor.FromXML(SeedXml);
|
_extendedServiceDescriptor = ServiceDescriptor.FromXML(seedXml);
|
||||||
Assert.That(_extendedServiceDescriptor.StartMode, Is.EqualTo(StartMode.Manual));
|
Assert.That(_extendedServiceDescriptor.StartMode, Is.EqualTo(StartMode.Manual));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,18 +9,17 @@ namespace winswTests.Util
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class CLITestHelper
|
public static class CLITestHelper
|
||||||
{
|
{
|
||||||
private const string SeedXml = "<service>"
|
private const string SeedXml =
|
||||||
+ "<id>service.exe</id>"
|
@"<service>
|
||||||
+ "<name>Service</name>"
|
<id>service.exe</id>
|
||||||
+ "<description>The service.</description>"
|
<name>Service</name>
|
||||||
+ "<executable>node.exe</executable>"
|
<description>The service.</description>
|
||||||
+ "<arguments>My Arguments</arguments>"
|
<executable>node.exe</executable>
|
||||||
+ "<logmode>rotate</logmode>"
|
<arguments>My Arguments</arguments>
|
||||||
+ "<workingdirectory>"
|
<logmode>rotate</logmode>
|
||||||
+ @"C:\winsw\workdir"
|
<workingdirectory>C:\winsw\workdir</workingdirectory>
|
||||||
+ "</workingdirectory>"
|
<logpath>C:\winsw\logs</logpath>
|
||||||
+ @"<logpath>C:\winsw\logs</logpath>"
|
</service>";
|
||||||
+ "</service>";
|
|
||||||
|
|
||||||
private static readonly ServiceDescriptor DefaultServiceDescriptor = ServiceDescriptor.FromXML(SeedXml);
|
private static readonly ServiceDescriptor DefaultServiceDescriptor = ServiceDescriptor.FromXML(SeedXml);
|
||||||
|
|
||||||
|
@ -33,8 +32,7 @@ namespace winswTests.Util
|
||||||
/// <exception cref="Exception">Command failure</exception>
|
/// <exception cref="Exception">Command failure</exception>
|
||||||
public static string CLITest(string[] args, ServiceDescriptor descriptor = null)
|
public static string CLITest(string[] args, ServiceDescriptor descriptor = null)
|
||||||
{
|
{
|
||||||
using (StringWriter sw = new StringWriter())
|
using StringWriter sw = new StringWriter();
|
||||||
{
|
|
||||||
TextWriter tmp = Console.Out;
|
TextWriter tmp = Console.Out;
|
||||||
Console.SetOut(sw);
|
Console.SetOut(sw);
|
||||||
WrapperService.Run(args, descriptor ?? DefaultServiceDescriptor);
|
WrapperService.Run(args, descriptor ?? DefaultServiceDescriptor);
|
||||||
|
@ -42,7 +40,6 @@ namespace winswTests.Util
|
||||||
Console.Write(sw.ToString());
|
Console.Write(sw.ToString());
|
||||||
return sw.ToString();
|
return sw.ToString();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Runs a simle test, which returns the output CLI
|
/// Runs a simle test, which returns the output CLI
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace winswTests.Util
|
||||||
public string XMLComment { get; set; }
|
public string XMLComment { get; set; }
|
||||||
public List<string> ExtensionXmls { get; private set; }
|
public List<string> ExtensionXmls { get; private set; }
|
||||||
|
|
||||||
private List<string> configEntries;
|
private readonly List<string> configEntries;
|
||||||
|
|
||||||
// TODO: Switch to the initializer?
|
// TODO: Switch to the initializer?
|
||||||
private ConfigXmlBuilder()
|
private ConfigXmlBuilder()
|
||||||
|
|
|
@ -5,28 +5,10 @@ namespace winswTests.Util
|
||||||
{
|
{
|
||||||
class ExceptionHelper
|
class ExceptionHelper
|
||||||
{
|
{
|
||||||
public static void assertFails(string expectedMessagePart, Type expectedExceptionType, ExceptionHelperExecutionBody body)
|
public static void AssertFails(string expectedMessagePart, Type expectedExceptionType, TestDelegate body)
|
||||||
{
|
{
|
||||||
try
|
Exception exception = Assert.Throws(expectedExceptionType ?? typeof(Exception), body);
|
||||||
{
|
StringAssert.Contains(expectedMessagePart, exception.Message);
|
||||||
body();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.Out.WriteLine("Caught exception: " + ex);
|
|
||||||
Assert.That(ex, Is.InstanceOf(expectedExceptionType ?? typeof(Exception)), "Wrong exception type");
|
|
||||||
if (expectedMessagePart != null)
|
|
||||||
{
|
|
||||||
Assert.That(ex.Message, Does.Contain(expectedMessagePart), "Wrong error message");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Else the exception is fine
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert.Fail("Expected exception " + expectedExceptionType + " to be thrown by the operation");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public delegate void ExceptionHelperExecutionBody();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using winsw.Util;
|
using winsw.Util;
|
||||||
|
|
||||||
|
@ -38,12 +38,11 @@ namespace winswTests.Util
|
||||||
var envVars = FilesystemTestHelper.parseSetOutput(envFile);
|
var envVars = FilesystemTestHelper.parseSetOutput(envFile);
|
||||||
string[] keys = new string[envVars.Count];
|
string[] keys = new string[envVars.Count];
|
||||||
envVars.Keys.CopyTo(keys, 0);
|
envVars.Keys.CopyTo(keys, 0);
|
||||||
String availableVars = "[" + string.Join(",", keys) + "]";
|
string availableVars = "[" + string.Join(",", keys) + "]";
|
||||||
Assert.That(envVars.ContainsKey("TEST_KEY"), "No TEST_KEY in the injected vars: " + availableVars);
|
Assert.That(envVars.ContainsKey("TEST_KEY"), "No TEST_KEY in the injected vars: " + availableVars);
|
||||||
|
|
||||||
// And just ensure that the parsing logic is case-sensitive
|
// And just ensure that the parsing logic is case-sensitive
|
||||||
Assert.That(!envVars.ContainsKey("test_key"), "Test error: the environment parsing logic is case-insensitive");
|
Assert.That(!envVars.ContainsKey("test_key"), "Test error: the environment parsing logic is case-insensitive");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -51,8 +50,8 @@ namespace winswTests.Util
|
||||||
{
|
{
|
||||||
var tmpDir = FilesystemTestHelper.CreateTmpDirectory();
|
var tmpDir = FilesystemTestHelper.CreateTmpDirectory();
|
||||||
string scriptFile = Path.Combine(tmpDir, "print_lots_to_stdout.bat");
|
string scriptFile = Path.Combine(tmpDir, "print_lots_to_stdout.bat");
|
||||||
var lotsOfStdOut = string.Join(string.Empty, _Range(1, 1000));
|
var lotsOfStdOut = string.Join(string.Empty, Enumerable.Range(1, 1000));
|
||||||
File.WriteAllText(scriptFile, string.Format("echo \"{0}\"", lotsOfStdOut));
|
File.WriteAllText(scriptFile, $"echo \"{lotsOfStdOut}\"");
|
||||||
|
|
||||||
Process proc = new Process();
|
Process proc = new Process();
|
||||||
var ps = proc.StartInfo;
|
var ps = proc.StartInfo;
|
||||||
|
@ -65,16 +64,5 @@ namespace winswTests.Util
|
||||||
Assert.Fail("Process " + proc + " didn't exit after 5 seconds");
|
Assert.Fail("Process " + proc + " didn't exit after 5 seconds");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string[] _Range(int start, int limit)
|
|
||||||
{
|
|
||||||
var range = new List<string>();
|
|
||||||
for (var i = start; i < limit; i++)
|
|
||||||
{
|
|
||||||
range.Add(i.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return range.ToArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net40;net461;netcoreapp3.1</TargetFrameworks>
|
<TargetFrameworks>net40;net461;netcoreapp3.1</TargetFrameworks>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
<Version><!-- Populated by AppVeyor --></Version>
|
<Version><!-- Populated by AppVeyor --></Version>
|
||||||
<RootNamespace>winswTests</RootNamespace>
|
<RootNamespace>winswTests</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
Loading…
Reference in New Issue