using System; using System.Buffers; using System.IO; using Server.Gumps; using Server.Tests.Network; using Xunit; namespace Server.Tests.Gumps; [Collection("Sequential Tests")] public class TestLayoutGumps { [Fact] public void TestDynamicGumpPacket() { var legacyGump = new LegacyTestGump("Test"); var legacyPacketData = legacyGump.Compile().Compile(); var staticGump = new DynamicTestGump("Test"); var buffer = GC.AllocateUninitializedArray(512); var writer = new SpanWriter(buffer); staticGump.Compile(ref writer); AssertThat.Equal(writer.Span, legacyPacketData); } [Fact] public void TestStaticLayoutGumpPacket() { var expectedLayout = "{ page 0 }{ resizepic 10 10 9260 265 140 }{ tilepic 205 40 4 }{ tilepic 227 40 5 }{ tilepic 180 78 3246 }{ tilepic 195 90 3245 }{ tilepic 218 95 3248 }{ htmlgump 30 30 150 75 1 0 0 }{ htmlgump 30 70 150 25 00002 1 0 }{ button 40 105 2074 2075 1 0 1 }{ button 110 105 2073 2072 1 0 2 }\0"u8; string[] strings = [ "
Wilt thou sanctify the resurrection of:
", "
Test
" ]; InternalTestStaticGump(expectedLayout, new StaticLayoutTestGump("Test"), strings); } [Fact] public void TestStaticGumpPacket() { var expectedLayout = "{ page 0 }{ resizepic 10 10 9260 265 140 }{ tilepic 205 40 4 }{ tilepic 227 40 5 }{ tilepic 180 78 3246 }{ tilepic 195 90 3245 }{ tilepic 218 95 3248 }{ htmlgump 30 30 150 75 1 0 0 }{ htmlgump 30 70 150 25 2 1 0 }{ button 40 105 2074 2075 1 0 1 }{ button 110 105 2073 2072 1 0 2 }\0"u8; string[] strings = [ "
Wilt thou sanctify the resurrection of:
", "
Test
" ]; InternalTestStaticGump(expectedLayout, new StaticTestGump(), strings); } [Fact] public void TestStaticGumpIsCached() { var gump = new CachedGump(); var buffer = GC.AllocateUninitializedArray(512); var writer = new SpanWriter(buffer); gump.Compile(ref writer); var packet = writer.Span.ToArray(); // Reset the writer writer.Seek(0, SeekOrigin.Begin); // Second call should not call BuildLayout gump.Compile(ref writer); AssertThat.Equal(writer.Span, packet); } private static void InternalTestStaticGump(ReadOnlySpan expectedLayout, StaticGump staticGump, string[] strings) where T : StaticGump { // Expected layout var expectedBuffer = GC.AllocateUninitializedArray(512); var expectedBufferWriter = new SpanWriter(expectedBuffer); OutgoingGumpPackets.WritePacked(expectedLayout, ref expectedBufferWriter); var layoutLength = expectedBufferWriter.BytesWritten; var buffer = GC.AllocateUninitializedArray(512); var writer = new SpanWriter(buffer); staticGump.Compile(ref writer); // Assert layout is exactly what we are expecting AssertThat.Equal(writer.Span.Slice(19, layoutLength), expectedBufferWriter.Span); // Assert strings count AssertThat.Equal(writer.Span.Slice(19 + layoutLength, 4), stackalloc byte[] { 0, 0, 0, 3 }); var expectedStringsBuffer = GC.AllocateUninitializedArray(512); var expectedStringsWriter = new SpanWriter(expectedStringsBuffer); // Empty string expectedStringsWriter.Write((ushort)0); // loop through the strings, write them to the strings writer foreach (var str in strings) { expectedStringsWriter.Write((ushort)str.Length); expectedStringsWriter.WriteBigUni(str); } // Reset buffer expectedBufferWriter.Seek(0, SeekOrigin.Begin); OutgoingGumpPackets.WritePacked(expectedStringsWriter.Span, ref expectedBufferWriter); // Assert strings are exactly what we are expecting AssertThat.Equal(writer.Span[(19 + layoutLength + 4)..], expectedBufferWriter.Span); } private class CachedGump : StaticGump { private bool _isCachedLayout; public CachedGump() : base(50, 50) { Serial = (Serial)0x124; TypeID = 0x5346; } protected override void BuildLayout(ref StaticGumpBuilder builder) { Assert.False(_isCachedLayout); _isCachedLayout = true; builder.AddPage(); builder.AddHtml(30, 30, 150, 75, "Some text"); } protected override void BuildStrings(ref GumpStringsBuilder builder) { Assert.Fail("BuildStrings should not be called when the layout is cached."); } } }