153 lines
4.4 KiB
Go
153 lines
4.4 KiB
Go
package shared
|
|
|
|
import (
|
|
"context"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitea.maximumdirect.net/eric/notarius/internal/core/source"
|
|
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
|
|
)
|
|
|
|
func TestPrepareChunkExtraction(t *testing.T) {
|
|
canceled, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
tests := []struct {
|
|
name string
|
|
ctx context.Context
|
|
configure func(*contracts.TypedExtractionRequest)
|
|
sourceInput contracts.LLMInputMaterial
|
|
want contracts.LLMInputMaterial
|
|
wantErr string
|
|
mutateOutput bool
|
|
}{
|
|
{
|
|
name: "nil context",
|
|
wantErr: "context must not be nil",
|
|
},
|
|
{
|
|
name: "canceled context",
|
|
ctx: canceled,
|
|
wantErr: "context error before extraction",
|
|
},
|
|
{
|
|
name: "nil source",
|
|
configure: func(req *contracts.TypedExtractionRequest) {
|
|
req.Source = nil
|
|
},
|
|
wantErr: "source must not be nil",
|
|
},
|
|
{
|
|
name: "nil chunk",
|
|
configure: func(req *contracts.TypedExtractionRequest) {
|
|
req.Chunk = nil
|
|
},
|
|
wantErr: "chunk must not be nil",
|
|
},
|
|
{
|
|
name: "empty chunk units",
|
|
configure: func(req *contracts.TypedExtractionRequest) {
|
|
req.Chunk = &source.Chunk{ID: req.Chunk.ID}
|
|
},
|
|
wantErr: "units must not be empty",
|
|
},
|
|
{
|
|
name: "fallback to chunk content",
|
|
want: contracts.NewLLMInputMaterial("source", "application/json", []byte(`{"units":[1,2]}`), "", ""),
|
|
mutateOutput: true,
|
|
},
|
|
{
|
|
name: "clone isolation",
|
|
sourceInput: contracts.NewLLMInputMaterial("source", "application/json", []byte(`{"units":[1,2]}`), "sha256:source", "file:///source.json"),
|
|
want: contracts.NewLLMInputMaterial("source", "application/json", []byte(`{"units":[1,2]}`), "sha256:source", "file:///source.json"),
|
|
mutateOutput: true,
|
|
},
|
|
{
|
|
name: "mismatched content",
|
|
sourceInput: contracts.NewLLMInputMaterial("source", "application/json", []byte(`{"units":[9]}`), "sha256:other", "file:///other.json"),
|
|
wantErr: "source input must match chunk",
|
|
},
|
|
{
|
|
name: "default fields",
|
|
sourceInput: contracts.LLMInputMaterial{
|
|
Content: []byte(`{"units":[1,2]}`),
|
|
Digest: "sha256:source",
|
|
OriginURI: "file:///source.json",
|
|
},
|
|
want: contracts.LLMInputMaterial{
|
|
Name: "source",
|
|
MediaType: "application/json",
|
|
Content: []byte(`{"units":[1,2]}`),
|
|
Digest: "sha256:source",
|
|
OriginURI: "file:///source.json",
|
|
SizeBytes: int64(len(`{"units":[1,2]}`)),
|
|
},
|
|
},
|
|
{
|
|
name: "preserve explicit metadata",
|
|
sourceInput: contracts.LLMInputMaterial{
|
|
Name: "transcript",
|
|
MediaType: "text/plain",
|
|
Content: []byte(`{"units":[1,2]}`),
|
|
Digest: "sha256:explicit",
|
|
OriginURI: "file:///explicit.txt",
|
|
SizeBytes: 42,
|
|
},
|
|
want: contracts.LLMInputMaterial{
|
|
Name: "transcript",
|
|
MediaType: "text/plain",
|
|
Content: []byte(`{"units":[1,2]}`),
|
|
Digest: "sha256:explicit",
|
|
OriginURI: "file:///explicit.txt",
|
|
SizeBytes: 42,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
req := extractionRequest()
|
|
req.SourceInput = test.sourceInput
|
|
if test.configure != nil {
|
|
test.configure(&req)
|
|
}
|
|
ctx := test.ctx
|
|
if ctx == nil && test.wantErr != "context must not be nil" {
|
|
ctx = context.Background()
|
|
}
|
|
got, err := PrepareChunkExtraction(ctx, req)
|
|
if test.wantErr != "" {
|
|
if err == nil || !strings.Contains(err.Error(), test.wantErr) {
|
|
t.Fatalf("PrepareChunkExtraction() error = %v, want %q", err, test.wantErr)
|
|
}
|
|
return
|
|
}
|
|
if err != nil {
|
|
t.Fatalf("PrepareChunkExtraction() error = %v, want nil", err)
|
|
}
|
|
if !reflect.DeepEqual(got, test.want) {
|
|
t.Fatalf("PrepareChunkExtraction() = %#v, want %#v", got, test.want)
|
|
}
|
|
if test.mutateOutput {
|
|
got.Content[0] = 'x'
|
|
if string(req.SourceInput.Content) != string(test.sourceInput.Content) || string(req.Chunk.Content) != `{"units":[1,2]}` {
|
|
t.Fatal("PrepareChunkExtraction() output shares request content")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func extractionRequest() contracts.TypedExtractionRequest {
|
|
doc := &source.SourceDocument{ID: "session-alpha"}
|
|
chunk := &source.Chunk{
|
|
ID: "session-alpha:chunk:0",
|
|
SourceID: doc.ID,
|
|
Content: []byte(`{"units":[1,2]}`),
|
|
MediaType: "application/json",
|
|
Units: []source.SourceUnit{{ID: 1}},
|
|
}
|
|
return contracts.TypedExtractionRequest{Source: doc, Chunk: chunk}
|
|
}
|