diff --git a/tests/Tgstation.Server.Tests/AdministrationTest.cs b/tests/Tgstation.Server.Tests/AdministrationTest.cs index ef20efe158..9bad0c0168 100644 --- a/tests/Tgstation.Server.Tests/AdministrationTest.cs +++ b/tests/Tgstation.Server.Tests/AdministrationTest.cs @@ -1,6 +1,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Runtime.InteropServices; +using System.Threading; using System.Threading.Tasks; using Tgstation.Server.Client; @@ -15,14 +16,14 @@ namespace Tgstation.Server.Tests this.client = client ?? throw new ArgumentNullException(nameof(client)); } - public async Task Run() + public async Task Run(CancellationToken cancellationToken) { - await TestRead().ConfigureAwait(false); + await TestRead(cancellationToken).ConfigureAwait(false); } - async Task TestRead() + async Task TestRead(CancellationToken cancellationToken) { - var model = await client.Read(default).ConfigureAwait(false); + var model = await client.Read(cancellationToken).ConfigureAwait(false); Assert.AreEqual(RuntimeInformation.IsOSPlatform(OSPlatform.Windows), model.WindowsHost); //uhh not much else to do diff --git a/tests/Tgstation.Server.Tests/Instance/ConfigurationTest.cs b/tests/Tgstation.Server.Tests/Instance/ConfigurationTest.cs new file mode 100644 index 0000000000..df33996edb --- /dev/null +++ b/tests/Tgstation.Server.Tests/Instance/ConfigurationTest.cs @@ -0,0 +1,63 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.IO; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Tgstation.Server.Api.Models; +using Tgstation.Server.Client; +using Tgstation.Server.Client.Components; + +namespace Tgstation.Server.Tests.Instance +{ + sealed class ConfigurationTest + { + readonly IConfigurationClient configurationClient; + readonly Api.Models.Instance instance; + + public ConfigurationTest(IConfigurationClient configurationClient, Api.Models.Instance instance) + { + this.configurationClient = configurationClient ?? throw new ArgumentNullException(nameof(configurationClient)); + this.instance = instance ?? throw new ArgumentNullException(nameof(instance)); + } + + bool FileExists(ConfigurationFile file) + { + var tmp = (file.Path?.StartsWith('/') ?? false) ? '.' + file.Path : file.Path; + var path = Path.Combine(instance.Path, "Configuration", tmp); + return File.Exists(path); + } + + async Task TestDeleteDirectory(CancellationToken cancellationToken) + { + //try to delete non-existent + var TestDir = new ConfigurationFile + { + Path = "/TestDeleteDir" + }; + + await configurationClient.DeleteEmptyDirectory(TestDir, cancellationToken).ConfigureAwait(false); + + //try to delete non-empty + var file = await configurationClient.Write(new ConfigurationFile + { + Content = Encoding.UTF8.GetBytes("Hello world!"), + Path = TestDir.Path + "/test.txt" + }, cancellationToken).ConfigureAwait(false); + + Assert.IsTrue(FileExists(file)); + + await Assert.ThrowsExceptionAsync(() => configurationClient.DeleteEmptyDirectory(TestDir, cancellationToken)).ConfigureAwait(false); + + file.Content = null; + await configurationClient.Write(file, cancellationToken).ConfigureAwait(false); + + await configurationClient.DeleteEmptyDirectory(TestDir, cancellationToken).ConfigureAwait(false); + } + + public async Task Run(CancellationToken cancellationToken) + { + await TestDeleteDirectory(cancellationToken).ConfigureAwait(false); + } + } +} diff --git a/tests/Tgstation.Server.Tests/Instance/InstanceTest.cs b/tests/Tgstation.Server.Tests/Instance/InstanceTest.cs new file mode 100644 index 0000000000..cd65f015f2 --- /dev/null +++ b/tests/Tgstation.Server.Tests/Instance/InstanceTest.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Tgstation.Server.Client.Components; + +namespace Tgstation.Server.Tests.Instance +{ + sealed class InstanceTest + { + readonly IInstanceClient instanceClient; + + public InstanceTest(IInstanceClient instanceClient) + { + this.instanceClient = instanceClient ?? throw new ArgumentNullException(nameof(instanceClient)); + } + + public async Task RunTests(CancellationToken cancellationToken) + { + var configTests = new ConfigurationTest(instanceClient.Configuration, instanceClient.Metadata); + await configTests.Run(cancellationToken).ConfigureAwait(false); + } + } +} diff --git a/tests/Tgstation.Server.Tests/InstanceManagerTest.cs b/tests/Tgstation.Server.Tests/InstanceManagerTest.cs new file mode 100644 index 0000000000..3464217fd6 --- /dev/null +++ b/tests/Tgstation.Server.Tests/InstanceManagerTest.cs @@ -0,0 +1,116 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.IO; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using Tgstation.Server.Api.Models; +using Tgstation.Server.Client; +using Tgstation.Server.Host.Controllers; +using Tgstation.Server.Tests.Instance; + +namespace Tgstation.Server.Tests +{ + sealed class InstanceManagerTest + { + readonly IInstanceManagerClient instanceManagerClient; + readonly string testRootPath; + + long counter; + + public InstanceManagerTest(IInstanceManagerClient instanceManagerClient, string testRootPath) + { + this.instanceManagerClient = instanceManagerClient ?? throw new ArgumentNullException(nameof(instanceManagerClient)); + this.testRootPath = testRootPath ?? throw new ArgumentNullException(nameof(testRootPath)); + + counter = 0; + } + + Task CreateTestInstance(CancellationToken cancellationToken) => instanceManagerClient.CreateOrAttach(new Api.Models.Instance + { + Name = "TestInstance-" + ++counter, + Path = Path.Combine(testRootPath, Guid.NewGuid().ToString()), + Online = true + }, cancellationToken); + + public async Task Run(CancellationToken cancellationToken) + { + var firstTest = await CreateTestInstance(cancellationToken).ConfigureAwait(false); + //instances always start offline + Assert.AreEqual(false, firstTest.Online); + //check it exists + Assert.IsTrue(Directory.Exists(firstTest.Path)); + + //cant create instances in existent directories + var testNonEmpty = Path.Combine(testRootPath, Guid.NewGuid().ToString()); + Directory.CreateDirectory(testNonEmpty); + await Assert.ThrowsExceptionAsync(() => instanceManagerClient.CreateOrAttach(new Api.Models.Instance + { + Path = testNonEmpty, + Name = "NonEmptyTest" + }, cancellationToken)).ConfigureAwait(false); + await Assert.ThrowsExceptionAsync(() => instanceManagerClient.CreateOrAttach(firstTest, cancellationToken)).ConfigureAwait(false); + + //can't move to existent directories + await Assert.ThrowsExceptionAsync(() => instanceManagerClient.Update(new Api.Models.Instance + { + Id = firstTest.Id, + Path = testNonEmpty + }, cancellationToken)).ConfigureAwait(false); + + //test basic move + Directory.Delete(testNonEmpty); + var initialPath = firstTest.Path; + firstTest = await instanceManagerClient.Update(new Api.Models.Instance + { + Id = firstTest.Id, + Path = testNonEmpty + }, cancellationToken).ConfigureAwait(false); + + Assert.IsNotNull(firstTest.MoveJob); + + do + { + firstTest = await instanceManagerClient.GetId(firstTest, cancellationToken).ConfigureAwait(false); + await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false); + } while (firstTest.MoveJob != null); + + + //online it for real for component tests + firstTest.Online = true; + firstTest.ConfigurationType = ConfigurationType.HostWrite; + firstTest = await instanceManagerClient.Update(firstTest, cancellationToken).ConfigureAwait(false); + Assert.AreEqual(true, firstTest.Online); + Assert.AreEqual(ConfigurationType.HostWrite, firstTest.ConfigurationType); + + //can't move online instance + await Assert.ThrowsExceptionAsync(() => instanceManagerClient.Update(new Api.Models.Instance + { + Id = firstTest.Id, + Path = initialPath + }, cancellationToken)).ConfigureAwait(false); + + var testSuite1 = new InstanceTest(instanceManagerClient.CreateClient(firstTest)); + await testSuite1.RunTests(cancellationToken).ConfigureAwait(false); + + //can't detach online instance + await Assert.ThrowsExceptionAsync(() => instanceManagerClient.Detach(firstTest, cancellationToken)).ConfigureAwait(false); + + firstTest.Online = false; + firstTest = await instanceManagerClient.Update(firstTest, cancellationToken).ConfigureAwait(false); + await instanceManagerClient.Detach(firstTest, cancellationToken).ConfigureAwait(false); + + var instanceAttachFileName = (string)typeof(InstanceController).GetField("InstanceAttachFileName", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null); + var attachPath = Path.Combine(firstTest.Path, instanceAttachFileName); + Assert.IsTrue(File.Exists(attachPath)); + + //can recreate detached instance + firstTest = await instanceManagerClient.CreateOrAttach(firstTest, cancellationToken).ConfigureAwait(false); + + //but only if the attach file exists + await instanceManagerClient.Detach(firstTest, cancellationToken).ConfigureAwait(false); + File.Delete(attachPath); + await Assert.ThrowsExceptionAsync(() => instanceManagerClient.CreateOrAttach(firstTest, cancellationToken)).ConfigureAwait(false); + } + } +} diff --git a/tests/Tgstation.Server.Tests/IntegrationTest.cs b/tests/Tgstation.Server.Tests/IntegrationTest.cs index b9d7277265..018cd8d897 100644 --- a/tests/Tgstation.Server.Tests/IntegrationTest.cs +++ b/tests/Tgstation.Server.Tests/IntegrationTest.cs @@ -1,5 +1,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System; +using System.IO; using System.Net.Http.Headers; using System.Reflection; using System.Threading; @@ -22,7 +23,8 @@ namespace Tgstation.Server.Tests using (var server = new TestingServer()) using (var serverCts = new CancellationTokenSource()) { - var serverTask = server.RunAsync(serverCts.Token); + var cancellationToken = serverCts.Token; + var serverTask = server.RunAsync(cancellationToken); try { using (var adminClient = await clientFactory.CreateServerClient(server.Url, User.AdminName, User.DefaultAdminPassword).ConfigureAwait(false)) @@ -32,7 +34,8 @@ namespace Tgstation.Server.Tests Assert.AreEqual(ApiHeaders.Version, serverInfo.ApiVersion); Assert.AreEqual(typeof(IServer).Assembly.GetName().Version, serverInfo.Version); - await new AdministrationTest(adminClient.Administration).Run().ConfigureAwait(false); + await new AdministrationTest(adminClient.Administration).Run(cancellationToken).ConfigureAwait(false); + await new InstanceManagerTest(adminClient.Instances, server.Directory).Run(cancellationToken).ConfigureAwait(false); } } finally diff --git a/tests/Tgstation.Server.Tests/TestingServer.cs b/tests/Tgstation.Server.Tests/TestingServer.cs index c943f1d821..4e1df5f740 100644 --- a/tests/Tgstation.Server.Tests/TestingServer.cs +++ b/tests/Tgstation.Server.Tests/TestingServer.cs @@ -10,6 +10,8 @@ namespace Tgstation.Server.Tests sealed class TestingServer : IServer { public Uri Url { get; } + + public string Directory { get; } public bool RestartRequested => realServer.RestartRequested; readonly IServer realServer; @@ -17,8 +19,10 @@ namespace Tgstation.Server.Tests public TestingServer() { - databasePath = Path.GetTempFileName(); - File.Delete(databasePath); + Directory = Path.GetTempFileName(); + File.Delete(Directory); + System.IO.Directory.CreateDirectory(Directory); + databasePath = Path.Combine(Directory, "TGS.db3"); Url = new Uri("http://localhost:5001"); realServer = new ServerFactory().CreateServer(new string[] { @@ -33,7 +37,7 @@ namespace Tgstation.Server.Tests public void Dispose() { realServer.Dispose(); - File.Delete(databasePath); + System.IO.Directory.Delete(Directory, true); } public Task RunAsync(CancellationToken cancellationToken) => realServer.RunAsync(cancellationToken);