unit Myc.Test.Trade.DataStream; interface uses System.SysUtils, System.Generics.Collections, DUnitX.TestFramework, Myc.Signals, Myc.Mutable, Myc.Futures, Myc.Trade.Types, Myc.Trade.DataPoint, Myc.Trade.DataStream; type // Test fixture for TDataServer and TAuraTABFileServer, focusing on data equivalence // with TDataSeries.LoadDataSeries. [TestFixture] [IgnoreMemoryLeaks(true)] TTest_TABFileServer_Equivalence = class(TObject) private FServer: IDataServer; FStream: IDataStream; public [SetupFixture] procedure SetupFixture; [Setup] procedure Setup; [TearDown] procedure TearDown; [TearDownFixture] procedure TearDownFixture; [Test] procedure Test_ServerReturnsSameDataAs_LoadDataSeries; end; implementation uses Myc.TaskManager; const // The reference data file for this test. C_TEST_PATH = '\\COFFEE\TickData\Pepperstone'; C_TEST_SYMBOL = 'GER40'; // The chunk size for fetching data from the server. C_MAX_FETCH = 200; { TTest_TABFileServer_Equivalence } procedure TTest_TABFileServer_Equivalence.SetupFixture; begin FServer := TAuraTABFileServer.Create(C_TEST_PATH); // TAskBid.ClearCache ensures a clean state for data series loading. FServer.ClearCache; end; procedure TTest_TABFileServer_Equivalence.TearDownFixture; begin FServer := nil; end; procedure TTest_TABFileServer_Equivalence.Setup; begin // Initializes the data server with a specific test file. FStream := FServer.CreateStream(C_TEST_SYMBOL); end; procedure TTest_TABFileServer_Equivalence.TearDown; begin // Releases the data server instance. FStream := nil; // Clears any cached data to prevent interference with subsequent tests. FServer.ClearCache; end; procedure TTest_TABFileServer_Equivalence.Test_ServerReturnsSameDataAs_LoadDataSeries; var chunk: array[0..C_MAX_FETCH - 1] of TDataPoint; dst: TArray>; i: Int64; n: Integer; cnt: Int64; timeout: Integer; filename: TAuraDataFile; expectedData: TArray>; begin // 1. Expected data is loaded directly using LoadDataSeries. filename := (FServer as TAuraDataServer).FindFirstFile(C_TEST_SYMBOL).WaitFor; Assert.IsTrue(filename.IsValid, 'Test data file could not be found.'); expectedData := (FServer as TAuraTABFileServer).LoadDataSeries(filename).WaitFor; SetLength(dst, Length(expectedData)); // 2. Fetch data chunks from the stream until all data is retrieved. cnt := 0; timeout := 0; while (cnt < Length(expectedData)) do begin n := FStream.GetChunk(chunk); if n > 0 then begin Move(chunk[0], dst[cnt], n * SizeOf(TDataPoint)); Inc(cnt, n); timeout := 0; // Reset timeout on progress end else begin // If GetChunk returns 0, the stream might be waiting for async I/O. // A small sleep prevents a tight loop from consuming 100% CPU. Sleep(1); Inc(timeout); Assert.IsTrue(timeout < 5000, 'Test timed out waiting for data from stream.'); end; end; // 3. A final call should return 0, as the stream must be depleted. n := FStream.GetChunk(chunk); Assert.AreEqual(0, n, 'Stream returned data after it should have been depleted.'); n := FStream.GetChunk(chunk); Assert.AreEqual(0, n, 'Stream returned data after it should have been depleted.'); // --- Assertions --- // 4. Verify that the total number of records fetched matches the expected count. Assert.AreEqual(Length(expectedData), cnt, 'Data record count mismatch.'); // 5. Verify that the content of each record is identical. // The loop checks every 1000th element for efficiency. for n := 0 to High(expectedData) div 1000 do begin i := n * 1000; Assert.AreEqual(expectedData[i].Time, dst[i].Time, 'Timestamp mismatch at index ' + i.ToString); Assert.AreEqual(expectedData[i].Data.Ask, dst[i].Data.Ask, 'Ask price mismatch at index ' + i.ToString); Assert.AreEqual(expectedData[i].Data.Bid, dst[i].Data.Bid, 'Bid price mismatch at index ' + i.ToString); end; end; initialization // Registers the test fixture with DUnitX. TDUnitX.RegisterTestFixture(TTest_TABFileServer_Equivalence); end.