using FsCheck; using FsCheck.Fluent; using System; using System.Collections.Generic; using System.Linq; using XplorePlane.Models; namespace XplorePlane.Tests.Generators { /// /// FsCheck 3.x 自定义生成器:为配方相关模型定义 Arbitrary 生成器。 /// public class RecipeGenerators { public static Arbitrary PipelineModelArb() { var gen = from id in ArbMap.Default.GeneratorFor() from name in ArbMap.Default.GeneratorFor() from deviceId in ArbMap.Default.GeneratorFor() from ticks in Gen.Choose(0, int.MaxValue) let createdAt = DateTime.MinValue.AddTicks((long)ticks * 10000) let updatedAt = createdAt select new PipelineModel { Id = id, Name = name.Get, DeviceId = deviceId.Get, CreatedAt = createdAt, UpdatedAt = updatedAt, Nodes = new List() }; return gen.ToArbitrary(); } public static Arbitrary RecipeStepArb() { var gen = from stepIndex in Gen.Choose(0, 100) from motion in StateGenerators.MotionStateArb().Generator from ray in StateGenerators.RaySourceStateArb().Generator from detector in StateGenerators.DetectorStateArb().Generator from pipeline in PipelineModelArb().Generator select new RecipeStep(stepIndex, motion, ray, detector, pipeline); return gen.ToArbitrary(); } public static Arbitrary InspectionRecipeArb() { var gen = from id in ArbMap.Default.GeneratorFor() from name in ArbMap.Default.GeneratorFor() from ticks in Gen.Choose(0, int.MaxValue) let createdAt = DateTime.MinValue.AddTicks((long)ticks * 10000) let updatedAt = createdAt from stepCount in Gen.Choose(0, 10) from steps in GenSequentialSteps(stepCount) select new InspectionRecipe( id, name.Get, createdAt, updatedAt, steps.AsReadOnly()); return gen.ToArbitrary(); } public static Arbitrary RecipeExecutionStateArb() { var gen = from totalSteps in Gen.Choose(0, 50) from currentStep in Gen.Choose(0, Math.Max(totalSteps, 1) - 1) from status in Gen.Elements( RecipeExecutionStatus.Idle, RecipeExecutionStatus.Running, RecipeExecutionStatus.Paused, RecipeExecutionStatus.Completed, RecipeExecutionStatus.Error) from recipeName in ArbMap.Default.GeneratorFor() select new RecipeExecutionState(currentStep, totalSteps, status, recipeName.Get); return gen.ToArbitrary(); } private static Gen> GenSequentialSteps(int count) { if (count == 0) return Gen.Constant(new List()); // Build list step by step using SelectMany chain Gen> result = Gen.Constant(new List()); for (int i = 0; i < count; i++) { var idx = i; result = from list in result from motion in StateGenerators.MotionStateArb().Generator from ray in StateGenerators.RaySourceStateArb().Generator from detector in StateGenerators.DetectorStateArb().Generator from pipeline in PipelineModelArb().Generator select new List(list) { new RecipeStep(idx, motion, ray, detector, pipeline) }; } return result; } } }