first commit
This commit is contained in:
79
Nitrox.Test/Model/Packets/PacketsSerializableTest.cs
Normal file
79
Nitrox.Test/Model/Packets/PacketsSerializableTest.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using BinaryPack.Attributes;
|
||||
using KellermanSoftware.CompareNetObjects;
|
||||
using KellermanSoftware.CompareNetObjects.TypeComparers;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Nitrox.Test.Helper.Faker;
|
||||
using NitroxModel_Subnautica.Logger;
|
||||
using NitroxModel.DataStructures;
|
||||
|
||||
namespace NitroxModel.Packets;
|
||||
|
||||
[TestClass]
|
||||
public class PacketsSerializableTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void InitSerializerTest()
|
||||
{
|
||||
Packet.InitSerializer();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PacketSerializationTest()
|
||||
{
|
||||
ComparisonConfig config = new();
|
||||
config.SkipInvalidIndexers = true;
|
||||
config.AttributesToIgnore.Add(typeof(IgnoredMemberAttribute));
|
||||
config.CustomComparers.Add(new CustomComparer<NitroxId, NitroxId>((id1, id2) => id1.Equals(id2)));
|
||||
CompareLogic comparer = new(config);
|
||||
|
||||
IEnumerable<Type> types = typeof(Packet).Assembly.GetTypes().Concat(typeof(SubnauticaInGameLogger).Assembly.GetTypes());
|
||||
Type[] packetTypes = types.Where(p => typeof(Packet).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract).ToArray();
|
||||
|
||||
// We want to ignore packets with no members when using ShouldNotCompare
|
||||
Type[] emptyPackets = packetTypes.Where(t => !t.GetMembers(BindingFlags.Public | BindingFlags.Instance)
|
||||
.Any(member => member.MemberType is MemberTypes.Field or MemberTypes.Property &&
|
||||
!member.GetCustomAttributes<IgnoredMemberAttribute>().Any()))
|
||||
.ToArray();
|
||||
|
||||
// We generate two different versions of each packet to verify comparison is actually working
|
||||
List<(Packet, Packet)> generatedPackets = new();
|
||||
|
||||
foreach (Type type in packetTypes)
|
||||
{
|
||||
dynamic faker = NitroxFaker.GetOrCreateFaker(type);
|
||||
|
||||
Packet packet = faker.Generate();
|
||||
Packet packet2 = null;
|
||||
|
||||
if (!emptyPackets.Contains(type))
|
||||
{
|
||||
ComparisonResult result;
|
||||
do
|
||||
{
|
||||
packet2 = faker.Generate();
|
||||
result = comparer.Compare(packet, packet2);
|
||||
} while (result == null || result.AreEqual);
|
||||
}
|
||||
|
||||
generatedPackets.Add(new ValueTuple<Packet, Packet>(packet, packet2));
|
||||
}
|
||||
|
||||
Packet.InitSerializer();
|
||||
|
||||
foreach (ValueTuple<Packet, Packet> packet in generatedPackets)
|
||||
{
|
||||
Packet deserialized = Packet.Deserialize(packet.Item1.Serialize());
|
||||
|
||||
packet.Item1.ShouldCompare(deserialized, $"with {packet.Item1.GetType()}", config);
|
||||
|
||||
if (!emptyPackets.Contains(packet.Item1.GetType()))
|
||||
{
|
||||
packet.Item2.ShouldNotCompare(deserialized, $"with {packet.Item1.GetType()}", config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
118
Nitrox.Test/Model/Packets/Processors/PacketProcessorTest.cs
Normal file
118
Nitrox.Test/Model/Packets/Processors/PacketProcessorTest.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Nitrox.Test;
|
||||
using NitroxClient;
|
||||
using NitroxClient.Communication.Packets.Processors.Abstract;
|
||||
using NitroxModel.Core;
|
||||
using NitroxModel.Packets.Processors.Abstract;
|
||||
using NitroxServer;
|
||||
using NitroxServer.Communication.Packets;
|
||||
using NitroxServer.Communication.Packets.Processors;
|
||||
using NitroxServer.Communication.Packets.Processors.Abstract;
|
||||
using NitroxServer_Subnautica;
|
||||
|
||||
namespace NitroxModel.Packets.Processors
|
||||
{
|
||||
[TestClass]
|
||||
public class PacketProcessorTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void ClientPacketProcessorSanity()
|
||||
{
|
||||
typeof(ClientPacketProcessor<>).Assembly.GetTypes()
|
||||
.Where(p => typeof(PacketProcessor).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract)
|
||||
.ToList()
|
||||
.ForEach(processor =>
|
||||
{
|
||||
// Make sure that each packet-processor is derived from the ClientPacketProcessor class,
|
||||
// so that it's packet-type can be determined.
|
||||
Assert.IsNotNull(processor.BaseType, $"{processor} does not derive from any type!");
|
||||
Assert.IsTrue(processor.BaseType.IsGenericType, $"{processor} does not derive from a generic type!");
|
||||
Assert.IsTrue(processor.BaseType.IsAssignableToGenericType(typeof(ClientPacketProcessor<>)), $"{processor} does not derive from ClientPacketProcessor!");
|
||||
|
||||
// Check constructor availability:
|
||||
int numCtors = processor.GetConstructors().Length;
|
||||
Assert.IsTrue(numCtors == 1, $"{processor} should have exactly 1 constructor! (has {numCtors})");
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ServerPacketProcessorSanity()
|
||||
{
|
||||
typeof(PacketHandler).Assembly.GetTypes()
|
||||
.Where(p => typeof(PacketProcessor).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract)
|
||||
.ToList()
|
||||
.ForEach(processor =>
|
||||
{
|
||||
// Make sure that each packet-processor is derived from the ClientPacketProcessor class,
|
||||
// so that it's packet-type can be determined.
|
||||
Assert.IsNotNull(processor.BaseType, $"{processor} does not derive from any type!");
|
||||
Assert.IsTrue(processor.BaseType.IsGenericType, $"{processor} does not derive from a generic type!");
|
||||
Assert.IsTrue(processor.BaseType.IsAssignableToGenericType(typeof(AuthenticatedPacketProcessor<>)) ||
|
||||
processor.BaseType.IsAssignableToGenericType(typeof(UnauthenticatedPacketProcessor<>)), $"{processor} does not derive from (Un)AuthenticatedPacketProcessor!");
|
||||
|
||||
// Check constructor availability:
|
||||
int numCtors = processor.GetConstructors().Length;
|
||||
Assert.IsTrue(numCtors == 1, $"{processor} should have exactly 1 constructor! (has {numCtors})");
|
||||
|
||||
// Unable to check parameters, these are defined in PacketHandler.ctor
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SameAmountOfServerPacketProcessors()
|
||||
{
|
||||
IEnumerable<Type> processors = typeof(PacketHandler).Assembly.GetTypes()
|
||||
.Where(p => typeof(PacketProcessor).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract);
|
||||
ServerAutoFacRegistrar serverDependencyRegistrar = new ServerAutoFacRegistrar();
|
||||
NitroxServiceLocator.InitializeDependencyContainer(serverDependencyRegistrar);
|
||||
NitroxServiceLocator.BeginNewLifetimeScope();
|
||||
|
||||
List<Type> packetTypes = typeof(DefaultServerPacketProcessor).Assembly.GetTypes()
|
||||
.Where(p => typeof(PacketProcessor).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract)
|
||||
.ToList();
|
||||
|
||||
int both = packetTypes.Count;
|
||||
Assert.AreEqual(processors.Count(), both,
|
||||
$"Not all(Un) AuthenticatedPacketProcessors have been discovered by the runtime code (auth + unauth: {both} out of {processors.Count()}). Perhaps the runtime matching code is too strict, or a processor does not derive from ClientPacketProcessor (and will hence not be detected).");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AllPacketsAreHandled()
|
||||
{
|
||||
List<Type> packetTypes = typeof(DefaultServerPacketProcessor).Assembly.GetTypes()
|
||||
.Where(p => typeof(PacketProcessor).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract)
|
||||
.ToList();
|
||||
|
||||
List<Type> abstractProcessorTypes = new();
|
||||
|
||||
abstractProcessorTypes.AddRange(typeof(ClientPacketProcessor<>)
|
||||
.Assembly.GetTypes()
|
||||
.Where(p => p.IsClass && p.IsAbstract && p.IsAssignableToGenericType(typeof(ClientPacketProcessor<>))));
|
||||
|
||||
abstractProcessorTypes.AddRange(typeof(AuthenticatedPacketProcessor<>)
|
||||
.Assembly.GetTypes()
|
||||
.Where(p => p.IsClass && p.IsAbstract && (p.IsAssignableToGenericType(typeof(AuthenticatedPacketProcessor<>)) || p.IsAssignableToGenericType(typeof(UnauthenticatedPacketProcessor<>)))));
|
||||
|
||||
NitroxServiceLocator.InitializeDependencyContainer(new ClientAutoFacRegistrar(), new SubnauticaServerAutoFacRegistrar(), new TestAutoFacRegistrar());
|
||||
NitroxServiceLocator.BeginNewLifetimeScope();
|
||||
|
||||
foreach (Type packet in typeof(Packet).Assembly.GetTypes().Where(p => typeof(Packet).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract).ToList())
|
||||
{
|
||||
Assert.IsTrue(packetTypes.Contains(packet) || abstractProcessorTypes.Any(genericProcessor =>
|
||||
{
|
||||
Type processorType = genericProcessor.MakeGenericType(packet);
|
||||
return NitroxServiceLocator.LocateOptionalService(processorType).HasValue;
|
||||
}), $"Packet of type '{packet}' should have at least one processor.");
|
||||
}
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
NitroxServiceLocator.EndCurrentLifetimeScope();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user