2020-03-30 03:47:35 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Net.Http;
|
|
|
|
|
using System.Reactive.Linq;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Microsoft.Extensions.Hosting;
|
2020-04-08 11:26:54 +00:00
|
|
|
|
using Wabbajack.BuildServer.Model.Models;
|
|
|
|
|
using Wabbajack.BuildServer.Models.JobQueue;
|
2020-03-30 03:47:35 +00:00
|
|
|
|
using Wabbajack.Common;
|
|
|
|
|
using Wabbajack.Common.Http;
|
|
|
|
|
using Wabbajack.Common.StatusFeed;
|
2020-04-08 04:19:36 +00:00
|
|
|
|
using Wabbajack.Lib.FileUploader;
|
2020-03-30 03:47:35 +00:00
|
|
|
|
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 = new TempFolder();
|
2020-04-03 22:33:19 +00:00
|
|
|
|
private bool _disposed = false;
|
2020-03-30 03:47:35 +00:00
|
|
|
|
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
|
|
|
|
|
2020-03-30 03:47:35 +00:00
|
|
|
|
|
|
|
|
|
public BuildServerFixture()
|
|
|
|
|
{
|
|
|
|
|
var builder = Program.CreateHostBuilder(
|
|
|
|
|
new[]
|
|
|
|
|
{
|
|
|
|
|
$"WabbajackSettings:DownloadDir={"tmp".RelativeTo(AbsolutePath.EntryPoint)}",
|
|
|
|
|
$"WabbajackSettings:ArchiveDir={"archives".RelativeTo(AbsolutePath.EntryPoint)}",
|
2020-03-30 04:02:29 +00:00
|
|
|
|
$"WabbajackSettings:TempFolder={ServerTempFolder}",
|
2020-03-30 03:47:35 +00:00
|
|
|
|
$"WabbajackSettings:SQLConnection={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",
|
|
|
|
|
"WabbajackSettinss:DisableNexusForwarding=true"
|
2020-03-30 03:47:35 +00:00
|
|
|
|
}, true);
|
|
|
|
|
_host = builder.Build();
|
|
|
|
|
_token = new CancellationTokenSource();
|
|
|
|
|
_task = _host.RunAsync(_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
|
|
|
|
|
|
|
|
|
"ServerWhitelist.yaml".RelativeTo(ServerPublicFolder).WriteAllText(
|
|
|
|
|
"GoogleIDs:\nAllowedPrefixes:\n - http://localhost");
|
2020-03-30 03:47:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
2020-03-30 03:47:35 +00:00
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
2020-04-03 22:33:19 +00:00
|
|
|
|
if (_disposed) return;
|
|
|
|
|
_disposed = true;
|
2020-03-30 03:47:35 +00:00
|
|
|
|
if (!_token.IsCancellationRequested)
|
|
|
|
|
_token.Cancel();
|
2020-03-31 22:05:36 +00:00
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
_task.Wait();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception)
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-30 03:47:35 +00:00
|
|
|
|
_severTempFolder.DisposeAsync().AsTask().Wait();
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-01 11:47:47 +00:00
|
|
|
|
|
|
|
|
|
/// <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-01 11:47:47 +00:00
|
|
|
|
}
|
2020-03-30 03:47:35 +00:00
|
|
|
|
|
2020-04-09 12:46:33 +00:00
|
|
|
|
|
2020-04-01 11:47:47 +00:00
|
|
|
|
[Collection("ServerTests")]
|
|
|
|
|
public class ABuildServerSystemTest : XunitContextBase, IClassFixture<SingletonAdaptor<BuildServerFixture>>
|
2020-03-30 03:47:35 +00:00
|
|
|
|
{
|
|
|
|
|
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;
|
2020-03-30 03:47:35 +00:00
|
|
|
|
|
|
|
|
|
|
2020-04-01 11:47:47 +00:00
|
|
|
|
public ABuildServerSystemTest(ITestOutputHelper output, SingletonAdaptor<BuildServerFixture> fixture) : base(output)
|
2020-03-30 03:47:35 +00:00
|
|
|
|
{
|
2020-03-30 20:38:46 +00:00
|
|
|
|
Filters.Clear();
|
2020-03-30 03:47:35 +00:00
|
|
|
|
_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();
|
2020-04-01 11:47:47 +00:00
|
|
|
|
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-30 03:47:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-31 22:05:36 +00:00
|
|
|
|
public WorkQueue Queue { get; set; }
|
|
|
|
|
|
2020-03-30 03:47:35 +00:00
|
|
|
|
public BuildServerFixture Fixture { get; set; }
|
|
|
|
|
|
|
|
|
|
protected string MakeURL(string path)
|
|
|
|
|
{
|
|
|
|
|
return "http://localhost:8080/" + path;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-09 12:46:33 +00:00
|
|
|
|
|
|
|
|
|
protected byte[] RandomData()
|
|
|
|
|
{
|
|
|
|
|
var arr = new byte[_random.Next(1024)];
|
|
|
|
|
_random.NextBytes(arr);
|
|
|
|
|
return arr;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-08 11:26:54 +00:00
|
|
|
|
protected async Task ClearJobQueue()
|
|
|
|
|
{
|
|
|
|
|
var sql = Fixture.GetService<SqlService>();
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
var job = await sql.GetJob();
|
|
|
|
|
if (job == null) break;
|
|
|
|
|
|
|
|
|
|
job.Result = JobResult.Success();
|
|
|
|
|
await sql.FinishJob(job);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-09 12:46:33 +00:00
|
|
|
|
|
|
|
|
|
protected async Task RunAllJobs()
|
|
|
|
|
{
|
|
|
|
|
var sql = Fixture.GetService<SqlService>();
|
|
|
|
|
var settings = Fixture.GetService<AppSettings>();
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
var job = await sql.GetJob();
|
|
|
|
|
if (job == null) break;
|
|
|
|
|
|
|
|
|
|
job.Result = await job.Payload.Execute(sql, settings);
|
|
|
|
|
await sql.FinishJob(job);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-08 11:26:54 +00:00
|
|
|
|
|
2020-03-30 03:47:35 +00:00
|
|
|
|
public override void Dispose()
|
|
|
|
|
{
|
2020-03-31 22:05:36 +00:00
|
|
|
|
Queue.Dispose();
|
2020-03-30 03:47:35 +00:00
|
|
|
|
base.Dispose();
|
|
|
|
|
_unsubMsgs.Dispose();
|
|
|
|
|
_unsubErr.Dispose();
|
2020-03-31 22:05:36 +00:00
|
|
|
|
|
2020-03-30 03:47:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|