Files
notarius/internal/core/config/effective_config_test.go

170 lines
5.3 KiB
Go

package config
import (
"strings"
"testing"
"time"
"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
)
func TestResolveRejectsEmptyAndUnknownPipelineID(t *testing.T) {
tests := []struct {
name string
pipelineID string
want string
}{
{name: "empty", pipelineID: " ", want: "pipeline id"},
{name: "unknown", pipelineID: "missing", want: "not configured"},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
_, err := validConfig().Resolve(ResolveInput{PipelineID: tc.pipelineID, Catalog: fakeCatalog(t)})
if err == nil || !strings.Contains(err.Error(), tc.want) {
t.Fatalf("expected error containing %q, got %v", tc.want, err)
}
})
}
}
func TestResolveLaneFilteringSuccessAndFailure(t *testing.T) {
effective, err := validConfig().Resolve(ResolveInput{
PipelineID: " example ",
Only: []string{" notes "},
Catalog: fakeCatalog(t),
})
if err != nil {
t.Fatalf("Resolve: %v", err)
}
if effective.PipelineID != "example" {
t.Fatalf("unexpected pipeline ID: %q", effective.PipelineID)
}
if len(effective.ResolvedPipeline.ArtifactLanes) != 1 || effective.ResolvedPipeline.ArtifactLanes[0].ID != "notes" {
t.Fatalf("unexpected resolved lanes: %+v", effective.ResolvedPipeline.ArtifactLanes)
}
if effective.ResolvedPipeline.Digest == "" {
t.Fatalf("expected digest")
}
_, err = validConfig().Resolve(ResolveInput{
PipelineID: "example",
Only: []string{"missing"},
Catalog: fakeCatalog(t),
})
if err == nil || !strings.Contains(err.Error(), "selected artifact lane") {
t.Fatalf("expected invalid lane error, got %v", err)
}
}
func TestResolveUsesTrimmedPipelineMapKeys(t *testing.T) {
cfg := validConfig()
cfg.Pipelines[" example "] = cfg.Pipelines["example"]
delete(cfg.Pipelines, "example")
effective, err := cfg.Resolve(ResolveInput{PipelineID: "example", Catalog: fakeCatalog(t)})
if err != nil {
t.Fatalf("Resolve: %v", err)
}
if effective.PipelineID != "example" {
t.Fatalf("unexpected pipeline ID: %q", effective.PipelineID)
}
}
func TestResolveSurfacesUnknownModuleKeyThroughCatalog(t *testing.T) {
cfg := validConfig()
lane := cfg.Pipelines["example"].Artifacts["events"]
lane.Extract = pipeline.Binding("missing/extract")
cfg.Pipelines["example"].Artifacts["events"] = lane
_, err := cfg.Resolve(ResolveInput{PipelineID: "example", Catalog: fakeCatalog(t)})
if err == nil || !strings.Contains(err.Error(), "missing/extract") || !strings.Contains(err.Error(), "events") {
t.Fatalf("expected unknown module error with lane context, got %v", err)
}
}
func TestResolveSurfacesMissingCapabilityThroughCatalog(t *testing.T) {
_, err := validConfig().Resolve(ResolveInput{
PipelineID: "example",
Catalog: fakeCatalog(t, pipeline.ModuleSpec{
Key: "json",
Stage: pipeline.StageOutput,
Requires: []string{"missing-capability"},
}),
})
if err == nil || !strings.Contains(err.Error(), "missing capability") || !strings.Contains(err.Error(), "json") {
t.Fatalf("expected missing capability error, got %v", err)
}
}
func TestResolveDigestChangesWhenEffectiveConfigChanges(t *testing.T) {
cfg := validConfig()
first, err := cfg.Resolve(ResolveInput{PipelineID: "example", Catalog: fakeCatalog(t)})
if err != nil {
t.Fatalf("Resolve first: %v", err)
}
lane := cfg.Pipelines["example"].Artifacts["events"]
lane.Extract.Options = map[string]any{"temperature": 0.2}
cfg.Pipelines["example"].Artifacts["events"] = lane
second, err := cfg.Resolve(ResolveInput{PipelineID: "example", Catalog: fakeCatalog(t)})
if err != nil {
t.Fatalf("Resolve second: %v", err)
}
if first.ResolvedPipeline.Digest == second.ResolvedPipeline.Digest {
t.Fatalf("expected digest to change, got %q", first.ResolvedPipeline.Digest)
}
}
func TestOpenAICompatibleClientConfigRejectsIncompleteDefaultProfile(t *testing.T) {
cfg := Default()
_, err := cfg.OpenAICompatibleClientConfig("default")
if err == nil || !strings.Contains(err.Error(), "base URL") {
t.Fatalf("expected incomplete profile error, got %v", err)
}
}
func TestOpenAICompatibleClientConfigSuccess(t *testing.T) {
cfg := validConfig()
profile := cfg.LLMProfiles["default"]
profile.APIKey = "secret"
profile.TimeoutSeconds = 45
profile.MaxRetries = 4
cfg.LLMProfiles["default"] = profile
llmCfg, err := cfg.OpenAICompatibleClientConfig(" default ")
if err != nil {
t.Fatalf("OpenAICompatibleClientConfig: %v", err)
}
if llmCfg.BaseURL != "https://example.invalid/v1" || llmCfg.Model != "test-model" || llmCfg.APIKey != "secret" {
t.Fatalf("unexpected client config strings: %+v", llmCfg)
}
if llmCfg.MaxRetries != 4 {
t.Fatalf("unexpected max retries: %d", llmCfg.MaxRetries)
}
if llmCfg.RequestTimeout != 45*time.Second {
t.Fatalf("unexpected timeout: %s", llmCfg.RequestTimeout)
}
}
func TestOpenAICompatibleClientConfigRejectsUnknownAndUnsupportedProfiles(t *testing.T) {
_, err := validConfig().OpenAICompatibleClientConfig("missing")
if err == nil || !strings.Contains(err.Error(), "not configured") {
t.Fatalf("expected unknown profile error, got %v", err)
}
cfg := validConfig()
profile := cfg.LLMProfiles["default"]
profile.Provider = "unsupported"
cfg.LLMProfiles["default"] = profile
_, err = cfg.OpenAICompatibleClientConfig("default")
if err == nil || !strings.Contains(err.Error(), "provider") {
t.Fatalf("expected unsupported provider error, got %v", err)
}
}