mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-29 08:00:19 +01:00
201 lines
8.5 KiB
C#
201 lines
8.5 KiB
C#
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Tgstation.Server.Api.Models;
|
|
using Tgstation.Server.Api.Rights;
|
|
using Tgstation.Server.Client;
|
|
using Tgstation.Server.Host.Controllers;
|
|
|
|
namespace Tgstation.Server.Tests
|
|
{
|
|
sealed class InstanceManagerTest
|
|
{
|
|
public const string TestInstanceName = "IntegrationTestInstance";
|
|
|
|
readonly IInstanceManagerClient instanceManagerClient;
|
|
readonly IUsersClient usersClient;
|
|
readonly string testRootPath;
|
|
|
|
public InstanceManagerTest(IInstanceManagerClient instanceManagerClient, IUsersClient usersClient, string testRootPath)
|
|
{
|
|
this.instanceManagerClient = instanceManagerClient ?? throw new ArgumentNullException(nameof(instanceManagerClient));
|
|
this.usersClient = usersClient ?? throw new ArgumentNullException(nameof(usersClient));
|
|
this.testRootPath = testRootPath ?? throw new ArgumentNullException(nameof(testRootPath));
|
|
}
|
|
|
|
public Task<Api.Models.Instance> CreateTestInstance(CancellationToken cancellationToken) => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
|
|
{
|
|
Name = TestInstanceName,
|
|
Path = Path.Combine(testRootPath, Guid.NewGuid().ToString()),
|
|
Online = true,
|
|
ChatBotLimit = 2
|
|
}, cancellationToken);
|
|
|
|
public async Task<Api.Models.Instance> RunPreInstanceTest(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));
|
|
|
|
var firstClient = instanceManagerClient.CreateClient(firstTest);
|
|
await ApiAssert.ThrowsException<ConflictException>(() => firstClient.DreamDaemon.Start(cancellationToken), ErrorCode.InstanceOffline);
|
|
|
|
//cant create instances in existent directories
|
|
var testNonEmpty = Path.Combine(testRootPath, Guid.NewGuid().ToString());
|
|
Directory.CreateDirectory(testNonEmpty);
|
|
var testFile = Path.Combine(testNonEmpty, "asdf");
|
|
await File.WriteAllBytesAsync(testFile, Array.Empty<byte>(), cancellationToken).ConfigureAwait(false);
|
|
await ApiAssert.ThrowsException<ConflictException>(() => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
|
|
{
|
|
Path = testNonEmpty,
|
|
Name = "NonEmptyTest"
|
|
}, cancellationToken), ErrorCode.InstanceAtExistingPath).ConfigureAwait(false);
|
|
|
|
//check it works for truly empty directories
|
|
File.Delete(testFile);
|
|
var secondTry = await instanceManagerClient.CreateOrAttach(new Api.Models.Instance
|
|
{
|
|
Path = Path.Combine(testRootPath, Guid.NewGuid().ToString()),
|
|
Name = "NonEmptyTest"
|
|
}, cancellationToken).ConfigureAwait(false);
|
|
|
|
await Assert.ThrowsExceptionAsync<ConflictException>(() => instanceManagerClient.CreateOrAttach(firstTest, cancellationToken)).ConfigureAwait(false);
|
|
Assert.IsTrue(Directory.Exists(firstTest.Path));
|
|
|
|
//can't create instances in installation directory
|
|
await ApiAssert.ThrowsException<ConflictException>(() => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
|
|
{
|
|
Path = "./A/Local/Path",
|
|
Name = "NoInstallDirTest"
|
|
}, cancellationToken), ErrorCode.InstanceAtConflictingPath).ConfigureAwait(false);
|
|
|
|
//can't create instances as children of other instances
|
|
await ApiAssert.ThrowsException<ConflictException>(() => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
|
|
{
|
|
Path = Path.Combine(firstTest.Path, "subdir"),
|
|
Name = "NoOtherInstanceDirTest"
|
|
}, cancellationToken), ErrorCode.InstanceAtConflictingPath).ConfigureAwait(false);
|
|
Assert.IsTrue(Directory.Exists(firstTest.Path));
|
|
|
|
//can't move to existent directories
|
|
await ApiAssert.ThrowsException<ConflictException>(() => instanceManagerClient.Update(new Api.Models.Instance
|
|
{
|
|
Id = firstTest.Id,
|
|
Path = testNonEmpty
|
|
}, cancellationToken), ErrorCode.InstanceAtExistingPath).ConfigureAwait(false);
|
|
|
|
// test can't create instance outside of whitelist
|
|
await ApiAssert.ThrowsException<ApiConflictException>(() => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
|
|
{
|
|
Name = "TestInstanceOutsideOfWhitelist",
|
|
Path = Path.Combine(testRootPath, "..", Guid.NewGuid().ToString()),
|
|
Online = true,
|
|
ChatBotLimit = 1
|
|
}, cancellationToken), ErrorCode.InstanceNotAtWhitelistedPath);
|
|
|
|
//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);
|
|
Assert.IsTrue(Directory.Exists(firstTest.Path));
|
|
|
|
//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);
|
|
Assert.IsTrue(Directory.Exists(firstTest.Path));
|
|
|
|
//can't move online instance
|
|
await ApiAssert.ThrowsException<ConflictException>(() => instanceManagerClient.Update(new Api.Models.Instance
|
|
{
|
|
Id = firstTest.Id,
|
|
Path = initialPath
|
|
}, cancellationToken), ErrorCode.InstanceRelocateOnline).ConfigureAwait(false);
|
|
Assert.IsTrue(Directory.Exists(firstTest.Path));
|
|
|
|
return firstTest;
|
|
}
|
|
|
|
public async Task RunPostTest(CancellationToken cancellationToken)
|
|
{
|
|
var instances = await instanceManagerClient.List(null, cancellationToken);
|
|
var firstTest = instances.Single(x => x.Name == TestInstanceName);
|
|
var instanceClient = instanceManagerClient.CreateClient(firstTest);
|
|
|
|
//can regain permissions on instance without instance user
|
|
var ourInstanceUser = await instanceClient.PermissionSets.Read(cancellationToken).ConfigureAwait(false);
|
|
await instanceClient.PermissionSets.Delete(ourInstanceUser, cancellationToken).ConfigureAwait(false);
|
|
|
|
await Assert.ThrowsExceptionAsync<InsufficientPermissionsException>(() => instanceClient.PermissionSets.Read(cancellationToken)).ConfigureAwait(false);
|
|
|
|
await instanceManagerClient.GrantPermissions(new Api.Models.Instance
|
|
{
|
|
Id = firstTest.Id
|
|
}, cancellationToken).ConfigureAwait(false);
|
|
ourInstanceUser = await instanceClient.PermissionSets.Read(cancellationToken).ConfigureAwait(false);
|
|
|
|
Assert.AreEqual(RightsHelper.AllRights<DreamDaemonRights>(), ourInstanceUser.DreamDaemonRights.Value);
|
|
|
|
//can't detach online instance
|
|
await ApiAssert.ThrowsException<ConflictException>(() => instanceManagerClient.Detach(firstTest, cancellationToken), ErrorCode.InstanceDetachOnline).ConfigureAwait(false);
|
|
|
|
firstTest.Online = false;
|
|
firstTest = await instanceManagerClient.Update(firstTest, cancellationToken).ConfigureAwait(false);
|
|
|
|
await instanceManagerClient.Detach(firstTest, cancellationToken).ConfigureAwait(false);
|
|
|
|
var attachPath = Path.Combine(firstTest.Path, InstanceController.InstanceAttachFileName);
|
|
Assert.IsTrue(File.Exists(attachPath));
|
|
|
|
//can recreate detached instance
|
|
firstTest = await instanceManagerClient.CreateOrAttach(firstTest, cancellationToken).ConfigureAwait(false);
|
|
|
|
// Test updating only with SetChatBotLimit works
|
|
var current = await usersClient.Read(cancellationToken);
|
|
var update = new UserUpdate
|
|
{
|
|
Id = current.Id,
|
|
PermissionSet = new PermissionSet
|
|
{
|
|
InstanceManagerRights = InstanceManagerRights.SetChatBotLimit,
|
|
AdministrationRights = RightsHelper.AllRights<AdministrationRights>()
|
|
}
|
|
};
|
|
await usersClient.Update(update, cancellationToken);
|
|
var update2 = new Api.Models.Instance
|
|
{
|
|
Id = firstTest.Id,
|
|
ChatBotLimit = 77
|
|
};
|
|
var newThing = await instanceManagerClient.Update(update2, cancellationToken);
|
|
|
|
update.PermissionSet.InstanceManagerRights |= InstanceManagerRights.Delete | InstanceManagerRights.Create | InstanceManagerRights.List;
|
|
await usersClient.Update(update, cancellationToken);
|
|
|
|
//but only if the attach file exists
|
|
await instanceManagerClient.Detach(firstTest, cancellationToken).ConfigureAwait(false);
|
|
File.Delete(attachPath);
|
|
await ApiAssert.ThrowsException<ConflictException>(() => instanceManagerClient.CreateOrAttach(firstTest, cancellationToken), ErrorCode.InstanceAtExistingPath).ConfigureAwait(false);
|
|
}
|
|
}
|
|
}
|