using System;
using System.Collections.Generic;
using ExperionCrawler.Core.Application.Feedforward;
using ExperionCrawler.Infrastructure.Control;
using Xunit;
namespace ExperionCrawler.Tests;
/// WO-1 (P-5 confidence 자동강등) 엔진 통합 검증. Downgrade는 private이라 Tick 경유로 관측.
public class FeedforwardEngineTests
{
private static ColumnConfig Cfg(double feedFilterTau = 300, double moveThr = 0) => new()
{
Id = 1, Name = "C-TEST", Enabled = true, FeedTag = "f", ProductKey = "P",
ScanSec = 2, FeedFilterTauSec = feedFilterTau, FeedMoveThresholdPerMin = moveThr,
Streams = new[]
{
new StreamConfig { Key = "P", FlowTag = "ficq-6118", Role = StreamRole.Commanded,
Grade = Confidence.A, TargetCoeff = 0.95 }
}
};
private static PvSnapshot Snap(double feed, double streamVal, bool streamGood) => new(
new TagSample("f", feed, true, DateTime.UtcNow),
null,
Array.Empty(),
new Dictionary { ["P"] = new TagSample("ficq-6118", streamVal, streamGood, DateTime.UtcNow) });
[Fact] // 정상·신선 → config 등급(A) 유지, 사유 없음
public void Fresh_normal_keeps_config_grade()
{
var res = new FeedforwardEngine().Tick(Cfg(), Snap(100, 95, true), new ColumnState(), DateTime.UtcNow);
var p = res.Streams[0];
Assert.Equal(Confidence.A, p.Grade);
Assert.Null(p.GradeReason);
}
[Fact] // PV 신선도 불량 → 한 단계 강등(A→B) + 사유
public void Stale_pv_downgrades_one_level()
{
var res = new FeedforwardEngine().Tick(Cfg(), Snap(100, 80, false), new ColumnState(), DateTime.UtcNow);
var p = res.Streams[0];
Assert.Equal(Confidence.B, p.Grade);
Assert.Contains("신선도", p.GradeReason);
}
[Fact] // stale + 과도 동시 → 두 단계 강등(A→C) Clamp 확인
public void Stale_plus_transient_clamps_to_C()
{
var cfg = Cfg(feedFilterTau: 0, moveThr: 1); // 필터 off + 작은 임계 → 큰 피드점프가 과도 유발
var engine = new FeedforwardEngine();
var st = new ColumnState();
engine.Tick(cfg, Snap(100, 80, false), st, DateTime.UtcNow); // tick1: 시드
var res = engine.Tick(cfg, Snap(1000, 80, false), st, DateTime.UtcNow); // tick2: 피드 급변 → 과도
var p = res.Streams[0];
Assert.True(res.Transient);
Assert.Equal(Confidence.C, p.Grade); // A→(stale)B→(transient)C, C에서 클램프
}
}