diff options
Diffstat (limited to 'Impostor-dev/src/Impostor.Tests')
5 files changed, 634 insertions, 0 deletions
diff --git a/Impostor-dev/src/Impostor.Tests/Events/EventManagerTests.cs b/Impostor-dev/src/Impostor.Tests/Events/EventManagerTests.cs new file mode 100644 index 0000000..d222d79 --- /dev/null +++ b/Impostor-dev/src/Impostor.Tests/Events/EventManagerTests.cs @@ -0,0 +1,175 @@ +using System.Collections.Generic; +using System.Net.Sockets; +using System.Threading.Tasks; +using Impostor.Api.Events; +using Impostor.Api.Events.Managers; +using Impostor.Server.Events; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace Impostor.Tests.Events +{ + public class EventManagerTests + { + public static readonly IEnumerable<object[]> TestModes = new [] + { + new object[] { TestMode.Service }, + new object[] { TestMode.Temporary } + }; + + [Theory] + [MemberData(nameof(TestModes))] + public async ValueTask CallEvent(TestMode mode) + { + var listener = new EventListener(); + var eventManager = CreatEventManager(mode, listener); + + await eventManager.CallAsync(new SetValueEvent(1)); + + Assert.Equal(1, listener.Value); + } + + [Theory] + [MemberData(nameof(TestModes))] + public async Task CallPriority(TestMode mode) + { + var listener = new PriorityEventListener(); + var eventManager = CreatEventManager(mode, listener); + + await eventManager.CallAsync(new SetValueEvent(1)); + + Assert.Equal(new [] + { + EventPriority.Monitor, + EventPriority.Highest, + EventPriority.High, + EventPriority.Normal, + EventPriority.Low, + EventPriority.Lowest + }, listener.Priorities); + } + + [Theory] + [MemberData(nameof(TestModes))] + public async ValueTask CancelEvent(TestMode mode) + { + var listener = new EventListener(); + var eventManager = CreatEventManager( + mode, + new CancelAtHighEventListener(), + listener + ); + + await eventManager.CallAsync(new SetValueEvent(1)); + + Assert.Equal(0, listener.Value); + } + + [Theory] + [MemberData(nameof(TestModes))] + public async Task CancelPriority(TestMode mode) + { + var listener = new PriorityEventListener(); + var eventManager = CreatEventManager( + mode, + new CancelAtHighEventListener(), + listener + ); + + await eventManager.CallAsync(new SetValueEvent(1)); + + Assert.Equal(new [] + { + EventPriority.Monitor, + EventPriority.Highest + }, listener.Priorities); + } + + private static IEventManager CreatEventManager(TestMode mode, params IEventListener[] listeners) + { + var services = new ServiceCollection(); + services.AddLogging(); + services.AddSingleton<IEventManager, EventManager>(); + + if (mode == TestMode.Service) + { + foreach (var listener in listeners) + { + services.AddSingleton(listener); + } + } + + var eventManager = services.BuildServiceProvider().GetRequiredService<IEventManager>(); + + if (mode == TestMode.Temporary) + { + foreach (var listener in listeners) + { + eventManager.RegisterListener(listener); + } + } + + return eventManager; + } + + public enum TestMode + { + Service, + Temporary + } + + public interface ISetValueEvent : IEventCancelable + { + int Value { get; } + } + + public class SetValueEvent : ISetValueEvent + { + public SetValueEvent(int value) + { + Value = value; + } + + public int Value { get; } + + public bool IsCancelled { get; set; } + } + + private class CancelAtHighEventListener : IEventListener + { + [EventListener(Priority = EventPriority.High)] + public void OnSetCalled(ISetValueEvent e) => e.IsCancelled = true; + } + + private class EventListener : IEventListener + { + public int Value { get; private set; } + + [EventListener] + public void OnSetCalled(ISetValueEvent e) => Value = e.Value; + } + + private class PriorityEventListener : IEventListener + { + public List<EventPriority> Priorities { get; } = new List<EventPriority>(); + + [EventListener(EventPriority.Lowest)] + public void OnLowest(ISetValueEvent e) => Priorities.Add(EventPriority.Lowest); + + [EventListener(EventPriority.Low)] + public void OnLow(ISetValueEvent e) => Priorities.Add(EventPriority.Low); + + [EventListener] + public void OnNormal(ISetValueEvent e) => Priorities.Add(EventPriority.Normal); + + [EventListener(EventPriority.High)] + public void OnHigh(ISetValueEvent e) => Priorities.Add(EventPriority.High); + + [EventListener(EventPriority.Highest)] + public void OnHighest(ISetValueEvent e) => Priorities.Add(EventPriority.Highest); + + [EventListener(EventPriority.Monitor)] + public void OnMonitor(ISetValueEvent e) => Priorities.Add(EventPriority.Monitor); + } + } +} diff --git a/Impostor-dev/src/Impostor.Tests/GameCodeTests.cs b/Impostor-dev/src/Impostor.Tests/GameCodeTests.cs new file mode 100644 index 0000000..de98123 --- /dev/null +++ b/Impostor-dev/src/Impostor.Tests/GameCodeTests.cs @@ -0,0 +1,29 @@ +using Impostor.Api.Innersloth; + +using Xunit; + +namespace Impostor.Tests +{ + public class GameCodeTests + { + [Fact] + public void CodeV1() + { + const string code = "ABCD"; + const int codeInt = 0x44434241; + + Assert.Equal(code, GameCodeParser.IntToGameName(codeInt)); + Assert.Equal(codeInt, GameCodeParser.GameNameToInt(code)); + } + + [Fact] + public void CodeV2() + { + const string code = "ABCDEF"; + const int codeInt = -1943683525; + + Assert.Equal(code, GameCodeParser.IntToGameName(codeInt)); + Assert.Equal(codeInt, GameCodeParser.GameNameToInt(code)); + } + } +}
\ No newline at end of file diff --git a/Impostor-dev/src/Impostor.Tests/Hazel/MessageReaderTests.cs b/Impostor-dev/src/Impostor.Tests/Hazel/MessageReaderTests.cs new file mode 100644 index 0000000..e7fa0df --- /dev/null +++ b/Impostor-dev/src/Impostor.Tests/Hazel/MessageReaderTests.cs @@ -0,0 +1,372 @@ +using System; +using System.Linq; +using Impostor.Api; +using Impostor.Hazel; +using Impostor.Hazel.Extensions; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.ObjectPool; +using Xunit; + +namespace Impostor.Tests.Hazel +{ + public class MessageReaderTests + { + private ObjectPool<MessageReader> CreateReaderPool() + { + var services = new ServiceCollection(); + services.AddHazel(); + return services.BuildServiceProvider().GetRequiredService<ObjectPool<MessageReader>>(); + } + + [Fact] + public void ReadProperInt() + { + const int Test1 = int.MaxValue; + const int Test2 = int.MinValue; + + var msg = new MessageWriter(128); + msg.StartMessage(1); + msg.Write(Test1); + msg.Write(Test2); + msg.EndMessage(); + + Assert.Equal(11, msg.Length); + Assert.Equal(msg.Length, msg.Position); + + var readerPool = CreateReaderPool(); + var reader = readerPool.Get(); + reader.Update(msg.Buffer); + Assert.Equal(byte.MaxValue, reader.Tag); + var message = reader.ReadMessage(); + Assert.Equal(1, message.Tag); + Assert.Equal(Test1, message.ReadInt32()); + Assert.Equal(Test2, message.ReadInt32()); + } + + [Fact] + public void ReadProperBool() + { + const bool Test1 = true; + const bool Test2 = false; + + var msg = new MessageWriter(128); + msg.StartMessage(1); + msg.Write(Test1); + msg.Write(Test2); + msg.EndMessage(); + + Assert.Equal(5, msg.Length); + Assert.Equal(msg.Length, msg.Position); + + var readerPool = CreateReaderPool(); + var reader = readerPool.Get(); + reader.Update(msg.Buffer); + Assert.Equal(byte.MaxValue, reader.Tag); + var message = reader.ReadMessage(); + Assert.Equal(1, message.Tag); + Assert.Equal(Test1, message.ReadBoolean()); + Assert.Equal(Test2, message.ReadBoolean()); + } + + [Fact] + public void ReadProperString() + { + const string Test1 = "Hello"; + string Test2 = new string(' ', 1024); + var msg = new MessageWriter(2048); + msg.StartMessage(1); + msg.Write(Test1); + msg.Write(Test2); + msg.Write(string.Empty); + msg.EndMessage(); + + Assert.Equal(msg.Length, msg.Position); + + var readerPool = CreateReaderPool(); + var reader = readerPool.Get(); + reader.Update(msg.Buffer); + Assert.Equal(byte.MaxValue, reader.Tag); + var message = reader.ReadMessage(); + Assert.Equal(1, message.Tag); + Assert.Equal(Test1, message.ReadString()); + Assert.Equal(Test2, message.ReadString()); + Assert.Equal(string.Empty, message.ReadString()); + } + + [Fact] + public void ReadProperFloat() + { + const float Test1 = 12.34f; + + var msg = new MessageWriter(2048); + msg.StartMessage(1); + msg.Write(Test1); + msg.EndMessage(); + + Assert.Equal(7, msg.Length); + Assert.Equal(msg.Length, msg.Position); + + var readerPool = CreateReaderPool(); + var reader = readerPool.Get(); + reader.Update(msg.Buffer); + Assert.Equal(byte.MaxValue, reader.Tag); + var message = reader.ReadMessage(); + Assert.Equal(1, message.Tag); + Assert.Equal(Test1, message.ReadSingle()); + } + + [Fact] + public void CopyMessage() + { + var readerPool = CreateReaderPool(); + + // Create message. + const int msgLength = 18; + const byte Test1 = 12; + const byte Test2 = 146; + + var msg = new MessageWriter(2048); + + msg.StartMessage(1); + msg.StartMessage(2); + msg.Write(Test1); + msg.Write(Test2); + msg.StartMessage(2); + msg.Write(Test1); + msg.Write(Test2); + msg.StartMessage(2); + msg.Write(Test1); + msg.Write(Test2); + msg.EndMessage(); + msg.EndMessage(); + msg.EndMessage(); + msg.EndMessage(); + + // Read message. + using var reader = readerPool.Get(); + + reader.Update(msg.Buffer); + + // Read first message. + using var messageOne = reader.ReadMessage(); + + Assert.Equal(1, messageOne.Tag); + Assert.Equal(0, messageOne.Position); + Assert.Equal(3, messageOne.Offset); + Assert.Equal(msgLength - 3, messageOne.Length); + + using var messageTwo = messageOne.ReadMessage(); + + Assert.Equal(2, messageTwo.Tag); + Assert.Equal(0, messageTwo.Position); + Assert.Equal(6, messageTwo.Offset); + Assert.Equal(msgLength - 6, messageTwo.Length); + Assert.Equal(Test1, messageTwo.ReadByte()); + Assert.Equal(Test2, messageTwo.ReadByte()); + + using var messageThree = messageTwo.ReadMessage(); + + Assert.Equal(2, messageThree.Tag); + Assert.Equal(0, messageThree.Position); + Assert.Equal(11, messageThree.Offset); + Assert.Equal(msgLength - 11, messageThree.Length); + Assert.Equal(Test1, messageThree.ReadByte()); + Assert.Equal(Test2, messageThree.ReadByte()); + } + + [Fact] + public void CopySubMessage() + { + const byte Test1 = 12; + const byte Test2 = 146; + + var msg = new MessageWriter(2048); + msg.StartMessage(1); + + msg.StartMessage(2); + msg.Write(Test1); + msg.Write(Test2); + msg.EndMessage(); + + msg.EndMessage(); + + var readerPool = CreateReaderPool(); + var handleReader = readerPool.Get(); + handleReader.Update(msg.Buffer); + var handleMessage = handleReader.ReadMessage(); + Assert.Equal(1, handleMessage.Tag); + + using var parentReader = handleMessage.Copy(); + + Assert.Equal(1, parentReader.Tag); + + var reader = parentReader.ReadMessage(); + + Assert.Equal(2, reader.Tag); + Assert.Equal(Test1, reader.ReadByte()); + Assert.Equal(Test2, reader.ReadByte()); + } + + [Fact] + public void CopyToMessage() + { + var expected = new byte[] + { + 0x2A, 0x00, 0x01, 0x27, 0x00, 0x02, 0x26, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, + 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x20, 0x70, 0x61, + 0x63, 0x6B, 0x65, 0x74, 0x20, 0x74, 0x6F, 0x20, + 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x6F, 0x70, + 0x79, 0x69, 0x6E, 0x67, 0x2E + }; + + var readerPool = CreateReaderPool(); + + // Create packet. + var msg = new MessageWriter(2048); + msg.StartMessage(1); + msg.StartMessage(2); + msg.Write("This is a long packet to test copying."); + msg.EndMessage(); + msg.EndMessage(); + + // Create a reader. + var reader = readerPool.Get(); + + reader.Update(msg.Buffer); + + // Read the initial message. + var message = reader.ReadMessage(); + + // Copy the message to a new writer. + var writer = new MessageWriter(2048); + + message.CopyTo(writer); + + // Compare. + Assert.Equal(expected, writer.ToByteArray(true)); + } + + [Fact] + public void ReadMessageLength() + { + var msg = new MessageWriter(2048); + msg.StartMessage(1); + msg.Write(65534); + msg.StartMessage(2); + msg.Write("HO"); + msg.EndMessage(); + msg.StartMessage(2); + msg.Write("NO"); + msg.EndMessage(); + msg.EndMessage(); + + Assert.Equal(msg.Length, msg.Position); + + var readerPool = CreateReaderPool(); + var reader = readerPool.Get(); + reader.Update(msg.Buffer); + Assert.Equal(byte.MaxValue, reader.Tag); + var message = reader.ReadMessage(); + Assert.Equal(1, message.Tag); + Assert.Equal(65534, message.ReadInt32()); // Content + + var sub = message.ReadMessage(); + Assert.Equal(3, sub.Length); + Assert.Equal(2, sub.Tag); + Assert.Equal("HO", sub.ReadString()); + + sub = message.ReadMessage(); + Assert.Equal(3, sub.Length); + Assert.Equal(2, sub.Tag); + Assert.Equal("NO", sub.ReadString()); + } + + [Fact] + public void RemoveMessage() + { + // Create expected message. + var messageExpected = new MessageWriter(1024); + + messageExpected.StartMessage(0); + messageExpected.StartMessage(1); + messageExpected.Write("HiTest1"); + messageExpected.EndMessage(); + messageExpected.StartMessage(2); + messageExpected.Write("HiTest2"); + messageExpected.EndMessage(); + messageExpected.EndMessage(); + + // Create message. + var messageWriter = new MessageWriter(1024); + + messageWriter.StartMessage(0); + messageWriter.StartMessage(1); + messageWriter.Write("HiTest1"); + messageWriter.StartMessage(2); + messageWriter.Write("RemoveMe!"); + messageWriter.EndMessage(); + messageWriter.EndMessage(); + messageWriter.StartMessage(2); + messageWriter.Write("HiTest2"); + messageWriter.EndMessage(); + messageWriter.EndMessage(); + + // Copy buffer. + var bufferCopy = new byte[messageWriter.Length]; + Buffer.BlockCopy(messageWriter.Buffer, 0, bufferCopy, 0, bufferCopy.Length); + + var bufferCopyTwo = new byte[messageWriter.Length]; + Buffer.BlockCopy(messageWriter.Buffer, 0, bufferCopyTwo, 0, bufferCopyTwo.Length); + + // Do the magic. + var readerPool = CreateReaderPool(); + var reader = readerPool.Get(); + reader.Update(bufferCopy); + var inner = reader.ReadMessage(); + + while (inner.Position < inner.Length) + { + var message = inner.ReadMessage(); + if (message.Tag == 1) + { + Assert.Equal("HiTest1", message.ReadString()); + + var messageSub = message.ReadMessage(); + if (messageSub.Tag == 2) + { + Assert.Equal("RemoveMe!", messageSub.ReadString()); + + // Remove this message. + inner.RemoveMessage(messageSub); + } + } + else if (message.Tag == 2) + { + Assert.Equal("HiTest2", message.ReadString()); + } + else + { + Assert.True(false, "Invalid tag was read."); + } + } + + // Check if the magic was successful. + Assert.Equal(messageExpected.Length, reader.Length); + Assert.Equal(messageExpected.ToByteArray(true), reader.Buffer.Take(reader.Length).ToArray()); + + // Test ownership. + var readerTwo = readerPool.Get(); + + readerTwo.Update(bufferCopyTwo); + + Assert.Throws<ImpostorProtocolException>(() => reader.RemoveMessage(readerTwo.ReadMessage())); + } + + [Fact] + public void GetLittleEndian() + { + Assert.True(MessageWriter.IsLittleEndian()); + } + } +} diff --git a/Impostor-dev/src/Impostor.Tests/Hazel/MessageWriterTests.cs b/Impostor-dev/src/Impostor.Tests/Hazel/MessageWriterTests.cs new file mode 100644 index 0000000..83d67da --- /dev/null +++ b/Impostor-dev/src/Impostor.Tests/Hazel/MessageWriterTests.cs @@ -0,0 +1,38 @@ +using System; +using System.Linq; +using Impostor.Hazel; +using Xunit; + +namespace Impostor.Tests.Hazel +{ + public class MessageWriterTests + { + [Fact] + public void ReadOnlyMemoryWriteWorksTheSameAsArray() + { + var oldVer = new MessageWriter(1024); + var newVer = new MessageWriter(1024); + + var data = Enumerable.Repeat + ( + Enumerable.Range(0, byte.MaxValue) + .Select(x => (byte)x), + 2 + ).SelectMany(x => x).ToArray(); + + WriteSomeData(oldVer); + WriteSomeData(newVer); + + oldVer.Write(data); + newVer.Write(data.AsMemory()); + + Assert.True(oldVer.Buffer.AsSpan().SequenceEqual(newVer.Buffer.AsSpan())); + + static void WriteSomeData(MessageWriter oldVer) + { + oldVer.WritePacked(99); + oldVer.WritePacked(101); + } + } + } +}
\ No newline at end of file diff --git a/Impostor-dev/src/Impostor.Tests/Impostor.Tests.csproj b/Impostor-dev/src/Impostor.Tests/Impostor.Tests.csproj new file mode 100644 index 0000000..3f96bf6 --- /dev/null +++ b/Impostor-dev/src/Impostor.Tests/Impostor.Tests.csproj @@ -0,0 +1,20 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net5.0</TargetFramework> + <IsPackable>false</IsPackable> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" /> + <PackageReference Include="xunit" Version="2.4.1" /> + <PackageReference Include="xunit.runner.reporters" Version="2.4.1" /> + <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> + <PackageReference Include="coverlet.collector" Version="1.3.0" /> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="..\Impostor.Server\Impostor.Server.csproj" /> + </ItemGroup> + +</Project> |