Why: Allow consumers to download an immutable module revision without nested source checkouts or local path replacements. Evidence: SELF package tests and the prior canonical-path rejection are recorded in the Dev dependency-workspace task card; remote consumption is replayed against the committed candidate. Impact: Change the module identity and its Go imports while preserving API behavior. Existing historical submodule revisions remain buildable. Refs: Versioned dependencies U1/U3; feature/dependency-workspace
87 lines
2.7 KiB
Go
87 lines
2.7 KiB
Go
package httpx
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"git-ssh.u1680832.nyat.app/weichen/Error-Code-System.git/domains"
|
|
"git-ssh.u1680832.nyat.app/weichen/Error-Code-System.git/errcode"
|
|
)
|
|
|
|
func TestTraceGeneratesAndEchoes(t *testing.T) {
|
|
var seen string
|
|
h := Trace(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
seen = TraceID(r)
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}))
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
rec := httptest.NewRecorder()
|
|
h.ServeHTTP(rec, req)
|
|
if rec.Header().Get(TraceHeader) == "" || seen != rec.Header().Get(TraceHeader) {
|
|
t.Fatalf("generated trace header=%q seen=%q", rec.Header().Get(TraceHeader), seen)
|
|
}
|
|
|
|
req = httptest.NewRequest(http.MethodGet, "/", nil)
|
|
req.Header.Set(TraceHeader, "trace-from-caller")
|
|
rec = httptest.NewRecorder()
|
|
h.ServeHTTP(rec, req)
|
|
if rec.Header().Get(TraceHeader) != "trace-from-caller" {
|
|
t.Fatalf("echo = %s", rec.Header().Get(TraceHeader))
|
|
}
|
|
|
|
req = httptest.NewRequest(http.MethodGet, "/", nil)
|
|
req.Header.Set(TraceHeader, "bad id")
|
|
rec = httptest.NewRecorder()
|
|
h.ServeHTTP(rec, req)
|
|
if rec.Header().Get(TraceHeader) == "bad id" || rec.Header().Get(TraceHeader) == "" {
|
|
t.Fatal("invalid trace should be replaced")
|
|
}
|
|
}
|
|
|
|
func TestWriteErrorEnvelope(t *testing.T) {
|
|
reg := errcode.NewRegistry()
|
|
domains.RegisterAll(reg)
|
|
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
req.Header.Set(TraceHeader, "trace-abc-1234")
|
|
rec := httptest.NewRecorder()
|
|
err := errcode.Wrap(errors.New("dial timeout"), errcode.AgentProviderUnavailable, "模型不可达", "model", "glm-4")
|
|
WriteError(reg, rec, req, err)
|
|
if rec.Code != http.StatusServiceUnavailable {
|
|
t.Fatalf("status %d", rec.Code)
|
|
}
|
|
var env Envelope
|
|
if err := json.Unmarshal(rec.Body.Bytes(), &env); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if env.Error.Code != string(errcode.AgentProviderUnavailable) || env.Error.Message == "" {
|
|
t.Fatalf("body %+v", env.Error)
|
|
}
|
|
if env.Error.Reason != "模型不可达" || env.Error.TraceID != "trace-abc-1234" {
|
|
t.Fatalf("body %+v", env.Error)
|
|
}
|
|
if rec.Header().Get(TraceHeader) != "trace-abc-1234" {
|
|
t.Fatal("trace header not echoed")
|
|
}
|
|
}
|
|
|
|
func TestWriteErrorUnknownFallsBack(t *testing.T) {
|
|
reg := errcode.NewRegistry()
|
|
domains.RegisterAll(reg)
|
|
rec := httptest.NewRecorder()
|
|
WriteError(reg, rec, httptest.NewRequest(http.MethodGet, "/", nil), errcode.New("no.such_code", "x"))
|
|
if rec.Code != http.StatusInternalServerError {
|
|
t.Fatalf("status %d body %s", rec.Code, rec.Body.String())
|
|
}
|
|
var env Envelope
|
|
if err := json.Unmarshal(rec.Body.Bytes(), &env); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if env.Error.Code != string(errcode.SysUnknownCode) {
|
|
t.Fatalf("code %s", env.Error.Code)
|
|
}
|
|
}
|