150 lines
6.6 KiB
C#
150 lines
6.6 KiB
C#
using AyCode.Core.Serializers.Binaries;
|
|
using AyCode.Core.Tests.TestModels;
|
|
|
|
namespace AyCode.Core.Tests.Serialization;
|
|
|
|
/// <summary>
|
|
/// Tests for Source Generator based serialization integration.
|
|
/// </summary>
|
|
[TestClass]
|
|
public class GeneratedSerializerIntegrationTests
|
|
{
|
|
[TestMethod]
|
|
public void GeneratedSerializerType_Exists_ForMarkedTypes()
|
|
{
|
|
// Arrange - types marked with [AcBinarySerializable]
|
|
var type = typeof(GeneratedSerializerTestModel);
|
|
|
|
// Act - find the generated serializer type directly
|
|
var generatedTypeName = $"{type.FullName}_AcBinarySerializer";
|
|
var serializerType = type.Assembly.GetType(generatedTypeName);
|
|
|
|
// Assert
|
|
Assert.IsNotNull(serializerType,
|
|
$"Generated serializer type '{generatedTypeName}' should exist for [AcBinarySerializable] marked type");
|
|
}
|
|
|
|
[TestMethod]
|
|
public void GeneratedSerializerType_HasCorrectMethods()
|
|
{
|
|
// Arrange
|
|
var type = typeof(SimpleGeneratedModel);
|
|
|
|
// Act - find the generated serializer type directly
|
|
var generatedTypeName = $"{type.FullName}_AcBinarySerializer";
|
|
var serializerType = type.Assembly.GetType(generatedTypeName);
|
|
|
|
// Assert
|
|
Assert.IsNotNull(serializerType, $"Generated serializer type '{generatedTypeName}' should exist");
|
|
|
|
var serializeMethod = serializerType.GetMethod("Serialize",
|
|
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
|
|
Assert.IsNotNull(serializeMethod, "Serialize method should exist");
|
|
|
|
var deserializeMethod = serializerType.GetMethod("Deserialize",
|
|
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
|
|
Assert.IsNotNull(deserializeMethod, "Deserialize method should exist");
|
|
|
|
var propertyNamesField = serializerType.GetField("PropertyNames",
|
|
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
|
|
Assert.IsNotNull(propertyNamesField, "PropertyNames field should exist");
|
|
|
|
var propertyNames = propertyNamesField.GetValue(null) as string[];
|
|
Assert.IsNotNull(propertyNames, "PropertyNames should not be null");
|
|
Assert.AreEqual(3, propertyNames.Length, "SimpleGeneratedModel has 3 properties");
|
|
|
|
// Verify alphabetical order
|
|
Assert.AreEqual("Age", propertyNames[0]);
|
|
Assert.AreEqual("FirstName", propertyNames[1]);
|
|
Assert.AreEqual("LastName", propertyNames[2]);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void GeneratedSerializerPropertyNames_MatchRuntimeOrder()
|
|
{
|
|
// This test verifies that the generated property order matches the runtime serializer's order
|
|
// This is critical for binary compatibility!
|
|
|
|
var type = typeof(GeneratedSerializerTestModel);
|
|
|
|
// Get generated property names
|
|
var generatedTypeName = $"{type.FullName}_AcBinarySerializer";
|
|
var serializerType = type.Assembly.GetType(generatedTypeName);
|
|
Assert.IsNotNull(serializerType);
|
|
|
|
var propertyNamesField = serializerType.GetField("PropertyNames",
|
|
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
|
|
var generatedNames = propertyNamesField?.GetValue(null) as string[];
|
|
Assert.IsNotNull(generatedNames);
|
|
|
|
// Get runtime property names using the same logic as TypeMetadataBase
|
|
var runtimeProps = type.GetProperties(
|
|
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
|
|
.Where(p => p.CanRead && p.CanWrite && !p.GetIndexParameters().Any())
|
|
.OrderBy(p => p.Name, StringComparer.Ordinal)
|
|
.Select(p => p.Name)
|
|
.ToArray();
|
|
|
|
// Assert they match
|
|
CollectionAssert.AreEqual(runtimeProps, generatedNames,
|
|
"Generated property names must match runtime property order for binary compatibility");
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Serialization_WorksCorrectly_WithGeneratedSerializerPresent()
|
|
{
|
|
// This test ensures that regular serialization still works even when
|
|
// generated serializers are present (they are not yet integrated into the hot path)
|
|
|
|
var original = new GeneratedSerializerTestModel
|
|
{
|
|
Id = 42,
|
|
Name = "Test",
|
|
IsActive = true,
|
|
Value = 3.14,
|
|
Created = new DateTime(2025, 1, 5, 10, 30, 0, DateTimeKind.Utc),
|
|
UniqueId = Guid.NewGuid(),
|
|
Price = 99.99m,
|
|
BigNumber = 9999999999L
|
|
};
|
|
|
|
// Serialize and deserialize using the regular path
|
|
var bytes = AcBinarySerializer.Serialize(original, AcBinarySerializerOptions.WithoutReferenceHandling());
|
|
var deserialized = AcBinaryDeserializer.Deserialize<GeneratedSerializerTestModel>(bytes);
|
|
|
|
// Assert
|
|
Assert.IsNotNull(deserialized);
|
|
Assert.AreEqual(original.Id, deserialized.Id);
|
|
Assert.AreEqual(original.Name, deserialized.Name);
|
|
Assert.AreEqual(original.IsActive, deserialized.IsActive);
|
|
Assert.AreEqual(original.Value, deserialized.Value);
|
|
Assert.AreEqual(original.Created, deserialized.Created);
|
|
Assert.AreEqual(original.UniqueId, deserialized.UniqueId);
|
|
Assert.AreEqual(original.Price, deserialized.Price);
|
|
Assert.AreEqual(original.BigNumber, deserialized.BigNumber);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void NestedType_GeneratedSerializer_IsFound()
|
|
{
|
|
// Test that nested types (like QuickBenchmark.TestClassWithRepeatedValues)
|
|
// have their generated serializers properly named and discoverable
|
|
|
|
var type = typeof(QuickBenchmark.TestClassWithRepeatedValues);
|
|
var ns = type.Namespace ?? "";
|
|
|
|
// For nested types, the generated class is at namespace level with just the type name
|
|
var simpleName = $"{(string.IsNullOrEmpty(ns) ? "" : ns + ".")}{type.Name}_AcBinarySerializer";
|
|
var serializerType = type.Assembly.GetType(simpleName);
|
|
|
|
Assert.IsNotNull(serializerType,
|
|
$"Generated serializer for nested type should be found at '{simpleName}'");
|
|
|
|
// Verify it has the expected methods
|
|
Assert.IsNotNull(serializerType.GetMethod("Serialize",
|
|
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static));
|
|
Assert.IsNotNull(serializerType.GetMethod("Deserialize",
|
|
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static));
|
|
}
|
|
}
|