mirror of https://github.com/winsw/winsw
Increase code coverage
parent
70d83c045c
commit
94668c9f77
|
@ -1044,7 +1044,7 @@ namespace winsw
|
|||
appenders.ToArray());
|
||||
}
|
||||
|
||||
private static unsafe bool IsProcessElevated()
|
||||
internal static unsafe bool IsProcessElevated()
|
||||
{
|
||||
IntPtr process = Kernel32.GetCurrentProcess();
|
||||
if (!Advapi32.OpenProcessToken(process, TokenAccessLevels.Read, out IntPtr token))
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("winswTests")]
|
|
@ -12,7 +12,7 @@ namespace winswTests.Configuration
|
|||
/// The test uses a relative path to example files, which is based on the current project structure.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
class ExamplesTest
|
||||
public class ExamplesTest
|
||||
{
|
||||
[Test]
|
||||
public void AllOptionsConfigShouldDeclareDefaults()
|
||||
|
@ -40,10 +40,21 @@ namespace winswTests.Configuration
|
|||
ServiceDescriptorAssert.AssertAllOptionalPropertiesAreDefault(desc);
|
||||
}
|
||||
|
||||
private ServiceDescriptor Load(string exampleName)
|
||||
private static ServiceDescriptor Load(string exampleName)
|
||||
{
|
||||
var directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
string path = Path.GetFullPath($@"{directory}\..\..\..\..\..\..\examples\sample-{exampleName}.xml");
|
||||
string directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
while (true)
|
||||
{
|
||||
if (File.Exists(Path.Combine(directory, ".gitignore")))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
directory = Path.GetDirectoryName(directory);
|
||||
Assert.That(directory, Is.Not.Null);
|
||||
}
|
||||
|
||||
string path = Path.Combine(directory, $@"examples\sample-{exampleName}.xml");
|
||||
Assert.That(path, Does.Exist);
|
||||
|
||||
XmlDocument dom = new XmlDocument();
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System.IO;
|
||||
using System.Net;
|
||||
#if VNEXT
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
using NUnit.Framework;
|
||||
using winsw;
|
||||
using winswTests.Util;
|
||||
|
@ -10,61 +6,11 @@ using winswTests.Util;
|
|||
namespace winswTests
|
||||
{
|
||||
[TestFixture]
|
||||
class DownloadTest
|
||||
public class DownloadConfigTests
|
||||
{
|
||||
private const string From = "https://www.nosuchhostexists.foo.myorg/foo.xml";
|
||||
private const string To = "%BASE%\\foo.xml";
|
||||
|
||||
[Test]
|
||||
#if VNEXT
|
||||
public async Task DownloadFileAsync()
|
||||
#else
|
||||
public void DownloadFile()
|
||||
#endif
|
||||
{
|
||||
string from = Path.GetTempFileName();
|
||||
string to = Path.GetTempFileName();
|
||||
|
||||
try
|
||||
{
|
||||
const string contents = "WinSW";
|
||||
File.WriteAllText(from, contents);
|
||||
#if VNEXT
|
||||
await new Download(from, to).PerformAsync();
|
||||
#else
|
||||
new Download(from, to).Perform();
|
||||
#endif
|
||||
Assert.That(File.ReadAllText(to), Is.EqualTo(contents));
|
||||
}
|
||||
finally
|
||||
{
|
||||
File.Delete(from);
|
||||
File.Delete(to);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DownloadFile_NonExistent()
|
||||
{
|
||||
string from = Path.GetTempPath() + Path.GetRandomFileName();
|
||||
string to = Path.GetTempFileName();
|
||||
|
||||
try
|
||||
{
|
||||
Assert.That(
|
||||
#if VNEXT
|
||||
async () => await new Download(from, to).PerformAsync(),
|
||||
#else
|
||||
() => new Download(from, to).Perform(),
|
||||
#endif
|
||||
Throws.TypeOf<WebException>());
|
||||
}
|
||||
finally
|
||||
{
|
||||
File.Delete(to);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Roundtrip_Defaults()
|
||||
{
|
|
@ -0,0 +1,231 @@
|
|||
#if VNEXT
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using winsw;
|
||||
using winswTests.Util;
|
||||
|
||||
namespace winswTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class DownloadTests
|
||||
{
|
||||
private readonly HttpListener globalListener = new HttpListener();
|
||||
|
||||
private readonly byte[] contents = { 0x57, 0x69, 0x6e, 0x53, 0x57 };
|
||||
|
||||
private string globalPrefix;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
TcpListener tcpListener = new TcpListener(IPAddress.Loopback, 0);
|
||||
tcpListener.Start();
|
||||
int port = ((IPEndPoint)tcpListener.LocalEndpoint).Port;
|
||||
string prefix = $"http://localhost:{port}/";
|
||||
this.globalListener.Prefixes.Add(prefix);
|
||||
this.globalPrefix = prefix;
|
||||
{
|
||||
tcpListener.Stop();
|
||||
this.globalListener.Start();
|
||||
}
|
||||
}
|
||||
|
||||
[OneTimeTearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
this.globalListener.Stop();
|
||||
this.globalListener.Close();
|
||||
}
|
||||
|
||||
private async Task TestClientServerAsync(Func<string, string, Task> client, Action<HttpListenerContext> server, AuthenticationSchemes authenticationSchemes = AuthenticationSchemes.Anonymous, [CallerMemberName] string path = null)
|
||||
{
|
||||
HttpListener listener = new HttpListener();
|
||||
string prefix = $"{this.globalPrefix}{path}/";
|
||||
listener.Prefixes.Add(prefix);
|
||||
listener.AuthenticationSchemes = authenticationSchemes;
|
||||
listener.Start();
|
||||
|
||||
Task serverTask = null;
|
||||
try
|
||||
{
|
||||
serverTask = ListenAsync();
|
||||
|
||||
string dest = Path.GetTempFileName();
|
||||
try
|
||||
{
|
||||
await client(prefix, dest);
|
||||
}
|
||||
finally
|
||||
{
|
||||
File.Delete(dest);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
listener.Stop();
|
||||
listener.Close();
|
||||
if (serverTask != null)
|
||||
{
|
||||
await serverTask;
|
||||
}
|
||||
}
|
||||
|
||||
async Task ListenAsync()
|
||||
{
|
||||
HttpListenerContext context = await listener.GetContextAsync();
|
||||
try
|
||||
{
|
||||
server(context);
|
||||
}
|
||||
catch
|
||||
{
|
||||
context.Response.Abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestHttpAsync()
|
||||
{
|
||||
await this.TestClientServerAsync(
|
||||
async (source, dest) =>
|
||||
{
|
||||
await new Download(source, dest).PerformAsync();
|
||||
Assert.That(File.ReadAllBytes(dest), Is.EqualTo(this.contents));
|
||||
},
|
||||
context =>
|
||||
{
|
||||
context.Response.OutputStream.Write(this.contents, 0, this.contents.Length);
|
||||
context.Response.Close();
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestHttp_NoAuthAsync()
|
||||
{
|
||||
await this.TestClientServerAsync(
|
||||
async (source, dest) =>
|
||||
{
|
||||
await new Download(source, dest, false, Download.AuthType.none).PerformAsync();
|
||||
Assert.That(File.ReadAllBytes(dest), Is.EqualTo(this.contents));
|
||||
},
|
||||
context =>
|
||||
{
|
||||
if (((WebHeaderCollection)context.Request.Headers)[HttpRequestHeader.Authorization] != null)
|
||||
{
|
||||
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
|
||||
context.Response.Close();
|
||||
}
|
||||
|
||||
context.Response.OutputStream.Write(this.contents, 0, this.contents.Length);
|
||||
context.Response.Close();
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestHttp_BasicAuthAsync()
|
||||
{
|
||||
const string username = nameof(username);
|
||||
const string password = nameof(password);
|
||||
|
||||
await this.TestClientServerAsync(
|
||||
async (source, dest) =>
|
||||
{
|
||||
await new Download(source, dest, false, Download.AuthType.basic, username, password, true).PerformAsync();
|
||||
Assert.That(File.ReadAllBytes(dest), Is.EqualTo(this.contents));
|
||||
},
|
||||
context =>
|
||||
{
|
||||
HttpListenerBasicIdentity identity = (HttpListenerBasicIdentity)context.User.Identity;
|
||||
if (identity.Name != username || identity.Password != password)
|
||||
{
|
||||
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
|
||||
context.Response.Close();
|
||||
}
|
||||
|
||||
context.Response.OutputStream.Write(this.contents, 0, this.contents.Length);
|
||||
context.Response.Close();
|
||||
},
|
||||
AuthenticationSchemes.Basic);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestHttp_IfModifiedSince_ModifiedAsync()
|
||||
{
|
||||
DateTime lastModified = DateTime.Now.TrimToSeconds();
|
||||
DateTime prevModified = lastModified.AddDays(-1);
|
||||
|
||||
await this.TestClientServerAsync(
|
||||
async (source, dest) =>
|
||||
{
|
||||
File.WriteAllBytes(dest, this.contents);
|
||||
File.SetLastWriteTime(dest, prevModified);
|
||||
await new Download(source, dest).PerformAsync();
|
||||
Assert.That(File.GetLastWriteTime(dest), Is.EqualTo(lastModified));
|
||||
Assert.That(File.ReadAllBytes(dest), Is.Not.EqualTo(this.contents));
|
||||
},
|
||||
context =>
|
||||
{
|
||||
string ifModifiedSince = ((WebHeaderCollection)context.Request.Headers)[HttpRequestHeader.IfModifiedSince];
|
||||
if (ifModifiedSince != null && DateTime.Parse(ifModifiedSince) >= lastModified)
|
||||
{
|
||||
context.Response.StatusCode = (int)HttpStatusCode.NotModified;
|
||||
}
|
||||
|
||||
context.Response.Headers[HttpResponseHeader.LastModified] = lastModified.ToUniversalTime().ToString("r");
|
||||
context.Response.Close();
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestHttp_IfModifiedSince_NotModifiedAsync()
|
||||
{
|
||||
DateTime lastModified = DateTime.Now.TrimToSeconds();
|
||||
|
||||
await this.TestClientServerAsync(
|
||||
async (source, dest) =>
|
||||
{
|
||||
File.WriteAllBytes(dest, this.contents);
|
||||
File.SetLastWriteTime(dest, lastModified);
|
||||
await new Download(source, dest).PerformAsync();
|
||||
Assert.That(File.GetLastWriteTime(dest), Is.EqualTo(lastModified));
|
||||
Assert.That(File.ReadAllBytes(dest), Is.EqualTo(this.contents));
|
||||
},
|
||||
context =>
|
||||
{
|
||||
string ifModifiedSince = ((WebHeaderCollection)context.Request.Headers)[HttpRequestHeader.IfModifiedSince];
|
||||
if (ifModifiedSince != null && DateTime.Parse(ifModifiedSince) >= lastModified)
|
||||
{
|
||||
context.Response.StatusCode = (int)HttpStatusCode.NotModified;
|
||||
}
|
||||
|
||||
context.Response.Headers[HttpResponseHeader.LastModified] = lastModified.ToUniversalTime().ToString("r");
|
||||
context.Response.Close();
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestHttp_NotFound_ThrowsAsync()
|
||||
{
|
||||
await this.TestClientServerAsync(
|
||||
async (source, dest) =>
|
||||
{
|
||||
WebException exception = await AsyncAssert.ThrowsAsync<WebException>(
|
||||
async () => await new Download(source, dest).PerformAsync());
|
||||
|
||||
Assert.That(exception.Status, Is.EqualTo(WebExceptionStatus.ProtocolError));
|
||||
},
|
||||
context =>
|
||||
{
|
||||
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
|
||||
context.Response.Close();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Security.Principal;
|
||||
using System.ServiceProcess;
|
||||
using NUnit.Framework;
|
||||
using winsw;
|
||||
|
@ -8,8 +7,31 @@ using winswTests.Util;
|
|||
namespace winswTests
|
||||
{
|
||||
[TestFixture]
|
||||
class MainTest
|
||||
public class MainTest
|
||||
{
|
||||
[Test]
|
||||
public void TestInstall()
|
||||
{
|
||||
TestHelper.RequireProcessElevated();
|
||||
|
||||
try
|
||||
{
|
||||
_ = CLITestHelper.CLITest(new[] { "install" });
|
||||
|
||||
using ServiceController controller = new ServiceController(CLITestHelper.Id);
|
||||
Assert.That(controller.DisplayName, Is.EqualTo(CLITestHelper.Name));
|
||||
Assert.That(controller.CanStop, Is.False);
|
||||
Assert.That(controller.CanShutdown, Is.False);
|
||||
Assert.That(controller.CanPauseAndContinue, Is.False);
|
||||
Assert.That(controller.Status, Is.EqualTo(ServiceControllerStatus.Stopped));
|
||||
Assert.That(controller.ServiceType, Is.EqualTo(ServiceType.Win32OwnProcess));
|
||||
}
|
||||
finally
|
||||
{
|
||||
_ = CLITestHelper.CLITest(new[] { "uninstall" });
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PrintVersion()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
#if VNEXT
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Constraints;
|
||||
|
||||
namespace winswTests.Util
|
||||
{
|
||||
internal static class AsyncAssert
|
||||
{
|
||||
internal static async Task<TActual> ThrowsAsync<TActual>(AsyncTestDelegate code)
|
||||
where TActual : Exception
|
||||
{
|
||||
Exception caught = null;
|
||||
try
|
||||
{
|
||||
await code();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
caught = e;
|
||||
}
|
||||
|
||||
Assert.That(caught, new ExceptionTypeConstraint(typeof(TActual)));
|
||||
return (TActual)caught;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,12 @@
|
|||
#if VNEXT
|
||||
using System;
|
||||
|
||||
namespace winswTests.Util
|
||||
{
|
||||
internal static class DateTimeExtensions
|
||||
{
|
||||
internal static DateTime TrimToSeconds(this DateTime dateTime) =>
|
||||
dateTime.AddTicks(-(dateTime.Ticks % TimeSpan.TicksPerSecond));
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,16 @@
|
|||
using NUnit.Framework;
|
||||
using winsw;
|
||||
|
||||
namespace winswTests.Util
|
||||
{
|
||||
internal static class TestHelper
|
||||
{
|
||||
internal static void RequireProcessElevated()
|
||||
{
|
||||
if (!WrapperService.IsProcessElevated())
|
||||
{
|
||||
Assert.Ignore();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue