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{}, // monthly aggregation &altv1.AggregateMonthlyBarsRequest{}, &altv1.AggregateMonthlyBarsResponse{}, &altv1.MonthlyProvenance{}, // 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") } }