summaryrefslogtreecommitdiff
path: root/Impostor-dev/src/Impostor.Tests
diff options
context:
space:
mode:
Diffstat (limited to 'Impostor-dev/src/Impostor.Tests')
-rw-r--r--Impostor-dev/src/Impostor.Tests/Events/EventManagerTests.cs175
-rw-r--r--Impostor-dev/src/Impostor.Tests/GameCodeTests.cs29
-rw-r--r--Impostor-dev/src/Impostor.Tests/Hazel/MessageReaderTests.cs372
-rw-r--r--Impostor-dev/src/Impostor.Tests/Hazel/MessageWriterTests.cs38
-rw-r--r--Impostor-dev/src/Impostor.Tests/Impostor.Tests.csproj20
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>