zcbot/windows-node/Zcbot.WindowsNode.Tests/PersistenceSafetyTests.cs

41 lines
1.3 KiB
C#

namespace Zcbot.WindowsNode.Tests;
public sealed class PersistenceSafetyTests : IDisposable
{
private readonly string root = Path.Combine(
Path.GetTempPath(), "zcbot-persistence-tests", Guid.NewGuid().ToString("N"));
[Fact]
public void PathGuardAcceptsAChildAndRejectsTraversalOrRootedSegments()
{
var child = PathGuard.CombineUnderRoot(root, "jobs", "job-id", "state.json");
Assert.StartsWith(Path.GetFullPath(root), child, StringComparison.OrdinalIgnoreCase);
Assert.Throws<InvalidDataException>(
() => PathGuard.CombineUnderRoot(root, "..", "outside.json"));
Assert.Throws<InvalidDataException>(
() => PathGuard.CombineUnderRoot(root, Path.GetPathRoot(root)!));
}
[Fact]
public void AtomicFileReplacesTheTargetAndLeavesNoTemporaryFile()
{
var path = Path.Combine(root, "jobs", "state.json");
AtomicFile.Write(path, [1, 2, 3], overwrite: false);
AtomicFile.Write(path, [4, 5], overwrite: true);
Assert.Equal([4, 5], File.ReadAllBytes(path));
Assert.Empty(Directory.EnumerateFiles(
Path.GetDirectoryName(path)!, "state.json.tmp-*"));
}
public void Dispose()
{
if (Directory.Exists(root))
{
Directory.Delete(root, recursive: true);
}
}
}