Files
narratio/internal/artifactpolicy/policy_test.go

192 lines
7.6 KiB
Go

package artifactpolicy
import (
"errors"
"strings"
"testing"
)
func TestClassifySource(t *testing.T) {
tests := []struct {
name string
source string
wantKind SourceKind
wantKey string
wantErrLike string
}{
{name: "built in transcript", source: "narratio.transcript.final_trimmed", wantKind: SourceKindBuiltIn},
{name: "built in bounds", source: "narratio.bounds.session", wantKind: SourceKindBuiltIn},
{name: "configured artifact", source: "narratio.artifact.session_recap", wantKind: SourceKindConfiguredArtifact, wantKey: "session_recap"},
{name: "previous session configured", source: "narratio.previous_session.artifact.session_recap", wantKind: SourceKindPreviousArtifact, wantKey: "session_recap"},
{name: "unsupported", source: "narratio.unknown", wantErrLike: "unsupported artifact source"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ClassifySource(tt.source)
if tt.wantErrLike != "" {
if err == nil || !strings.Contains(err.Error(), tt.wantErrLike) {
t.Fatalf("ClassifySource() error = %v, want like %q", err, tt.wantErrLike)
}
return
}
if err != nil {
t.Fatalf("ClassifySource() error = %v", err)
}
if got.Kind != tt.wantKind {
t.Fatalf("ClassifySource().Kind = %q, want %q", got.Kind, tt.wantKind)
}
if got.ConfiguredKey != tt.wantKey {
t.Fatalf("ClassifySource().ConfiguredKey = %q, want %q", got.ConfiguredKey, tt.wantKey)
}
})
}
}
func TestValidatePublishSource(t *testing.T) {
configured := map[string]string{"session_recap": "artifacts/session_recap.md"}
if _, err := ValidatePublishSource("narratio.artifact.session_recap", configured); err != nil {
t.Fatalf("ValidatePublishSource(configured) error = %v", err)
}
if _, err := ValidatePublishSource("narratio.previous_session.artifact.session_recap", configured); err == nil {
t.Fatal("ValidatePublishSource(previous) error = nil, want error")
}
if _, err := ValidatePublishSource("narratio.artifact.missing", configured); err == nil {
t.Fatal("ValidatePublishSource(missing configured) error = nil, want error")
}
}
func TestResolvePublishedDestination(t *testing.T) {
configured := map[string]string{"session_recap": "artifacts/session_recap.md"}
got, err := ResolvePublishedDestination("narratio.transcript.final_trimmed", "", configured)
if err != nil {
t.Fatalf("ResolvePublishedDestination(built-in) error = %v", err)
}
if got != "transcripts/final.trimmed.json" {
t.Fatalf("built-in destination = %q, want transcripts/final.trimmed.json", got)
}
got, err = ResolvePublishedDestination("narratio.artifact.session_recap", "", configured)
if err != nil {
t.Fatalf("ResolvePublishedDestination(configured) error = %v", err)
}
if got != "artifacts/session_recap.md" {
t.Fatalf("configured destination = %q, want artifacts/session_recap.md", got)
}
got, err = ResolvePublishedDestination("narratio.transcript.final_trimmed", "published/../published/final.json", configured)
if err != nil {
t.Fatalf("ResolvePublishedDestination(explicit) error = %v", err)
}
if got != "published/final.json" {
t.Fatalf("explicit destination = %q, want published/final.json", got)
}
}
func TestResolvePublishedDestinationRejectsTraversal(t *testing.T) {
configured := map[string]string{"session_recap": "artifacts/session_recap.md"}
_, err := ResolvePublishedDestination("narratio.transcript.final_trimmed", "../escape.txt", configured)
if err == nil {
t.Fatal("ResolvePublishedDestination() error = nil, want traversal rejection")
}
}
func TestDescribeScriptoriumInputSource(t *testing.T) {
tests := []struct {
name string
source string
wantKind SourceKind
wantKey string
wantPrev bool
wantErr error
wantErrLike string
}{
{name: "built in", source: "narratio.transcript.final_trimmed", wantKind: SourceKindBuiltIn},
{name: "configured", source: "narratio.artifact.session_recap", wantKind: SourceKindConfiguredArtifact, wantKey: "session_recap"},
{name: "previous", source: "narratio.previous_session.artifact.session_recap", wantKind: SourceKindPreviousArtifact, wantKey: "session_recap", wantPrev: true},
{name: "invalid previous", source: "narratio.previous_session.artifact.", wantErr: ErrInvalidPreviousSessionSource},
{name: "unsupported", source: "narratio.unknown", wantErr: ErrUnsupportedScriptoriumInputSource},
{name: "empty", source: " ", wantErr: ErrUnsupportedScriptoriumInputSource},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := DescribeScriptoriumInputSource(tt.source)
if tt.wantErr != nil {
if !errors.Is(err, tt.wantErr) {
t.Fatalf("DescribeScriptoriumInputSource() error = %v, want %v", err, tt.wantErr)
}
return
}
if tt.wantErrLike != "" {
if err == nil || !strings.Contains(err.Error(), tt.wantErrLike) {
t.Fatalf("DescribeScriptoriumInputSource() error = %v, want like %q", err, tt.wantErrLike)
}
return
}
if err != nil {
t.Fatalf("DescribeScriptoriumInputSource() error = %v", err)
}
if got.Source.Kind != tt.wantKind {
t.Fatalf("DescribeScriptoriumInputSource().Source.Kind = %q, want %q", got.Source.Kind, tt.wantKind)
}
if got.Source.ConfiguredKey != tt.wantKey {
t.Fatalf("DescribeScriptoriumInputSource().Source.ConfiguredKey = %q, want %q", got.Source.ConfiguredKey, tt.wantKey)
}
if tt.wantPrev && got.PreviousSession == nil {
t.Fatal("DescribeScriptoriumInputSource().PreviousSession = nil, want descriptor")
}
if !tt.wantPrev && got.PreviousSession != nil {
t.Fatalf("DescribeScriptoriumInputSource().PreviousSession = %#v, want nil", got.PreviousSession)
}
})
}
}
func TestValidateInputConfiguredReference(t *testing.T) {
configured := map[string]struct{}{"session_recap": {}}
desc, err := DescribeScriptoriumInputSource("narratio.artifact.session_recap")
if err != nil {
t.Fatalf("DescribeScriptoriumInputSource(configured) error = %v", err)
}
if err := ValidateInputConfiguredReference(desc, configured); err != nil {
t.Fatalf("ValidateInputConfiguredReference(configured) error = %v", err)
}
prevDesc, err := DescribeScriptoriumInputSource("narratio.previous_session.artifact.session_recap")
if err != nil {
t.Fatalf("DescribeScriptoriumInputSource(previous) error = %v", err)
}
if err := ValidateInputConfiguredReference(prevDesc, configured); err != nil {
t.Fatalf("ValidateInputConfiguredReference(previous) error = %v", err)
}
missingDesc, err := DescribeScriptoriumInputSource("narratio.artifact.quest_log")
if err != nil {
t.Fatalf("DescribeScriptoriumInputSource(missing configured) error = %v", err)
}
err = ValidateInputConfiguredReference(missingDesc, configured)
var unknown *UnknownConfiguredArtifactError
if !errors.As(err, &unknown) || unknown.ConfiguredKey != "quest_log" {
t.Fatalf("ValidateInputConfiguredReference(missing configured) error = %v, want UnknownConfiguredArtifactError(quest_log)", err)
}
}
func TestPreviousSessionSourceDescriptorForConfiguredKey(t *testing.T) {
got, err := PreviousSessionSourceDescriptorForConfiguredKey("session_recap")
if err != nil {
t.Fatalf("PreviousSessionSourceDescriptorForConfiguredKey() error = %v", err)
}
if got.SourceID != "narratio.previous_session.artifact.session_recap" {
t.Fatalf("SourceID = %q, want narratio.previous_session.artifact.session_recap", got.SourceID)
}
if got.ConfiguredSourceID != "narratio.artifact.session_recap" {
t.Fatalf("ConfiguredSourceID = %q, want narratio.artifact.session_recap", got.ConfiguredSourceID)
}
if got.ConfiguredKey != "session_recap" {
t.Fatalf("ConfiguredKey = %q, want session_recap", got.ConfiguredKey)
}
}