diff --git a/AGENTS.md b/AGENTS.md index af9de38..12888cc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -76,19 +76,22 @@ pwsh scripts/check_unity_build.ps1 This automatically rebuilds Core.dll, copies it to Unity Plugins, and compiles Unity scripts. Exits 0 if all pass. -## 7. Run Targeted Tests, Not Full Suite +## 7. Run Targeted Tests First -**Never run all tests unless explicitly asked.** Always use `--filter` to run only the tests relevant to what you changed. +**Always run the narrowest relevant test first.** If you just changed `DefensePlannerTests`, run `--filter 'FullyQualifiedName~DefensePlannerTests'`. If you changed `FullPipelineTests`, run that filter. Don't start with `dotnet test` on the whole project — it wastes time and buries the failures you're looking for. + +Run full suite only after the targeted tests pass, to verify nothing else broke. ```bash -# Run a single test: -pwsh -Command "dotnet test test/unit/CounterDrone.Core.Tests/ --filter 'FullyQualifiedName~TestName'" - # Run a test class: pwsh -Command "dotnet test test/unit/CounterDrone.Core.Tests/ --filter 'FullyQualifiedName~DefensePlannerTests'" -``` -Running all 125+ tests wastes ~30 seconds every time and buries the failures you actually care about. +# Run a single test: +pwsh -Command "dotnet test test/unit/CounterDrone.Core.Tests/ --filter 'FullyQualifiedName~Scenario_AirBased'" + +# Run full suite (only after targeted passes): +pwsh -Command "dotnet test test/unit/CounterDrone.Core.Tests/" +``` --- diff --git a/src/Unity/Assets/Plugins/CounterDrone.Core/CounterDrone.Core.dll b/src/Unity/Assets/Plugins/CounterDrone.Core/CounterDrone.Core.dll index f57dbb9..1a4b171 100644 Binary files a/src/Unity/Assets/Plugins/CounterDrone.Core/CounterDrone.Core.dll and b/src/Unity/Assets/Plugins/CounterDrone.Core/CounterDrone.Core.dll differ diff --git a/src/Unity/Assets/Scripts/Managers/GroupManager.cs b/src/Unity/Assets/Scripts/Managers/GroupManager.cs index 3affea1..90402fe 100644 --- a/src/Unity/Assets/Scripts/Managers/GroupManager.cs +++ b/src/Unity/Assets/Scripts/Managers/GroupManager.cs @@ -11,16 +11,19 @@ namespace CounterDrone.Unity public class GroupManager : MonoBehaviour { private IGroupService _service; + private SQLite.SQLiteConnection _db; public IGroupService Service => _service; public void Awake() { var paths = new UnityPathProvider(); - var db = new DatabaseManager(paths).OpenMainDb(); - _service = new GroupService(new GroupRepository(db)); + _db = new DatabaseManager(paths).OpenMainDb(); + _service = new GroupService(new GroupRepository(_db)); } + void OnDestroy() => _db?.Close(); + public Group Create(string name, GroupType type, string desc = "") => _service.CreateGroup(name, type, desc); diff --git a/src/Unity/Assets/Scripts/Managers/ModelManager.cs b/src/Unity/Assets/Scripts/Managers/ModelManager.cs index c588f3d..cc009ac 100644 --- a/src/Unity/Assets/Scripts/Managers/ModelManager.cs +++ b/src/Unity/Assets/Scripts/Managers/ModelManager.cs @@ -13,16 +13,19 @@ namespace CounterDrone.Unity { private IModelService _service; private IPathProvider _paths; + private SQLite.SQLiteConnection _db; public IModelService Service => _service; public void Awake() { _paths = new UnityPathProvider(); - var db = new DatabaseManager(_paths).OpenMainDb(); - _service = new ModelService(new ModelRepository(db), _paths); + _db = new DatabaseManager(_paths).OpenMainDb(); + _service = new ModelService(new ModelRepository(_db), _paths); } + void OnDestroy() => _db?.Close(); + public ModelInfo Import(string filePath, string name) => _service.ImportModel(filePath, name); public void Delete(string id) => _service.DeleteModel(id); public List GetAll() => _service.GetAllModels(); diff --git a/src/Unity/Assets/Scripts/Managers/ReportManager.cs b/src/Unity/Assets/Scripts/Managers/ReportManager.cs index 3af2a2f..288415b 100644 --- a/src/Unity/Assets/Scripts/Managers/ReportManager.cs +++ b/src/Unity/Assets/Scripts/Managers/ReportManager.cs @@ -11,16 +11,19 @@ namespace CounterDrone.Unity { private IReportService _service; private IPathProvider _paths; + private SQLite.SQLiteConnection _db; public IReportService Service => _service; public void Awake() { _paths = new UnityPathProvider(); - var db = new DatabaseManager(_paths).OpenMainDb(); - _service = new ReportService(db, _paths); + _db = new DatabaseManager(_paths).OpenMainDb(); + _service = new ReportService(_db, _paths); } + void OnDestroy() => _db?.Close(); + public SimulationReport Generate(string taskId, TaskFullConfig cfg, List events, string status, float duration) => _service.Generate(taskId, cfg, events, status, duration); diff --git a/src/Unity/Assets/Scripts/Managers/ScenarioManager.cs b/src/Unity/Assets/Scripts/Managers/ScenarioManager.cs index 6266430..e729f51 100644 --- a/src/Unity/Assets/Scripts/Managers/ScenarioManager.cs +++ b/src/Unity/Assets/Scripts/Managers/ScenarioManager.cs @@ -11,6 +11,7 @@ namespace CounterDrone.Unity public class ScenarioManager : MonoBehaviour { private IScenarioService _service; + private SQLite.SQLiteConnection _db; public IScenarioService Service => _service; @@ -20,12 +21,12 @@ namespace CounterDrone.Unity { var paths = new UnityPathProvider(); Debug.Log($"ScenarioManager.Awake: dbPath={paths.GetMainDbPath()}"); - var db = new DatabaseManager(paths).OpenMainDb(); + _db = new DatabaseManager(paths).OpenMainDb(); _service = 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)); + new SimTaskRepository(_db), new CombatSceneRepository(_db), + new ControlZoneRepository(_db), new TargetConfigRepository(_db), + new EquipmentDeploymentRepository(_db), new CloudDispersalRepository(_db), + new RoutePlanRepository(_db), new WaypointRepository(_db)); Debug.Log("ScenarioManager.Awake: OK"); } catch (System.Exception ex) @@ -34,6 +35,8 @@ namespace CounterDrone.Unity } } + void OnDestroy() => _db?.Close(); + public SimTask CreateTask(string name, string number) => _service.CreateTask(name, number); public void DeleteTask(string id) => _service.DeleteTask(id); public TaskFullConfig GetDetail(string id) => _service.GetTaskDetail(id); diff --git a/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs b/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs index 7095997..87e0b40 100644 --- a/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs +++ b/src/Unity/Assets/Scripts/Managers/SimulationRunner.cs @@ -26,6 +26,7 @@ namespace CounterDrone.Unity private IScenarioService _scenario; private IPathProvider _paths; private string _taskId; + private SQLite.SQLiteConnection _db; private readonly Dictionary _entityVisuals = new(); private readonly Dictionary _clouds = new(); @@ -37,13 +38,13 @@ namespace CounterDrone.Unity public void Awake() { _paths = new UnityPathProvider(); - var db = new DatabaseManager(_paths).OpenMainDb(); + _db = new DatabaseManager(_paths).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)); + new SimTaskRepository(_db), new CombatSceneRepository(_db), + new ControlZoneRepository(_db), new TargetConfigRepository(_db), + new EquipmentDeploymentRepository(_db), new CloudDispersalRepository(_db), + new RoutePlanRepository(_db), new WaypointRepository(_db)); _frameStore = new FrameDataStore(_paths); _engine = new SimulationEngine(_scenario, _frameStore, new DamageModelRouter(), _paths); @@ -148,7 +149,7 @@ namespace CounterDrone.Unity } public void Stop() => _engine?.Stop(); - void OnDestroy() => Stop(); + void OnDestroy() { Stop(); _db?.Close(); } private void SpawnDroneVisual(DroneEntity drone) {