package stream import ( "encoding/json" "errors" "testing" ) // TestErrorEventJSONIncludesErrorInfo 校验 ErrorInfo 经 StreamEvent 序列化后 // 前端可从 error_info 字段读取到分类元数据(含 request_id)。 func TestErrorEventJSONIncludesErrorInfo(t *testing.T) { info := ClassifyError(errors.New("context deadline exceeded"), "dialogue_generating", "req_x", "sess_y", "") ev := StreamEvent{Type: EventError, Error: info.UserMessage, ErrorInfo: &info} b, err := json.Marshal(ev) if err != nil { t.Fatal(err) } var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { t.Fatal(err) } ei, ok := raw["error_info"].(map[string]any) if !ok { t.Fatalf("missing error_info in %s", string(b)) } if ei["request_id"] != "req_x" { t.Fatalf("request_id=%v", ei["request_id"]) } if ei["phase_id"] != "dialogue_generating" { t.Fatalf("phase_id=%v", ei["phase_id"]) } if ei["class"] != string(ErrorClassTransient) { t.Fatalf("class=%v", ei["class"]) } } // TestWithRequestID_RoundTrip 校验请求 ID 可经 Context 注入并读回。 func TestWithRequestID_RoundTrip(t *testing.T) { ctx := WithRequestID(t.Context(), "req_abc") if got := RequestIDFromContext(ctx); got != "req_abc" { t.Fatalf("got=%s want=req_abc", got) } if got := RequestIDFromContext(nil); got != "" { t.Fatalf("nil ctx should return empty, got=%s", got) } }