test: xUnit test project for Feedforward blocks (DeadTimeBuffer/RateLimiter/FirstOrderLag)
This commit is contained in:
29
tests/ExperionCrawler.Tests/ExperionCrawler.Tests.csproj
Normal file
29
tests/ExperionCrawler.Tests/ExperionCrawler.Tests.csproj
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.4.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Web\ExperionCrawler.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
48
tests/ExperionCrawler.Tests/FeedforwardBlocksTests.cs
Normal file
48
tests/ExperionCrawler.Tests/FeedforwardBlocksTests.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using ExperionCrawler.Infrastructure.Control;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
public class FeedforwardBlocksTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void DeadTime_delays_by_n_samples()
|
||||||
|
{
|
||||||
|
var d = new DeadTimeBuffer();
|
||||||
|
Assert.Equal(10.0, d.Through(10, 10, 2), 3);
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
Assert.Equal(10.0, d.Through(20, 10, 2), 3);
|
||||||
|
Assert.Equal(10.0, d.Through(20, 10, 2), 3);
|
||||||
|
Assert.Equal(20.0, d.Through(20, 10, 2), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DeadTime_asymmetric_theta_preserves_history()
|
||||||
|
{
|
||||||
|
// 비대칭 θ(20↔10) 토글 시에도 지연선이 리셋되지 않아야 한다.
|
||||||
|
var d = new DeadTimeBuffer();
|
||||||
|
double ts = 2;
|
||||||
|
for (int i = 0; i < 12; i++) d.Through(0, 20, ts); // θ=20 → n=10, 0으로 채움
|
||||||
|
// 입력을 100으로 바꾸고 θ를 작은 값으로 토글 — 재시드 버그면 즉시 100 누출
|
||||||
|
Assert.Equal(0.0, d.Through(100, 10, ts), 3); // n=5 지연 → 아직 0
|
||||||
|
Assert.Equal(0.0, d.Through(100, 20, ts), 3); // θ 되돌려도 0 (히스토리 보존)
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RateLimiter_clamps_asymmetric_up_down()
|
||||||
|
{
|
||||||
|
var r = new RateLimiter();
|
||||||
|
r.Seed(0);
|
||||||
|
Assert.Equal(1, r.Step(100, 60, 600, 1), 3);
|
||||||
|
r.Seed(100);
|
||||||
|
Assert.Equal(90, r.Step(0, 60, 600, 1), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void FirstOrderLag_reaches_63pct_after_tau()
|
||||||
|
{
|
||||||
|
var l = new FirstOrderLag();
|
||||||
|
l.Seed(0);
|
||||||
|
double y = 0; double ts = 1, tau = 10;
|
||||||
|
for (int i = 0; i < 10; i++) y = l.Step(1.0, tau, ts);
|
||||||
|
Assert.InRange(y, 0.60, 0.66);
|
||||||
|
}
|
||||||
|
}
|
||||||
1
tests/ExperionCrawler.Tests/GlobalUsings.cs
Normal file
1
tests/ExperionCrawler.Tests/GlobalUsings.cs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
global using Xunit;
|
||||||
Reference in New Issue
Block a user