AyCode.Core/AyCode.Core.Tests/TestModels/TestDataFactory.cs

538 lines
19 KiB
C#

namespace AyCode.Core.Tests.TestModels;
/// <summary>
/// Factory for creating test data hierarchies.
/// Used by both unit tests and benchmarks.
///
/// All placeholder strings use Hungarian (UTF-8 multi-byte) content to exercise the UTF-8
/// encoder/decoder path rather than the ASCII fast-path. This makes the benchmark reflect
/// realistic i18n payloads, not just the FixStrAscii / StringAscii marker fast-paths.
/// </summary>
public static class TestDataFactory
{
private static int _idCounter = 1;
/// <summary>
/// Reset the ID counter (call in test setup)
/// </summary>
public static void ResetIdCounter() => _idCounter = 1;
/// <summary>
/// Get the next unique ID
/// </summary>
public static int NextId() => _idCounter++;
#region Simple Object Creation
/// <summary>
/// Create a shared tag for cross-reference testing
/// </summary>
public static SharedTag_All_True CreateTag(string? name = null, string? color = null)
{
var id = _idCounter++;
return new SharedTag_All_True
{
Id = id,
Name = name ?? $"Címke-{id}",
Color = color ?? $"Szín-#{id:X2}{(id * 10) % 256:X2}{(id * 20) % 256:X2}",
Priority = id % 5,
IsActive = id % 2 == 0,
CreatedAt = DateTime.UtcNow.AddDays(-id),
Description = $"Címke leírása {id}"
};
}
/// <summary>
/// Create a shared category
/// </summary>
public static SharedCategory_All_True CreateCategory(string? name = null, int? parentId = null)
{
var id = _idCounter++;
return new SharedCategory_All_True
{
Id = id,
Name = name ?? $"Kategória-{id}",
Description = $"Kategória leírása {id}",
SortOrder = id * 100,
IsDefault = id == 1,
ParentCategoryId = parentId,
CreatedAt = DateTime.UtcNow.AddMonths(-id),
UpdatedAt = DateTime.UtcNow.AddDays(-id)
};
}
/// <summary>
/// Create a shared user for cross-reference testing
/// </summary>
public static SharedUser_All_True CreateUser(string? username = null, TestUserRole role = TestUserRole.User)
{
var id = _idCounter++;
return new SharedUser_All_True
{
Id = id,
Username = username ?? $"felhasználó{id}",
Email = $"felhasználó{id}@teszt.hu",
FirstName = $"Vezetéknév{id}",
LastName = $"Keresztnév{id}",
IsActive = true,
Role = role,
LastLoginAt = DateTime.UtcNow.AddHours(-id),
CreatedAt = DateTime.UtcNow.AddYears(-1),
Preferences = new UserPreferences_All_True
{
Theme = id % 2 == 0 ? "sötét" : "világos",
Language = "magyar",
NotificationsEnabled = true,
EmailDigestFrequency = "naponkénti"
}
};
}
/// <summary>
/// Create metadata info (non-IId)
/// </summary>
public static MetadataInfo_All_True CreateMetadata(string? key = null, bool withChild = false)
{
var id = _idCounter++;
return new MetadataInfo_All_True
{
Key = key ?? $"Metaadat-{id}",
Value = $"MetaÉrték-{id}",
Timestamp = DateTime.UtcNow.AddMinutes(-id * 10),
ChildMetadata = withChild ? CreateMetadata($"Gyermek-{id}", false) : null
};
}
#endregion
#region Hierarchy Creation (5 Levels)
/// <summary>
/// Create a deep order hierarchy with configurable depth.
/// Supports both IId-based (SharedTag_All_True, SharedUser, SharedCategory_All_True) and Non-IId (UserPreferences_All_True) shared references.
/// </summary>
public static TestOrder_All_True CreateOrder(
int itemCount = 2,
int palletsPerItem = 2,
int measurementsPerPallet = 2,
int pointsPerMeasurement = 3,
SharedTag_All_True? sharedTag = null,
SharedUser_All_True? sharedUser = null,
MetadataInfo_All_True? sharedMetadata = null,
UserPreferences_All_True? sharedPreferences = null,
SharedCategory_All_True? sharedCategory = null)
{
// If sharedUser is provided but no sharedPreferences, use the user's preferences as shared
sharedPreferences ??= sharedUser?.Preferences;
var order = new TestOrder_All_True
{
Id = _idCounter++,
OrderNumber = $"Megrendelés-{_idCounter:D4}",
Status = TestStatus.Pending,
CreatedAt = DateTime.UtcNow,
TotalAmount = 1000m + _idCounter * 100,
PrimaryTag = sharedTag,
SecondaryTag = sharedTag, // Same reference for $ref testing
Owner = sharedUser,
Category = sharedCategory,
OrderMetadata = sharedMetadata,
AuditMetadata = sharedMetadata // Same reference for Newtonsoft $ref
};
if (sharedTag != null)
{
order.Tags.Add(sharedTag);
}
for (int i = 0; i < itemCount; i++)
{
var item = CreateOrderItem(
palletsPerItem,
measurementsPerPallet,
pointsPerMeasurement,
sharedTag,
sharedUser,
sharedMetadata,
sharedPreferences,
sharedCategory);
item.ParentOrder = order;
order.Items.Add(item);
}
return order;
}
/// <summary>
/// Create an order item with pallets.
/// Supports both IId-based and Non-IId shared references.
/// </summary>
public static TestOrderItem_All_True CreateOrderItem(
int palletCount = 2,
int measurementsPerPallet = 2,
int pointsPerMeasurement = 3,
SharedTag_All_True? sharedTag = null,
SharedUser_All_True? sharedUser = null,
MetadataInfo_All_True? sharedMetadata = null,
UserPreferences_All_True? sharedPreferences = null,
SharedCategory_All_True? sharedCategory = null)
{
// Create assignee - if sharedUser provided, use it. Otherwise create new user with sharedPreferences
SharedUser_All_True? assignee = sharedUser;
if (assignee == null && sharedPreferences != null)
{
// Create a new user but with shared preferences (Non-IId ref testing)
assignee = CreateUser();
assignee.Preferences = sharedPreferences;
}
var item = new TestOrderItem_All_True
{
Id = _idCounter++,
ProductName = $"Termék-{_idCounter}",
Quantity = 10 + _idCounter,
UnitPrice = 5.5m * _idCounter,
Status = TestStatus.Pending,
Tag = sharedTag,
Assignee = assignee,
ItemMetadata = sharedMetadata
};
for (int i = 0; i < palletCount; i++)
{
// Pass shared references to all levels - creates many shared refs!
var pallet = CreatePallet(
measurementsPerPallet,
pointsPerMeasurement,
sharedMetadata,
sharedTag, // IId shared ref
sharedUser, // IId shared ref
sharedCategory); // IId shared ref
pallet.ParentItem = item;
item.Pallets.Add(pallet);
}
return item;
}
/// <summary>
/// Create a pallet with measurements
/// </summary>
public static TestPallet_All_True CreatePallet(
int measurementCount = 2,
int pointsPerMeasurement = 3,
MetadataInfo_All_True? sharedMetadata = null,
SharedTag_All_True? sharedTag = null,
SharedUser_All_True? sharedInspector = null,
SharedCategory_All_True? sharedCategory = null)
{
var pallet = new TestPallet_All_True
{
Id = _idCounter++,
PalletCode = $"Raklapkód-{_idCounter:D4}",
TrayCount = 5 + _idCounter % 10,
Status = TestStatus.Pending,
Weight = 100.5 + _idCounter,
PalletMetadata = sharedMetadata,
Tag = sharedTag,
Inspector = sharedInspector,
Category = sharedCategory
};
for (int i = 0; i < measurementCount; i++)
{
var measurement = CreateMeasurement(pointsPerMeasurement, sharedTag, sharedInspector);
measurement.ParentPallet = pallet;
pallet.Measurements.Add(measurement);
}
return pallet;
}
/// <summary>
/// Create a measurement with points
/// </summary>
public static TestMeasurement_All_True CreateMeasurement(
int pointCount = 3,
SharedTag_All_True? sharedTag = null,
SharedUser_All_True? sharedOperator = null)
{
var measurement = new TestMeasurement_All_True
{
Id = _idCounter++,
Name = $"Mérés-{_idCounter}",
TotalWeight = 100.5 + _idCounter,
CreatedAt = DateTime.UtcNow,
Tag = sharedTag,
Operator = sharedOperator
};
for (int i = 0; i < pointCount; i++)
{
var point = CreateMeasurementPoint(sharedTag, sharedOperator);
point.ParentMeasurement = measurement;
measurement.Points.Add(point);
}
return measurement;
}
/// <summary>
/// Create a measurement point
/// </summary>
public static TestMeasurementPoint_All_True CreateMeasurementPoint(
SharedTag_All_True? sharedTag = null,
SharedUser_All_True? sharedVerifier = null)
{
var id = _idCounter++;
return new TestMeasurementPoint_All_True
{
Id = id,
Label = $"MérőPont-{id}",
Value = 10.5 + (id * 0.1),
MeasuredAt = DateTime.UtcNow,
Tag = sharedTag,
Verifier = sharedVerifier
};
}
#endregion
#region Benchmark Data Generation
/// <summary>
/// Create a large graph for benchmarking with many cross-references.
/// Creates approximately (itemCount * palletsPerItem * measurementsPerPallet * pointsPerMeasurement) objects.
/// </summary>
public static TestOrder_All_True CreateBenchmarkOrder(
int itemCount = 5,
int palletsPerItem = 4,
int measurementsPerPallet = 3,
int pointsPerMeasurement = 5)
{
ResetIdCounter();
// Create shared references that will be used throughout
var sharedTags = Enumerable.Range(1, 10).Select(_ => CreateTag()).ToList();
var sharedUser = CreateUser("mérőfelhasználó", TestUserRole.Admin);
var sharedMetadata = CreateMetadata("mérőteszt", withChild: true);
var order = new TestOrder_All_True
{
Id = _idCounter++,
OrderNumber = $"MÉRŐTESZT-{_idCounter:D6}",
Status = TestStatus.Processing,
CreatedAt = DateTime.UtcNow,
TotalAmount = 999999.99m,
PrimaryTag = sharedTags[0],
SecondaryTag = sharedTags[0],
Owner = sharedUser,
Category = CreateCategory("Mérőteszt"),
OrderMetadata = sharedMetadata,
AuditMetadata = sharedMetadata,
Tags = sharedTags.Take(3).ToList()
};
for (int i = 0; i < itemCount; i++)
{
var item = new TestOrderItem_All_True
{
Id = _idCounter++,
ProductName = $"MérőTermék-{i}",
Quantity = 100 + i * 10,
UnitPrice = 25.99m + i,
Status = (TestStatus)(i % 5),
Tag = sharedTags[i % sharedTags.Count],
Assignee = sharedUser,
ItemMetadata = sharedMetadata
};
item.ParentOrder = order;
for (int p = 0; p < palletsPerItem; p++)
{
var pallet = new TestPallet_All_True
{
Id = _idCounter++,
PalletCode = $"Raklapkód-{i}-{p}",
TrayCount = 10 + p,
Status = (TestStatus)(p % 4),
Weight = 500.0 + p * 50,
PalletMetadata = sharedMetadata
};
pallet.ParentItem = item;
for (int m = 0; m < measurementsPerPallet; m++)
{
var measurement = new TestMeasurement_All_True
{
Id = _idCounter++,
Name = $"Mérés-{i}-{p}-{m}",
TotalWeight = 50.0 + m * 10,
CreatedAt = DateTime.UtcNow.AddMinutes(-m)
};
measurement.ParentPallet = pallet;
for (int pt = 0; pt < pointsPerMeasurement; pt++)
{
var point = new TestMeasurementPoint_All_True
{
Id = _idCounter++,
Label = $"MérőPnt-{i}-{p}-{m}-{pt}",
Value = 1.0 + pt * 0.5,
MeasuredAt = DateTime.UtcNow.AddSeconds(-pt)
};
point.ParentMeasurement = measurement;
measurement.Points.Add(point);
}
pallet.Measurements.Add(measurement);
}
item.Pallets.Add(pallet);
}
order.Items.Add(item);
}
return order;
}
/// <summary>
/// Create a large-scale benchmark order similar to production workloads.
/// Targets ~50,000-100,000+ IId objects with deep hierarchy and shared references.
/// </summary>
/// <param name="rootItemCount">Number of root items (default 500 for ~50K objects, use 2200 for production-like)</param>
/// <param name="palletsPerItem">Pallets per item</param>
/// <param name="measurementsPerPallet">Measurements per pallet</param>
/// <param name="pointsPerMeasurement">Points per measurement</param>
/// <returns>Large TestOrder_All_True with many IId references</returns>
public static TestOrder_All_True CreateLargeScaleBenchmarkOrder(
int rootItemCount = 500,
int palletsPerItem = 3,
int measurementsPerPallet = 3,
int pointsPerMeasurement = 4)
{
ResetIdCounter();
// Create shared references - these will be heavily reused (tests $ref handling)
var sharedTags = Enumerable.Range(1, 50).Select(_ => CreateTag()).ToList();
var sharedUsers = Enumerable.Range(1, 20).Select(i => CreateUser($"felhasználó{i}", (TestUserRole)(i % 4))).ToList();
var sharedMetadata = CreateMetadata("nagy-méretű", withChild: true);
var sharedCategories = Enumerable.Range(1, 10).Select(i => CreateCategory($"Kategória-{i}")).ToList();
var order = new TestOrder_All_True
{
Id = _idCounter++,
OrderNumber = $"NAGYMÉRET-{_idCounter:D8}",
Status = TestStatus.Processing,
CreatedAt = DateTime.UtcNow,
TotalAmount = 9999999.99m,
PrimaryTag = sharedTags[0],
SecondaryTag = sharedTags[0], // Same ref
Owner = sharedUsers[0],
Category = sharedCategories[0],
OrderMetadata = sharedMetadata,
AuditMetadata = sharedMetadata, // Same ref
Tags = sharedTags.Take(5).ToList()
};
for (int i = 0; i < rootItemCount; i++)
{
var item = new TestOrderItem_All_True
{
Id = _idCounter++,
ProductName = $"Termék-{i}",
Quantity = 100 + i,
UnitPrice = 10.99m + (i % 100),
Status = (TestStatus)(i % 5),
Tag = sharedTags[i % sharedTags.Count], // Shared ref
Assignee = sharedUsers[i % sharedUsers.Count], // Shared ref
ItemMetadata = sharedMetadata // Shared ref
};
item.ParentOrder = order;
for (int p = 0; p < palletsPerItem; p++)
{
var pallet = new TestPallet_All_True
{
Id = _idCounter++,
PalletCode = $"Raklapkód-{i}-{p}",
TrayCount = 5 + (p % 10),
Status = (TestStatus)(p % 4),
Weight = 100.0 + p * 10,
PalletMetadata = sharedMetadata // Shared ref
};
pallet.ParentItem = item;
for (int m = 0; m < measurementsPerPallet; m++)
{
var measurement = new TestMeasurement_All_True
{
Id = _idCounter++,
Name = $"Mérés-{i}-{p}-{m}",
TotalWeight = 10.0 + m,
CreatedAt = DateTime.UtcNow
};
measurement.ParentPallet = pallet;
for (int pt = 0; pt < pointsPerMeasurement; pt++)
{
var point = new TestMeasurementPoint_All_True
{
Id = _idCounter++,
Label = $"MérőPnt-{i}-{p}-{m}-{pt}",
Value = pt * 0.1,
MeasuredAt = DateTime.UtcNow
};
point.ParentMeasurement = measurement;
measurement.Points.Add(point);
}
pallet.Measurements.Add(measurement);
}
item.Pallets.Add(pallet);
}
order.Items.Add(item);
}
return order;
}
/// <summary>
/// Calculate approximate object count for large-scale benchmark.
/// </summary>
public static int CalculateObjectCount(int rootItems, int pallets, int measurements, int points)
{
// 1 order + rootItems + (rootItems * pallets) + (rootItems * pallets * measurements) + (rootItems * pallets * measurements * points)
// Plus shared objects (tags, users, metadata, categories)
var sharedObjects = 50 + 20 + 2 + 10; // tags + users + metadata + categories
var hierarchyObjects = 1 + rootItems + (rootItems * pallets) + (rootItems * pallets * measurements) + (rootItems * pallets * measurements * points);
return sharedObjects + hierarchyObjects;
}
/// <summary>
/// Create primitive test data for all-types testing
/// </summary>
public static PrimitiveTestClass CreatePrimitiveTestData()
{
return new PrimitiveTestClass
{
IntValue = int.MaxValue,
LongValue = long.MaxValue,
DoubleValue = 3.14159265358979,
DecimalValue = 12345.6789m,
FloatValue = 1.5f,
BoolValue = true,
StringValue = "Teszt Szöveg árvíztűrőtükörfúrógép",
GuidValue = Guid.Parse("12345678-1234-1234-1234-123456789abc"),
DateTimeValue = new DateTime(2024, 12, 25, 12, 30, 45, DateTimeKind.Utc),
EnumValue = TestStatus.Shipped,
ByteValue = 255,
ShortValue = short.MaxValue,
NullableInt = 42,
NullableIntNull = null
};
}
#endregion
}