first commit

This commit is contained in:
2025-07-06 00:23:46 +02:00
commit 38f50c8819
1788 changed files with 112878 additions and 0 deletions

View 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);
}
}
}
}

View 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();
}
}
}