namespace OpenNest.IO.Tests; /// /// Saving over a nest file must never leave it truncated: a write that fails part way keeps /// the previously saved nest. /// public class NestWriterAtomicSaveTests : IDisposable { private readonly string directory = Path.Combine(Path.GetTempPath(), "opennest-atomic-save-" + Guid.NewGuid()); public NestWriterAtomicSaveTests() => Directory.CreateDirectory(directory); public void Dispose() => Directory.Delete(directory, recursive: true); [Fact] public void FailedWrite_KeepsThePreviousFile() { var path = Path.Combine(directory, "job.nest"); var nest = new Nest("Good"); var drawing = TestDrawings.Square(); nest.Drawings.Add(drawing); var plate = new Plate(48, 96); plate.Parts.Add(new Part(drawing)); nest.Plates.Add(plate); Assert.True(new NestWriter(nest).Write(path)); var saved = File.ReadAllBytes(path); // JSON has no NaN, so serializing this plate throws part way through the archive. nest.Plates[0].PartSpacing = double.NaN; Assert.ThrowsAny(() => new NestWriter(nest).Write(path)); Assert.Equal(saved, File.ReadAllBytes(path)); Assert.Equal(new[] { path }, Directory.GetFiles(directory)); } [Fact] public void Write_ReplacesAnExistingFile() { var path = Path.Combine(directory, "job.nest"); File.WriteAllText(path, "old"); Assert.True(new NestWriter(new Nest("New")).Write(path)); using var stream = File.OpenRead(path); Assert.Equal("New", new NestReader(stream).Read().Name); Assert.Equal(new[] { path }, Directory.GetFiles(directory)); } }