wabbajack/Wabbajack.Server.Test/ABuildServerSystemTest.cs

268 lines
8.9 KiB
C#
Raw Normal View History

using System;
2020-05-19 03:46:33 +00:00
using System.Collections.Generic;
using System.IO.Compression;
using System.Reactive.Linq;
2020-05-19 03:46:33 +00:00
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Wabbajack.Common;
using Wabbajack.Common.Http;
using Wabbajack.Common.StatusFeed;
2020-05-19 03:46:33 +00:00
using Wabbajack.Lib;
using Wabbajack.Lib.Downloaders;
2020-04-08 04:19:36 +00:00
using Wabbajack.Lib.FileUploader;
2020-05-19 03:46:33 +00:00
using Wabbajack.Lib.ModListRegistry;
using Wabbajack.Server;
using Wabbajack.Server.DataLayer;
using Xunit;
using Xunit.Abstractions;
namespace Wabbajack.BuildServer.Test
{
public class BuildServerFixture : ADBTest, IDisposable
{
private IHost _host;
private CancellationTokenSource _token;
private Task _task;
public readonly TempFolder _severTempFolder = TempFolder.Create().Result;
2020-04-03 22:33:19 +00:00
private bool _disposed = false;
public AbsolutePath ServerTempFolder => _severTempFolder.Dir;
2020-04-08 04:19:36 +00:00
public AbsolutePath ServerPublicFolder => "public".RelativeTo(AbsolutePath.EntryPoint);
2020-04-09 12:46:33 +00:00
public AbsolutePath ServerArchivesFolder => "archives".RelativeTo(AbsolutePath.EntryPoint);
2020-04-10 03:54:02 +00:00
public AbsolutePath ServerUpdatesFolder => "updates".RelativeTo(AbsolutePath.EntryPoint);
2020-04-09 12:46:33 +00:00
public static async Task Start()
{
var fixture = new BuildServerFixture();
fixture.ServerArchivesFolder.DeleteDirectory().Wait();
fixture.ServerArchivesFolder.CreateDirectory();
var builder = Program.CreateHostBuilder(
new[]
{
$"WabbajackSettings:DownloadDir={"tmp".RelativeTo(AbsolutePath.EntryPoint)}",
$"WabbajackSettings:ArchiveDir={"archives".RelativeTo(AbsolutePath.EntryPoint)}",
$"WabbajackSettings:TempFolder={fixture.ServerTempFolder}",
$"WabbajackSettings:SQLConnection={fixture.PublicConnStr}",
2020-03-30 20:38:46 +00:00
$"WabbajackSettings:BunnyCDN_User=TEST",
$"WabbajackSettings:BunnyCDN_Password=TEST",
2020-03-31 22:05:36 +00:00
"WabbajackSettings:JobScheduler=false",
2020-04-02 21:16:46 +00:00
"WabbajackSettings:JobRunner=false",
2020-05-09 13:22:02 +00:00
"WabbajackSettings:RunBackEndJobs=false",
"WabbajackSettings:RunFrontEndJobs=false",
2020-04-02 21:16:46 +00:00
"WabbajackSettinss:DisableNexusForwarding=true"
}, true);
fixture._host = builder.Build();
fixture._token = new CancellationTokenSource();
fixture._task = fixture._host.RunAsync(fixture._token.Token);
2020-03-30 20:38:46 +00:00
Consts.WabbajackBuildServerUri = new Uri("http://localhost:8080");
2020-04-08 04:19:36 +00:00
await "ServerWhitelist.yaml".RelativeTo(fixture.ServerPublicFolder).WriteAllTextAsync(
2020-04-08 04:19:36 +00:00
"GoogleIDs:\nAllowedPrefixes:\n - http://localhost");
}
2020-04-03 22:33:19 +00:00
~BuildServerFixture()
{
Dispose();
}
2020-03-31 22:05:36 +00:00
public T GetService<T>()
{
return (T)_host.Services.GetService(typeof(T));
}
2020-04-09 12:46:33 +00:00
public void Dispose()
{
2020-04-03 22:33:19 +00:00
if (_disposed) return;
_disposed = true;
if (!_token.IsCancellationRequested)
_token.Cancel();
2020-03-31 22:05:36 +00:00
try
{
_task.Wait();
}
catch (Exception)
{
//
}
_severTempFolder.DisposeAsync().AsTask().Wait();
}
}
/// <summary>
/// Bit of a hack to get around that we don't want the system starting and stopping our
/// HTTP server for each class its testing.
/// </summary>
/// <typeparam name="T"></typeparam>
public class SingletonAdaptor<T> where T : new()
{
private static T _singleton = default;
private static object _lock = new object();
public SingletonAdaptor()
{
}
public T Deref()
{
lock (this)
{
if (_singleton == null)
{
_singleton = new T();
if (_singleton is IAsyncLifetime d)
{
d.InitializeAsync().Wait();
}
}
return _singleton;
}
}
2020-04-09 12:46:33 +00:00
}
2020-04-09 12:46:33 +00:00
[Collection("ServerTests")]
public class ABuildServerSystemTest : XunitContextBase, IClassFixture<SingletonAdaptor<BuildServerFixture>>
{
protected readonly Client _client;
private readonly IDisposable _unsubMsgs;
private readonly IDisposable _unsubErr;
protected Client _authedClient;
2020-03-30 20:38:46 +00:00
protected WorkQueue _queue;
2020-04-09 12:46:33 +00:00
private Random _random;
public ABuildServerSystemTest(ITestOutputHelper output, SingletonAdaptor<BuildServerFixture> fixture) : base(output)
{
2020-03-30 20:38:46 +00:00
Filters.Clear();
_unsubMsgs = Utils.LogMessages.OfType<IInfo>().Subscribe(onNext: msg => XunitContext.WriteLine(msg.ShortDescription));
_unsubErr = Utils.LogMessages.OfType<IUserIntervention>().Subscribe(msg =>
XunitContext.WriteLine("ERROR: User intervention required: " + msg.ShortDescription));
_client = new Client();
_authedClient = new Client();
Fixture = fixture.Deref();
_authedClient.Headers.Add(("x-api-key", Fixture.APIKey));
2020-04-08 04:19:36 +00:00
AuthorAPI.ApiKeyOverride = Fixture.APIKey;
2020-03-30 20:38:46 +00:00
_queue = new WorkQueue();
2020-03-31 22:05:36 +00:00
Queue = new WorkQueue();
2020-04-09 12:46:33 +00:00
_random = new Random();
2020-04-08 04:19:36 +00:00
Consts.ModlistSummaryURL = MakeURL("lists/status.json");
Consts.ServerWhitelistURL = MakeURL("ServerWhitelist.yaml");
}
2020-03-31 22:05:36 +00:00
public WorkQueue Queue { get; set; }
public BuildServerFixture Fixture { get; set; }
protected string MakeURL(string path)
{
return "http://localhost:8080/" + path;
}
2020-04-09 12:46:33 +00:00
2020-05-09 22:16:16 +00:00
protected byte[] RandomData(long? size = null)
2020-04-09 12:46:33 +00:00
{
2020-05-09 22:16:16 +00:00
var arr = new byte[size ?? _random.Next(1024)];
2020-04-09 12:46:33 +00:00
_random.NextBytes(arr);
return arr;
}
2020-04-08 11:26:54 +00:00
public override void Dispose()
{
2020-03-31 22:05:36 +00:00
Queue.Dispose();
base.Dispose();
_unsubMsgs.Dispose();
_unsubErr.Dispose();
2020-03-31 22:05:36 +00:00
}
2020-05-19 03:46:33 +00:00
2020-05-20 22:36:29 +00:00
protected async Task<Uri> MakeModList(string modFileName)
2020-05-19 03:46:33 +00:00
{
var archive_data = Encoding.UTF8.GetBytes("Cheese for Everyone!");
2020-05-20 22:36:29 +00:00
var test_archive_path = modFileName.RelativeTo(Fixture.ServerPublicFolder);
2020-05-19 03:46:33 +00:00
await test_archive_path.WriteAllBytesAsync(archive_data);
ModListData = new ModList();
ModListData.Archives.Add(
2020-05-20 22:36:29 +00:00
new Archive(new HTTPDownloader.State(MakeURL(modFileName.ToString())))
2020-05-19 03:46:33 +00:00
{
Hash = await test_archive_path.FileHashAsync(),
Name = "test_archive",
Size = test_archive_path.Size,
});
var modListPath = "test_modlist.wabbajack".RelativeTo(Fixture.ServerPublicFolder);
await using (var fs = await modListPath.Create())
2020-05-19 03:46:33 +00:00
{
using var za = new ZipArchive(fs, ZipArchiveMode.Create);
var entry = za.CreateEntry("modlist");
await using var es = entry.Open();
ModListData.ToJson(es);
}
ModListMetaData = new List<ModlistMetadata>
{
new ModlistMetadata
{
Official = false,
Author = "Test Suite",
Description = "A test",
DownloadMetadata = new DownloadMetadata
{
Hash = await modListPath.FileHashAsync(),
Size = modListPath.Size
},
Links = new ModlistMetadata.LinksObject
{
MachineURL = "test_list",
Download = MakeURL("test_modlist.wabbajack")
}
},
new ModlistMetadata
{
Official = true,
Author = "Test Suite",
Description = "A list with a broken hash",
DownloadMetadata = new DownloadMetadata()
{
Hash = Hash.FromLong(42),
Size = 42
},
Links = new ModlistMetadata.LinksObject
{
MachineURL = "broken_list",
Download = MakeURL("test_modlist.wabbajack")
}
}
};
var metadataPath = "test_mod_list_metadata.json".RelativeTo(Fixture.ServerPublicFolder);
await ModListMetaData.ToJsonAsync(metadataPath);
2020-05-19 03:46:33 +00:00
return new Uri(MakeURL("test_mod_list_metadata.json"));
}
public ModList ModListData { get; set; }
public List<ModlistMetadata> ModListMetaData { get; set; }
}
}