using FsCheck; using FsCheck.Fluent; using FsCheck.Xunit; using Moq; using Prism.Events; using XP.Common.Logging.Interfaces; using XplorePlane.Services.MainViewport; namespace XplorePlane.Tests.Services { /// /// FsCheck property-based tests for DetectorFramePipelineService configuration correction. /// Property 11 validates that values <= 0 are corrected to 1. /// public class ConfigCorrectionPropertyTests { // ── Helpers ────────────────────────────────────────────────────────── private static DetectorFramePipelineService CreateServiceWithConfig( int acquireCapacity, int processCapacity, int processEveryN) { var mockLogger = new Mock(); mockLogger.Setup(l => l.ForModule()).Returns(mockLogger.Object); var mockMainViewport = new Mock(); var eventAggregator = new EventAggregator(); return new DetectorFramePipelineService( eventAggregator, mockMainViewport.Object, mockLogger.Object, acquireCapacity, processCapacity, processEveryN); } // ── Property 11 ────────────────────────────────────────────────────── // Feature: live-image-display, Property 11: 配置值下界修正 // Validates: Requirements 6.3, 6.4 // // For any integer config value <= 0 (ProcessEveryNFrames, AcquireQueueCapacity, // ProcessQueueCapacity), DetectorFramePipelineService corrects it to 1. [Property(MaxTest = 100)] public Property InvalidConfigValues_AreCorrectedToOne() { // Generate values <= 0 (including 0 and negative integers) var nonPositiveGen = Gen.Choose(int.MinValue / 2, 0); var gen = from acquireCapacity in nonPositiveGen from processCapacity in nonPositiveGen from processEveryN in nonPositiveGen select (acquireCapacity, processCapacity, processEveryN); return Prop.ForAll( gen.ToArbitrary(), tuple => { var (acquireCapacity, processCapacity, processEveryN) = tuple; using var service = CreateServiceWithConfig(acquireCapacity, processCapacity, processEveryN); // All three values must be corrected to 1 bool acquireCorrected = service.AcquireQueueCapacity == 1; bool processCorrected = service.ProcessQueueCapacity == 1; bool everyNCorrected = service.ProcessEveryNFrames == 1; return acquireCorrected && processCorrected && everyNCorrected; }); } // Additional property: valid positive values are preserved as-is [Property(MaxTest = 100)] public Property ValidConfigValues_ArePreservedAsIs() { var positiveGen = Gen.Choose(1, 1000); var gen = from acquireCapacity in positiveGen from processCapacity in positiveGen from processEveryN in positiveGen select (acquireCapacity, processCapacity, processEveryN); return Prop.ForAll( gen.ToArbitrary(), tuple => { var (acquireCapacity, processCapacity, processEveryN) = tuple; using var service = CreateServiceWithConfig(acquireCapacity, processCapacity, processEveryN); return service.AcquireQueueCapacity == acquireCapacity && service.ProcessQueueCapacity == processCapacity && service.ProcessEveryNFrames == processEveryN; }); } } }