Files
deepdrft/DeepDrftTests/UploadStagingPathTests.cs
T
daniel-c-harvey d7071fdbc2 fix: always delete staging file on mid-copy abort
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.
2026-06-19 17:36:06 -04:00

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");
}
}