using System; using System.IO; using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Host.Stability; namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Host.Tests; [Trait("Category", "Unit")] public sealed class PostMortemMmfTests : IDisposable { private readonly string _path = Path.Combine(Path.GetTempPath(), $"mmf-test-{Guid.NewGuid():N}.bin"); public void Dispose() { if (File.Exists(_path)) File.Delete(_path); } [Fact] public void Write_then_read_round_trips_entries_in_oldest_first_order() { using (var mmf = new PostMortemMmf(_path, capacity: 10)) { mmf.Write(0x30, "read tag-1"); mmf.Write(0x30, "read tag-2"); mmf.Write(0x32, "write tag-3"); } using var reopen = new PostMortemMmf(_path, capacity: 10); var entries = reopen.ReadAll(); entries.Length.ShouldBe(3); entries[0].Message.ShouldBe("read tag-1"); entries[1].Message.ShouldBe("read tag-2"); entries[2].Message.ShouldBe("write tag-3"); entries[0].OpKind.ShouldBe(0x30L); } [Fact] public void Ring_buffer_wraps_and_oldest_entry_is_overwritten() { using var mmf = new PostMortemMmf(_path, capacity: 3); mmf.Write(1, "A"); mmf.Write(2, "B"); mmf.Write(3, "C"); mmf.Write(4, "D"); // overwrites A var entries = mmf.ReadAll(); entries.Length.ShouldBe(3); entries[0].Message.ShouldBe("B"); entries[1].Message.ShouldBe("C"); entries[2].Message.ShouldBe("D"); } [Fact] public void Message_longer_than_capacity_is_truncated_safely() { using var mmf = new PostMortemMmf(_path, capacity: 2); var huge = new string('x', 500); mmf.Write(0, huge); var entries = mmf.ReadAll(); entries[0].Message.Length.ShouldBeLessThan(PostMortemMmf.EntryBytes); } }