package market import ( "context" "fmt" "git.sundynix.cn/Blizzard/Veyra/internal/model" "net/http" "net/http/httptest" "testing" ) func TestMarketPrecisionAndTimestamp(t *testing.T) { server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, `{"rc":0,"data":{"total":1,"diff":{"0":{"f12":"600000","f13":1,"f14":"fixture","f2":1001,"f124":1700000000,"f152":2}}}}`) })) defer server.Close() client := &Client{http: server.Client()} rows, e := client.Snapshot(context.Background(), model.ProviderConfig{BaseURL: server.URL, ID: "source", Version: 3}) if e != nil || len(rows) != 1 { t.Fatalf("snapshot: %v", e) } if rows[0].Price != "10.01" || rows[0].ObservedAt.Unix() != 1700000000 || rows[0].SourceVersion != 3 { t.Fatal("lost integer precision or provider timestamp") } } func TestHistoryOHLCAndDates(t *testing.T) { response := `{"rc":0,"data":{"code":"600000","name":"fixture","klines":["2025-01-02,10.01,10.11,10.21,9.99,100,1"]}}` server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Query().Get("fqt") != "0" { t.Error("adjustment changed") } fmt.Fprint(w, response) })) defer server.Close() client := &Client{http: server.Client()} input := model.ProviderConfig{HistoryBaseURL: server.URL, Version: 4} data, e := client.History(context.Background(), input, "600000", "SSE", "2025-01-01", "2025-01-03") if e != nil || len(data.Bars) != 1 || data.Bars[0].Close != "10.11" || data.Adjustment != "unadjusted" { t.Fatalf("history: %v", e) } response = `{"rc":0,"data":{"code":"600000","name":"fixture","klines":["2025-01-02,10.01,10.11,10.00,9.99,100,1"]}}` if _, e := client.History(context.Background(), input, "600000", "SSE", "2025-01-01", "2025-01-03"); e == nil { t.Fatal("invalid high accepted") } } func TestSinaQuotesKeepVendorDate(t *testing.T) { server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/quotes_service/api/json_v2.php/Market_Center.getHQNodeData": fmt.Fprint(w, `[{"symbol":"sh600000","code":"600000","name":"fixture"}]`) case "/list=sh600000": fmt.Fprint(w, `var hq_str_sh600000="fixture,10.000,10.000,10.010,10.100,9.900,10.000,10.010,100,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2025-01-02,15:00:00,00";`) default: t.Errorf("unexpected route %s", r.URL.Path) } })) defer server.Close() client := &Client{http: server.Client()} rows, e := client.Snapshot(context.Background(), model.ProviderConfig{MarketAdapter: "sina_public", BaseURL: server.URL, QuoteBaseURL: server.URL}) if e != nil || len(rows) != 1 || rows[0].Price != "10.01" || rows[0].ObservedAt.Format("2006-01-02T15:04:05Z") != "2025-01-02T07:00:00Z" { t.Fatalf("quote validation: %+v, %v", rows, e) } } func TestPublicPricesRejectRounding(t *testing.T) { for _, v := range []string{"10.001", "1e2", "NaN"} { if _, e := exactPublicPrice(v); e == nil { t.Fatalf("rounded or invalid price %s", v) } } if v, e := exactPublicPrice("10.010"); e != nil || v != 1001 { t.Fatal("exact extra zero rejected") } }