using System; using ExperionCrawler.Infrastructure.Control; using Xunit; namespace ExperionCrawler.Tests; public class FeedforwardThetaTests { // 알려진 지연(5 샘플)으로 응답이 피드를 따라가면 θ≈5*ts 로 식별되어야 함 [Fact] public void Estimator_finds_known_lag() { var est = new CrossCorrLagEstimator(maxLagSamples: 20, historySamples: 400, minSignalStd: 1e-9, recomputeEvery: 1); var feed = new System.Collections.Generic.List(); (double thetaUpSec, double thetaDnSec, double conf)? last = null; for (int t = 0; t < 400; t++) { double df = Math.Sin(t * 0.3); // 풍부한 양/음 외란 feed.Add(df); double dr = t >= 5 ? feed[t - 5] : 0.0; // 응답 = 피드 5샘플 지연 last = est.Push(df, dr, 0.0, tsSec: 1.0); // 스팀 0 } Assert.NotNull(last); Assert.InRange(last!.Value.thetaUpSec, 4.0, 6.0); Assert.InRange(last!.Value.thetaDnSec, 4.0, 6.0); Assert.True(last!.Value.conf > 0.5); } // 피드 외란이 없으면(평탄) 제안 억제(null) [Fact] public void Estimator_suppresses_when_no_excitation() { var est = new CrossCorrLagEstimator(maxLagSamples: 20, historySamples: 400, minSignalStd: 1e-6, recomputeEvery: 1); (double, double, double)? last = (0, 0, 0); for (int t = 0; t < 200; t++) last = est.Push(0.0, 0.0, 0.0, 1.0); // Δ 전부 0 Assert.Null(last); } }