121 lines
4.0 KiB
Go
121 lines
4.0 KiB
Go
package pipeline
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitea.maximumdirect.net/eric/notarius/internal/core/source"
|
|
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
|
|
)
|
|
|
|
func TestCleanDebugPathPreservesRawComponents(t *testing.T) {
|
|
for _, test := range []struct {
|
|
value string
|
|
want string
|
|
}{
|
|
{value: "", want: "%"},
|
|
{value: ".", want: "%2E"},
|
|
{value: "..", want: "%2E%2E"},
|
|
{value: "a//b", want: "a/%/b"},
|
|
{value: "/a/", want: "%/a/%"},
|
|
{value: " a ", want: "%20a%20"},
|
|
} {
|
|
if got := cleanDebugPath(test.value); got != test.want {
|
|
t.Errorf("cleanDebugPath(%q) = %q, want %q", test.value, got, test.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDebugLLMPathsKeepDotIdentitiesDistinct(t *testing.T) {
|
|
recorder := newCapturedDebugRecorder()
|
|
client := WithDebugLLMRecording(attemptDebugLLM{}, recorder)
|
|
for _, test := range []struct {
|
|
stageName string
|
|
path string
|
|
}{
|
|
{stageName: ".", path: "%2E/response-0001.json"},
|
|
{stageName: "..", path: "%2E%2E/response-0002.json"},
|
|
} {
|
|
if _, err := client.CompleteStructured(context.Background(), contracts.StructuredCompletionRequest{StageName: test.stageName}, nil); err != nil {
|
|
t.Fatalf("CompleteStructured(%q): %v", test.stageName, err)
|
|
}
|
|
if !recorder.has(test.path) {
|
|
t.Errorf("debug artifact %q was not written; names = %#v", test.path, recorder.names())
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDebugSourceDocumentPreservesUnitReferences(t *testing.T) {
|
|
doc := validSourceDocument()
|
|
envelope := debugSourceDocumentEnvelope(doc)
|
|
encoded, err := json.Marshal(envelope)
|
|
if err != nil {
|
|
t.Fatalf("Marshal(debug source document) error = %v, want nil", err)
|
|
}
|
|
|
|
var decoded debugSourceDocument
|
|
if err := json.Unmarshal(encoded, &decoded); err != nil {
|
|
t.Fatalf("Unmarshal(debug source document) error = %v, want nil", err)
|
|
}
|
|
if got, want := decoded.Units[0].Ref, (source.SourceRef{SourceID: "source-1", StartUnitID: 1, EndUnitID: 1}); got != want {
|
|
t.Fatalf("debug source unit ref = %#v, want %#v", got, want)
|
|
}
|
|
|
|
envelope.Units[0].Ref.SourceID = "mutated"
|
|
if got := doc.Units[0].Ref.SourceID; got != "source-1" {
|
|
t.Fatalf("source document ref = %q after debug mutation, want source-1", got)
|
|
}
|
|
}
|
|
|
|
func TestDebugSourceUnitsRedactSecrets(t *testing.T) {
|
|
units := []source.SourceUnit{{
|
|
ID: 1,
|
|
Kind: "paragraph",
|
|
Text: "application text Bearer secretvalue sk-secretvalue",
|
|
Ref: source.SourceRef{SourceID: "source-1", StartUnitID: 1, EndUnitID: 1},
|
|
Metadata: map[string]any{"api_key": "sk-secretvalue"},
|
|
}}
|
|
|
|
got := cloneSourceUnitsForDebug(units)
|
|
if len(got) != 1 {
|
|
t.Fatalf("debug unit count = %d, want 1", len(got))
|
|
}
|
|
if !strings.Contains(got[0].Text, "application text") {
|
|
t.Fatalf("debug unit text = %q, want application content retained", got[0].Text)
|
|
}
|
|
for _, forbidden := range []string{"secretvalue", "sk-secretvalue"} {
|
|
if strings.Contains(got[0].Text, forbidden) {
|
|
t.Fatalf("debug unit text contains %q: %q", forbidden, got[0].Text)
|
|
}
|
|
}
|
|
if got, want := got[0].Metadata["api_key"], "[REDACTED]"; got != want {
|
|
t.Fatalf("debug unit metadata api_key = %#v, want %q", got, want)
|
|
}
|
|
if units[0].Text != "application text Bearer secretvalue sk-secretvalue" {
|
|
t.Fatalf("source unit text was mutated: %q", units[0].Text)
|
|
}
|
|
}
|
|
|
|
func TestDebugSourceChunkPreservesReference(t *testing.T) {
|
|
doc := validSourceDocument()
|
|
chunk := source.Chunk{
|
|
ID: "chunk-1", SourceID: doc.ID, Index: 0,
|
|
Ref: source.SourceRef{SourceID: doc.ID, StartUnitID: 1, EndUnitID: 1},
|
|
Content: []byte("chunk content"), MediaType: "text/plain", Units: doc.Units[:1],
|
|
}
|
|
envelope := debugSourceChunkEnvelope(chunk)
|
|
encoded, err := json.Marshal(envelope)
|
|
if err != nil {
|
|
t.Fatalf("Marshal(debug source chunk) error = %v, want nil", err)
|
|
}
|
|
var decoded debugSourceChunk
|
|
if err := json.Unmarshal(encoded, &decoded); err != nil {
|
|
t.Fatalf("Unmarshal(debug source chunk) error = %v, want nil", err)
|
|
}
|
|
if decoded.Ref != chunk.Ref {
|
|
t.Fatalf("debug chunk ref = %#v, want %#v", decoded.Ref, chunk.Ref)
|
|
}
|
|
}
|