diff --git a/src/Tgstation.Server.Host/Server.cs b/src/Tgstation.Server.Host/Server.cs index f4e6c195b7..0a3ca3b007 100644 --- a/src/Tgstation.Server.Host/Server.cs +++ b/src/Tgstation.Server.Host/Server.cs @@ -34,6 +34,11 @@ namespace Tgstation.Server.Host updatePath != null; #endif + /// + /// The of the running server. + /// + internal IHost Host { get; private set; } + /// /// The for the . /// @@ -119,26 +124,35 @@ namespace Tgstation.Server.Host fsWatcher.EnableRaisingEvents = true; } - using var host = hostBuilder.Build(); try { - swarmService = host.Services.GetRequiredService(); - logger = host.Services.GetRequiredService>(); - using (cancellationToken.Register(() => logger.LogInformation("Server termination requested!"))) + using (Host = hostBuilder.Build()) { - var generalConfigurationOptions = host.Services.GetRequiredService>(); - generalConfiguration = generalConfigurationOptions.Value; - await host.RunAsync(cancellationTokenSource.Token); + try + { + swarmService = Host.Services.GetRequiredService(); + logger = Host.Services.GetRequiredService>(); + using (cancellationToken.Register(() => logger.LogInformation("Server termination requested!"))) + { + var generalConfigurationOptions = Host.Services.GetRequiredService>(); + generalConfiguration = generalConfigurationOptions.Value; + await Host.RunAsync(cancellationTokenSource.Token); + } + } + catch (OperationCanceledException ex) + { + logger?.LogDebug(ex, "Server run cancelled!"); + } + catch (Exception ex) + { + CheckExceptionPropagation(ex); + throw; + } } } - catch (OperationCanceledException ex) + finally { - logger?.LogDebug(ex, "Server run cancelled!"); - } - catch (Exception ex) - { - CheckExceptionPropagation(ex); - throw; + Host = null; } } diff --git a/tests/Tgstation.Server.Tests/Instance/InstanceTest.cs b/tests/Tgstation.Server.Tests/Instance/InstanceTest.cs index 0c20e778a4..ebd46b7bea 100644 --- a/tests/Tgstation.Server.Tests/Instance/InstanceTest.cs +++ b/tests/Tgstation.Server.Tests/Instance/InstanceTest.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Tgstation.Server.Client; using Tgstation.Server.Client.Components; +using Tgstation.Server.Host.Components; namespace Tgstation.Server.Tests.Instance { @@ -11,11 +12,13 @@ namespace Tgstation.Server.Tests.Instance { readonly IInstanceClient instanceClient; readonly IInstanceManagerClient instanceManagerClient; + readonly IInstanceManager instanceManager; - public InstanceTest(IInstanceClient instanceClient, IInstanceManagerClient instanceManagerClient) + public InstanceTest(IInstanceClient instanceClient, IInstanceManagerClient instanceManagerClient, IInstanceManager instanceManager) { this.instanceClient = instanceClient ?? throw new ArgumentNullException(nameof(instanceClient)); this.instanceManagerClient = instanceManagerClient ?? throw new ArgumentNullException(nameof(instanceManagerClient)); + this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager)); } public async Task RunTests(CancellationToken cancellationToken) @@ -35,7 +38,7 @@ namespace Tgstation.Server.Tests.Instance await configTest.Run(cancellationToken); await chatTests; await repoTests; - await new WatchdogTest(instanceClient).Run(cancellationToken); + await new WatchdogTest(instanceClient, instanceManager).Run(cancellationToken); } } } diff --git a/tests/Tgstation.Server.Tests/Instance/WatchdogTest.cs b/tests/Tgstation.Server.Tests/Instance/WatchdogTest.cs index 1c350fda37..0ff9495638 100644 --- a/tests/Tgstation.Server.Tests/Instance/WatchdogTest.cs +++ b/tests/Tgstation.Server.Tests/Instance/WatchdogTest.cs @@ -1,8 +1,11 @@ using Byond.TopicSender; + using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; + using System; +using System.Globalization; using System.IO; using System.Linq; using System.Net; @@ -17,7 +20,9 @@ using Tgstation.Server.Api.Models.Request; 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.Interop; +using Tgstation.Server.Host.Components.Watchdog; using Tgstation.Server.Host.Extensions; using Tgstation.Server.Host.IO; using Tgstation.Server.Host.System; @@ -27,13 +32,15 @@ namespace Tgstation.Server.Tests.Instance sealed class WatchdogTest : JobsRequiredTest { readonly IInstanceClient instanceClient; + readonly IInstanceManager instanceManager; bool ranTimeoutTest = false; - public WatchdogTest(IInstanceClient instanceClient) + public WatchdogTest(IInstanceClient instanceClient, IInstanceManager instanceManager) : base(instanceClient.Jobs) { this.instanceClient = instanceClient ?? throw new ArgumentNullException(nameof(instanceClient)); + this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager)); } public async Task Run(CancellationToken cancellationToken) @@ -66,6 +73,9 @@ namespace Tgstation.Server.Tests.Instance await TestDMApiFreeDeploy(cancellationToken); await RunLongRunningTestThenUpdate(cancellationToken); + + await GhettoChatCommandTest(cancellationToken); + await RunLongRunningTestThenUpdateWithNewDme(cancellationToken); await RunLongRunningTestThenUpdateWithByondVersionSwitch(cancellationToken); @@ -318,6 +328,63 @@ namespace Tgstation.Server.Tests.Instance return await instanceClient.DreamDaemon.Start(cancellationToken); } + async Task GhettoChatCommandTest(CancellationToken cancellationToken) + { + var startJob = await StartDD(cancellationToken); + + await WaitForJob(startJob, 40, false, null, cancellationToken); + + // oh god, oh fuck, blackbox testing + using var instanceReference = instanceManager.GetInstanceReference(instanceClient.Metadata); + + var startTime = DateTimeOffset.UtcNow - TimeSpan.FromSeconds(5); + var response = await ((BasicWatchdog)instanceReference.Watchdog).HandleChatCommand( + "embeds_test", + String.Empty, + new Host.Components.Chat.ChatUser + { + Channel = new Host.Components.Chat.ChannelRepresentation + { + IsAdminChannel = true, + ConnectionName = "test_connection", + EmbedsSupported = true, + FriendlyName = "Test Connection", + Id = "test_channel_id", + IsPrivateChannel = false, + }, + FriendlyName = "Test Sender", + Id = "test_user_id", + Mention = "test_user_mention", + RealId = 1234, + }, + cancellationToken); + var endTime = DateTimeOffset.UtcNow + TimeSpan.FromSeconds(5); + + Assert.IsNotNull(response); + Assert.AreEqual("Embed support test2", response.Text); + Assert.AreEqual("desc", response.Embed.Description); + Assert.AreEqual("title", response.Embed.Title); + Assert.AreEqual("#0000FF", response.Embed.Colour); + Assert.AreEqual("Dominion", response.Embed.Author?.Name); + Assert.AreEqual("https://github.com/Cyberboss", response.Embed.Author.Url); + Assert.IsTrue(DateTimeOffset.TryParse(response.Embed.Timestamp, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var timestamp)); + Assert.IsTrue(startTime < timestamp && endTime > timestamp); + Assert.AreEqual("https://github.com/tgstation/tgstation-server", response.Embed.Url); + Assert.AreEqual(3, response.Embed.Fields?.Count); + Assert.AreEqual("field1", response.Embed.Fields.ElementAt(0).Name); + Assert.AreEqual("value1", response.Embed.Fields.ElementAt(0).Value); + Assert.IsNull(response.Embed.Fields.ElementAt(0).IsInline); + Assert.AreEqual("field2", response.Embed.Fields.ElementAt(1).Name); + Assert.AreEqual("value2", response.Embed.Fields.ElementAt(1).Value); + Assert.IsTrue(response.Embed.Fields.ElementAt(1).IsInline); + Assert.AreEqual("field3", response.Embed.Fields.ElementAt(2).Name); + Assert.AreEqual("value3", response.Embed.Fields.ElementAt(2).Value); + Assert.IsTrue(response.Embed.Fields.ElementAt(2).IsInline); + Assert.AreEqual("Footer text", response.Embed.Footer?.Text); + + await instanceClient.DreamDaemon.Shutdown(cancellationToken); + } + async Task RunLongRunningTestThenUpdate(CancellationToken cancellationToken) { global::System.Console.WriteLine("TEST: WATCHDOG LONG RUNNING WITH UPDATE TEST"); diff --git a/tests/Tgstation.Server.Tests/IntegrationTest.cs b/tests/Tgstation.Server.Tests/IntegrationTest.cs index f45fef48bc..f14acea7be 100644 --- a/tests/Tgstation.Server.Tests/IntegrationTest.cs +++ b/tests/Tgstation.Server.Tests/IntegrationTest.cs @@ -27,6 +27,8 @@ using Tgstation.Server.Api.Models.Response; using Tgstation.Server.Api.Rights; using Tgstation.Server.Client; using Tgstation.Server.Client.Components; +using Tgstation.Server.Host; +using Tgstation.Server.Host.Components; using Tgstation.Server.Host.Components.Events; using Tgstation.Server.Host.Components.Repository; using Tgstation.Server.Host.Configuration; @@ -827,6 +829,8 @@ namespace Tgstation.Server.Tests TerminateAllDDs(); + IInstanceManager GetInstanceManager() => ((Host.Server)server.RealServer).Host.Services.GetRequiredService(); + // main run var serverTask = server.Run(cancellationToken); @@ -874,7 +878,7 @@ namespace Tgstation.Server.Tests Assert.IsTrue(Directory.Exists(instanceClient.Metadata.Path)); - var instanceTests = FailFast(new InstanceTest(instanceClient, adminClient.Instances).RunTests(cancellationToken)); + var instanceTests = FailFast(new InstanceTest(instanceClient, adminClient.Instances, GetInstanceManager()).RunTests(cancellationToken)); await Task.WhenAll(rootTest, adminTest, instanceTests, usersTest); @@ -994,7 +998,7 @@ namespace Tgstation.Server.Tests Assert.AreEqual(WatchdogStatus.Online, dd.Status.Value); var compileJob = await instanceClient.DreamMaker.Compile(cancellationToken); - var wdt = new WatchdogTest(instanceClient); + var wdt = new WatchdogTest(instanceClient, GetInstanceManager()); await wdt.WaitForJob(compileJob, 30, false, null, cancellationToken); dd = await instanceClient.DreamDaemon.Read(cancellationToken); @@ -1041,7 +1045,7 @@ namespace Tgstation.Server.Tests Assert.AreEqual(WatchdogStatus.Online, currentDD.Status); Assert.AreEqual(expectedStaged, currentDD.StagedCompileJob.Job.Id.Value); - var wdt = new WatchdogTest(instanceClient); + var wdt = new WatchdogTest(instanceClient, GetInstanceManager()); currentDD = await wdt.TellWorldToReboot(cancellationToken); Assert.AreEqual(expectedStaged, currentDD.ActiveCompileJob.Job.Id.Value); Assert.IsNull(currentDD.StagedCompileJob); diff --git a/tests/Tgstation.Server.Tests/TestingServer.cs b/tests/Tgstation.Server.Tests/TestingServer.cs index 3490255754..d653bcdb00 100644 --- a/tests/Tgstation.Server.Tests/TestingServer.cs +++ b/tests/Tgstation.Server.Tests/TestingServer.cs @@ -27,11 +27,11 @@ namespace Tgstation.Server.Tests public bool DumpOpenApiSpecpath { get; } - public bool RestartRequested => realServer.RestartRequested; + public bool RestartRequested => RealServer.RestartRequested; string[] args; - IServer realServer; + public IServer RealServer { get; private set; } public TestingServer(SwarmConfiguration swarmConfiguration, bool enableOAuth, ushort port = 5010) { @@ -154,8 +154,8 @@ namespace Tgstation.Server.Tests public async Task Run(CancellationToken cancellationToken) { Console.WriteLine("TEST SERVER START"); - var firstRun = realServer == null; - realServer = await Application + var firstRun = RealServer == null; + RealServer = await Application .CreateDefaultServerFactory() .CreateServer( args, @@ -169,7 +169,8 @@ namespace Tgstation.Server.Tests args = tmp.ToArray(); } - await realServer.Run(cancellationToken); + await RealServer.Run(cancellationToken); + RealServer = null; Console.WriteLine("TEST SERVER END"); } }