diff --git a/src/Tgstation.Server.Client/ApiClient.cs b/src/Tgstation.Server.Client/ApiClient.cs index 36344c265f..a01db4e9d8 100644 --- a/src/Tgstation.Server.Client/ApiClient.cs +++ b/src/Tgstation.Server.Client/ApiClient.cs @@ -107,7 +107,9 @@ namespace Tgstation.Server.Client } #pragma warning disable IDE0010 // Add missing cases +#pragma warning disable IDE0066 // Convert switch statement to expression switch (response.StatusCode) +#pragma warning restore IDE0066 // Convert switch statement to expression #pragma warning restore IDE0010 // Add missing cases { case HttpStatusCode.UpgradeRequired: diff --git a/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs b/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs index e7fb0b81a5..d409c71bd7 100644 --- a/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs +++ b/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs @@ -358,7 +358,7 @@ namespace Tgstation.Server.Host.Components.Deployment // The difficulty with compile jobs is they have a two part commit await databaseContext.Save(cancellationToken); - logger.LogTrace("Created CompileJob {0}", compileJob.Id); + logger.LogTrace("Created CompileJob {compileJobId}", compileJob.Id); try { await compileJobConsumer.LoadCompileJob(compileJob, cancellationToken); @@ -576,7 +576,7 @@ namespace Tgstation.Server.Host.Components.Deployment CancellationToken cancellationToken) { var outputDirectory = job.DirectoryName.ToString(); - logger.LogTrace("Compile output GUID: {0}", outputDirectory); + logger.LogTrace("Compile output GUID: {dirGuid}", outputDirectory); try { @@ -624,7 +624,7 @@ namespace Tgstation.Server.Host.Components.Deployment throw new JobException(ErrorCode.DreamMakerMissingDme); } - logger.LogDebug("Selected {0}.dme for compilation!", job.DmeName); + logger.LogDebug("Selected {dmeName}.dme for compilation!", job.DmeName); currentStage = "Modifying .dme"; await ModifyDme(job, cancellationToken); @@ -727,7 +727,7 @@ namespace Tgstation.Server.Host.Components.Deployment if (estimatedDuration.HasValue) { - logger.LogDebug("Compile is expected to take: {0}", estimatedDuration); + logger.LogDebug("Compile is expected to take: {estimatedDuration}", estimatedDuration); } else { @@ -792,7 +792,7 @@ namespace Tgstation.Server.Host.Components.Deployment bool logOutput, CancellationToken cancellationToken) { - logger.LogTrace("Verifying {0}DMAPI...", requireValidate ? "required " : String.Empty); + logger.LogTrace("Verifying {possiblyRequired}DMAPI...", requireValidate ? "required " : String.Empty); var launchParameters = new DreamDaemonLaunchParameters { AllowWebClient = false, @@ -827,7 +827,7 @@ namespace Tgstation.Server.Host.Components.Deployment if (requireValidate && validationStatus == ApiValidationStatus.NeverValidated) throw new JobException(ErrorCode.DreamMakerNeverValidated); - logger.LogTrace("API validation status: {0}", validationStatus); + logger.LogTrace("API validation status: {validationStatus}", validationStatus); job.DMApiVersion = controller.DMApiVersion; } @@ -883,10 +883,10 @@ namespace Tgstation.Server.Host.Components.Deployment exitCode = await dm.Lifetime; cancellationToken.ThrowIfCancellationRequested(); - logger.LogDebug("DreamMaker exit code: {0}", exitCode); + logger.LogDebug("DreamMaker exit code: {exitCode}", exitCode); job.Output = await dm.GetCombinedOutput(cancellationToken); currentDreamMakerOutput = job.Output; - logger.LogDebug("DreamMaker output: {0}{1}", Environment.NewLine, job.Output); + logger.LogDebug("DreamMaker output: {newLine}{output}", Environment.NewLine, job.Output); return exitCode; } @@ -926,7 +926,7 @@ namespace Tgstation.Server.Host.Components.Deployment { var headIncludeLineNumber = dmeLineIndex + 1; logger.LogDebug( - "Inserting HeadInclude.dm at line {0}: {1}", + "Inserting HeadInclude.dm at line {lineNumber}: {includeLine}", headIncludeLineNumber, dmeModifications.HeadIncludeLine); dmeLines.Insert(headIncludeLineNumber, dmeModifications.HeadIncludeLine); @@ -935,7 +935,7 @@ namespace Tgstation.Server.Host.Components.Deployment else if (line.Contains("END_INCLUDE", StringComparison.Ordinal) && dmeModifications.TailIncludeLine != null) { logger.LogDebug( - "Inserting TailInclude.dm at line {0}: {1}", + "Inserting TailInclude.dm at line {lineNumber}: {includeLine}", dmeLineIndex, dmeModifications.TailIncludeLine); dmeLines.Insert(dmeLineIndex, dmeModifications.TailIncludeLine); @@ -968,7 +968,7 @@ namespace Tgstation.Server.Host.Components.Deployment } catch (Exception e) { - logger.LogWarning(e, "Error cleaning up compile directory {0}!", ioManager.ResolvePath(jobPath)); + logger.LogWarning(e, "Error cleaning up compile directory {path}!", ioManager.ResolvePath(jobPath)); } } diff --git a/src/Tgstation.Server.Host/Components/Repository/Repository.cs b/src/Tgstation.Server.Host/Components/Repository/Repository.cs index db3d04bcc9..8bdbadc48e 100644 --- a/src/Tgstation.Server.Host/Components/Repository/Repository.cs +++ b/src/Tgstation.Server.Host/Components/Repository/Repository.cs @@ -33,7 +33,7 @@ namespace Tgstation.Server.Host.Components.Repository /// /// Template error message for when tracking of the most recent origin commit fails. /// - public const string OriginTrackingErrorTemplate = "Unable to determine most recent origin commit of {0}. Marking it as an origin commit. This may result in invalid git metadata until the next hard reset to an origin reference."; + public const string OriginTrackingErrorTemplate = "Unable to determine most recent origin commit of {sha}. Marking it as an origin commit. This may result in invalid git metadata until the next hard reset to an origin reference."; /// /// The branch name used for publishing testmerge commits. diff --git a/src/Tgstation.Server.Host/System/WindowsProcessFeatures.cs b/src/Tgstation.Server.Host/System/WindowsProcessFeatures.cs index 1657fcbd50..d06120d944 100644 --- a/src/Tgstation.Server.Host/System/WindowsProcessFeatures.cs +++ b/src/Tgstation.Server.Host/System/WindowsProcessFeatures.cs @@ -44,11 +44,11 @@ namespace Tgstation.Server.Host.System foreach (ProcessThread thread in process.Threads) { var threadId = (uint)thread.Id; - logger.LogTrace("Suspending thread {0}...", threadId); + logger.LogTrace("Suspending thread {threadId}...", threadId); var pOpenThread = NativeMethods.OpenThread(NativeMethods.ThreadAccess.SuspendResume, false, threadId); if (pOpenThread == IntPtr.Zero) { - logger.LogDebug(new Win32Exception(), "Failed to open thread {0}!", threadId); + logger.LogDebug(new Win32Exception(), "Failed to open thread {threadId}!", threadId); continue; } @@ -74,11 +74,11 @@ namespace Tgstation.Server.Host.System foreach (ProcessThread thread in process.Threads) { var threadId = (uint)thread.Id; - logger.LogTrace("Resuming thread {0}...", threadId); + logger.LogTrace("Resuming thread {threadId}...", threadId); var pOpenThread = NativeMethods.OpenThread(NativeMethods.ThreadAccess.SuspendResume, false, threadId); if (pOpenThread == IntPtr.Zero) { - logger.LogDebug(new Win32Exception(), "Failed to open thread {0}!", threadId); + logger.LogDebug(new Win32Exception(), "Failed to open thread {threadId}!", threadId); continue; } @@ -99,7 +99,7 @@ namespace Tgstation.Server.Host.System { string query = $"SELECT * FROM Win32_Process WHERE ProcessId = {process?.Id ?? throw new ArgumentNullException(nameof(process))}"; using var searcher = new ManagementObjectSearcher(query); - foreach (ManagementObject obj in searcher.Get()) + foreach (var obj in searcher.Get().Cast()) { var argList = new string[] { String.Empty, String.Empty }; var returnString = obj.InvokeMethod( diff --git a/tests/Tgstation.Server.Tests/Instance/ByondTest.cs b/tests/Tgstation.Server.Tests/Instance/ByondTest.cs index d7eacaff2d..9ff14817d0 100644 --- a/tests/Tgstation.Server.Tests/Instance/ByondTest.cs +++ b/tests/Tgstation.Server.Tests/Instance/ByondTest.cs @@ -34,10 +34,16 @@ namespace Tgstation.Server.Tests.Instance this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata)); } - public async Task Run(CancellationToken cancellationToken) + public Task Run(CancellationToken cancellationToken, out Task firstInstall) { + firstInstall = TestInstallStable(cancellationToken); + return RunContinued(firstInstall, cancellationToken); + } + + async Task RunContinued(Task firstInstall, CancellationToken cancellationToken) + { + await firstInstall; await TestNoVersion(cancellationToken); - await TestInstallStable(cancellationToken); await TestInstallFakeVersion(cancellationToken); await TestCustomInstalls(cancellationToken); } diff --git a/tests/Tgstation.Server.Tests/Instance/ConfigurationTest.cs b/tests/Tgstation.Server.Tests/Instance/ConfigurationTest.cs index cf61a02737..f07dd4d8c7 100644 --- a/tests/Tgstation.Server.Tests/Instance/ConfigurationTest.cs +++ b/tests/Tgstation.Server.Tests/Instance/ConfigurationTest.cs @@ -70,7 +70,7 @@ namespace Tgstation.Server.Tests.Instance Assert.IsNotNull(requestStream); var response = (HttpResponseMessage)requestStream.GetType().GetField("response", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(requestStream); Assert.AreEqual(response.Content.Headers.ContentType.MediaType, MediaTypeNames.Application.Octet); - await downloadStream.CopyToAsync(downloadMemoryStream); + await downloadStream.CopyToAsync(downloadMemoryStream, cancellationToken); } Assert.AreEqual(TestString, Encoding.UTF8.GetString(downloadMemoryStream.ToArray()).Trim()); } diff --git a/tests/Tgstation.Server.Tests/Instance/DeploymentTest.cs b/tests/Tgstation.Server.Tests/Instance/DeploymentTest.cs index 6de276f66e..596e52270d 100644 --- a/tests/Tgstation.Server.Tests/Instance/DeploymentTest.cs +++ b/tests/Tgstation.Server.Tests/Instance/DeploymentTest.cs @@ -5,6 +5,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Tgstation.Server.Api.Models; using Tgstation.Server.Api.Models.Request; +using Tgstation.Server.Api.Models.Response; using Tgstation.Server.Api.Rights; using Tgstation.Server.Client; using Tgstation.Server.Client.Components; @@ -22,7 +23,7 @@ namespace Tgstation.Server.Tests.Instance public DeploymentTest(IInstanceClient instanceClient, IJobsClient jobsClient) : base(jobsClient) { - this.instanceClient = instanceClient ?? throw new ArgumentException(nameof(instanceClient)); + this.instanceClient = instanceClient ?? throw new ArgumentNullException(nameof(instanceClient)); this.dreamMakerClient = instanceClient.DreamMaker; this.dreamDaemonClient = instanceClient.DreamDaemon; } @@ -40,7 +41,7 @@ namespace Tgstation.Server.Tests.Instance Assert.AreEqual(null, dmSettings.ProjectName); } - public async Task RunPostRepoClone(CancellationToken cancellationToken) + public async Task RunPostRepoClone(Task byondTask, CancellationToken cancellationToken) { Assert.IsNotNull(vpTest); // by alphabetization rules, it should discover api_free here @@ -71,17 +72,26 @@ namespace Tgstation.Server.Tests.Instance Assert.AreEqual(15U, updatedDD.StartupTimeout); Assert.AreEqual(IntegrationTest.DDPort, updatedDD.Port); - await ApiAssert.ThrowsException(() => dreamDaemonClient.Update(new DreamDaemonRequest + async Task CompileAfterByondInstall() { - Port = IntegrationTest.DMPort - }, cancellationToken), ErrorCode.PortNotAvailable); + await byondTask; + return await dreamMakerClient.Compile(cancellationToken); + } - await ApiAssert.ThrowsException(() => dreamMakerClient.Update(new DreamMakerRequest - { - ApiValidationPort = IntegrationTest.DDPort - }, cancellationToken), ErrorCode.PortNotAvailable); + var deployJobTask = CompileAfterByondInstall(); + await Task.WhenAll( + ApiAssert.ThrowsException(() => dreamDaemonClient.Update(new DreamDaemonRequest + { + Port = IntegrationTest.DMPort + }, cancellationToken), ErrorCode.PortNotAvailable), + ApiAssert.ThrowsException(() => dreamMakerClient.Update(new DreamMakerRequest + { + ApiValidationPort = IntegrationTest.DDPort + }, cancellationToken), ErrorCode.PortNotAvailable), + deployJobTask); + + var deployJob = await deployJobTask; - var deployJob = await dreamMakerClient.Compile(cancellationToken); await WaitForJob(deployJob, 40, true, ErrorCode.DreamMakerNeverValidated, cancellationToken); const string FailProject = "tests/DMAPI/BuildFail/build_fail"; diff --git a/tests/Tgstation.Server.Tests/Instance/InstanceTest.cs b/tests/Tgstation.Server.Tests/Instance/InstanceTest.cs index fa9c1664d3..6aec98aadc 100644 --- a/tests/Tgstation.Server.Tests/Instance/InstanceTest.cs +++ b/tests/Tgstation.Server.Tests/Instance/InstanceTest.cs @@ -31,21 +31,22 @@ namespace Tgstation.Server.Tests.Instance var repoTest = new RepositoryTest(instanceClient.Repository, instanceClient.Jobs); var dmTest = new DeploymentTest(instanceClient, instanceClient.Jobs); - var byondTask = byondTest.Run(cancellationToken); + var byondTask = byondTest.Run(cancellationToken, out var firstInstall); var chatTask = chatTest.RunPreWatchdog(cancellationToken); var repoLongJob = repoTest.RunLongClone(cancellationToken); await dmTest.RunPreRepoClone(cancellationToken); - await repoTest.AbortLongCloneAndCloneSomethingQuick(await repoLongJob, cancellationToken); + await repoTest.AbortLongCloneAndCloneSomethingQuick(repoLongJob, cancellationToken); await configTest.RunPreWatchdog(cancellationToken); - var dmTask = dmTest.RunPostRepoClone(cancellationToken); + var dmTask = dmTest.RunPostRepoClone(firstInstall, cancellationToken); - await byondTask; await chatTask; await dmTask; await new WatchdogTest(instanceClient, instanceManager, serverPort).Run(cancellationToken); + + await byondTask; } } } diff --git a/tests/Tgstation.Server.Tests/Instance/RepositoryTest.cs b/tests/Tgstation.Server.Tests/Instance/RepositoryTest.cs index 9e6cc18466..61b3c1479d 100644 --- a/tests/Tgstation.Server.Tests/Instance/RepositoryTest.cs +++ b/tests/Tgstation.Server.Tests/Instance/RepositoryTest.cs @@ -62,9 +62,9 @@ namespace Tgstation.Server.Tests.Instance return clone.ActiveJob; } - public async Task AbortLongCloneAndCloneSomethingQuick(JobResponse longCloneJob, CancellationToken cancellationToken) + public async Task AbortLongCloneAndCloneSomethingQuick(Task longCloneJob, CancellationToken cancellationToken) { - await WaitForJobProgressThenCancel(longCloneJob, 40, cancellationToken); + await WaitForJobProgressThenCancel(await longCloneJob, 40, cancellationToken); var secondRead = await repositoryClient.Read(cancellationToken); Assert.IsNotNull(secondRead); diff --git a/tests/Tgstation.Server.Tests/Instance/WatchdogTest.cs b/tests/Tgstation.Server.Tests/Instance/WatchdogTest.cs index 97076d702f..ed30eb27e2 100644 --- a/tests/Tgstation.Server.Tests/Instance/WatchdogTest.cs +++ b/tests/Tgstation.Server.Tests/Instance/WatchdogTest.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; using Newtonsoft.Json; @@ -23,6 +24,7 @@ using Tgstation.Server.Api.Models.Response; using Tgstation.Server.Client; using Tgstation.Server.Client.Components; using Tgstation.Server.Host.Components; +using Tgstation.Server.Host.Components.Chat; using Tgstation.Server.Host.Components.Interop; using Tgstation.Server.Host.Components.Watchdog; using Tgstation.Server.Host.Controllers; @@ -51,27 +53,26 @@ namespace Tgstation.Server.Tests.Instance public async Task Run(CancellationToken cancellationToken) { global::System.Console.WriteLine("TEST: START WATCHDOG TESTS"); - // Increase startup timeout, disable heartbeats - var initialSettings = await instanceClient.DreamDaemon.Update(new DreamDaemonRequest - { - StartupTimeout = 15, - HeartbeatSeconds = 0, - Port = IntegrationTest.DDPort - }, cancellationToken); - await ApiAssert.ThrowsException(() => instanceClient.DreamDaemon.Update(new DreamDaemonRequest - { - Port = 0 - }, cancellationToken), ErrorCode.ModelValidationFailure); - - await ApiAssert.ThrowsException(() => instanceClient.DreamDaemon.Update(new DreamDaemonRequest - { - SoftShutdown = true, - SoftRestart = true - }, cancellationToken), ErrorCode.DreamDaemonDoubleSoft); - - await ApiAssert.ThrowsException(() => instanceClient.DreamDaemon.CreateDump(cancellationToken), ErrorCode.WatchdogNotRunning); - await ApiAssert.ThrowsException(() => instanceClient.DreamDaemon.Restart(cancellationToken), ErrorCode.WatchdogNotRunning); + await Task.WhenAll( + // Increase startup timeout, disable heartbeats + instanceClient.DreamDaemon.Update(new DreamDaemonRequest + { + StartupTimeout = 15, + HeartbeatSeconds = 0, + Port = IntegrationTest.DDPort + }, cancellationToken), + ApiAssert.ThrowsException(() => instanceClient.DreamDaemon.Update(new DreamDaemonRequest + { + SoftShutdown = true, + SoftRestart = true + }, cancellationToken), ErrorCode.DreamDaemonDoubleSoft), + ApiAssert.ThrowsException(() => instanceClient.DreamDaemon.Update(new DreamDaemonRequest + { + Port = 0 + }, cancellationToken), ErrorCode.ModelValidationFailure), + ApiAssert.ThrowsException(() => instanceClient.DreamDaemon.CreateDump(cancellationToken), ErrorCode.WatchdogNotRunning), + ApiAssert.ThrowsException(() => instanceClient.DreamDaemon.Restart(cancellationToken), ErrorCode.WatchdogNotRunning)); await RunBasicTest(cancellationToken); @@ -94,18 +95,21 @@ namespace Tgstation.Server.Tests.Instance { await StartAndLeaveRunning(cancellationToken); - await Task.WhenAll( - WhiteBoxChatCommandTest(cancellationToken), - SendChatOverloadCommand(cancellationToken)); + await WhiteBoxChatCommandTest(cancellationToken); + await SendChatOverloadCommand(cancellationToken); + await ValidateTopicLimits(cancellationToken); // This one fucks with the access_identifer, run it in isolation - await WhiteBoxValidateDMApiLimits(cancellationToken); + await WhiteBoxValidateBridgeRequestLimitAndTestChunking(cancellationToken); + + var ddInfo = await instanceClient.DreamDaemon.Read(cancellationToken); + await CheckDMApiFail(ddInfo.ActiveCompileJob, cancellationToken); // And this freezes DD await DumpTests(cancellationToken); } - async Task SendChatOverloadCommand(CancellationToken cancellationToken) + static async Task SendChatOverloadCommand(CancellationToken cancellationToken) { // for the code coverage really... var topicRequestResult = await TopicClient.SendTopic( @@ -271,7 +275,7 @@ namespace Tgstation.Server.Tests.Instance using var ddProc = ddProcs.Single(); IProcessExecutor executor = null; executor = new ProcessExecutor( - System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? new WindowsProcessFeatures(Mock.Of>()) : new PosixProcessFeatures(new Lazy(() => executor), Mock.Of(), Mock.Of>()), Mock.Of(), @@ -363,7 +367,9 @@ namespace Tgstation.Server.Tests.Instance public string Payload { get; set; } } - async Task WhiteBoxValidateDMApiLimits(CancellationToken cancellationToken) + // - Uses instance manager concrete + // - Injects a custom bridge handler into the bridge registrar and makes the test hack into the DMAPI and change its access_identifier + async Task WhiteBoxValidateBridgeRequestLimitAndTestChunking(CancellationToken cancellationToken) { // first check the bridge limits var bridgeTestsTcs = new TaskCompletionSource(); @@ -389,7 +395,10 @@ namespace Tgstation.Server.Tests.Instance // Time for DD to revert the bridge access identifier change await Task.Delay(TimeSpan.FromSeconds(3), cancellationToken); + } + static async Task ValidateTopicLimits(CancellationToken cancellationToken) + { // Time for topic tests // Request @@ -484,21 +493,19 @@ namespace Tgstation.Server.Tests.Instance cancellationToken.ThrowIfCancellationRequested(); Assert.AreEqual(DMApiConstants.MaximumTopicResponseLength, (uint)lastSize); - - var ddInfo = await instanceClient.DreamDaemon.Read(cancellationToken); - await CheckDMApiFail(ddInfo.ActiveCompileJob, cancellationToken); } + // - Uses instance manager concrete + // - Injects a custom bridge handler into the bridge registrar and makes the test hack into the DMAPI and change its access_identifier async Task WhiteBoxChatCommandTest(CancellationToken cancellationToken) { - // oh god, oh fuck, blackbox testing MessageContent embedsResponse, overloadResponse, overloadResponse2, embedsResponse2; var startTime = DateTimeOffset.UtcNow - TimeSpan.FromSeconds(5); using (var instanceReference = instanceManager.GetInstanceReference(instanceClient.Metadata)) { - var mockChatUser = new Host.Components.Chat.ChatUser + var mockChatUser = new ChatUser { - Channel = new Host.Components.Chat.ChannelRepresentation + Channel = new ChannelRepresentation { IsAdminChannel = true, ConnectionName = "test_connection", @@ -513,25 +520,25 @@ namespace Tgstation.Server.Tests.Instance RealId = 1234, }; - var embedsResponseTask = ((BasicWatchdog)instanceReference.Watchdog).HandleChatCommand( + var embedsResponseTask = ((WatchdogBase)instanceReference.Watchdog).HandleChatCommand( "embeds_test", String.Empty, mockChatUser, cancellationToken); - var embedsResponseTask2 = ((BasicWatchdog)instanceReference.Watchdog).HandleChatCommand( + var embedsResponseTask2 = ((WatchdogBase)instanceReference.Watchdog).HandleChatCommand( "embeds_test", new string('a', (int)DMApiConstants.MaximumTopicRequestLength * 3), mockChatUser, cancellationToken); - var overloadResponseTask2 = ((BasicWatchdog)instanceReference.Watchdog).HandleChatCommand( + var overloadResponseTask2 = ((WatchdogBase)instanceReference.Watchdog).HandleChatCommand( "response_overload_test", String.Empty, mockChatUser, cancellationToken); - overloadResponse = await ((BasicWatchdog)instanceReference.Watchdog).HandleChatCommand( + overloadResponse = await ((WatchdogBase)instanceReference.Watchdog).HandleChatCommand( "response_overload_test", String.Empty, mockChatUser, @@ -557,7 +564,7 @@ namespace Tgstation.Server.Tests.Instance Assert.AreEqual(expectedString, overloadResponse2.Text); } - void CheckEmbedsTest(MessageContent embedsResponse, DateTimeOffset startTime, DateTimeOffset endTime) + static void CheckEmbedsTest(MessageContent embedsResponse, DateTimeOffset startTime, DateTimeOffset endTime) { Assert.IsNotNull(embedsResponse); Assert.AreEqual("Embed support test2", embedsResponse.Text); diff --git a/tests/Tgstation.Server.Tests/InstanceManagerTest.cs b/tests/Tgstation.Server.Tests/InstanceManagerTest.cs index 62cde7552f..1f21d41eff 100644 --- a/tests/Tgstation.Server.Tests/InstanceManagerTest.cs +++ b/tests/Tgstation.Server.Tests/InstanceManagerTest.cs @@ -46,7 +46,7 @@ namespace Tgstation.Server.Tests ChatBotLimit = 2 }, cancellationToken); - static TRequestType FromResponse(InstanceResponse response) where TRequestType : Api.Models.Instance, new() => new TRequestType + static TRequestType FromResponse(InstanceResponse response) where TRequestType : Api.Models.Instance, new() => new () { Id = response.Id, Path = response.Path, @@ -181,7 +181,7 @@ namespace Tgstation.Server.Tests var token = serverClient.Token.Bearer; // check that 400s are returned appropriately using var httpClient = new HttpClient(); - using var request = new HttpRequestMessage(HttpMethod.Get, url.ToString() + Routes.ListRoute(Routes.InstanceManager).Substring(1) + "?pageSize=2"); + using var request = new HttpRequestMessage(HttpMethod.Get, String.Concat(url.ToString(), Routes.ListRoute(Routes.InstanceManager).AsSpan(1), "?pageSize=2")); request.Headers.Accept.Clear(); request.Headers.UserAgent.Add(new ProductInfoHeaderValue("RegressionTest1256", "1.0.0")); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json)); @@ -190,7 +190,7 @@ namespace Tgstation.Server.Tests using var response = await httpClient.SendAsync(request, cancellationToken); response.EnsureSuccessStatusCode(); - var json = await response.Content.ReadAsStringAsync(); + var json = await response.Content.ReadAsStringAsync(cancellationToken); var paginated = JsonConvert.DeserializeObject>(json); Assert.AreEqual(2, paginated.PageSize); diff --git a/tests/Tgstation.Server.Tests/IntegrationTest.cs b/tests/Tgstation.Server.Tests/IntegrationTest.cs index f78ae71c02..a3677a1708 100644 --- a/tests/Tgstation.Server.Tests/IntegrationTest.cs +++ b/tests/Tgstation.Server.Tests/IntegrationTest.cs @@ -871,7 +871,7 @@ namespace Tgstation.Server.Tests } } - var rootTest = FailFast(new RawRequestTests().Run(clientFactory, adminClient, cancellationToken)); + var rootTest = FailFast(RawRequestTests.Run(clientFactory, adminClient, cancellationToken)); var adminTest = FailFast(new AdministrationTest(adminClient.Administration).Run(cancellationToken)); var usersTest = FailFast(new UsersTest(adminClient).Run(cancellationToken)); instance = await new InstanceManagerTest(adminClient, server.Directory).RunPreInstanceTest(cancellationToken); @@ -1151,10 +1151,10 @@ namespace Tgstation.Server.Tests using var repo = new Repository( libGit2Repo, new LibGit2Commands(), - Mock.Of(), + Mock.Of(), Mock.Of(), Mock.Of(), - Mock.Of(), + Mock.Of(), Mock.Of(), Mock.Of>(), () => { }); @@ -1165,7 +1165,7 @@ namespace Tgstation.Server.Tests Assert.IsTrue(result); Assert.AreEqual(StartSha, repo.Head); result = await repo.ShaIsParent("f636418bf47d238d33b0e4a34f0072b23a8aad0e", default); - Assert.IsFalse(result); ; + Assert.IsFalse(result); Assert.AreEqual(StartSha, repo.Head); } } diff --git a/tests/Tgstation.Server.Tests/RawRequestTests.cs b/tests/Tgstation.Server.Tests/RawRequestTests.cs index f958c6e984..61c5260d58 100644 --- a/tests/Tgstation.Server.Tests/RawRequestTests.cs +++ b/tests/Tgstation.Server.Tests/RawRequestTests.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; using System; using System.Net; @@ -18,9 +18,9 @@ using Tgstation.Server.Host; namespace Tgstation.Server.Tests { - sealed class RawRequestTests + static class RawRequestTests { - async Task TestRequestValidation(IServerClient serverClient, CancellationToken cancellationToken) + static async Task TestRequestValidation(IServerClient serverClient, CancellationToken cancellationToken) { var url = serverClient.Url; var token = serverClient.Token.Bearer; @@ -50,7 +50,7 @@ namespace Tgstation.Server.Tests request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json)); using var response = await httpClient.SendAsync(request, cancellationToken); Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode); - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); var message = JsonConvert.DeserializeObject(content); Assert.AreEqual(ErrorCode.BadHeaders, message.ErrorCode); } @@ -63,7 +63,7 @@ namespace Tgstation.Server.Tests request.Headers.Add(ApiHeaders.ApiVersionHeader, "Tgstation.Server.Api/" + ApiHeaders.Version); using var response = await httpClient.SendAsync(request, cancellationToken); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); var message = JsonConvert.DeserializeObject(content); Assert.AreEqual(ApiHeaders.Version, message.ApiVersion); } @@ -77,12 +77,12 @@ namespace Tgstation.Server.Tests request.Headers.Authorization = new AuthenticationHeaderValue(ApiHeaders.BearerAuthenticationScheme, token); using var response = await httpClient.SendAsync(request, cancellationToken); Assert.AreEqual(HttpStatusCode.UpgradeRequired, response.StatusCode); - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); var message = JsonConvert.DeserializeObject(content); Assert.AreEqual(ErrorCode.ApiMismatch, message.ErrorCode); } - using (var request = new HttpRequestMessage(HttpMethod.Get, url.ToString() + Routes.Administration.Substring(1))) + using (var request = new HttpRequestMessage(HttpMethod.Get, String.Concat(url.ToString(), Routes.Administration.AsSpan(1)))) { request.Headers.Accept.Clear(); request.Headers.UserAgent.Add(new ProductInfoHeaderValue("RootTest", "1.0.0")); @@ -91,12 +91,12 @@ namespace Tgstation.Server.Tests request.Headers.Authorization = new AuthenticationHeaderValue(ApiHeaders.BearerAuthenticationScheme, token); using var response = await httpClient.SendAsync(request, cancellationToken); Assert.AreEqual(HttpStatusCode.UpgradeRequired, response.StatusCode); - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); var message = JsonConvert.DeserializeObject(content); Assert.AreEqual(ErrorCode.ApiMismatch, message.ErrorCode); } - using (var request = new HttpRequestMessage(HttpMethod.Post, url.ToString() + Routes.Administration.Substring(1))) + using (var request = new HttpRequestMessage(HttpMethod.Post, String.Concat(url.ToString(), Routes.Administration.AsSpan(1)))) { request.Headers.Accept.Clear(); request.Headers.UserAgent.Add(new ProductInfoHeaderValue("RootTest", "1.0.0")); @@ -109,12 +109,12 @@ namespace Tgstation.Server.Tests MediaTypeNames.Application.Json); using var response = await httpClient.SendAsync(request, cancellationToken); Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode); - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); var message = JsonConvert.DeserializeObject(content); Assert.AreEqual(ErrorCode.ModelValidationFailure, message.ErrorCode); } - using (var request = new HttpRequestMessage(HttpMethod.Post, url.ToString() + Routes.DreamDaemon.Substring(1))) + using (var request = new HttpRequestMessage(HttpMethod.Post, String.Concat(url.ToString(), Routes.DreamDaemon.AsSpan(1)))) { request.Headers.Accept.Clear(); request.Headers.UserAgent.Add(new ProductInfoHeaderValue("RootTest", "1.0.0")); @@ -124,7 +124,7 @@ namespace Tgstation.Server.Tests Assert.AreEqual(HttpStatusCode.Unauthorized, response.StatusCode); } - using (var request = new HttpRequestMessage(HttpMethod.Post, url.ToString() + Routes.DreamDaemon.Substring(1))) + using (var request = new HttpRequestMessage(HttpMethod.Post, String.Concat(url.ToString(), Routes.DreamDaemon.AsSpan(1)))) { request.Headers.Accept.Clear(); request.Headers.UserAgent.Add(new ProductInfoHeaderValue("RootTest", "1.0.0")); @@ -133,7 +133,7 @@ namespace Tgstation.Server.Tests request.Headers.Authorization = new AuthenticationHeaderValue(ApiHeaders.BearerAuthenticationScheme, token); using var response = await httpClient.SendAsync(request, cancellationToken); Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode); - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); var message = JsonConvert.DeserializeObject(content); Assert.AreEqual(ErrorCode.InstanceHeaderRequired, message.ErrorCode); } @@ -147,7 +147,7 @@ namespace Tgstation.Server.Tests request.Headers.Authorization = new AuthenticationHeaderValue(ApiHeaders.BearerAuthenticationScheme.ToLower(), token); using var response = await httpClient.SendAsync(request, cancellationToken); Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode); - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); var message = JsonConvert.DeserializeObject(content); Assert.AreEqual(ErrorCode.BadHeaders, message.ErrorCode); } @@ -162,7 +162,7 @@ namespace Tgstation.Server.Tests request.Headers.Add(ApiHeaders.OAuthProviderHeader, "FakeProvider"); using var response = await httpClient.SendAsync(request, cancellationToken); Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode); - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); var message = JsonConvert.DeserializeObject(content); Assert.AreEqual(ErrorCode.BadHeaders, message.ErrorCode); } @@ -179,13 +179,13 @@ namespace Tgstation.Server.Tests Encoding.UTF8.GetBytes(":"))); using var response = await httpClient.SendAsync(request, cancellationToken); Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode); - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); var message = JsonConvert.DeserializeObject(content); Assert.AreEqual(ErrorCode.BadHeaders, message.ErrorCode); } } - async Task TestServerInformation(IServerClientFactory clientFactory, IServerClient serverClient, CancellationToken cancellationToken) + static async Task TestServerInformation(IServerClientFactory clientFactory, IServerClient serverClient, CancellationToken cancellationToken) { var serverInfo = await serverClient.ServerInformation(default); @@ -209,7 +209,7 @@ namespace Tgstation.Server.Tests await Assert.ThrowsExceptionAsync(() => badClient.Administration.Read(cancellationToken)); } - async Task TestOAuthFails(IServerClient serverClient, CancellationToken cancellationToken) + static async Task TestOAuthFails(IServerClient serverClient, CancellationToken cancellationToken) { var url = serverClient.Url; var token = serverClient.Token.Bearer; @@ -230,14 +230,15 @@ namespace Tgstation.Server.Tests Assert.AreEqual(HttpStatusCode.Unauthorized, response.StatusCode); } } - async Task TestInvalidTransfers(IServerClient serverClient, CancellationToken cancellationToken) + + static async Task TestInvalidTransfers(IServerClient serverClient, CancellationToken cancellationToken) { var url = serverClient.Url; var token = serverClient.Token.Bearer; // check that 400s are returned appropriately using var httpClient = new HttpClient(); - using (var request = new HttpRequestMessage(HttpMethod.Get, url.ToString() + Routes.Transfer.Substring(1))) + using (var request = new HttpRequestMessage(HttpMethod.Get, String.Concat(url.ToString(), Routes.Transfer.AsSpan(1)))) { request.Headers.Accept.Clear(); request.Headers.UserAgent.Add(new ProductInfoHeaderValue("RootTest", "1.0.0")); @@ -246,13 +247,13 @@ namespace Tgstation.Server.Tests request.Headers.Authorization = new AuthenticationHeaderValue(ApiHeaders.BearerAuthenticationScheme, token); using var response = await httpClient.SendAsync(request, cancellationToken); Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode); - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); var message = JsonConvert.DeserializeObject(content); Assert.AreEqual(MediaTypeNames.Application.Json, response.Content.Headers.ContentType.MediaType); Assert.AreEqual(ErrorCode.ModelValidationFailure, message.ErrorCode); } - using (var request = new HttpRequestMessage(HttpMethod.Put, url.ToString() + Routes.Transfer.Substring(1))) + using (var request = new HttpRequestMessage(HttpMethod.Put, String.Concat(url.ToString(), Routes.Transfer.AsSpan(1)))) { request.Headers.Accept.Clear(); request.Headers.UserAgent.Add(new ProductInfoHeaderValue("RootTest", "1.0.0")); @@ -261,13 +262,13 @@ namespace Tgstation.Server.Tests request.Headers.Authorization = new AuthenticationHeaderValue(ApiHeaders.BearerAuthenticationScheme, token); using var response = await httpClient.SendAsync(request, cancellationToken); Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode); - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); var message = JsonConvert.DeserializeObject(content); Assert.AreEqual(MediaTypeNames.Application.Json, response.Content.Headers.ContentType.MediaType); Assert.AreEqual(ErrorCode.ModelValidationFailure, message.ErrorCode); } - using (var request = new HttpRequestMessage(HttpMethod.Get, url.ToString() + Routes.Transfer.Substring(1) + "?ticket=veryfaketicket")) + using (var request = new HttpRequestMessage(HttpMethod.Get, String.Concat(url.ToString(), Routes.Transfer.AsSpan(1), "?ticket=veryfaketicket"))) { request.Headers.Accept.Clear(); request.Headers.UserAgent.Add(new ProductInfoHeaderValue("RootTest", "1.0.0")); @@ -279,7 +280,7 @@ namespace Tgstation.Server.Tests Assert.AreEqual(HttpStatusCode.NotAcceptable, response.StatusCode); } - using (var request = new HttpRequestMessage(HttpMethod.Get, url.ToString() + Routes.Transfer.Substring(1) + "?ticket=veryfaketicket")) + using (var request = new HttpRequestMessage(HttpMethod.Get, String.Concat(url.ToString(), Routes.Transfer.AsSpan(1), "?ticket=veryfaketicket"))) { request.Headers.Accept.Clear(); request.Headers.UserAgent.Add(new ProductInfoHeaderValue("RootTest", "1.0.0")); @@ -292,7 +293,7 @@ namespace Tgstation.Server.Tests Assert.AreEqual(HttpStatusCode.Gone, response.StatusCode); } - using (var request = new HttpRequestMessage(HttpMethod.Put, url.ToString() + Routes.Transfer.Substring(1) + "?ticket=veryfaketicket")) + using (var request = new HttpRequestMessage(HttpMethod.Put, String.Concat(url.ToString(), Routes.Transfer.AsSpan(1), "?ticket=veryfaketicket"))) { request.Headers.Accept.Clear(); request.Headers.UserAgent.Add(new ProductInfoHeaderValue("RootTest", "1.0.0")); @@ -305,7 +306,7 @@ namespace Tgstation.Server.Tests } } - async Task RegressionTestForLeakedPasswordHashesBug(IServerClient serverClient, CancellationToken cancellationToken) + static async Task RegressionTestForLeakedPasswordHashesBug(IServerClient serverClient, CancellationToken cancellationToken) { // See what https://github.com/tgstation/tgstation-server/commit/6c8dc87c4af36620885b262175d7974aca2b3c2b fixed @@ -314,7 +315,7 @@ namespace Tgstation.Server.Tests // check that 400s are returned appropriately using var httpClient = new HttpClient(); - using (var request = new HttpRequestMessage(HttpMethod.Get, url.ToString() + Routes.User.Substring(1))) + using (var request = new HttpRequestMessage(HttpMethod.Get, String.Concat(url.ToString(), Routes.User.AsSpan(1)))) { request.Headers.Accept.Clear(); request.Headers.UserAgent.Add(new ProductInfoHeaderValue("RootTest", "1.0.0")); @@ -323,11 +324,11 @@ namespace Tgstation.Server.Tests request.Headers.Authorization = new AuthenticationHeaderValue(ApiHeaders.BearerAuthenticationScheme, token); using var response = await httpClient.SendAsync(request, cancellationToken); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); Assert.IsFalse(content.Contains("passwordHash")); } - using (var request = new HttpRequestMessage(HttpMethod.Get, url.ToString() + Routes.User.Substring(1) + '/' + Routes.List + "?pageSize=100")) + using (var request = new HttpRequestMessage(HttpMethod.Get, url.ToString() + Routes.User[1..] + '/' + Routes.List + "?pageSize=100")) { request.Headers.Accept.Clear(); request.Headers.UserAgent.Add(new ProductInfoHeaderValue("RootTest", "1.0.0")); @@ -336,12 +337,12 @@ namespace Tgstation.Server.Tests request.Headers.Authorization = new AuthenticationHeaderValue(ApiHeaders.BearerAuthenticationScheme, token); using var response = await httpClient.SendAsync(request, cancellationToken); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); - var content = await response.Content.ReadAsStringAsync(); + var content = await response.Content.ReadAsStringAsync(cancellationToken); Assert.IsFalse(content.Contains("passwordHash")); } } - public Task Run(IServerClientFactory clientFactory, IServerClient serverClient, CancellationToken cancellationToken) + public static Task Run(IServerClientFactory clientFactory, IServerClient serverClient, CancellationToken cancellationToken) => Task.WhenAll( TestRequestValidation(serverClient, cancellationToken), TestOAuthFails(serverClient, cancellationToken),