namespace AyCode.Core.Tests.TestModels; /// /// Factory for creating test data hierarchies. /// Used by both unit tests and benchmarks. /// public static class TestDataFactory { private static int _idCounter = 1; /// /// Reset the ID counter (call in test setup) /// public static void ResetIdCounter() => _idCounter = 1; /// /// Get the next unique ID /// public static int NextId() => _idCounter++; #region Simple Object Creation /// /// Create a shared tag for cross-reference testing /// public static SharedTag CreateTag(string? name = null, string? color = null) { var id = _idCounter++; return new SharedTag { Id = id, Name = name ?? $"Tag-{id}", Color = color ?? $"#{id:X2}{(id * 10) % 256:X2}{(id * 20) % 256:X2}", Priority = id % 5, IsActive = id % 2 == 0, CreatedAt = DateTime.UtcNow.AddDays(-id), Description = $"Description for tag {id}" }; } /// /// Create a shared category /// public static SharedCategory CreateCategory(string? name = null, int? parentId = null) { var id = _idCounter++; return new SharedCategory { Id = id, Name = name ?? $"Category-{id}", Description = $"Category description {id}", SortOrder = id * 100, IsDefault = id == 1, ParentCategoryId = parentId, CreatedAt = DateTime.UtcNow.AddMonths(-id), UpdatedAt = DateTime.UtcNow.AddDays(-id) }; } /// /// Create a shared user for cross-reference testing /// public static SharedUser CreateUser(string? username = null, TestUserRole role = TestUserRole.User) { var id = _idCounter++; return new SharedUser { Id = id, Username = username ?? $"user{id}", Email = $"user{id}@test.com", FirstName = $"First{id}", LastName = $"Last{id}", IsActive = true, Role = role, LastLoginAt = DateTime.UtcNow.AddHours(-id), CreatedAt = DateTime.UtcNow.AddYears(-1), Preferences = new UserPreferences { Theme = id % 2 == 0 ? "dark" : "light", Language = "en-US", NotificationsEnabled = true, EmailDigestFrequency = "daily" } }; } /// /// Create metadata info (non-IId) /// public static MetadataInfo CreateMetadata(string? key = null, bool withChild = false) { var id = _idCounter++; return new MetadataInfo { Key = key ?? $"Meta-{id}", Value = $"MetaValue-{id}", Timestamp = DateTime.UtcNow.AddMinutes(-id * 10), ChildMetadata = withChild ? CreateMetadata($"Child-{id}", false) : null }; } #endregion #region Hierarchy Creation (5 Levels) /// /// Create a deep order hierarchy with configurable depth /// public static TestOrder CreateOrder( int itemCount = 2, int palletsPerItem = 2, int measurementsPerPallet = 2, int pointsPerMeasurement = 3, SharedTag? sharedTag = null, SharedUser? sharedUser = null, MetadataInfo? sharedMetadata = null) { var order = new TestOrder { Id = _idCounter++, OrderNumber = $"ORD-{_idCounter:D4}", Status = TestStatus.Pending, CreatedAt = DateTime.UtcNow, TotalAmount = 1000m + _idCounter * 100, PrimaryTag = sharedTag, SecondaryTag = sharedTag, // Same reference for $ref testing Owner = sharedUser, 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); item.ParentOrder = order; order.Items.Add(item); } return order; } /// /// Create an order item with pallets /// public static TestOrderItem CreateOrderItem( int palletCount = 2, int measurementsPerPallet = 2, int pointsPerMeasurement = 3, SharedTag? sharedTag = null, SharedUser? sharedUser = null, MetadataInfo? sharedMetadata = null) { var item = new TestOrderItem { Id = _idCounter++, ProductName = $"Product-{_idCounter}", Quantity = 10 + _idCounter, UnitPrice = 5.5m * _idCounter, Status = TestStatus.Pending, Tag = sharedTag, Assignee = sharedUser, ItemMetadata = sharedMetadata }; for (int i = 0; i < palletCount; i++) { var pallet = CreatePallet(measurementsPerPallet, pointsPerMeasurement, sharedMetadata); pallet.ParentItem = item; item.Pallets.Add(pallet); } return item; } /// /// Create a pallet with measurements /// public static TestPallet CreatePallet( int measurementCount = 2, int pointsPerMeasurement = 3, MetadataInfo? sharedMetadata = null) { var pallet = new TestPallet { Id = _idCounter++, PalletCode = $"PLT-{_idCounter:D4}", TrayCount = 5 + _idCounter % 10, Status = TestStatus.Pending, Weight = 100.5 + _idCounter, PalletMetadata = sharedMetadata }; for (int i = 0; i < measurementCount; i++) { var measurement = CreateMeasurement(pointsPerMeasurement); measurement.ParentPallet = pallet; pallet.Measurements.Add(measurement); } return pallet; } /// /// Create a measurement with points /// public static TestMeasurement CreateMeasurement(int pointCount = 3) { var measurement = new TestMeasurement { Id = _idCounter++, Name = $"Measurement-{_idCounter}", TotalWeight = 100.5 + _idCounter, CreatedAt = DateTime.UtcNow }; for (int i = 0; i < pointCount; i++) { var point = CreateMeasurementPoint(); point.ParentMeasurement = measurement; measurement.Points.Add(point); } return measurement; } /// /// Create a measurement point /// public static TestMeasurementPoint CreateMeasurementPoint() { var id = _idCounter++; return new TestMeasurementPoint { Id = id, Label = $"Point-{id}", Value = 10.5 + (id * 0.1), MeasuredAt = DateTime.UtcNow }; } #endregion #region Benchmark Data Generation /// /// Create a large graph for benchmarking with many cross-references. /// Creates approximately (itemCount * palletsPerItem * measurementsPerPallet * pointsPerMeasurement) objects. /// public static TestOrder 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("benchuser", TestUserRole.Admin); var sharedMetadata = CreateMetadata("benchmark", withChild: true); var order = new TestOrder { Id = _idCounter++, OrderNumber = $"BENCH-{_idCounter:D6}", Status = TestStatus.Processing, CreatedAt = DateTime.UtcNow, TotalAmount = 999999.99m, PrimaryTag = sharedTags[0], SecondaryTag = sharedTags[0], Owner = sharedUser, Category = CreateCategory("Benchmark"), OrderMetadata = sharedMetadata, AuditMetadata = sharedMetadata, Tags = sharedTags.Take(3).ToList() }; for (int i = 0; i < itemCount; i++) { var item = new TestOrderItem { Id = _idCounter++, ProductName = $"BenchProduct-{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 { Id = _idCounter++, PalletCode = $"PLT-{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 { Id = _idCounter++, Name = $"Meas-{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 { Id = _idCounter++, Label = $"Pt-{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; } /// /// Create a large-scale benchmark order similar to production workloads. /// Targets ~50,000-100,000+ IId objects with deep hierarchy and shared references. /// /// Number of root items (default 500 for ~50K objects, use 2200 for production-like) /// Pallets per item /// Measurements per pallet /// Points per measurement /// Large TestOrder with many IId references public static TestOrder 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($"user{i}", (TestUserRole)(i % 4))).ToList(); var sharedMetadata = CreateMetadata("large-scale", withChild: true); var sharedCategories = Enumerable.Range(1, 10).Select(i => CreateCategory($"Cat-{i}")).ToList(); var order = new TestOrder { Id = _idCounter++, OrderNumber = $"LARGE-{_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 { Id = _idCounter++, ProductName = $"Product-{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 { Id = _idCounter++, PalletCode = $"P-{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 { Id = _idCounter++, Name = $"M-{i}-{p}-{m}", TotalWeight = 10.0 + m, CreatedAt = DateTime.UtcNow }; measurement.ParentPallet = pallet; for (int pt = 0; pt < pointsPerMeasurement; pt++) { var point = new TestMeasurementPoint { Id = _idCounter++, Label = $"Pt-{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; } /// /// Calculate approximate object count for large-scale benchmark. /// 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; } /// /// Create primitive test data for all-types testing /// 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 = "Test String ?? ????", 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 }