Paper trading readiness에서 API/worker/CLI가 같은 protobuf 계약으로 paper state를 시작하고 조회할 수 있어야 한다. Headless 운영 경로를 먼저 닫기 위해 contract, worker runtime, API forwarding, CLI scenario, client parser map과 검증 artifact를 함께 반영한다.
88 lines
2.7 KiB
Go
88 lines
2.7 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{},
|
|
}
|
|
}
|
|
|
|
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")
|
|
}
|
|
}
|