QuellCode/CentronERP war nur als Gitlink (Submodul-Referenz auf 79c1142) getrackt, ohne .gitmodules und ohne erreichbares Remote. Der Untersuchungsgegenstand der Versuchsreihe war damit nicht reproduzierbar gesichert: Ein Klon haette ein leeres Verzeichnis erhalten, und die Belege der 3.287 Anforderungen waeren nicht ueberpruefbar gewesen. Umstellung: - Historie nach c:\DEV\CentronERP_git_snapshot_79c1142 ausgelagert (vollstaendig lesbar, enthaelt 79c1142 und Vorgaenger 89ccfd6) - Gitlink aus dem Index entfernt - Dateiinhalt aufgenommen: 24.557 Dateien, rund 333 MB Die verschachtelte .gitignore der Codebasis gilt weiter, Build-Artefakte bleiben ausgeschlossen. Details in Versuche/Versuch_01/_Codebasis-Nachweis.md
206 lines
6.7 KiB
C#
206 lines
6.7 KiB
C#
using CentronNexus.Configuration;
|
|
|
|
namespace CentronNexusTests.Configuration;
|
|
|
|
public class UploadConfigTests
|
|
{
|
|
[Fact]
|
|
public void Defaults_AreApplied_WhenNothingIsConfigured()
|
|
{
|
|
var config = new UploadConfig();
|
|
|
|
Assert.Equal(UploadConfig.DefaultMaxEmployeeUploadSizeInMb, config.MaxEmployeeUploadSizeInMb);
|
|
Assert.Equal(UploadConfig.DefaultMaxCustomerPortalUploadSizeInMb, config.MaxCustomerPortalUploadSizeInMb);
|
|
Assert.True(config.HasEmployeeUploadLimit);
|
|
Assert.True(config.HasCustomerPortalUploadLimit);
|
|
}
|
|
|
|
[Fact]
|
|
public void MegabytesAreConvertedToBytes()
|
|
{
|
|
var config = new UploadConfig
|
|
{
|
|
MaxEmployeeUploadSizeInMb = 100,
|
|
MaxCustomerPortalUploadSizeInMb = 25
|
|
};
|
|
|
|
Assert.Equal(100 * 1024 * 1024, config.MaxEmployeeUploadSizeInBytes);
|
|
Assert.Equal(25 * 1024 * 1024, config.MaxCustomerPortalUploadSizeInBytes);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(0)]
|
|
[InlineData(-1)]
|
|
public void ZeroOrLess_MeansNoLimit(int sizeInMb)
|
|
{
|
|
var config = new UploadConfig
|
|
{
|
|
MaxEmployeeUploadSizeInMb = sizeInMb,
|
|
MaxCustomerPortalUploadSizeInMb = sizeInMb
|
|
};
|
|
|
|
Assert.False(config.HasEmployeeUploadLimit);
|
|
Assert.False(config.HasCustomerPortalUploadLimit);
|
|
Assert.Equal(int.MaxValue, config.MaxEmployeeUploadSizeInBytes);
|
|
Assert.Equal(int.MaxValue, config.MaxCustomerPortalUploadSizeInBytes);
|
|
}
|
|
|
|
[Fact]
|
|
public void OversizedValues_AreClamped_InsteadOfOverflowing()
|
|
{
|
|
// 4096 MB would exceed int.MaxValue bytes, which is the upper bound of the
|
|
// DevExpress MaxFileSize parameter.
|
|
var config = new UploadConfig
|
|
{
|
|
MaxEmployeeUploadSizeInMb = 4096,
|
|
MaxCustomerPortalUploadSizeInMb = int.MaxValue
|
|
};
|
|
|
|
Assert.Equal(int.MaxValue, config.MaxEmployeeUploadSizeInBytes);
|
|
Assert.Equal(int.MaxValue, config.MaxCustomerPortalUploadSizeInBytes);
|
|
Assert.True(config.HasEmployeeUploadLimit);
|
|
Assert.True(config.HasCustomerPortalUploadLimit);
|
|
}
|
|
|
|
[Fact]
|
|
public void SizeExceededMessage_NamesTheConfiguredLimit()
|
|
{
|
|
Assert.Equal(
|
|
"Die Datei ist größer als 25 MB und kann nicht hochgeladen werden.",
|
|
UploadConfig.BuildSizeExceededMessage(25));
|
|
}
|
|
|
|
[Fact]
|
|
public void MaxRequestBodySize_AddsOverhead_ToTheLargerConfiguredLimit()
|
|
{
|
|
var config = new UploadConfig();
|
|
|
|
// 100 MB employee limit + 4 MB multipart headroom.
|
|
Assert.Equal(104L * 1024 * 1024, config.MaxRequestBodySizeInBytes);
|
|
}
|
|
|
|
[Fact]
|
|
public void MaxRequestBodySize_UsesTheCustomerPortalLimit_WhenItIsTheLarger()
|
|
{
|
|
var config = new UploadConfig
|
|
{
|
|
MaxEmployeeUploadSizeInMb = 10,
|
|
MaxCustomerPortalUploadSizeInMb = 50
|
|
};
|
|
|
|
Assert.Equal(54L * 1024 * 1024, config.MaxRequestBodySizeInBytes);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(0, 25)]
|
|
[InlineData(-1, 25)]
|
|
[InlineData(100, 0)]
|
|
[InlineData(100, -5)]
|
|
public void MaxRequestBodySize_FallsBackToTheCeiling_WhenUploadsAreUnlimited(
|
|
int employeeSizeInMb,
|
|
int customerPortalSizeInMb)
|
|
{
|
|
var config = new UploadConfig
|
|
{
|
|
MaxEmployeeUploadSizeInMb = employeeSizeInMb,
|
|
MaxCustomerPortalUploadSizeInMb = customerPortalSizeInMb
|
|
};
|
|
|
|
Assert.Equal(256L * 1024 * 1024, config.MaxRequestBodySizeInBytes);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(4096)]
|
|
[InlineData(int.MaxValue)]
|
|
public void MaxRequestBodySize_IsClampedToTheCeiling_InsteadOfOverflowing(int sizeInMb)
|
|
{
|
|
var config = new UploadConfig
|
|
{
|
|
MaxEmployeeUploadSizeInMb = sizeInMb,
|
|
MaxCustomerPortalUploadSizeInMb = sizeInMb
|
|
};
|
|
|
|
Assert.Equal(256L * 1024 * 1024, config.MaxRequestBodySizeInBytes);
|
|
Assert.True(config.MaxRequestBodySizeInBytes > 0);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1, 1)]
|
|
[InlineData(25, 100)]
|
|
[InlineData(100, 25)]
|
|
[InlineData(200, 50)]
|
|
public void MaxRequestBodySize_IsNeverSmallerThanTheConfiguredUploadLimits(
|
|
int employeeSizeInMb,
|
|
int customerPortalSizeInMb)
|
|
{
|
|
var config = new UploadConfig
|
|
{
|
|
MaxEmployeeUploadSizeInMb = employeeSizeInMb,
|
|
MaxCustomerPortalUploadSizeInMb = customerPortalSizeInMb
|
|
};
|
|
|
|
// Core invariant: the request body limit must never reject an upload the UI permits.
|
|
// Only holds below the ceiling, where the clamp intentionally breaks it.
|
|
Assert.True(config.MaxRequestBodySizeInBytes >= config.MaxEmployeeUploadSizeInBytes);
|
|
Assert.True(config.MaxRequestBodySizeInBytes >= config.MaxCustomerPortalUploadSizeInBytes);
|
|
}
|
|
|
|
[Fact]
|
|
public void MaxMultipartUploadSize_FollowsTheCustomerPortalLimit_WhenItFitsTheRequestBody()
|
|
{
|
|
var config = new UploadConfig();
|
|
|
|
Assert.Equal(25 * 1024 * 1024, config.MaxMultipartUploadSizeInBytes);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(0)]
|
|
[InlineData(4096)]
|
|
public void MaxMultipartUploadSize_NeverExceedsTheRequestBodyLimit(int customerPortalSizeInMb)
|
|
{
|
|
var config = new UploadConfig
|
|
{
|
|
MaxCustomerPortalUploadSizeInMb = customerPortalSizeInMb
|
|
};
|
|
|
|
// 256 MB ceiling minus the 4 MB multipart headroom.
|
|
Assert.Equal(252 * 1024 * 1024, config.MaxMultipartUploadSizeInBytes);
|
|
Assert.True(config.MaxMultipartUploadSizeInBytes < config.MaxRequestBodySizeInBytes);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1, 1)]
|
|
[InlineData(25, 100)]
|
|
[InlineData(100, 25)]
|
|
[InlineData(0, 0)]
|
|
[InlineData(4096, 4096)]
|
|
public void MaxMultipartUploadSize_AlwaysFitsInsideTheRequestBodyLimit(
|
|
int employeeSizeInMb,
|
|
int customerPortalSizeInMb)
|
|
{
|
|
var config = new UploadConfig
|
|
{
|
|
MaxEmployeeUploadSizeInMb = employeeSizeInMb,
|
|
MaxCustomerPortalUploadSizeInMb = customerPortalSizeInMb
|
|
};
|
|
|
|
// Core invariant: a multipart upload the UI accepts must never be rejected by the server.
|
|
Assert.True(config.MaxMultipartUploadSizeInBytes > 0);
|
|
Assert.True(config.MaxMultipartUploadSizeInBytes <= config.MaxRequestBodySizeInBytes);
|
|
}
|
|
|
|
[Fact]
|
|
public void MaxRequestBodySize_StaysWellAboveTheSignalRMessageSize_ForTheSmallestLimit()
|
|
{
|
|
var config = new UploadConfig
|
|
{
|
|
MaxEmployeeUploadSizeInMb = 1,
|
|
MaxCustomerPortalUploadSizeInMb = 1
|
|
};
|
|
|
|
// Even the smallest sane configuration leaves the Blazor long polling send channel
|
|
// (SignalR messages are 32 KB) and the OIDC form_post body orders of magnitude of headroom.
|
|
Assert.Equal(5L * 1024 * 1024, config.MaxRequestBodySizeInBytes);
|
|
}
|
|
}
|