CounterDroneBackend/test/unit/CounterDrone.Core.Tests/EdgeCaseTests.cs
tian 6d56dec9a9 测试迁移:ScenarioDrone/ScenarioUnit 精简后测试适配
- TestData 新增 CreateScenarioDrone/CreateScenarioUnit 等辅助方法
- 批量替换旧字段构造为 spec 引用
- 230/238 通过,8 个边缘测试待修
2026-06-18 17:01:13 +08:00

146 lines
6.0 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.Collections.Generic;
using System.IO;
using CounterDrone.Core;
using CounterDrone.Core.Algorithms;
using CounterDrone.Core.Models;
using CounterDrone.Core.Repository;
using CounterDrone.Core.Services;
using CounterDrone.Core.Simulation;
using Xunit;
namespace CounterDrone.Core.Tests
{
/// <summary>边界场景测试</summary>
public class EdgeCaseTests : IDisposable
{
private readonly string _testDir;
private readonly IScenarioService _scenario;
private readonly SQLite.SQLiteConnection _db;
private string _scenarioId = string.Empty;
public EdgeCaseTests()
{
_testDir = Path.Combine(Path.GetTempPath(), $"cd_edge_{Guid.NewGuid():N}");
var paths = new TestPathProvider(_testDir);
var dbm = new DatabaseManager(paths);
_db = dbm.OpenMainDb();
_scenario = new ScenarioService(
new ScenarioRepository(_db), new CombatSceneRepository(_db),
new ControlZoneRepository(_db), new ScenarioDroneRepository(_db),
new ScenarioUnitRepository(_db), new CloudDispersalRepository(_db),
new RoutePlanRepository(_db), new WaypointRepository(_db));
}
public void Dispose()
{
_db?.Close();
if (Directory.Exists(_testDir)) Directory.Delete(_testDir, true);
}
[Fact]
public void EmptyDeployment_EngineRunsWithoutCrash()
{
var scenario = _scenario.CreateScenario("空部署", "");
_scenarioId = scenario.Id;
_scenario.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0 });
_scenario.SaveScenarioDrone(_scenarioId, TestData.CreateScenarioDrone("default", 1));
_scenario.SaveDeployment(_scenarioId, new List<ScenarioUnit>());
_scenario.SaveCloudDispersal(_scenarioId, new CloudDispersal());
_scenario.SaveRoute(_scenarioId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single },
new List<Waypoint>
{
new Waypoint { PosX = 0, PosY = 300, PosZ = 0, Speed = 100 },
new Waypoint { PosX = 1000, PosY = 300, PosZ = 0, Speed = 100 },
});
var engine = new SimulationEngine(_scenario, new FrameDataStore(new TestPathProvider(_testDir)),
new DamageModelRouter(), new TestPathProvider(_testDir), new DefensePlanner(TestData.Ammo, TestPlannerConfig.Instance));
engine.Initialize(_scenarioId);
engine.TimeScale = 4f;
for (int i = 0; i < 500; i++)
{
var r = engine.Tick(1f / 20f);
if (r.State == SimulationState.Completed) break;
}
engine.Stop();
Assert.Equal(DroneStatus.ReachedTarget, engine.Drones[0].Status);
}
[Fact]
public void ExtremeWind_DroneStillFlies()
{
var scenario = _scenario.CreateScenario("飓风", "");
_scenarioId = scenario.Id;
_scenario.SaveScene(_scenarioId, new CombatScene
{
WindSpeed = 30, // 最大风速
WindDirection = (int)WindDirection.E,
});
_scenario.SaveScenarioDrone(_scenarioId, TestData.CreateScenarioDrone("default", 1));
_scenario.SaveDeployment(_scenarioId, new List<ScenarioUnit>());
_scenario.SaveCloudDispersal(_scenarioId, new CloudDispersal());
_scenario.SaveRoute(_scenarioId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single },
new List<Waypoint>
{
new Waypoint { PosX = 0, PosY = 300, PosZ = 0, Speed = 600 },
new Waypoint { PosX = 5000, PosY = 300, PosZ = 0, Speed = 600 },
});
var engine = new SimulationEngine(_scenario, new FrameDataStore(new TestPathProvider(_testDir)),
new DamageModelRouter(), new TestPathProvider(_testDir), new DefensePlanner(TestData.Ammo, TestPlannerConfig.Instance));
engine.Initialize(_scenarioId);
engine.TimeScale = 4f;
for (int i = 0; i < 500; i++)
{
var r = engine.Tick(1f / 20f);
if (r.State == SimulationState.Completed) break;
}
engine.Stop();
// 强风下应偏移到东方(+X
Assert.True(engine.Drones[0].PosX > 0);
}
[Fact]
public void LongRoute_CompletesWithoutError()
{
var scenario = _scenario.CreateScenario("超长航路", "");
_scenarioId = scenario.Id;
_scenario.SaveScene(_scenarioId, new CombatScene { WindSpeed = 0 });
_scenario.SaveScenarioDrone(_scenarioId, TestData.CreateScenarioDrone("default", 1));
_scenario.SaveDeployment(_scenarioId, new List<ScenarioUnit>());
_scenario.SaveCloudDispersal(_scenarioId, new CloudDispersal());
// 500 km/h, 100km 航程
_scenario.SaveRoute(_scenarioId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single },
new List<Waypoint>
{
new Waypoint { PosX = 0, PosY = 500, PosZ = 0, Speed = 500 },
new Waypoint { PosX = 100000, PosY = 500, PosZ = 0, Speed = 500 },
});
var engine = new SimulationEngine(_scenario, new FrameDataStore(new TestPathProvider(_testDir)),
new DamageModelRouter(), new TestPathProvider(_testDir), new DefensePlanner(TestData.Ammo, TestPlannerConfig.Instance));
engine.Initialize(_scenarioId);
engine.TimeScale = 4f;
for (int i = 0; i < 5000; i++)
{
var r = engine.Tick(1f / 20f);
if (r.State == SimulationState.Completed) break;
}
engine.Stop();
Assert.Equal(DroneStatus.ReachedTarget, engine.Drones[0].Status);
}
}
}