d7071fdbc2
Build the staging path before the copy in both UploadTrack and ReplaceAudio so the finally block deletes it on cancellation or IO error, not only on success.
66 lines
3.1 KiB
C#
66 lines
3.1 KiB
C#
using DeepDrftAPI;
|
|
|
|
namespace DeepDrftTests;
|
|
|
|
/// <summary>
|
|
/// Guards the upload-staging directory resolution (<see cref="Startup.ResolveStagingPath"/>). The
|
|
/// load-bearing invariant: large audio bodies must stage on the data disk, never the system temp
|
|
/// mount — on the Linux host /tmp is a small RAM-backed tmpfs that cannot hold a multi-hundred-MB WAV.
|
|
/// </summary>
|
|
[TestFixture]
|
|
public class UploadStagingPathTests
|
|
{
|
|
[Test]
|
|
public void ResolveStagingPath_DefaultsToStagingUnderVault_WhenUnconfigured()
|
|
{
|
|
var vaultPath = Path.Combine(Path.GetTempPath(), "DeepDrftTests", Guid.NewGuid().ToString());
|
|
|
|
foreach (var configured in new[] { null, "", " " })
|
|
{
|
|
var resolved = Startup.ResolveStagingPath(configured, vaultPath);
|
|
|
|
Assert.Multiple(() =>
|
|
{
|
|
Assert.That(resolved, Is.EqualTo(Path.GetFullPath(Path.Combine(vaultPath, "staging"))),
|
|
"An unset/blank StagingPath must default to a 'staging' subdirectory under the vault path");
|
|
Assert.That(Path.IsPathFullyQualified(resolved), Is.True,
|
|
"The resolved staging path must be absolute");
|
|
});
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void ResolveStagingPath_HonoursExplicitOverride()
|
|
{
|
|
var vaultPath = Path.Combine("data", "vaults");
|
|
var configured = Path.Combine(Path.GetTempPath(), "DeepDrftTests", "custom-staging", Guid.NewGuid().ToString());
|
|
|
|
var resolved = Startup.ResolveStagingPath(configured, vaultPath);
|
|
|
|
Assert.That(resolved, Is.EqualTo(Path.GetFullPath(configured)),
|
|
"An explicit Upload:StagingPath must win over the vault-path default");
|
|
}
|
|
|
|
[Test]
|
|
public void ResolveStagingPath_NeverResolvesIntoSystemTempDirectory_ForDataDiskVault()
|
|
{
|
|
// A production-shaped vault path on the data disk (the real config is a relative "../Database/Vaults").
|
|
// The resolved staging dir must sit under that vault, not under Path.GetTempPath() (= /tmp on Linux).
|
|
var vaultPath = Path.Combine("..", "Database", "Vaults");
|
|
|
|
var resolved = Startup.ResolveStagingPath(configuredPath: null, vaultPath);
|
|
|
|
var systemTemp = Path.GetFullPath(Path.GetTempPath());
|
|
// Note: because vaultPath is relative, Path.GetFullPath resolves it against the CWD, which is
|
|
// never the system temp directory. The StartsWith guard therefore catches the case where
|
|
// ResolveStagingPath mistakenly uses Path.GetTempPath() directly, rather than proving the
|
|
// absolute production path never overlaps with /tmp on any machine. The EndsWith assertion
|
|
// is the load-bearing check: it verifies the output is rooted under the vault tree, not
|
|
// under a hard-coded temp location.
|
|
Assert.That(resolved.StartsWith(systemTemp, StringComparison.Ordinal), Is.False,
|
|
"The default staging directory must never live under the system temp mount");
|
|
Assert.That(resolved, Does.EndWith(Path.Combine("Database", "Vaults", "staging")),
|
|
"The default staging directory must hang off the vault path on the data disk");
|
|
}
|
|
}
|