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
{
/// 边界场景测试
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();
foreach (var a in DefaultAmmunition.GetAll()) _db.Insert(a);
_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
{
GroupId = "default",
TargetType = (int)TargetType.Piston,
Quantity = 1,
TypicalSpeed = 100,
TypicalAltitude = 300,
});
_scenario.SaveDeployment(_taskId, new List());
_scenario.SaveCloudDispersal(_taskId, new CloudDispersal());
_scenario.SaveRoute(_taskId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single },
new List
{
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));
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
{
GroupId = "default",
TargetType = (int)TargetType.Piston,
Quantity = 1,
TypicalSpeed = 600, // 高速对抗强风
});
_scenario.SaveDeployment(_taskId, new List());
_scenario.SaveCloudDispersal(_taskId, new CloudDispersal());
_scenario.SaveRoute(_taskId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single },
new List
{
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));
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
{
GroupId = "default",
TargetType = (int)TargetType.HighSpeed,
Quantity = 1,
TypicalSpeed = 500,
});
_scenario.SaveDeployment(_taskId, new List());
_scenario.SaveCloudDispersal(_taskId, new CloudDispersal());
// 500 km/h, 100km 航程
_scenario.SaveRoute(_taskId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single },
new List
{
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));
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);
}
}
}