package main import ( "bytes" "encoding/json" "io" "log" "net/http" "net/http/httptest" "strings" "testing" ) func TestAcceptanceFixtureContract(t *testing.T) { server := httptest.NewServer(newFixtureServer(log.New(io.Discard, "", 0))) t.Cleanup(server.Close) t.Run("knowledge", func(t *testing.T) { resp, err := http.Get(server.URL + "/knowledge") if err != nil { t.Fatal(err) } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) if resp.StatusCode != http.StatusOK || !bytes.Contains(body, []byte("KBASE-LOCAL-2026")) { t.Fatalf("knowledge status=%d marker=%t", resp.StatusCode, bytes.Contains(body, []byte("KBASE-LOCAL-2026"))) } }) t.Run("chat retry and faq", func(t *testing.T) { fail := `{"model":"gpt-5.6-luna","messages":[{"role":"user","content":"[fixture:fail]"}]}` if status := post(t, server.URL+"/v1/chat/completions", fail, nil); status != http.StatusServiceUnavailable { t.Fatalf("failure status=%d", status) } recovered := `{"model":"gpt-5.6-luna","messages":[{"role":"user","content":"[fixture:fail]"},{"role":"user","content":"recovered"}]}` if status := post(t, server.URL+"/v1/chat/completions", recovered, nil); status != http.StatusOK { t.Fatalf("recovery status=%d", status) } retry := `{"model":"gpt-5.6-luna","messages":[{"role":"user","content":"[fixture:retry] one"}]}` if status := post(t, server.URL+"/v1/chat/completions", retry, nil); status != http.StatusServiceUnavailable { t.Fatalf("first retry status=%d", status) } if status := post(t, server.URL+"/v1/chat/completions", retry, nil); status != http.StatusOK { t.Fatalf("second retry status=%d", status) } faq := `{"model":"gpt-5.6-luna","messages":[{"role":"system","content":"Extract factual, self-contained FAQs"}]}` var response struct { Choices []struct { Message chatMessage `json:"message"` } `json:"choices"` } if status := post(t, server.URL+"/v1/chat/completions", faq, &response); status != http.StatusOK || len(response.Choices) != 1 || !strings.Contains(response.Choices[0].Message.Content, `"faqs"`) { t.Fatalf("faq status=%d choices=%d", status, len(response.Choices)) } grounded := `{"model":"gpt-5.6-luna","messages":[{"role":"system","content":"Knowledge Base Context:\nSource: http://captain-fixture:8080/knowledge"},{"role":"user","content":"warranty?"}]}` if status := post(t, server.URL+"/v1/chat/completions", grounded, &response); status != http.StatusOK || !strings.Contains(response.Choices[0].Message.Content, "[[1](http://captain-fixture:8080/knowledge)]") { t.Fatalf("grounded status=%d content=%q", status, response.Choices[0].Message.Content) } }) t.Run("skill activation", func(t *testing.T) { request := `{"model":"gpt-5.6-luna","messages":[{"role":"system","content":"[{\"name\":\"local-skill\"}]"},{"role":"user","content":"[fixture:skill]"}],"tools":[{"type":"function","function":{"name":"activate_skill"}}]}` var response struct { Choices []struct { Message chatMessage `json:"message"` } `json:"choices"` } status := post(t, server.URL+"/v1/chat/completions", request, &response) if status != http.StatusOK || len(response.Choices) != 1 || len(response.Choices[0].Message.ToolCalls) != 1 || response.Choices[0].Message.ToolCalls[0].Function.Name != "activate_skill" { t.Fatalf("status=%d choices=%d", status, len(response.Choices)) } }) t.Run("embedding dimensions", func(t *testing.T) { var response struct { Data []struct { Embedding []float64 `json:"embedding"` } `json:"data"` } status := post(t, server.URL+"/v1/embeddings", `{"model":"fixture-embedding","input":["hello"]}`, &response) if status != http.StatusOK || len(response.Data) != 1 || len(response.Data[0].Embedding) != 1536 { t.Fatalf("status=%d vectors=%d dimensions=%d", status, len(response.Data), len(response.Data[0].Embedding)) } }) } func post(t *testing.T, url, body string, dst any) int { t.Helper() resp, err := http.Post(url, "application/json", strings.NewReader(body)) if err != nil { t.Fatal(err) } defer resp.Body.Close() if dst != nil { if err := json.NewDecoder(resp.Body).Decode(dst); err != nil { t.Fatal(err) } } return resp.StatusCode }