package shared import ( "testing" "gitea.maximumdirect.net/eric/notarius/internal/core/source" ) func TestChunkCoverageRequiresCompleteDocumentOrderedSpan(t *testing.T) { doc := coverageDocument(30, 10, 20, 40) index := source.NewDocumentIndex(doc) for _, test := range []struct { name string chunk *source.Chunk ref source.SourceRef want bool }{ {name: "complete non-monotonic span", chunk: coverageChunk(doc.ID, 30, 10, 20), ref: coverageRef(doc.ID, 30, 20), want: true}, {name: "single unit", chunk: coverageChunk(doc.ID, 10), ref: coverageRef(doc.ID, 10, 10), want: true}, {name: "missing middle unit", chunk: coverageChunk(doc.ID, 30, 20), ref: coverageRef(doc.ID, 30, 20)}, {name: "only endpoints", chunk: coverageChunk(doc.ID, 30, 40), ref: coverageRef(doc.ID, 30, 40)}, {name: "reversed", chunk: coverageChunk(doc.ID, 30, 10), ref: coverageRef(doc.ID, 10, 30)}, {name: "wrong source", chunk: coverageChunk(doc.ID, 30), ref: coverageRef("other", 30, 30)}, {name: "missing endpoint", chunk: coverageChunk(doc.ID, 30), ref: coverageRef(doc.ID, 30, 999)}, {name: "nil chunk", ref: coverageRef(doc.ID, 30, 30)}, } { t.Run(test.name, func(t *testing.T) { coverage := NewChunkCoverage(test.chunk) if got := coverage.Contains(index, doc, test.ref); got != test.want { t.Fatalf("Contains() = %t, want %t", got, test.want) } }) } if NewChunkCoverage(coverageChunk(doc.ID, 30)).Contains(source.DocumentIndex{}, nil, coverageRef(doc.ID, 30, 30)) { t.Fatal("Contains() with nil document and zero index = true, want false") } } func TestChunkCoverageDoesNotRetainMutableChunkState(t *testing.T) { doc := coverageDocument(1, 2) chunk := coverageChunk(doc.ID, 1, 2) coverage := NewChunkCoverage(chunk) chunk.SourceID = "changed" chunk.Units[0].ID = 99 if !coverage.Contains(source.NewDocumentIndex(doc), doc, coverageRef(doc.ID, 1, 2)) { t.Fatal("Contains() changed after mutating source chunk") } } func coverageDocument(ids ...int) *source.SourceDocument { doc := &source.SourceDocument{ID: "session", Units: make([]source.SourceUnit, len(ids))} for index, id := range ids { doc.Units[index] = source.SourceUnit{ID: id} } return doc } func coverageChunk(sourceID string, ids ...int) *source.Chunk { chunk := &source.Chunk{SourceID: sourceID, Units: make([]source.SourceUnit, len(ids))} for index, id := range ids { chunk.Units[index] = source.SourceUnit{ID: id} } return chunk } func coverageRef(sourceID string, start, end int) source.SourceRef { return source.SourceRef{SourceID: sourceID, StartUnitID: start, EndUnitID: end} }