package orbit import ( "context" "encoding/json" "fmt" "io" "net/http" "net/http/httptest" "strings" "sync/atomic" "testing" ) func TestBatchSDKWireValidationAndNoAutomaticRetry(t *testing.T) { id := strings.Repeat("1", 32) var calls atomic.Int32 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { calls.Add(1) if r.URL.Path != "/v1/tasks:batch" || r.Method != "POST" || r.Header.Get("Authorization") != "Bearer test-token" || r.Header.Get("Idempotency-Key") != "" { t.Error("invalid batch transport") } raw, _ := io.ReadAll(r.Body) if !strings.Contains(string(raw), `"idempotency_key":"one"`) || !strings.Contains(string(raw), `9007199254740993`) { t.Error("identity/precision lost") } if calls.Load() == 1 { w.WriteHeader(503) fmt.Fprintf(w, `{"request_id":%q,"error":{"code":"UNAVAILABLE","message":"retry original identities"}}`, id) return } fmt.Fprintf(w, `{"request_id":%q,"data":{"items":[{"index":0,"status":"ACCEPTED","receipt":{"task_id":%q,"queue_id":%q,"revision":"9007199254740993","created_at":"2026-09-17T00:00:00Z","deduplicated":true}}]}}`, id, id, id) })) defer srv.Close() c, _ := NewClient(srv.URL, Options{Token: "test-token"}) in := SubmitTasksRequest{Items: []SubmitTasksItem{{IdempotencyKey: "one", Task: SubmitTaskRequest{QueueID: id, Payload: json.RawMessage(`{"n":9007199254740993}`)}}}} if _, err := c.SubmitTasks(context.Background(), in); err == nil || calls.Load() != 1 { t.Fatal("request silently retried", err) } out, err := c.SubmitTasks(context.Background(), in) if err != nil || out.Items[0].Receipt.Revision != 9007199254740993 || !out.Items[0].Receipt.Deduplicated { t.Fatal(out, err) } for _, bad := range []SubmitTasksRequest{{}, {Items: make([]SubmitTasksItem, 33)}, {Items: []SubmitTasksItem{in.Items[0], in.Items[0]}}, {Items: []SubmitTasksItem{{IdempotencyKey: " "}}}} { if _, err := c.SubmitTasks(context.Background(), bad); err == nil { t.Fatal("accepted invalid batch") } } in.Items[0].Task.Payload = json.RawMessage(`"` + strings.Repeat("x", 512<<10) + `"`) if _, err := c.SubmitTasks(context.Background(), in); err == nil || calls.Load() != 2 { t.Fatal("unbounded batch reached network") } } func TestBatchSDKRejectsIncompleteAndContradictoryReceipts(t *testing.T) { id := strings.Repeat("1", 32) for _, data := range []string{ `{"items":[]}`, `{"items":[{"index":1,"status":"REJECTED","error":{"code":"INVALID_ARGUMENT","message":"bad"}}]}`, `{"items":[{"index":0,"status":"UNKNOWN","error":{"code":"INVALID_ARGUMENT","message":"bad"}}]}`, `{"items":[{"index":0,"status":"REJECTED","error":{"code":"UNAVAILABLE","message":"unknown"}}]}`, `{"items":[{"index":0,"status":"NOT_ATTEMPTED","error":{"code":"UNAVAILABLE","message":"bad"}}]}`, `{"items":[{"index":0,"status":"ACCEPTED"}]}`, `{"items":[{"index":0,"status":"REJECTED","receipt":{},"error":{"code":"QUEUE_FULL","message":"full"}}]}`, `{"items":[{"index":0,"status":"NEW_STATUS"}]}`, } { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, `{"request_id":%q,"data":%s}`, id, data) })) c, _ := NewClient(srv.URL, Options{Token: "test-token"}) out, err := c.SubmitTasks(context.Background(), SubmitTasksRequest{Items: []SubmitTasksItem{{IdempotencyKey: "one", Task: SubmitTaskRequest{QueueID: id}}}}) srv.Close() if err == nil || len(out.Items) != 0 { t.Fatal("malformed response exposed as success", out, data) } } }