using System; using System.Collections.Generic; using System.IO; using CounterDrone.Core; using CounterDrone.Core.Models; using CounterDrone.Core.Simulation; using Xunit; namespace CounterDrone.Core.Tests { public class FrameDataStoreTests : IDisposable { private readonly string _testDir; private readonly FrameDataStore _store; public FrameDataStoreTests() { _testDir = Path.Combine(Path.GetTempPath(), $"cd_frames_{Guid.NewGuid():N}"); var paths = new TestPathProvider(_testDir); _store = new FrameDataStore(paths); } public void Dispose() { if (Directory.Exists(_testDir)) Directory.Delete(_testDir, true); } private void CreateFakeDb(string scenarioId) { _store.BeginRecording(scenarioId); _store.RecordFrame(0, 0f, new List { new EntitySnapshot { EntityId = "d1" } }); _store.Flush(); } [Fact] public void CleanupExpired_DeletesOldFiles() { _store.RetentionDays = 0; CreateFakeDb("scenario_old_1"); CreateFakeDb("scenario_old_2"); var deleted = _store.CleanupExpired(); Assert.Equal(2, deleted); Assert.False(File.Exists(Path.Combine(_testDir, "frames", "scenario_old_1.db"))); Assert.False(File.Exists(Path.Combine(_testDir, "frames", "scenario_old_2.db"))); } [Fact] public void CleanupExpired_KeepsRecentFiles() { _store.RetentionDays = 365; CreateFakeDb("scenario_new"); var filePath = Path.Combine(_testDir, "frames", "scenario_new.db"); File.SetCreationTime(filePath, DateTime.Now); var deleted = _store.CleanupExpired(); Assert.Equal(0, deleted); Assert.True(File.Exists(filePath)); } [Fact] public void CleanupExpired_EmptyDir_ReturnsZero() { Assert.Equal(0, _store.CleanupExpired()); } [Fact] public void RecordAndFlush_ThenReadFrames() { _store.BeginRecording("scenario_rw"); var snapshots = new List { new EntitySnapshot { EntityId = "d1", EntityType = Models.EntityType.Drone, PosX = 100 }, }; _store.RecordFrame(0, 0f, snapshots); _store.RecordFrame(1, 0.05f, snapshots); _store.RecordFrame(2, 0.10f, snapshots); _store.Flush(); var frames = _store.ReadFrames("scenario_rw", 1, 2); Assert.Equal(2, frames.Count); Assert.Equal(1, frames[0].FrameIndex); Assert.Equal(2, frames[1].FrameIndex); } [Fact] public void Flush_EmptyBuffer_DoesNothing() { _store.BeginRecording("scenario_empty"); _store.Flush(); // no crash Assert.False(File.Exists(Path.Combine(_testDir, "frames", "scenario_empty.db"))); } [Fact] public void Discard_ClearsBuffer() { _store.BeginRecording("scenario_discard"); _store.RecordFrame(0, 0f, new List { new EntitySnapshot { EntityId = "d1" } }); _store.Discard(); Assert.Equal(0, _store.BufferedFrameCount); } } }