Files
Radicade/ServerTests/AdminBundleUploadTests.cs
T
2026-10-16 23:33:13 -07:00

73 lines
3.7 KiB
C#

using System.Net;
using System.Security.Cryptography;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using RadicadeServer.Admin;
using RadicadeServer.DB;
using Xunit;
namespace RadicadeServer.Tests;
[Collection(DbFactoryCollection.Name)]
public class AdminBundleUploadTests
{
[Theory]
[InlineData("/admin/panel/upload/datablob")]
[InlineData("/admin/rooms/upload/datablob")]
public async Task LargeBundleUploadsPreserveBytesAndStillRequireTheKey(string route)
{
var root = Directory.CreateTempSubdirectory("radicade-upload-test-").FullName;
var oldStorage = DBConfig.CDNStorage;
var oldKey = DBConfig.AdminApiKey;
DBConfig.CDNStorage = root;
DBConfig.AdminApiKey = "bundle-upload-test-key";
var builder = WebApplication.CreateBuilder();
builder.WebHost.UseKestrel().UseUrls("http://127.0.0.1:0");
builder.Logging.ClearProviders();
builder.Services.AddControllers().AddApplicationPart(typeof(AdminPanelAPI).Assembly);
builder.Services.AddCors(options => options.AddPolicy("AdminPanel", policy => policy.AllowAnyOrigin()));
builder.Services.Configure<FormOptions>(options => options.MultipartBodyLengthLimit = 256L * 1024 * 1024);
builder.Services.AddDbContext<RecDBContext>(options => options.UseInMemoryDatabase(Guid.NewGuid().ToString()));
await using var app = builder.Build();
app.UseCors();
app.MapControllers();
try
{
await app.StartAsync();
using var client = new HttpClient { BaseAddress = new Uri(app.Urls.Single()) };
// Exercise real Kestrel and MVC model binding, beyond the default 30 MB ceiling.
var bytes = new byte[39_000_000];
RandomNumberGenerator.Fill(bytes);
using var form = new MultipartFormDataContent();
form.Add(new ByteArrayContent(bytes), "file", "bundle.assetbundle");
using var response = await client.PostAsync(route + "?key=bundle-upload-test-key&name=bundle.assetbundle", form);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(SHA256.HashData(bytes), SHA256.HashData(await File.ReadAllBytesAsync(Path.Join(root, "bundle.assetbundle"))));
using var unauthorizedForm = new MultipartFormDataContent();
unauthorizedForm.Add(new ByteArrayContent(new byte[] { 1, 2, 3 }), "file", "unauthorized.assetbundle");
using var unauthorized = await client.PostAsync(route + "?key=wrong&name=unauthorized.assetbundle", unauthorizedForm);
Assert.Equal(HttpStatusCode.Unauthorized, unauthorized.StatusCode);
Assert.False(File.Exists(Path.Join(root, "unauthorized.assetbundle")));
using var malformed = new ByteArrayContent(new byte[] { 1, 2, 3 });
malformed.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("multipart/form-data");
using var badRequest = await client.PostAsync(route + "?key=bundle-upload-test-key&name=broken.assetbundle", malformed);
Assert.Equal(HttpStatusCode.BadRequest, badRequest.StatusCode);
Assert.DoesNotContain("Invalid secret", await badRequest.Content.ReadAsStringAsync());
Assert.False(File.Exists(Path.Join(root, "broken.assetbundle")));
}
finally
{
await app.StopAsync();
DBConfig.CDNStorage = oldStorage;
DBConfig.AdminApiKey = oldKey;
Directory.Delete(root, recursive: true);
}
}
}