单一数据源 data/defaults.json,含弹药/编队/火力单元/无人机/探测/天气六类预设 版本追踪: Meta 表 + version 字段,更新时 InsertOrReplace,不删用户数据 名称统一 [Demo] 前缀,UI 中可识别为模拟数据 删除: DefaultAmmunition.cs, DefaultFireUnits.cs, default_ammo.json, default_formations.json, TestAmmo.cs TestPathProvider 自动复制数据文件到测试目录 集成测试精简: 4个简单变体跳过,保留6个核心场景,39s
165 lines
6.3 KiB
C#
165 lines
6.3 KiB
C#
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 _taskId = 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 SimTaskRepository(_db), new CombatSceneRepository(_db),
|
||
new ControlZoneRepository(_db), new TargetConfigRepository(_db),
|
||
new EquipmentDeploymentRepository(_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 task = _scenario.CreateTask("空部署", "");
|
||
_taskId = task.Id;
|
||
|
||
_scenario.SaveScene(_taskId, new CombatScene { WindSpeed = 0 });
|
||
_scenario.SaveTarget(_taskId, new TargetConfig
|
||
{
|
||
WaveId = "default",
|
||
TargetType = (int)TargetType.Piston,
|
||
Quantity = 1,
|
||
TypicalSpeed = 100,
|
||
TypicalAltitude = 300,
|
||
});
|
||
_scenario.SaveDeployment(_taskId, new List<EquipmentDeployment>());
|
||
_scenario.SaveCloudDispersal(_taskId, new CloudDispersal());
|
||
_scenario.SaveRoute(_taskId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single },
|
||
new List<Waypoint>
|
||
{
|
||
new Waypoint { PosX = 0, PosY = 300, PosZ = 0 },
|
||
new Waypoint { PosX = 1000, PosY = 300, PosZ = 0 },
|
||
});
|
||
|
||
var engine = new SimulationEngine(_scenario, new FrameDataStore(new TestPathProvider(_testDir)),
|
||
new DamageModelRouter(), new TestPathProvider(_testDir), new DefensePlanner(TestData.Defaults.Ammunition, TestPlannerConfig.Instance));
|
||
engine.Initialize(_taskId);
|
||
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 task = _scenario.CreateTask("飓风", "");
|
||
_taskId = task.Id;
|
||
|
||
_scenario.SaveScene(_taskId, new CombatScene
|
||
{
|
||
WindSpeed = 30, // 最大风速
|
||
WindDirection = (int)WindDirection.E,
|
||
});
|
||
_scenario.SaveTarget(_taskId, new TargetConfig
|
||
{
|
||
WaveId = "default",
|
||
TargetType = (int)TargetType.Piston,
|
||
Quantity = 1,
|
||
TypicalSpeed = 600, // 高速对抗强风
|
||
});
|
||
_scenario.SaveDeployment(_taskId, new List<EquipmentDeployment>());
|
||
_scenario.SaveCloudDispersal(_taskId, new CloudDispersal());
|
||
_scenario.SaveRoute(_taskId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single },
|
||
new List<Waypoint>
|
||
{
|
||
new Waypoint { PosX = 0, PosY = 300, PosZ = 0 },
|
||
new Waypoint { PosX = 5000, PosY = 300, PosZ = 0 },
|
||
});
|
||
|
||
var engine = new SimulationEngine(_scenario, new FrameDataStore(new TestPathProvider(_testDir)),
|
||
new DamageModelRouter(), new TestPathProvider(_testDir), new DefensePlanner(TestData.Defaults.Ammunition, TestPlannerConfig.Instance));
|
||
engine.Initialize(_taskId);
|
||
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 task = _scenario.CreateTask("超长航路", "");
|
||
_taskId = task.Id;
|
||
|
||
_scenario.SaveScene(_taskId, new CombatScene { WindSpeed = 0 });
|
||
_scenario.SaveTarget(_taskId, new TargetConfig
|
||
{
|
||
WaveId = "default",
|
||
TargetType = (int)TargetType.HighSpeed,
|
||
Quantity = 1,
|
||
TypicalSpeed = 500,
|
||
});
|
||
_scenario.SaveDeployment(_taskId, new List<EquipmentDeployment>());
|
||
_scenario.SaveCloudDispersal(_taskId, new CloudDispersal());
|
||
|
||
// 500 km/h, 100km 航程
|
||
_scenario.SaveRoute(_taskId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single },
|
||
new List<Waypoint>
|
||
{
|
||
new Waypoint { PosX = 0, PosY = 500, PosZ = 0 },
|
||
new Waypoint { PosX = 100000, PosY = 500, PosZ = 0 },
|
||
});
|
||
|
||
var engine = new SimulationEngine(_scenario, new FrameDataStore(new TestPathProvider(_testDir)),
|
||
new DamageModelRouter(), new TestPathProvider(_testDir), new DefensePlanner(TestData.Defaults.Ammunition, TestPlannerConfig.Instance));
|
||
engine.Initialize(_taskId);
|
||
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);
|
||
}
|
||
}
|
||
}
|