CounterDroneBackend/test/unit/CounterDrone.Core.Tests/PlannerConfigTests.cs
tian 8515f7821a feat(v0.5.0): weather into planner + unified physics model
Planner no longer writes local physics formulas. All kinematics/geometry/damage go through shared utility classes (Kinematics/RouteGeometry/CloudExpansionModel/DamageAssessment).

Core: RouteGeometry (route geometry), PlannerConfig + planner_config.json (config externalization). Planner route-aware layout (offset along tangent), cloud overlap 20pct. DroneEntity arc-length driven.

Fixes: PathInSphere cloud-frame correction (root cause), GaussianPuffDispersion hardcoded Sunny, ComputeEffectiveRadius cloud age, planner wind offset, remove drone wind bias.

Tests 167 to 191, 41s. Windy scenarios pass.
2026-06-14 14:49:53 +08:00

96 lines
3.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.IO;
using CounterDrone.Core.Algorithms;
using CounterDrone.Core.Models;
using Xunit;
namespace CounterDrone.Core.Tests
{
public class PlannerConfigTests : IDisposable
{
private readonly string _testDir;
public PlannerConfigTests()
{
_testDir = Path.Combine(Path.GetTempPath(), $"cd_cfg_{Guid.NewGuid():N}");
Directory.CreateDirectory(_testDir);
}
public void Dispose()
{
if (Directory.Exists(_testDir)) Directory.Delete(_testDir, true);
}
private void WriteConfig(string json)
=> File.WriteAllText(Path.Combine(_testDir, "planner_config.json"), json);
private static readonly string ValidJson = @"
{
""CloudOverlapRatio"": 0.2,
""CriticalProbabilityThreshold"": 0.5,
""MaxInterceptProbability"": 0.95,
""TypeCoefficient"": {
""HighSpeed"": 4.0, ""FixedWing"": 2.0, ""Piston"": 2.0,
""Rotor"": 1.0, ""Electric"": 1.0
},
""AmmoMatch"": {
""Electric"": ""InertGas"", ""Piston"": ""InertGas"", ""Jet"": ""ActiveMaterial""
}
}";
[Fact]
public void Load_ValidJson_ReturnsAllFields()
{
WriteConfig(ValidJson);
var cfg = PlannerConfig.Load(_testDir);
Assert.Equal(0.2f, cfg.CloudOverlapRatio);
Assert.Equal(0.5f, cfg.CriticalProbabilityThreshold);
Assert.Equal(0.95f, cfg.MaxInterceptProbability);
Assert.Equal(4.0f, cfg.TypeCoefficient[TargetType.HighSpeed]);
Assert.Equal(AerosolType.InertGas, cfg.AmmoMatch[PowerType.Piston]);
Assert.Equal(AerosolType.ActiveMaterial, cfg.AmmoMatch[PowerType.Jet]);
}
[Fact]
public void Load_MissingFile_Throws()
{
// 不写文件
Assert.Throws<FileNotFoundException>(() => PlannerConfig.Load(_testDir));
}
[Fact]
public void Load_MissingField_Throws()
{
// 缺 CriticalProbabilityThreshold
WriteConfig(@"{ ""CloudOverlapRatio"": 0.2, ""MaxInterceptProbability"": 0.95,
""TypeCoefficient"": {""Piston"": 2.0}, ""AmmoMatch"": {""Piston"": ""InertGas""} }");
Assert.Throws<InvalidDataException>(() => PlannerConfig.Load(_testDir));
}
[Fact]
public void Load_OverlapOutOfRange_Throws()
{
// CloudOverlapRatio = 1.0 非法(必须 < 1
var bad = ValidJson.Replace("0.2", "1.0");
WriteConfig(bad);
Assert.Throws<InvalidDataException>(() => PlannerConfig.Load(_testDir));
}
[Fact]
public void Load_EmptyDataRoot_Throws()
{
Assert.Throws<ArgumentException>(() => PlannerConfig.Load(""));
}
[Fact]
public void Load_EnumParsedFromString()
{
// 验证枚举用字符串(非数字)也能正确解析
WriteConfig(ValidJson);
var cfg = PlannerConfig.Load(_testDir);
Assert.Equal(1.0f, cfg.TypeCoefficient[TargetType.Rotor]);
Assert.Equal(AerosolType.InertGas, cfg.AmmoMatch[PowerType.Electric]);
}
}
}