112 lines
4.9 KiB
Go
112 lines
4.9 KiB
Go
package itemoccurrences
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
|
|
itemidentity "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/items/identity"
|
|
)
|
|
|
|
func TestExtractGroundsOccurrencesInRequiredRegistry(t *testing.T) {
|
|
id := itemidentity.DeriveID("Torch")
|
|
client := &fakeItemOccurrencesLLMClient{response: extractionResponse{Occurrences: []itemOccurrenceResponse{
|
|
{ItemID: id, Name: "Torch", Kind: "lost", From: "party", SourceRefs: responseRefs(1, 1)},
|
|
}}}
|
|
req := extractionRequest()
|
|
req.References = itemRegistryReferences(t)
|
|
result, err := newExtractor(t, client, req.References).Extract(context.Background(), req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(result.Value.Occurrences) != 1 || result.Value.Occurrences[0].ItemID != id || result.Value.Occurrences[0].Name != "Torch" {
|
|
t.Fatalf("occurrences = %#v", result.Value.Occurrences)
|
|
}
|
|
input := client.requests[0].Inputs[ItemRegistryReferenceSlot]
|
|
if input.Name != ItemRegistryReferenceSlot || string(input.Content) == "" {
|
|
t.Fatalf("registry prompt input = %#v", input)
|
|
}
|
|
}
|
|
|
|
func TestExtractRejectsInvalidRegistryPairs(t *testing.T) {
|
|
id := itemidentity.DeriveID("Torch")
|
|
for _, test := range []struct {
|
|
name string
|
|
occurrence itemOccurrenceResponse
|
|
wantError string
|
|
}{
|
|
{
|
|
name: "unknown item ID",
|
|
occurrence: itemOccurrenceResponse{ItemID: "unknown", Name: "Torch", Kind: "lost", From: "party", SourceRefs: responseRefs(1, 1)},
|
|
wantError: "occurrences[0].item_id is not in the item registry",
|
|
},
|
|
{
|
|
name: "mismatched item name",
|
|
occurrence: itemOccurrenceResponse{ItemID: id, Name: "Lantern", Kind: "lost", From: "party", SourceRefs: responseRefs(1, 1)},
|
|
wantError: "occurrences[0].name does not match item_id",
|
|
},
|
|
} {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
client := &fakeItemOccurrencesLLMClient{response: extractionResponse{Occurrences: []itemOccurrenceResponse{test.occurrence}}}
|
|
req := extractionRequest()
|
|
req.References = itemRegistryReferences(t)
|
|
result, err := newExtractor(t, client, req.References).Extract(context.Background(), req)
|
|
if err == nil || !strings.Contains(err.Error(), test.wantError) {
|
|
t.Fatalf("Extract() error = %v, want %q", err, test.wantError)
|
|
}
|
|
if len(result.Value.Occurrences) != 0 {
|
|
t.Fatalf("Extract() returned partial occurrences: %#v", result.Value.Occurrences)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestExtractRejectsResponseWithInvalidRegistryPairAfterValidOccurrence(t *testing.T) {
|
|
id := itemidentity.DeriveID("Torch")
|
|
client := &fakeItemOccurrencesLLMClient{response: extractionResponse{Occurrences: []itemOccurrenceResponse{
|
|
{ItemID: id, Name: "Torch", Kind: "lost", From: "party", SourceRefs: responseRefs(1, 1)},
|
|
{ItemID: "unknown", Name: "Unknown", Kind: "lost", From: "party", SourceRefs: responseRefs(2, 2)},
|
|
}}}
|
|
req := extractionRequest()
|
|
req.References = itemRegistryReferences(t)
|
|
result, err := newExtractor(t, client, req.References).Extract(context.Background(), req)
|
|
if err == nil || !strings.Contains(err.Error(), "occurrences[1].item_id") {
|
|
t.Fatalf("Extract() error = %v, want occurrence index and item ID", err)
|
|
}
|
|
if len(result.Value.Occurrences) != 0 {
|
|
t.Fatalf("Extract() returned partial occurrences: %#v", result.Value.Occurrences)
|
|
}
|
|
}
|
|
|
|
func TestExtractRequiresItemRegistry(t *testing.T) {
|
|
_, err := newExtractor(t, &fakeItemOccurrencesLLMClient{}).Extract(context.Background(), extractionRequest())
|
|
if err == nil {
|
|
t.Fatal("Extract() error = nil, want required registry error")
|
|
}
|
|
}
|
|
|
|
func TestExtractPreservesNullableFields(t *testing.T) {
|
|
id := itemidentity.DeriveID("Torch")
|
|
client := &fakeItemOccurrencesLLMClient{content: []byte(`{"occurrences":[{"item_id":"` + id + `","name":"Torch","kind":"discovered","quantity":null,"from":null,"to":null,"source_refs":[{"start_segment":1,"end_segment":1}]}]}`)}
|
|
req := extractionRequest()
|
|
req.References = itemRegistryReferences(t)
|
|
result, err := newExtractor(t, client, req.References).Extract(context.Background(), req)
|
|
if err != nil || len(result.Value.Occurrences) != 1 || result.Value.Occurrences[0].Quantity != nil || result.Value.Occurrences[0].From != "" || result.Value.Occurrences[0].To != "" {
|
|
t.Fatalf("result = %#v, %v", result, err)
|
|
}
|
|
}
|
|
|
|
func TestExtractUsesOnlySupportedPromptInputs(t *testing.T) {
|
|
client := &fakeItemOccurrencesLLMClient{response: extractionResponse{Occurrences: []itemOccurrenceResponse{}}}
|
|
req := extractionRequest()
|
|
req.References = itemRegistryReferences(t)
|
|
req.References.Slots["unrelated"] = contracts.ResolvedReferenceSlot{Slot: contracts.ReferenceSlot{Name: "unrelated"}, Items: []contracts.ReferenceItem{{SlotName: "unrelated", Content: []byte("ignored")}}}
|
|
if _, err := newExtractor(t, client, req.References).Extract(context.Background(), req); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, ok := client.requests[0].Inputs["unrelated"]; ok {
|
|
t.Fatalf("unexpected prompt input: %#v", client.requests[0].Inputs)
|
|
}
|
|
}
|