core services and tests
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
using QuantEngine.Application.Services;
|
||||
using QuantEngine.Core.Interfaces;
|
||||
|
||||
namespace QuantEngine.Core.Tests;
|
||||
|
||||
public class HistoryIngestionE2ETests
|
||||
{
|
||||
[Fact]
|
||||
public async Task AppendDecisionThenReadSnapshotRoundTripsThroughApplicationFlow()
|
||||
{
|
||||
var store = new FakeHistoryStore();
|
||||
var ingestion = new HistoryIngestionService(store);
|
||||
var reader = new PostgresqlHistorySnapshotReader(store);
|
||||
|
||||
var appendCount = await ingestion.AppendDecisionAsync(new Dictionary<string, object?>
|
||||
{
|
||||
["decision_id"] = "dec-001",
|
||||
["decided_at"] = DateTimeOffset.Parse("2026-06-26T09:00:00+09:00"),
|
||||
["instrument_id"] = "005930",
|
||||
["action"] = "BUY",
|
||||
["gate"] = "PASS",
|
||||
["score"] = 87.5,
|
||||
["source_version"] = "v1",
|
||||
["provenance"] = new Dictionary<string, object?>
|
||||
{
|
||||
["source"] = "unit-test"
|
||||
}
|
||||
});
|
||||
|
||||
Assert.Equal(1, appendCount);
|
||||
|
||||
var rows = await reader.ReadAsync("decision_result_history", 10);
|
||||
Assert.Single(rows);
|
||||
Assert.Equal("dec-001", rows[0]["decision_id"]);
|
||||
Assert.Equal("005930", rows[0]["instrument_id"]);
|
||||
Assert.Equal("BUY", rows[0]["action"]);
|
||||
Assert.Equal("PASS", rows[0]["gate"]);
|
||||
Assert.Equal(87.5, rows[0]["score"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AppendFactorOutputThenReadSnapshotPreservesPayload()
|
||||
{
|
||||
var store = new FakeHistoryStore();
|
||||
var ingestion = new HistoryIngestionService(store);
|
||||
var reader = new PostgresqlHistorySnapshotReader(store);
|
||||
|
||||
var appendCount = await ingestion.AppendFactorOutputAsync(
|
||||
factorId: "RS_VERDICT_V2",
|
||||
factorVersion: "2026-06-26",
|
||||
outputValue: 1.23,
|
||||
outputGate: "PASS",
|
||||
sourceVersion: "source-42",
|
||||
observedAt: DateTimeOffset.Parse("2026-06-26T10:00:00+09:00"));
|
||||
|
||||
Assert.Equal(1, appendCount);
|
||||
|
||||
var rows = await reader.ReadAsync("factor_output_history", 10);
|
||||
Assert.Single(rows);
|
||||
Assert.Equal("RS_VERDICT_V2", rows[0]["factor_id"]);
|
||||
Assert.Equal("2026-06-26", rows[0]["factor_version"]);
|
||||
Assert.Equal(1.23, rows[0]["output_value"]);
|
||||
Assert.Equal("PASS", rows[0]["output_gate"]);
|
||||
Assert.Equal("source-42", rows[0]["source_version"]);
|
||||
}
|
||||
|
||||
private sealed class FakeHistoryStore : IPostgresqlHistoryStore
|
||||
{
|
||||
private readonly Dictionary<string, List<IDictionary<string, object?>>> _rows = new();
|
||||
|
||||
public Task<int> AppendAsync(string domain, IDictionary<string, object?> payload)
|
||||
{
|
||||
if (!_rows.TryGetValue(domain, out var list))
|
||||
{
|
||||
list = new List<IDictionary<string, object?>>();
|
||||
_rows[domain] = list;
|
||||
}
|
||||
|
||||
list.Add(new Dictionary<string, object?>(payload));
|
||||
return Task.FromResult(1);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<IDictionary<string, object?>>> SnapshotAsync(string domain, int limit = 500)
|
||||
{
|
||||
if (!_rows.TryGetValue(domain, out var list))
|
||||
{
|
||||
return Task.FromResult<IReadOnlyList<IDictionary<string, object?>>>(Array.Empty<IDictionary<string, object?>>());
|
||||
}
|
||||
|
||||
return Task.FromResult<IReadOnlyList<IDictionary<string, object?>>>(list.Take(limit).ToList());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user