mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-22 12:37:24 +01:00
Add tests for RepositoryFactory
This commit is contained in:
@@ -250,12 +250,21 @@ namespace Tgstation.Server.Host.Components
|
||||
throw;
|
||||
}
|
||||
}
|
||||
#pragma warning restore CA1506
|
||||
#pragma warning restore CA1506
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task StartAsync(CancellationToken cancellationToken) => byondInstaller.CleanCache(cancellationToken);
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
CheckSystemCompatibility();
|
||||
return byondInstaller.CleanCache(cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
/// Test that the <see cref="repositoryFactory"/> is functional.
|
||||
/// </summary>
|
||||
private void CheckSystemCompatibility() => repositoryFactory.CreateInMemory().Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ using Tgstation.Server.Host.Core;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.IO;
|
||||
using Tgstation.Server.Host.Jobs;
|
||||
using Tgstation.Server.Host.Security;
|
||||
using Tgstation.Server.Host.System;
|
||||
|
||||
namespace Tgstation.Server.Host.Components
|
||||
@@ -52,6 +53,11 @@ namespace Tgstation.Server.Host.Components
|
||||
/// </summary>
|
||||
readonly IPlatformIdentifier platformIdentifier;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ISystemIdentityFactory"/> for the <see cref="InstanceManager"/>
|
||||
/// </summary>
|
||||
readonly ISystemIdentityFactory systemIdentityFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> for the <see cref="InstanceManager"/>
|
||||
/// </summary>
|
||||
@@ -82,6 +88,7 @@ namespace Tgstation.Server.Host.Components
|
||||
/// <param name="jobManager">The value of <see cref="jobManager"/></param>
|
||||
/// <param name="serverControl">The value of <see cref="serverControl"/></param>
|
||||
/// <param name="platformIdentifier">The value of <see cref="platformIdentifier"/>.</param>
|
||||
/// <param name="systemIdentityFactory">The value of <see cref="systemIdentityFactory"/>.</param>
|
||||
/// <param name="logger">The value of <see cref="logger"/></param>
|
||||
public InstanceManager(
|
||||
IInstanceFactory instanceFactory,
|
||||
@@ -91,6 +98,7 @@ namespace Tgstation.Server.Host.Components
|
||||
IJobManager jobManager,
|
||||
IServerControl serverControl,
|
||||
IPlatformIdentifier platformIdentifier,
|
||||
ISystemIdentityFactory systemIdentityFactory,
|
||||
ILogger<InstanceManager> logger)
|
||||
{
|
||||
this.instanceFactory = instanceFactory ?? throw new ArgumentNullException(nameof(instanceFactory));
|
||||
@@ -100,6 +108,7 @@ namespace Tgstation.Server.Host.Components
|
||||
this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
|
||||
this.serverControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl));
|
||||
this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
|
||||
this.systemIdentityFactory = systemIdentityFactory ?? throw new ArgumentNullException(nameof(systemIdentityFactory));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
serverControl.RegisterForRestart(this);
|
||||
@@ -228,7 +237,7 @@ namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
try
|
||||
{
|
||||
platformIdentifier.CheckCompatibility();
|
||||
CheckSystemCompatibility();
|
||||
var factoryStartup = instanceFactory.StartAsync(cancellationToken);
|
||||
await databaseContext.Initialize(cancellationToken).ConfigureAwait(false);
|
||||
await jobManager.StartAsync(cancellationToken).ConfigureAwait(false);
|
||||
@@ -283,5 +292,15 @@ namespace Tgstation.Server.Host.Components
|
||||
downgradeVersion = updateVersion != null && updateVersion < application.Version ? updateVersion : null;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check we have a valid system identity.
|
||||
/// </summary>
|
||||
private void CheckSystemCompatibility()
|
||||
{
|
||||
using var systemIdentity = systemIdentityFactory.GetCurrent();
|
||||
if (!systemIdentity.CanCreateSymlinks)
|
||||
throw new InvalidOperationException("The user running tgstation-server cannot create symlinks! Please try running as an administrative user!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
progressReporter(50 + ((int)(50 * ((float)sentBytes) / totalBytes)));
|
||||
return !cancellationToken.IsCancellationRequested;
|
||||
},
|
||||
CredentialsProvider = credentialsProvider.GenerateHandler(username, password)
|
||||
CredentialsProvider = credentialsProvider.GenerateCredentialsHandler(username, password)
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -262,7 +262,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
return !cancellationToken.IsCancellationRequested;
|
||||
},
|
||||
OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
|
||||
CredentialsProvider = credentialsProvider.GenerateHandler(username, password)
|
||||
CredentialsProvider = credentialsProvider.GenerateCredentialsHandler(username, password)
|
||||
}, logMessage);
|
||||
}
|
||||
catch (UserCancelledException) { }
|
||||
@@ -375,7 +375,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
return !cancellationToken.IsCancellationRequested;
|
||||
},
|
||||
OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
|
||||
CredentialsProvider = credentialsProvider.GenerateHandler(username, password)
|
||||
CredentialsProvider = credentialsProvider.GenerateCredentialsHandler(username, password)
|
||||
}, "Fetch origin commits");
|
||||
}
|
||||
catch (UserCancelledException)
|
||||
|
||||
@@ -70,11 +70,12 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
ILogger<RepositoryManager> logger,
|
||||
RepositorySettings repositorySettings)
|
||||
{
|
||||
this.repositorySettings = repositorySettings ?? throw new ArgumentNullException(nameof(repositorySettings));
|
||||
this.repositoryFactory = repositoryFactory ?? throw new ArgumentNullException(nameof(repositoryFactory));
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
|
||||
this.repositoryLogger = repositoryLogger ?? throw new ArgumentNullException(nameof(repositoryLogger));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
this.repositorySettings = repositorySettings ?? throw new ArgumentNullException(nameof(repositorySettings));
|
||||
semaphore = new SemaphoreSlim(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,5 @@
|
||||
/// The extension of executable script files for the system
|
||||
/// </summary>
|
||||
string ScriptFileExtension { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Check if the system is capable of running tgstation-server.
|
||||
/// </summary>
|
||||
void CheckCompatibility();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Tgstation.Server.Host.Components.Repository;
|
||||
using Tgstation.Server.Host.Security;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Tgstation.Server.Host.System
|
||||
{
|
||||
@@ -15,56 +11,13 @@ namespace Tgstation.Server.Host.System
|
||||
/// <inheritdoc />
|
||||
public string ScriptFileExtension { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ISystemIdentityFactory"/> for the <see cref="PlatformIdentifier"/>.
|
||||
/// </summary>
|
||||
readonly ISystemIdentityFactory systemIdentityFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IRepositoryFactory"/> for the <see cref="PlatformIdentifier"/>.
|
||||
/// </summary>
|
||||
readonly IRepositoryFactory repositoryFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> for the <see cref="PlatformIdentifier"/>.
|
||||
/// </summary>
|
||||
readonly ILogger<PlatformIdentifier> logger;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="PlatformIdentifier"/>
|
||||
/// </summary>
|
||||
/// <param name="systemIdentityFactory">The value of <see cref="systemIdentityFactory"/>.</param>
|
||||
/// <param name="repositoryFactory">The value of <see cref="repositoryFactory"/>.</param>
|
||||
/// <param name="logger">The value of <see cref="logger"/>.</param>
|
||||
public PlatformIdentifier(
|
||||
ISystemIdentityFactory systemIdentityFactory,
|
||||
IRepositoryFactory repositoryFactory,
|
||||
ILogger<PlatformIdentifier> logger)
|
||||
public PlatformIdentifier()
|
||||
{
|
||||
this.systemIdentityFactory = systemIdentityFactory ?? throw new ArgumentNullException(nameof(systemIdentityFactory));
|
||||
this.repositoryFactory = repositoryFactory ?? throw new ArgumentNullException(nameof(repositoryFactory));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
||||
ScriptFileExtension = IsWindows ? "bat" : "sh";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void CheckCompatibility()
|
||||
{
|
||||
try
|
||||
{
|
||||
repositoryFactory.CreateInMemory().Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
logger.LogCritical("Unable to initialize libgit2! This is a common problem on POSIX installations. Try using Docker.");
|
||||
throw;
|
||||
}
|
||||
|
||||
using var systemIdentity = systemIdentityFactory.GetCurrent();
|
||||
if (!systemIdentity.CanCreateSymlinks)
|
||||
throw new InvalidOperationException("The user running tgstation-server cannot create symlinks! Please try running as an administrative user!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
using LibGit2Sharp;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Tgstation.Server.Host.Components.Repository.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for <see cref="RepositoryFactory"/>.
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public sealed class TestRepositoryFactory
|
||||
{
|
||||
static IRepositoryFactory CreateFactory() => new RepositoryFactory(Mock.Of<ILogger<RepositoryFactory>>());
|
||||
|
||||
static Task<LibGit2Sharp.IRepository> TestRepoLoading(
|
||||
string path,
|
||||
IRepositoryFactory repositoryFactory = null) =>
|
||||
(repositoryFactory ?? CreateFactory())
|
||||
.CreateFromPath(path, default);
|
||||
|
||||
[TestMethod]
|
||||
public void TestConstructionThrows() => Assert.ThrowsException<ArgumentNullException>(() => new RepositoryFactory(null));
|
||||
|
||||
[TestMethod]
|
||||
public void TestInMemoryRepoCreation()
|
||||
{
|
||||
using var repo = new RepositoryFactory(Mock.Of<ILogger<RepositoryFactory>>()).CreateInMemory();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task TestLoadedRepoCreation()
|
||||
{
|
||||
using var repo = await TestRepoLoading(Path.GetFullPath("../../../../.."));
|
||||
|
||||
// Checking the commit previous to the one that creates this function exists
|
||||
var gitObject = repo.Lookup("4802806bdccee27cb3d5fa8c2d0dfbdc117fdb4d");
|
||||
Assert.IsNotNull(gitObject);
|
||||
var commit = gitObject.Peel<Commit>();
|
||||
|
||||
Assert.AreEqual("Cleanup repository management code", commit.Message.Trim());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task TestCloning()
|
||||
{
|
||||
var tempDir = Path.GetTempFileName();
|
||||
File.Delete(tempDir);
|
||||
try
|
||||
{
|
||||
var factory = CreateFactory();
|
||||
await factory.Clone(
|
||||
new Uri("https://github.com/Cyberboss/Test"),
|
||||
new CloneOptions
|
||||
{
|
||||
CredentialsProvider = factory.GenerateCredentialsHandler(null, null)
|
||||
},
|
||||
tempDir,
|
||||
default);
|
||||
|
||||
using (var repo = await TestRepoLoading(tempDir))
|
||||
{
|
||||
var gitObject = repo.Lookup("f636418bf47d238d33b0e4a34f0072b23a8aad0e");
|
||||
Assert.IsNotNull(gitObject);
|
||||
var commit = gitObject.Peel<Commit>();
|
||||
|
||||
Assert.AreEqual("Update Test.md", commit.Message);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Takes a while to release the repo handle sometimes...
|
||||
for (var i = 0; i < 5; ++i)
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempDir, true);
|
||||
break;
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user