alt/services/api/internal/contracts/parser_map_test.go
toki c0db4b24c1 feat(live-trading): 계좌 동기화와 감사 추적을 추가한다
Live Trading Boundary의 남은 account-sync/audit-trail 작업을 완료해 운영자 headless workflow와 roadmap 완료 후보 상태를 함께 반영한다.
2026-06-08 11:18:41 +09:00

96 lines
3 KiB
Go

package contracts
import (
"testing"
"google.golang.org/protobuf/proto"
altv1 "git.toki-labs.com/toki/alt/packages/contracts/gen/go/alt/v1"
protoSocket "git.toki-labs.com/toki/proto-socket/go"
)
// requiredAPIMessages is the milestone contract surface the API parser map must
// cover. It is declared independently from messageFactories so that removing a
// message from the parser map is caught here as a missing parser instead of
// silently shrinking both sides together.
func requiredAPIMessages() []proto.Message {
return []proto.Message{
&altv1.HelloRequest{},
&altv1.HelloResponse{},
// market instruments / bars
&altv1.ListInstrumentsRequest{},
&altv1.ListInstrumentsResponse{},
&altv1.ListBarsRequest{},
&altv1.ListBarsResponse{},
// market import command: daily bars
&altv1.ImportDailyBarsRequest{},
&altv1.ImportDailyBarsResponse{},
// backtest start / list / detail / result / compare
&altv1.StartBacktestRequest{},
&altv1.StartBacktestResponse{},
&altv1.GetBacktestRunRequest{},
&altv1.GetBacktestRunResponse{},
&altv1.GetBacktestResultRequest{},
&altv1.GetBacktestResultResponse{},
&altv1.BacktestResult{},
&altv1.ListBacktestRunsRequest{},
&altv1.ListBacktestRunsResponse{},
&altv1.GetBacktestRunDetailRequest{},
&altv1.GetBacktestRunDetailResponse{},
&altv1.CompareBacktestRunsRequest{},
&altv1.CompareBacktestRunsResponse{},
// paper trading start / state
&altv1.StartPaperTradingRequest{},
&altv1.StartPaperTradingResponse{},
&altv1.GetPaperTradingStateRequest{},
&altv1.GetPaperTradingStateResponse{},
&altv1.PaperTradingState{},
// live account sync surface: sync from broker / get last snapshot
&altv1.SyncLiveAccountRequest{},
&altv1.SyncLiveAccountResponse{},
&altv1.GetLiveAccountSnapshotRequest{},
&altv1.GetLiveAccountSnapshotResponse{},
&altv1.LiveAccountSnapshot{},
&altv1.LiveCashBalance{},
&altv1.LivePositionSnapshot{},
}
}
func TestParserMapIncludesAltMessages(t *testing.T) {
pm := ParserMap()
for _, msg := range requiredAPIMessages() {
typeName := protoSocket.TypeNameOf(msg)
t.Run(typeName, func(t *testing.T) {
parser := pm[typeName]
if parser == nil {
t.Fatalf("parser not registered for type %s", typeName)
}
data, err := proto.Marshal(msg)
if err != nil {
t.Fatalf("failed to marshal message: %v", err)
}
parsed, err := parser(data)
if err != nil {
t.Fatalf("failed to parse message: %v", err)
}
if protoSocket.TypeNameOf(parsed) != typeName {
t.Errorf("parsed type mismatch: expected %s, got %s", typeName, protoSocket.TypeNameOf(parsed))
}
})
}
}
// TestParserMapReportsMissingParser confirms a missing parser is observable as
// a nil lookup, so the coverage assertions above fail loudly when a required
// message is dropped from the parser map.
func TestParserMapReportsMissingParser(t *testing.T) {
pm := ParserMap()
if parser := pm["alt.v1.UnregisteredProbeMessage"]; parser != nil {
t.Fatal("expected nil parser for an unregistered message type")
}
}