mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-04-10 22:35:33 +01:00
258 lines
9.6 KiB
C#
258 lines
9.6 KiB
C#
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
|
|
using Serilog.Context;
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.IO.Abstractions;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
using Tgstation.Server.Api;
|
|
using Tgstation.Server.Api.Models;
|
|
using Tgstation.Server.Host;
|
|
using Tgstation.Server.Host.Configuration;
|
|
using Tgstation.Server.Host.Core;
|
|
using Tgstation.Server.Host.Extensions;
|
|
using Tgstation.Server.Host.IO;
|
|
using Tgstation.Server.Host.Setup;
|
|
using Tgstation.Server.Host.Utils;
|
|
|
|
namespace Tgstation.Server.Tests.Live
|
|
{
|
|
sealed class LiveTestingServer : IServer, IDisposable
|
|
{
|
|
static bool needCleanup = false;
|
|
public static string BaseDirectory { get; }
|
|
|
|
static LiveTestingServer()
|
|
{
|
|
SerilogContextHelper.AddSwarmNodeIdentifierToTemplate();
|
|
BaseDirectory = Environment.GetEnvironmentVariable("TGS_TEST_TEMP_DIRECTORY");
|
|
if (string.IsNullOrWhiteSpace(BaseDirectory))
|
|
{
|
|
BaseDirectory = Path.Combine(Path.GetTempPath(), "TGS_INTEGRATION_TEST");
|
|
needCleanup = true;
|
|
}
|
|
}
|
|
|
|
static async Task Cleanup(string directory)
|
|
{
|
|
for (int i = 0; i < 5; ++i)
|
|
try
|
|
{
|
|
new DefaultIOManager(new FileSystem()).DeleteDirectory(directory, default).GetAwaiter().GetResult();
|
|
}
|
|
catch
|
|
{
|
|
GC.Collect(int.MaxValue, GCCollectionMode.Forced, false);
|
|
await Task.Delay(3000);
|
|
}
|
|
}
|
|
|
|
public Uri ApiUrl { get; }
|
|
|
|
public Uri RootUrl { get; }
|
|
|
|
public Uri OpenDreamUrl { get; }
|
|
|
|
public string Directory { get; }
|
|
|
|
public string UpdatePath { get; }
|
|
|
|
public string DatabaseType { get; }
|
|
|
|
public bool DumpOpenApiSpecpath { get; }
|
|
|
|
public bool HighPriorityDreamDaemon { get; }
|
|
public bool LowPriorityDeployments { get; }
|
|
|
|
public bool UsingBasicWatchdog { get; }
|
|
|
|
public bool RestartRequested => RealServer.RestartRequested;
|
|
|
|
readonly List<string> args;
|
|
readonly List<string> swarmArgs;
|
|
|
|
string swarmNodeId;
|
|
|
|
public IServer RealServer { get; private set; }
|
|
|
|
public LiveTestingServer(SwarmConfiguration swarmConfiguration, bool enableOAuth, ushort port = 15010)
|
|
{
|
|
if (needCleanup)
|
|
{
|
|
needCleanup = false;
|
|
Cleanup(BaseDirectory).GetAwaiter().GetResult();
|
|
}
|
|
|
|
System.Console.WriteLine($"RunningInGitHubActions: {TestingUtils.RunningInGitHubActions}");
|
|
|
|
Assert.IsTrue(port >= 10000); // for testing bridge request limit
|
|
Directory = BaseDirectory;
|
|
|
|
Directory = Path.Combine(Directory, swarmConfiguration?.Identifier ?? "default");
|
|
System.IO.Directory.CreateDirectory(Directory);
|
|
string urlString = $"http://localhost:{port}";
|
|
RootUrl = new Uri(urlString);
|
|
ApiUrl = new Uri(urlString + Routes.ApiRoot);
|
|
|
|
//so we need a db
|
|
//we have to rely on env vars
|
|
DatabaseType = Environment.GetEnvironmentVariable("TGS_TEST_DATABASE_TYPE");
|
|
var connectionString = Environment.GetEnvironmentVariable("TGS_TEST_CONNECTION_STRING");
|
|
var gitHubAccessToken = Environment.GetEnvironmentVariable("TGS_TEST_GITHUB_TOKEN");
|
|
var dumpOpenAPISpecPathEnvVar = Environment.GetEnvironmentVariable("TGS_TEST_DUMP_API_SPEC");
|
|
|
|
UsingBasicWatchdog = Boolean.TryParse(Environment.GetEnvironmentVariable("General__UseBasicWatchdog"), out var result) && result;
|
|
|
|
if (String.IsNullOrEmpty(DatabaseType))
|
|
Assert.Inconclusive("No database type configured in env var TGS_TEST_DATABASE_TYPE!");
|
|
|
|
if (String.IsNullOrEmpty(connectionString))
|
|
Assert.Inconclusive("No connection string configured in env var TGS_TEST_CONNECTION_STRING!");
|
|
|
|
if (String.IsNullOrEmpty(gitHubAccessToken))
|
|
System.Console.WriteLine("WARNING: No GitHub access token configured, test may fail due to rate limits!");
|
|
|
|
DumpOpenApiSpecpath = !String.IsNullOrEmpty(dumpOpenAPISpecPathEnvVar);
|
|
|
|
// neither of these should really matter but it's better that we test them
|
|
// high prio DD might help with some topic flakiness actually
|
|
// github doesn't allow nicing on linux though
|
|
var windows = new Host.System.PlatformIdentifier().IsWindows;
|
|
var nicingAllowed = windows || !TestingUtils.RunningInGitHubActions;
|
|
HighPriorityDreamDaemon = nicingAllowed;
|
|
LowPriorityDeployments = nicingAllowed;
|
|
|
|
var odGitDir = Environment.GetEnvironmentVariable("TGS_TEST_OD_GIT_DIRECTORY");
|
|
if (!String.IsNullOrWhiteSpace(odGitDir))
|
|
OpenDreamUrl = new Uri($"file://{Path.GetFullPath(odGitDir).Replace('\\', '/')}");
|
|
else
|
|
OpenDreamUrl = new GeneralConfiguration().OpenDreamGitUrl;
|
|
|
|
args = new List<string>()
|
|
{
|
|
String.Format(CultureInfo.InvariantCulture, "Database:DropDatabase={0}", true), // Replaced after first Run
|
|
String.Format(CultureInfo.InvariantCulture, "General:ConfigVersion={0}", GeneralConfiguration.CurrentConfigVersion),
|
|
String.Format(CultureInfo.InvariantCulture, "General:ApiPort={0}", port),
|
|
String.Format(CultureInfo.InvariantCulture, "Database:DatabaseType={0}", DatabaseType),
|
|
String.Format(CultureInfo.InvariantCulture, "Database:ConnectionString={0}", connectionString),
|
|
String.Format(CultureInfo.InvariantCulture, "General:SetupWizardMode={0}", SetupWizardMode.Never),
|
|
String.Format(CultureInfo.InvariantCulture, "General:MinimumPasswordLength={0}", 10),
|
|
String.Format(CultureInfo.InvariantCulture, "General:InstanceLimit={0}", 11),
|
|
String.Format(CultureInfo.InvariantCulture, "General:UserLimit={0}", 150),
|
|
String.Format(CultureInfo.InvariantCulture, "General:UserGroupLimit={0}", 47),
|
|
String.Format(CultureInfo.InvariantCulture, "General:HostApiDocumentation={0}", DumpOpenApiSpecpath),
|
|
String.Format(CultureInfo.InvariantCulture, "FileLogging:Directory={0}", Path.Combine(Directory, "Logs")),
|
|
String.Format(CultureInfo.InvariantCulture, "FileLogging:LogLevel={0}", "Trace"),
|
|
String.Format(CultureInfo.InvariantCulture, "FileLogging:Disable={0}", false),
|
|
String.Format(CultureInfo.InvariantCulture, "General:ValidInstancePaths:0={0}", Directory),
|
|
"General:ByondTopicTimeout=10000",
|
|
$"Session:HighPriorityLiveDreamDaemon={HighPriorityDreamDaemon}",
|
|
$"Session:LowPriorityDeploymentProcesses={LowPriorityDeployments}",
|
|
$"General:SkipAddingByondFirewallException={!TestingUtils.RunningInGitHubActions}",
|
|
$"General:OpenDreamGitUrl={OpenDreamUrl}",
|
|
$"Security:TokenExpiryMinutes=120", // timeouts are useless for us
|
|
$"General:OpenDreamSuppressInstallOutput={TestingUtils.RunningInGitHubActions}",
|
|
$"General:PrometheusPort={port}",
|
|
$"General:ByondZipDownloadTemplate={TestingUtils.ByondZipDownloadTemplate}"
|
|
};
|
|
|
|
if (MultiServerClient.UseGraphQL)
|
|
args.Add("Internal:EnableGraphQL=true");
|
|
|
|
swarmArgs = new List<string>();
|
|
if (swarmConfiguration != null)
|
|
{
|
|
UpdateSwarmArguments(swarmConfiguration);
|
|
}
|
|
|
|
// enable all oauth providers
|
|
if (enableOAuth)
|
|
foreach (var I in Enum.GetValues(typeof(OAuthProvider)))
|
|
{
|
|
args.Add($"Security:OAuth:{I}:ClientId=Fake");
|
|
args.Add($"Security:OAuth:{I}:ClientSecret=Faker");
|
|
args.Add($"Security:OAuth:{I}:RedirectUrl=https://fakest.com");
|
|
args.Add($"Security:OAuth:{I}:ServerUrl=https://fakestest.com");
|
|
}
|
|
else
|
|
args.Add($"Security:OAuth=null");
|
|
|
|
// SPECIFICALLY DELETE THE DEV APPSETTINGS, WE DON'T WANT IT IN THE WAY
|
|
File.Delete("appsettings.Development.yml");
|
|
File.Delete("appsettings.Development.json");
|
|
|
|
if (!string.IsNullOrEmpty(gitHubAccessToken))
|
|
args.Add(string.Format(CultureInfo.InvariantCulture, "General:GitHubAccessToken={0}", gitHubAccessToken));
|
|
|
|
if (DumpOpenApiSpecpath)
|
|
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
|
|
|
|
UpdatePath = Path.Combine(Directory, Guid.NewGuid().ToString());
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
}
|
|
|
|
public void UpdateSwarmArguments(SwarmConfiguration swarmConfiguration)
|
|
{
|
|
swarmArgs.Clear();
|
|
swarmArgs.Add($"Swarm:PrivateKey={swarmConfiguration.PrivateKey}");
|
|
swarmArgs.Add($"Swarm:Identifier={swarmConfiguration.Identifier}");
|
|
swarmArgs.Add($"Swarm:Address={swarmConfiguration.Address}");
|
|
swarmArgs.Add($"Swarm:PublicAddress={swarmConfiguration.PublicAddress}");
|
|
if (swarmConfiguration.ControllerAddress != null)
|
|
swarmArgs.Add($"Swarm:ControllerAddress={swarmConfiguration.ControllerAddress}");
|
|
|
|
if (swarmConfiguration.UpdateRequiredNodeCount != 0)
|
|
swarmArgs.Add($"Swarm:UpdateRequiredNodeCount={swarmConfiguration.UpdateRequiredNodeCount}");
|
|
|
|
swarmNodeId = swarmConfiguration.Identifier;
|
|
}
|
|
|
|
public async ValueTask RunNoArgumentsTest(CancellationToken cancellationToken)
|
|
{
|
|
Assert.IsNull(Environment.GetEnvironmentVariable("General:SetupWizardMode"));
|
|
Environment.SetEnvironmentVariable("General:SetupWizardMode", "Never");
|
|
await Application
|
|
.CreateDefaultServerFactory()
|
|
.CreateServer(
|
|
Array.Empty<string>(),
|
|
UpdatePath,
|
|
cancellationToken);
|
|
Environment.SetEnvironmentVariable("General:SetupWizardMode", null);
|
|
}
|
|
|
|
public async ValueTask Run(CancellationToken cancellationToken)
|
|
{
|
|
var messageAddition = swarmNodeId != null ? $": {swarmNodeId}" : String.Empty;
|
|
System.Console.WriteLine("TEST SERVER START" + messageAddition);
|
|
var firstRun = RealServer == null;
|
|
var arrayArgs = args.Concat(swarmArgs).ToArray();
|
|
RealServer = await Application
|
|
.CreateDefaultServerFactory()
|
|
.CreateServer(
|
|
arrayArgs,
|
|
UpdatePath,
|
|
cancellationToken);
|
|
|
|
if (firstRun)
|
|
args[0] = string.Format(CultureInfo.InvariantCulture, "Database:DropDatabase={0}", false);
|
|
|
|
var swarmMode = swarmNodeId != null;
|
|
ApplicationBuilderExtensions.LogSwarmIdentifier = swarmMode;
|
|
using (swarmMode
|
|
? LogContext.PushProperty(SerilogContextHelper.SwarmIdentifierContextProperty, swarmNodeId)
|
|
: null)
|
|
await RealServer.Run(cancellationToken);
|
|
System.Console.WriteLine($"TEST SERVER END" + messageAddition);
|
|
}
|
|
}
|
|
}
|