269 lines
8.5 KiB
C#
269 lines
8.5 KiB
C#
using AyCode.Core.Extensions;
|
|
using MessagePack;
|
|
using MessagePack.Resolvers;
|
|
|
|
namespace AyCode.Core.Tests.TestModels;
|
|
|
|
/// <summary>
|
|
/// Common SignalR test/benchmark infrastructure.
|
|
/// Provides message creation and serialization helpers used by both tests and benchmarks.
|
|
/// </summary>
|
|
public static class SignalRMessageFactory
|
|
{
|
|
/// <summary>
|
|
/// Cached MessagePack options for ContractlessStandardResolver
|
|
/// </summary>
|
|
public static readonly MessagePackSerializerOptions ContractlessOptions = ContractlessStandardResolver.Options;
|
|
|
|
/// <summary>
|
|
/// Creates a MessagePack message for multiple parameters using IdMessage format.
|
|
/// Each parameter is serialized directly as JSON.
|
|
/// </summary>
|
|
public static byte[] CreateIdMessage(params object[] values)
|
|
{
|
|
var idMessage = new SignalRIdMessageDto(values);
|
|
var postMessage = new SignalRPostMessageDto { PostDataJson = idMessage.ToJson() };
|
|
return MessagePackSerializer.Serialize(postMessage, ContractlessOptions);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a MessagePack message for a single primitive parameter.
|
|
/// </summary>
|
|
public static byte[] CreateSingleParamMessage<T>(T value) where T : notnull
|
|
{
|
|
return CreateIdMessage(value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a MessagePack message for a complex object parameter.
|
|
/// Uses PostDataJson pattern for single complex objects.
|
|
/// </summary>
|
|
public static byte[] CreateComplexObjectMessage<T>(T obj)
|
|
{
|
|
var json = obj.ToJson();
|
|
var postMessage = new SignalRPostMessageDto { PostDataJson = json };
|
|
return MessagePackSerializer.Serialize(postMessage, ContractlessOptions);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates an empty MessagePack message for parameterless methods.
|
|
/// </summary>
|
|
public static byte[] CreateEmptyMessage()
|
|
{
|
|
var postMessage = new SignalRPostMessageDto();
|
|
return MessagePackSerializer.Serialize(postMessage, ContractlessOptions);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a response message in MessagePack format.
|
|
/// </summary>
|
|
public static byte[] CreateResponseMessage(int messageTag, byte status, string? responseDataJson)
|
|
{
|
|
var response = new SignalRResponseDto
|
|
{
|
|
MessageTag = messageTag,
|
|
Status = status,
|
|
ResponseData = responseDataJson
|
|
};
|
|
return MessagePackSerializer.Serialize(response, ContractlessOptions);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a success response message in MessagePack format.
|
|
/// </summary>
|
|
public static byte[] CreateSuccessResponse<T>(int messageTag, T data)
|
|
{
|
|
return CreateResponseMessage(messageTag, 5, data.ToJson()); // 5 = Success
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates an error response message in MessagePack format.
|
|
/// </summary>
|
|
public static byte[] CreateErrorResponse(int messageTag)
|
|
{
|
|
return CreateResponseMessage(messageTag, 0, null); // 0 = Error
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deserializes a MessagePack message to IdMessage DTO.
|
|
/// </summary>
|
|
public static SignalRIdMessageDto? DeserializeToIdMessage(byte[] messageBytes)
|
|
{
|
|
if (messageBytes == null || messageBytes.Length == 0) return null;
|
|
|
|
try
|
|
{
|
|
var postMessage = MessagePackSerializer.Deserialize<SignalRPostMessageDto>(messageBytes, ContractlessOptions);
|
|
return postMessage.PostDataJson?.JsonTo<SignalRIdMessageDto>();
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deserializes a MessagePack response message.
|
|
/// </summary>
|
|
public static SignalRResponseDto? DeserializeResponse(byte[] messageBytes)
|
|
{
|
|
if (messageBytes == null || messageBytes.Length == 0) return null;
|
|
|
|
try
|
|
{
|
|
return MessagePackSerializer.Deserialize<SignalRResponseDto>(messageBytes, ContractlessOptions);
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Lightweight DTO for IdMessage serialization/deserialization in tests and benchmarks.
|
|
/// Mirrors the structure of IdMessage without dependencies on AyCode.Services.
|
|
/// </summary>
|
|
public class SignalRIdMessageDto
|
|
{
|
|
public List<string> Ids { get; set; } = [];
|
|
|
|
public SignalRIdMessageDto()
|
|
{
|
|
}
|
|
|
|
public SignalRIdMessageDto(object[] ids)
|
|
{
|
|
Ids.AddRange(ids.Select(x => x.ToJson()));
|
|
}
|
|
|
|
public SignalRIdMessageDto(object id)
|
|
{
|
|
Ids.Add(id.ToJson());
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Lightweight DTO for SignalR post message serialization.
|
|
/// Mirrors SignalPostJsonMessage structure.
|
|
/// </summary>
|
|
[MessagePackObject]
|
|
public class SignalRPostMessageDto
|
|
{
|
|
[Key(0)]
|
|
public string? PostDataJson { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Lightweight DTO for SignalR response message serialization.
|
|
/// Mirrors SignalResponseJsonMessage structure.
|
|
/// </summary>
|
|
[MessagePackObject]
|
|
public class SignalRResponseDto
|
|
{
|
|
[Key(0)]
|
|
public int MessageTag { get; set; }
|
|
|
|
[Key(1)]
|
|
public byte Status { get; set; }
|
|
|
|
[Key(2)]
|
|
public string? ResponseData { get; set; }
|
|
|
|
[IgnoreMember]
|
|
public bool IsSuccess => Status == 5;
|
|
|
|
[IgnoreMember]
|
|
public bool IsError => Status == 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Common SignalR message tags for testing.
|
|
/// These mirror the production tags but are defined here for test/benchmark independence.
|
|
/// </summary>
|
|
public static class CommonSignalRTags
|
|
{
|
|
// Primitive parameter tags
|
|
public const int SingleIntParam = 100;
|
|
public const int TwoIntParams = 101;
|
|
public const int BoolParam = 102;
|
|
public const int StringParam = 103;
|
|
public const int GuidParam = 104;
|
|
public const int EnumParam = 105;
|
|
public const int NoParams = 107;
|
|
public const int MultipleTypesParams = 109;
|
|
|
|
// Extended primitives
|
|
public const int DecimalParam = 140;
|
|
public const int DateTimeParam = 141;
|
|
public const int DoubleParam = 143;
|
|
public const int LongParam = 144;
|
|
|
|
// Complex object tags
|
|
public const int TestOrderItemParam = 120;
|
|
public const int TestOrderParam = 121;
|
|
public const int SharedTagParam = 122;
|
|
|
|
// Collection tags
|
|
public const int IntArrayParam = 130;
|
|
public const int GuidArrayParam = 131;
|
|
public const int StringListParam = 132;
|
|
public const int TestOrderItemListParam = 133;
|
|
public const int IntListParam = 134;
|
|
public const int BoolArrayParam = 135;
|
|
public const int MixedWithArrayParam = 136;
|
|
|
|
// Mixed parameter scenarios
|
|
public const int IntAndDtoParam = 160;
|
|
public const int DtoAndListParam = 161;
|
|
public const int ThreeComplexParams = 162;
|
|
public const int FiveParams = 164;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Pre-built test messages for benchmarking.
|
|
/// Caches serialized messages to avoid setup overhead in benchmark iterations.
|
|
/// </summary>
|
|
public class SignalRBenchmarkData
|
|
{
|
|
// Pre-serialized messages
|
|
public byte[] SingleIntMessage { get; }
|
|
public byte[] TwoIntMessage { get; }
|
|
public byte[] FiveParamsMessage { get; }
|
|
public byte[] ComplexOrderItemMessage { get; }
|
|
public byte[] ComplexOrderMessage { get; }
|
|
public byte[] IntArrayMessage { get; }
|
|
public byte[] MixedParamsMessage { get; }
|
|
|
|
// Test data
|
|
public TestOrderItem TestOrderItem { get; }
|
|
public TestOrder TestOrder { get; }
|
|
public int[] IntArray { get; }
|
|
public Guid TestGuid { get; }
|
|
|
|
public SignalRBenchmarkData()
|
|
{
|
|
// Create test data
|
|
TestGuid = Guid.NewGuid();
|
|
IntArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
TestOrderItem = new TestOrderItem
|
|
{
|
|
Id = 42,
|
|
ProductName = "Benchmark Product",
|
|
Quantity = 100,
|
|
UnitPrice = 99.99m,
|
|
Status = TestStatus.Active
|
|
};
|
|
TestOrder = TestDataFactory.CreateOrder(itemCount: 3, palletsPerItem: 2, measurementsPerPallet: 2);
|
|
|
|
// Pre-serialize messages
|
|
SingleIntMessage = SignalRMessageFactory.CreateSingleParamMessage(42);
|
|
TwoIntMessage = SignalRMessageFactory.CreateIdMessage(10, 20);
|
|
FiveParamsMessage = SignalRMessageFactory.CreateIdMessage(42, "hello", true, TestGuid, 99.99m);
|
|
ComplexOrderItemMessage = SignalRMessageFactory.CreateComplexObjectMessage(TestOrderItem);
|
|
ComplexOrderMessage = SignalRMessageFactory.CreateComplexObjectMessage(TestOrder);
|
|
IntArrayMessage = SignalRMessageFactory.CreateComplexObjectMessage(IntArray);
|
|
MixedParamsMessage = SignalRMessageFactory.CreateIdMessage(true, IntArray, "hello");
|
|
}
|
|
}
|