78 lines
3.9 KiB
Go
78 lines
3.9 KiB
Go
package invariants
|
|
|
|
import (
|
|
"context"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitea.maximumdirect.net/eric/notarius/internal/core/source"
|
|
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
|
|
"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
|
|
"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
|
|
)
|
|
|
|
func TestValidatorApprovesCanonicalOrderForEveryKind(t *testing.T) {
|
|
kinds := []dnd.LocationOccurrenceKind{dnd.LocationOccurrenceKindVisited, dnd.LocationOccurrenceKindPlanned, dnd.LocationOccurrenceKindRecalled, dnd.LocationOccurrenceKindMentioned}
|
|
occurrences := make([]dnd.LocationOccurrence, len(kinds))
|
|
for index, kind := range kinds {
|
|
occurrences[index] = occurrence(kind, 1)
|
|
}
|
|
result, err := New(Options{}).Validate(context.Background(), request(dnd.LocationOccurrenceList{Occurrences: occurrences}))
|
|
if err != nil || !result.Approved {
|
|
t.Fatalf("Validate() = %#v, %v", result, err)
|
|
}
|
|
}
|
|
|
|
func TestValidatorRejectsOrderingAndExactDuplicateInvariants(t *testing.T) {
|
|
for _, test := range []struct {
|
|
name string
|
|
value dnd.LocationOccurrenceList
|
|
want string
|
|
}{
|
|
{"references", dnd.LocationOccurrenceList{Occurrences: []dnd.LocationOccurrence{{LocationID: "id", Name: "Moon Gate", Kind: dnd.LocationOccurrenceKindVisited, SourceRefs: []source.SourceRef{{SourceID: "session", StartUnitID: 2, EndUnitID: 2}, {SourceID: "session", StartUnitID: 1, EndUnitID: 1}}}}}, "not in canonical order"},
|
|
{"list", dnd.LocationOccurrenceList{Occurrences: []dnd.LocationOccurrence{occurrence(dnd.LocationOccurrenceKindVisited, 2), occurrence(dnd.LocationOccurrenceKindVisited, 1)}}, "occurrences are not in canonical order"},
|
|
{"duplicate", dnd.LocationOccurrenceList{Occurrences: []dnd.LocationOccurrence{occurrence(dnd.LocationOccurrenceKindVisited, 1), occurrence(dnd.LocationOccurrenceKindVisited, 1)}}, "duplicates occurrence"},
|
|
} {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
result, err := New(Options{}).Validate(context.Background(), request(test.value))
|
|
if err != nil || result.Approved || result.ReasonCode != ReasonCode || !strings.Contains(result.Message, test.want) {
|
|
t.Fatalf("Validate() = %#v, %v", result, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestValidatorDefersInvalidEvidenceAndDoesNotMutate(t *testing.T) {
|
|
value := dnd.LocationOccurrenceList{Occurrences: []dnd.LocationOccurrence{{LocationID: "id", Name: "Moon Gate", Kind: dnd.LocationOccurrenceKindVisited, SourceRefs: []source.SourceRef{{SourceID: "session", StartUnitID: 99, EndUnitID: 99}}}}}
|
|
before := cloneList(value)
|
|
result, err := New(Options{}).Validate(context.Background(), request(value))
|
|
if err != nil || !result.Approved || !reflect.DeepEqual(value, before) {
|
|
t.Fatalf("invalid evidence deferral = %#v, %v", result, err)
|
|
}
|
|
registry := pipeline.NewValidatorRegistry()
|
|
if err := Register(registry); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got := New(Options{}).CheckpointFingerprints(); len(got) != 1 || got[0].Value != policy {
|
|
t.Fatalf("fingerprints = %#v", got)
|
|
}
|
|
}
|
|
|
|
func request(value dnd.LocationOccurrenceList) contracts.TypedValidationRequest[dnd.LocationOccurrenceList] {
|
|
return contracts.TypedValidationRequest[dnd.LocationOccurrenceList]{Source: document(), Value: value}
|
|
}
|
|
func document() *source.SourceDocument {
|
|
return &source.SourceDocument{ID: "session", Units: []source.SourceUnit{{ID: 1}, {ID: 2}}}
|
|
}
|
|
func occurrence(kind dnd.LocationOccurrenceKind, unit int) dnd.LocationOccurrence {
|
|
return dnd.LocationOccurrence{LocationID: "id", Name: "Moon Gate", Kind: kind, SourceRefs: []source.SourceRef{{SourceID: "session", StartUnitID: unit, EndUnitID: unit}}}
|
|
}
|
|
func cloneList(value dnd.LocationOccurrenceList) dnd.LocationOccurrenceList {
|
|
cloned := dnd.LocationOccurrenceList{Occurrences: append([]dnd.LocationOccurrence(nil), value.Occurrences...)}
|
|
for index := range cloned.Occurrences {
|
|
cloned.Occurrences[index].SourceRefs = append([]source.SourceRef(nil), value.Occurrences[index].SourceRefs...)
|
|
}
|
|
return cloned
|
|
}
|