634 lines
20 KiB
C#
634 lines
20 KiB
C#
namespace AyCode.Core.Tests.Serialization;
|
|
|
|
/// <summary>
|
|
/// Test models for binary serializer tests.
|
|
/// </summary>
|
|
public static class AcSerializerModels
|
|
{
|
|
public class TestSimpleClass
|
|
{
|
|
public int Id { get; set; }
|
|
public string Name { get; set; } = "";
|
|
public double Value { get; set; }
|
|
public bool IsActive { get; set; }
|
|
}
|
|
|
|
public class TestNestedClass
|
|
{
|
|
public int Id { get; set; }
|
|
public string Name { get; set; } = "";
|
|
public TestSimpleClass? Child { get; set; }
|
|
}
|
|
|
|
public class TestClassWithList
|
|
{
|
|
public int Id { get; set; }
|
|
public List<string> Items { get; set; } = new();
|
|
}
|
|
|
|
public class TestClassWithRepeatedStrings
|
|
{
|
|
public string Field1 { get; set; } = "";
|
|
public string Field2 { get; set; } = "";
|
|
public string Field3 { get; set; } = "";
|
|
public string Field4 { get; set; } = "";
|
|
}
|
|
|
|
public class TestClassWithLongPropertyNames
|
|
{
|
|
public string FirstProperty { get; set; } = "";
|
|
public string SecondProperty { get; set; } = "";
|
|
public string ThirdProperty { get; set; } = "";
|
|
public string FourthProperty { get; set; } = "";
|
|
}
|
|
|
|
public class TestClassWithMixedStrings
|
|
{
|
|
public int Id { get; set; }
|
|
public string ShortName { get; set; } = "";
|
|
public string LongName { get; set; } = "";
|
|
public string Description { get; set; } = "";
|
|
public string Tag { get; set; } = "";
|
|
}
|
|
|
|
public class TestNestedStructure
|
|
{
|
|
public string RootName { get; set; } = "";
|
|
public List<TestLevel1> Level1Items { get; set; } = new();
|
|
}
|
|
|
|
public class TestLevel1
|
|
{
|
|
public string Level1Name { get; set; } = "";
|
|
public List<TestLevel2> Level2Items { get; set; } = new();
|
|
}
|
|
|
|
public class TestLevel2
|
|
{
|
|
public string Level2Name { get; set; } = "";
|
|
public string Value { get; set; } = "";
|
|
}
|
|
|
|
public class TestClassWithRepeatedValues
|
|
{
|
|
public int Id { get; set; }
|
|
public string Status { get; set; } = "";
|
|
public string Category { get; set; } = "";
|
|
public string Priority { get; set; } = "";
|
|
}
|
|
|
|
public class TestClassWithNameValue
|
|
{
|
|
public string Name { get; set; } = "";
|
|
public string Value { get; set; } = "";
|
|
}
|
|
|
|
public class TestClassWithNullableStrings
|
|
{
|
|
public int Id { get; set; }
|
|
public string RequiredName { get; set; } = "";
|
|
public string? OptionalName { get; set; }
|
|
public string? Description { get; set; }
|
|
}
|
|
|
|
public class TestCustomerLikeDto
|
|
{
|
|
public int Id { get; set; }
|
|
public string FirstName { get; set; } = "";
|
|
public string LastName { get; set; } = "";
|
|
public string Email { get; set; } = "";
|
|
public string Company { get; set; } = "";
|
|
public string Department { get; set; } = "";
|
|
public string Role { get; set; } = "";
|
|
public string Status { get; set; } = "";
|
|
public List<TestAttribute> Attributes { get; set; } = new();
|
|
}
|
|
|
|
public class TestAttribute
|
|
{
|
|
public string Key { get; set; } = "";
|
|
public string Value { get; set; } = "";
|
|
}
|
|
|
|
public class TestHighReuseDto
|
|
{
|
|
public int Id { get; set; }
|
|
public string CategoryCode { get; set; } = "";
|
|
public string StatusCode { get; set; } = "";
|
|
public string TypeCode { get; set; } = "";
|
|
public string PriorityCode { get; set; } = "";
|
|
public string UniqueField { get; set; } = "";
|
|
}
|
|
|
|
public class TestClassWithNullableProperties
|
|
{
|
|
public int Id { get; set; }
|
|
|
|
public int? NullableInt { get; set; }
|
|
public int? NullableIntNull { get; set; }
|
|
|
|
public long? NullableLong { get; set; }
|
|
public long? NullableLongNull { get; set; }
|
|
|
|
public double? NullableDouble { get; set; }
|
|
public double? NullableDoubleNull { get; set; }
|
|
|
|
public decimal? NullableDecimal { get; set; }
|
|
public decimal? NullableDecimalNull { get; set; }
|
|
|
|
public DateTime? NullableDateTime { get; set; }
|
|
public DateTime? NullableDateTimeNull { get; set; }
|
|
|
|
public Guid? NullableGuid { get; set; }
|
|
public Guid? NullableGuidNull { get; set; }
|
|
|
|
public bool? NullableBool { get; set; }
|
|
public bool? NullableBoolNull { get; set; }
|
|
}
|
|
|
|
public class TestParentWithNullableChild
|
|
{
|
|
public int Id { get; set; }
|
|
public string Name { get; set; } = "";
|
|
public TestClassWithNullableProperties? Child { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Test model mimicking StockTaking entity structure.
|
|
/// /// </summary>
|
|
public class TestStockTaking
|
|
{
|
|
public int Id { get; set; }
|
|
public DateTime StartDateTime { get; set; }
|
|
public bool IsClosed { get; set; }
|
|
public int Creator { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
public List<TestStockTakingItem>? StockTakingItems { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Test model mimicking StockTakingItem entity structure.
|
|
/// /// </summary>
|
|
public class TestStockTakingItem
|
|
{
|
|
public int Id { get; set; }
|
|
public int StockTakingId { get; set; }
|
|
public int ProductId { get; set; }
|
|
public bool IsMeasured { get; set; }
|
|
public int OriginalStockQuantity { get; set; }
|
|
public int MeasuredStockQuantity { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
public List<TestStockTakingItemPallet>? StockTakingItemPallets { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Test model mimicking StockTakingItemPallet/MeasuringItemPalletBase entity structure.
|
|
/// Contains nullable int properties (CreatorId, ModifierId) that caused the production bug.
|
|
/// </summary>
|
|
public class TestStockTakingItemPallet
|
|
{
|
|
public int Id { get; set; }
|
|
public int StockTakingItemId { get; set; }
|
|
public int TrayQuantity { get; set; }
|
|
public double TareWeight { get; set; }
|
|
public double PalletWeight { get; set; }
|
|
public double GrossWeight { get; set; }
|
|
public bool IsMeasured { get; set; }
|
|
|
|
public int? CreatorId { get; set; }
|
|
public int? ModifierId { get; set; }
|
|
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
}
|
|
|
|
public class TestEntityWithDateTimeAndInt
|
|
{
|
|
public int Id { get; set; }
|
|
public int IntValue { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
public int StatusCode { get; set; }
|
|
public string Name { get; set; } = "";
|
|
}
|
|
|
|
public class TestEntityWithManyIntsBeforeDateTime
|
|
{
|
|
public int Id { get; set; }
|
|
public int Value1 { get; set; }
|
|
public int Value2 { get; set; }
|
|
public int Value3 { get; set; }
|
|
public int Value4 { get; set; }
|
|
public int Value5 { get; set; }
|
|
public DateTime FirstDateTime { get; set; }
|
|
public DateTime SecondDateTime { get; set; }
|
|
public int FinalValue { get; set; }
|
|
}
|
|
|
|
public class TestParentEntityWithDateTimeChild
|
|
{
|
|
public int ParentId { get; set; }
|
|
public string ParentName { get; set; } = "";
|
|
public TestEntityWithDateTimeAndInt? Child { get; set; }
|
|
}
|
|
|
|
public class TestParentWithDateTimeItemCollection
|
|
{
|
|
public int Id { get; set; }
|
|
public string Name { get; set; } = "";
|
|
public DateTime Created { get; set; }
|
|
public List<TestEntityWithDateTimeAndInt>? Items { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Base class to simulate inheritance hierarchy like MgEntityBase.
|
|
/// Id property is in base class, so reflection may return it last.
|
|
/// </summary>
|
|
public abstract class TestEntityBase
|
|
{
|
|
public int Id { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Simulates MgStockTaking structure with inheritance.
|
|
/// Properties are ordered: StartDateTime, IsClosed, StockTakingItems, Creator, Created, Modified
|
|
/// Id comes from base class and may appear last in reflection.
|
|
/// </summary>
|
|
public class TestStockTakingWithInheritance : TestEntityBase
|
|
{
|
|
public DateTime StartDateTime { get; set; }
|
|
public bool IsClosed { get; set; }
|
|
public List<TestStockTakingItemWithInheritance>? StockTakingItems { get; set; }
|
|
public int Creator { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Simulates StockTakingItem with inheritance.
|
|
/// </summary>
|
|
public class TestStockTakingItemWithInheritance : TestEntityBase
|
|
{
|
|
public int StockTakingId { get; set; }
|
|
public int ProductId { get; set; }
|
|
public bool IsMeasured { get; set; }
|
|
public int OriginalStockQuantity { get; set; }
|
|
public int MeasuredStockQuantity { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
public List<TestStockTakingItemPalletWithInheritance>? StockTakingItemPallets { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Simulates MeasuringItemPalletBase with inheritance and ForeignKey pattern.
|
|
/// </summary>
|
|
public class TestStockTakingItemPalletWithInheritance : TestEntityBase
|
|
{
|
|
public int StockTakingItemId { get; set; }
|
|
public int TrayQuantity { get; set; }
|
|
public double TareWeight { get; set; }
|
|
public double PalletWeight { get; set; }
|
|
public double GrossWeight { get; set; }
|
|
public bool IsMeasured { get; set; }
|
|
public int? CreatorId { get; set; }
|
|
public int? ModifierId { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
}
|
|
|
|
#region Schema Mismatch Tests
|
|
|
|
/// <summary>
|
|
/// Server-side model with extra properties that client doesn't know about.
|
|
/// </summary>
|
|
public class ServerStockTaking
|
|
{
|
|
public int Id { get; set; }
|
|
public DateTime StartDateTime { get; set; }
|
|
public bool IsClosed { get; set; }
|
|
public int Creator { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
public List<ServerStockTakingItem>? StockTakingItems { get; set; }
|
|
|
|
// Extra properties that client doesn't have
|
|
public string? ExtraServerProperty1 { get; set; }
|
|
public int ExtraServerProperty2 { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Server-side item with Product navigation property.
|
|
/// </summary>
|
|
public class ServerStockTakingItem
|
|
{
|
|
public int Id { get; set; }
|
|
public int StockTakingId { get; set; }
|
|
public int ProductId { get; set; }
|
|
public bool IsMeasured { get; set; }
|
|
public int OriginalStockQuantity { get; set; }
|
|
public int MeasuredStockQuantity { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
|
|
// Navigation property - this gets serialized on server!
|
|
public ServerProductDto? Product { get; set; }
|
|
|
|
public List<ServerStockTakingItemPallet>? StockTakingItemPallets { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Server-side product DTO.
|
|
/// </summary>
|
|
public class ServerProductDto
|
|
{
|
|
public int Id { get; set; }
|
|
public string Name { get; set; } = "";
|
|
public string Description { get; set; } = "";
|
|
public double Price { get; set; }
|
|
public int CategoryId { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Server-side pallet with all properties.
|
|
/// </summary>
|
|
public class ServerStockTakingItemPallet
|
|
{
|
|
public int Id { get; set; }
|
|
public int StockTakingItemId { get; set; }
|
|
public int TrayQuantity { get; set; }
|
|
public double TareWeight { get; set; }
|
|
public double PalletWeight { get; set; }
|
|
public double GrossWeight { get; set; }
|
|
public bool IsMeasured { get; set; }
|
|
public int? CreatorId { get; set; }
|
|
public int? ModifierId { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Client-side model - MISSING some properties that server sends.
|
|
/// </summary>
|
|
public class ClientStockTaking
|
|
{
|
|
public int Id { get; set; }
|
|
public DateTime StartDateTime { get; set; }
|
|
public bool IsClosed { get; set; }
|
|
public int Creator { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
public List<ClientStockTakingItem>? StockTakingItems { get; set; }
|
|
// Note: ExtraServerProperty1 and ExtraServerProperty2 are MISSING
|
|
}
|
|
|
|
/// <summary>
|
|
/// Client-side item - MISSING Product navigation property.
|
|
/// </summary>
|
|
public class ClientStockTakingItem
|
|
{
|
|
public int Id { get; set; }
|
|
public int StockTakingId { get; set; }
|
|
public int ProductId { get; set; }
|
|
public bool IsMeasured { get; set; }
|
|
public int OriginalStockQuantity { get; set; }
|
|
public int MeasuredStockQuantity { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
// Note: Product property is MISSING - server sends it, client skips it
|
|
public List<ClientStockTakingItemPallet>? StockTakingItemPallets { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Client-side pallet.
|
|
/// </summary>
|
|
public class ClientStockTakingItemPallet
|
|
{
|
|
public int Id { get; set; }
|
|
public int StockTakingItemId { get; set; }
|
|
public int TrayQuantity { get; set; }
|
|
public double TareWeight { get; set; }
|
|
public double PalletWeight { get; set; }
|
|
public double GrossWeight { get; set; }
|
|
public bool IsMeasured { get; set; }
|
|
public int? CreatorId { get; set; }
|
|
public int? ModifierId { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Circular Reference Test Models
|
|
|
|
/// <summary>
|
|
/// Parent entity with circular reference to child.
|
|
/// </summary>
|
|
public class CircularParent
|
|
{
|
|
public int Id { get; set; }
|
|
public string Name { get; set; } = "";
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
public int Creator { get; set; }
|
|
public List<CircularChild>? Children { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Child entity with back-reference to parent (circular).
|
|
/// </summary>
|
|
public class CircularChild
|
|
{
|
|
public int Id { get; set; }
|
|
public int ParentId { get; set; }
|
|
public string Name { get; set; } = "";
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
|
|
// Back-reference to parent - creates circular reference!
|
|
public CircularParent? Parent { get; set; }
|
|
|
|
public List<CircularGrandChild>? GrandChildren { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Grandchild with back-reference.
|
|
/// </summary>
|
|
public class CircularGrandChild
|
|
{
|
|
public int Id { get; set; }
|
|
public int ChildId { get; set; }
|
|
public int? CreatorId { get; set; }
|
|
public int? ModifierId { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
|
|
// Back-reference
|
|
public CircularChild? Child { get; set; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Generic Type Parameter Test Models
|
|
|
|
/// <summary>
|
|
/// Interface with fewer properties than implementation.
|
|
/// </summary>
|
|
public interface IGenericItem
|
|
{
|
|
int Id { get; set; }
|
|
string Name { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Implementation with MORE properties than interface.
|
|
/// This is the exact pattern of StockTakingItem.
|
|
/// </summary>
|
|
public class GenericItemImpl : IGenericItem
|
|
{
|
|
public int Id { get; set; }
|
|
public string Name { get; set; } = "";
|
|
|
|
// Extra properties NOT in interface
|
|
public int ExtraInt { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
public string Description { get; set; } = "";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parent class with generic type parameter for items.
|
|
/// Similar to MgStockTaking<TStockTakingItem>.
|
|
/// </summary>
|
|
public class GenericParent<TItem> where TItem : class, IGenericItem
|
|
{
|
|
public int Id { get; set; }
|
|
public string Name { get; set; } = "";
|
|
public int Creator { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
public List<TItem>? Items { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Concrete implementation.
|
|
/// Similar to StockTaking : MgStockTaking<StockTakingItem>.
|
|
/// </summary>
|
|
public class ConcreteParent : GenericParent<GenericItemImpl>
|
|
{
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Navigation Property Test Models
|
|
|
|
/// <summary>
|
|
/// Product entity that is NOT in the parent's generic type hierarchy.
|
|
/// </summary>
|
|
public class ProductEntity
|
|
{
|
|
public int Id { get; set; }
|
|
public string Name { get; set; } = "";
|
|
public string Description { get; set; } = "";
|
|
public double Price { get; set; }
|
|
public int CategoryId { get; set; }
|
|
public DateTime Created { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Item entity with navigation property to Product.
|
|
/// This simulates StockTakingItem.Product.
|
|
/// </summary>
|
|
public class ItemWithNavigationProperty
|
|
{
|
|
public int Id { get; set; }
|
|
public int ParentId { get; set; }
|
|
public int ProductId { get; set; }
|
|
public bool IsMeasured { get; set; }
|
|
public int Quantity { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
|
|
// Navigation property - NOT in parent's generic type!
|
|
// When populated, its properties need to be in metadata table too!
|
|
public ProductEntity? Product { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parent entity with items that have navigation properties.
|
|
/// This simulates StockTaking with StockTakingItems that have Product.
|
|
/// </summary>
|
|
public class ParentWithNavigatingItems
|
|
{
|
|
public int Id { get; set; }
|
|
public string Name { get; set; } = "";
|
|
public int Creator { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
public List<ItemWithNavigationProperty>? Items { get; set; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Property Order Test Models
|
|
|
|
/// <summary>
|
|
/// Simulates NopCommerce BaseEntity.
|
|
/// </summary>
|
|
public abstract class NopBaseEntity
|
|
{
|
|
public int Id { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Simulates MgEntityBase : BaseEntity.
|
|
/// </summary>
|
|
public abstract class SimMgEntityBase : NopBaseEntity
|
|
{
|
|
public override string ToString() => $"{GetType().Name}; Id: {Id}";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Simulates MgStockTaking with exact property order from production.
|
|
/// CRITICAL: Property order in code may differ from reflection order!
|
|
/// </summary>
|
|
public abstract class SimMgStockTaking<TStockTakingItem> : SimMgEntityBase
|
|
where TStockTakingItem : class
|
|
{
|
|
public DateTime StartDateTime { get; set; }
|
|
public bool IsClosed { get; set; }
|
|
public List<TStockTakingItem>? StockTakingItems { get; set; }
|
|
public int Creator { get; set; }
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Simulates the concrete StockTaking class.
|
|
/// </summary>
|
|
public class SimStockTaking : SimMgStockTaking<SimStockTakingItem>
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Simulates StockTakingItem with navigation properties.
|
|
/// </summary>
|
|
public class SimStockTakingItem : SimMgEntityBase
|
|
{
|
|
public int StockTakingId { get; set; }
|
|
public int ProductId { get; set; }
|
|
public bool IsMeasured { get; set; }
|
|
public int OriginalStockQuantity { get; set; }
|
|
public int MeasuredStockQuantity { get; set; }
|
|
|
|
// Navigation property back to parent (circular!)
|
|
public SimStockTaking? StockTaking { get; set; }
|
|
|
|
public DateTime Created { get; set; }
|
|
public DateTime Modified { get; set; }
|
|
}
|
|
|
|
#endregion
|
|
}
|